diff --git a/.php_cs.dist.php b/.php_cs.dist.php index 4ad5af914..bf15b5876 100644 --- a/.php_cs.dist.php +++ b/.php_cs.dist.php @@ -1,15 +1,14 @@ getQuery()->getResult(Query::HYDRATE_SCALAR); + return $query->getQuery()->getResult(Query::HYDRATE_SCALAR); } public function getTitle() @@ -106,9 +105,9 @@ class CountPerson implements ExportInterface return $qb; } - public function requiredRole() + public function requiredRole(): string { - return new Role(PersonVoter::STATS); + return PersonVoter::STATS; } public function supportsModifiers() diff --git a/docs/source/development/pagination/example.php b/docs/source/development/pagination/example.php index ed91d16a7..0d79395a7 100644 --- a/docs/source/development/pagination/example.php +++ b/docs/source/development/pagination/example.php @@ -1,14 +1,14 @@ getQuery()->getResult(Query::HYDRATE_SCALAR); + return $query->getQuery()->getResult(Query::HYDRATE_SCALAR); } public function getTitle(): string diff --git a/src/Bundle/ChillActivityBundle/Export/Export/LinkedToACP/AvgActivityVisitDuration.php b/src/Bundle/ChillActivityBundle/Export/Export/LinkedToACP/AvgActivityVisitDuration.php index 6514be3e0..359593059 100644 --- a/src/Bundle/ChillActivityBundle/Export/Export/LinkedToACP/AvgActivityVisitDuration.php +++ b/src/Bundle/ChillActivityBundle/Export/Export/LinkedToACP/AvgActivityVisitDuration.php @@ -1,14 +1,14 @@ getQuery()->getResult(Query::HYDRATE_SCALAR); + return $query->getQuery()->getResult(Query::HYDRATE_SCALAR); } public function getTitle(): string diff --git a/src/Bundle/ChillActivityBundle/Export/Export/LinkedToACP/CountActivity.php b/src/Bundle/ChillActivityBundle/Export/Export/LinkedToACP/CountActivity.php index 92e8cdc27..2dc844aa2 100644 --- a/src/Bundle/ChillActivityBundle/Export/Export/LinkedToACP/CountActivity.php +++ b/src/Bundle/ChillActivityBundle/Export/Export/LinkedToACP/CountActivity.php @@ -1,14 +1,14 @@ getQuery()->getResult(Query::HYDRATE_SCALAR); + return $query->getQuery()->getResult(Query::HYDRATE_SCALAR); } public function getTitle(): string diff --git a/src/Bundle/ChillActivityBundle/Export/Export/LinkedToACP/SumActivityDuration.php b/src/Bundle/ChillActivityBundle/Export/Export/LinkedToACP/SumActivityDuration.php index 692ff5530..1cf20dc5f 100644 --- a/src/Bundle/ChillActivityBundle/Export/Export/LinkedToACP/SumActivityDuration.php +++ b/src/Bundle/ChillActivityBundle/Export/Export/LinkedToACP/SumActivityDuration.php @@ -1,14 +1,14 @@ getQuery()->getResult(Query::HYDRATE_SCALAR); + return $query->getQuery()->getResult(Query::HYDRATE_SCALAR); } public function getTitle(): string diff --git a/src/Bundle/ChillActivityBundle/Export/Export/LinkedToACP/SumActivityVisitDuration.php b/src/Bundle/ChillActivityBundle/Export/Export/LinkedToACP/SumActivityVisitDuration.php index e9be03003..2c160f3cf 100644 --- a/src/Bundle/ChillActivityBundle/Export/Export/LinkedToACP/SumActivityVisitDuration.php +++ b/src/Bundle/ChillActivityBundle/Export/Export/LinkedToACP/SumActivityVisitDuration.php @@ -1,14 +1,14 @@ getQuery()->getResult(Query::HYDRATE_SCALAR); + return $query->getQuery()->getResult(Query::HYDRATE_SCALAR); } public function getTitle(): string diff --git a/src/Bundle/ChillActivityBundle/Export/Export/LinkedToPerson/CountActivity.php b/src/Bundle/ChillActivityBundle/Export/Export/LinkedToPerson/CountActivity.php index fec2b8617..4246df173 100644 --- a/src/Bundle/ChillActivityBundle/Export/Export/LinkedToPerson/CountActivity.php +++ b/src/Bundle/ChillActivityBundle/Export/Export/LinkedToPerson/CountActivity.php @@ -1,14 +1,14 @@ getQuery()->getResult(Query::HYDRATE_SCALAR); + return $query->getQuery()->getResult(Query::HYDRATE_SCALAR); } public function getTitle() diff --git a/src/Bundle/ChillActivityBundle/Export/Export/LinkedToPerson/ListActivity.php b/src/Bundle/ChillActivityBundle/Export/Export/LinkedToPerson/ListActivity.php index 78368b0eb..dee5dce8d 100644 --- a/src/Bundle/ChillActivityBundle/Export/Export/LinkedToPerson/ListActivity.php +++ b/src/Bundle/ChillActivityBundle/Export/Export/LinkedToPerson/ListActivity.php @@ -1,14 +1,14 @@ action) { return 'Sum activities linked to a person duration by various parameters.'; } + + throw new LogicException('this action is not supported: ' . $this->action); } public function getGroup(): string @@ -87,9 +89,9 @@ class StatActivityDuration implements ExportInterface, GroupedExportInterface return ['export_stat_activity']; } - public function getResult($qb, $data) + public function getResult($query, $data) { - return $qb->getQuery()->getResult(Query::HYDRATE_SCALAR); + return $query->getQuery()->getResult(Query::HYDRATE_SCALAR); } public function getTitle() @@ -97,6 +99,8 @@ class StatActivityDuration implements ExportInterface, GroupedExportInterface if (self::SUM === $this->action) { return 'Sum activity linked to a person duration'; } + + throw new LogicException('This action is not supported: ' . $this->action); } public function getType(): string diff --git a/src/Bundle/ChillActivityBundle/Export/Filter/ACPFilters/ActivityTypeFilter.php b/src/Bundle/ChillActivityBundle/Export/Filter/ACPFilters/ActivityTypeFilter.php index b6e26dfdb..575d11815 100644 --- a/src/Bundle/ChillActivityBundle/Export/Filter/ACPFilters/ActivityTypeFilter.php +++ b/src/Bundle/ChillActivityBundle/Export/Filter/ACPFilters/ActivityTypeFilter.php @@ -1,14 +1,14 @@ add('accepted_users', EntityType::class, [ - 'class' => User::class, - 'choice_label' => function (User $u) { - return $this->userRender->renderString($u, []); - }, + $builder->add('accepted_users', PickUserDynamicType::class, [ 'multiple' => true, - 'expanded' => true, ]); } diff --git a/src/Bundle/ChillActivityBundle/Export/Filter/ACPFilters/EmergencyFilter.php b/src/Bundle/ChillActivityBundle/Export/Filter/ACPFilters/EmergencyFilter.php index 63650b452..b79c2ca10 100644 --- a/src/Bundle/ChillActivityBundle/Export/Filter/ACPFilters/EmergencyFilter.php +++ b/src/Bundle/ChillActivityBundle/Export/Filter/ACPFilters/EmergencyFilter.php @@ -1,14 +1,14 @@ $v) { - if ($v === $data['accepted_emergency']) { - $choice = $k; - } - } - - return ['Filtered activity by emergency: only %emergency%', [ - '%emergency%' => $this->translator->trans($choice), - ]]; + return [ + 'Filtered by emergency: only %emergency%', [ + '%emergency%' => $this->translator->trans( + $data['accepted_emergency'] ? 'is emergency' : 'is not emergency' + ), + ], + ]; } public function getTitle(): string diff --git a/src/Bundle/ChillActivityBundle/Export/Filter/ACPFilters/LocationTypeFilter.php b/src/Bundle/ChillActivityBundle/Export/Filter/ACPFilters/LocationTypeFilter.php index 4ab27f043..023882cf9 100644 --- a/src/Bundle/ChillActivityBundle/Export/Filter/ACPFilters/LocationTypeFilter.php +++ b/src/Bundle/ChillActivityBundle/Export/Filter/ACPFilters/LocationTypeFilter.php @@ -1,23 +1,22 @@ add('accepted_locationtype', EntityType::class, [ - 'class' => LocationType::class, - 'choice_label' => function (LocationType $type) { - return $this->translatableStringHelper->localize($type->getTitle()); - }, + $builder->add('accepted_locationtype', Select2LocationTypeType::class, [ 'multiple' => true, - 'expanded' => true, + //'label' => false, ]); } diff --git a/src/Bundle/ChillActivityBundle/Export/Filter/ACPFilters/SentReceivedFilter.php b/src/Bundle/ChillActivityBundle/Export/Filter/ACPFilters/SentReceivedFilter.php index 98cb50e89..8daa7a781 100644 --- a/src/Bundle/ChillActivityBundle/Export/Filter/ACPFilters/SentReceivedFilter.php +++ b/src/Bundle/ChillActivityBundle/Export/Filter/ACPFilters/SentReceivedFilter.php @@ -1,14 +1,14 @@ add('accepted_users', EntityType::class, [ - 'class' => User::class, - 'choice_label' => function (User $u) { - return $this->userRender->renderString($u, []); - }, + $builder->add('accepted_users', PickUserDynamicType::class, [ 'multiple' => true, - 'expanded' => true, 'label' => 'Creators', ]); } diff --git a/src/Bundle/ChillActivityBundle/Export/Filter/ACPFilters/UserScopeFilter.php b/src/Bundle/ChillActivityBundle/Export/Filter/ACPFilters/UserScopeFilter.php index c0cda26a4..4568cd006 100644 --- a/src/Bundle/ChillActivityBundle/Export/Filter/ACPFilters/UserScopeFilter.php +++ b/src/Bundle/ChillActivityBundle/Export/Filter/ACPFilters/UserScopeFilter.php @@ -1,14 +1,14 @@ addSelect('caluser.id AS agent_aggregator'); - - $groupBy = $qb->getDQLPart('groupBy'); - - if (!empty($groupBy)) { - $qb->addGroupBy('agent_aggregator'); - } else { - $qb->groupBy('agent_aggregator'); - } + $qb->addGroupBy('agent_aggregator'); } public function applyOn(): string diff --git a/src/Bundle/ChillCalendarBundle/Export/Aggregator/CancelReasonAggregator.php b/src/Bundle/ChillCalendarBundle/Export/Aggregator/CancelReasonAggregator.php index 502f8000c..53ecba909 100644 --- a/src/Bundle/ChillCalendarBundle/Export/Aggregator/CancelReasonAggregator.php +++ b/src/Bundle/ChillCalendarBundle/Export/Aggregator/CancelReasonAggregator.php @@ -1,14 +1,14 @@ addSelect('IDENTITY(cal.cancelReason) as cancel_reason_aggregator'); - - $groupBy = $qb->getDQLPart('groupBy'); - - if (!empty($groupBy)) { - $qb->addGroupBy('cancel_reason_aggregator'); - } else { - $qb->groupBy('cancel_reason_aggregator'); - } + $qb->addGroupBy('cancel_reason_aggregator'); } public function applyOn(): string diff --git a/src/Bundle/ChillCalendarBundle/Export/Aggregator/JobAggregator.php b/src/Bundle/ChillCalendarBundle/Export/Aggregator/JobAggregator.php index d5471d36e..f56bc61cb 100644 --- a/src/Bundle/ChillCalendarBundle/Export/Aggregator/JobAggregator.php +++ b/src/Bundle/ChillCalendarBundle/Export/Aggregator/JobAggregator.php @@ -1,14 +1,14 @@ addSelect('IDENTITY(caluser.userJob) as job_aggregator'); - - $groupBy = $qb->getDQLPart('groupBy'); - - if (!empty($groupBy)) { - $qb->addGroupBy('job_aggregator'); - } else { - $qb->groupBy('job_aggregator'); - } + $qb->addGroupBy('job_aggregator'); } public function applyOn(): string diff --git a/src/Bundle/ChillCalendarBundle/Export/Aggregator/LocationAggregator.php b/src/Bundle/ChillCalendarBundle/Export/Aggregator/LocationAggregator.php index 7746bc7f2..cdd4c4b03 100644 --- a/src/Bundle/ChillCalendarBundle/Export/Aggregator/LocationAggregator.php +++ b/src/Bundle/ChillCalendarBundle/Export/Aggregator/LocationAggregator.php @@ -1,14 +1,14 @@ join('cal.location', 'calloc'); } $qb->addSelect('IDENTITY(cal.location) as location_aggregator'); - - $groupBy = $qb->getDQLPart('groupBy'); - - if (!empty($groupBy)) { - $qb->addGroupBy('location_aggregator'); - } else { - $qb->groupBy('location_aggregator'); - } + $qb->addGroupBy('location_aggregator'); } public function applyOn(): string diff --git a/src/Bundle/ChillCalendarBundle/Export/Aggregator/LocationTypeAggregator.php b/src/Bundle/ChillCalendarBundle/Export/Aggregator/LocationTypeAggregator.php index f48eafd79..6d42aed89 100644 --- a/src/Bundle/ChillCalendarBundle/Export/Aggregator/LocationTypeAggregator.php +++ b/src/Bundle/ChillCalendarBundle/Export/Aggregator/LocationTypeAggregator.php @@ -1,14 +1,14 @@ addSelect('IDENTITY(calloc.locationType) as location_type_aggregator'); - - $groupBy = $qb->getDQLPart('groupBy'); - - if (!empty($groupBy)) { - $qb->addGroupBy('location_type_aggregator'); - } else { - $qb->groupBy('location_type_aggregator'); - } + $qb->addGroupBy('location_type_aggregator'); } public function applyOn(): string diff --git a/src/Bundle/ChillCalendarBundle/Export/Aggregator/MonthYearAggregator.php b/src/Bundle/ChillCalendarBundle/Export/Aggregator/MonthYearAggregator.php index a74853119..11c6414ed 100644 --- a/src/Bundle/ChillCalendarBundle/Export/Aggregator/MonthYearAggregator.php +++ b/src/Bundle/ChillCalendarBundle/Export/Aggregator/MonthYearAggregator.php @@ -1,14 +1,14 @@ addSelect("to_char(cal.startDate, 'MM-YYYY') AS month_year_aggregator"); // $qb->addSelect("extract(month from age(cal.startDate, cal.endDate)) AS month_aggregator"); - $groupBy = $qb->getDQLPart('groupBy'); - - if (!empty($groupBy)) { - $qb->addGroupBy('month_year_aggregator'); - } else { - $qb->groupBy('month_year_aggregator'); - } + $qb->addGroupBy('month_year_aggregator'); } public function applyOn(): string @@ -54,10 +48,7 @@ class MonthYearAggregator implements AggregatorInterface return 'by month and year'; } - $month = substr($value, 0, 2); - $year = substr($value, 3, 4); - - return strftime('%B %G', mktime(0, 0, 0, $month, '1', $year)); + return $value; }; } diff --git a/src/Bundle/ChillCalendarBundle/Export/Aggregator/ScopeAggregator.php b/src/Bundle/ChillCalendarBundle/Export/Aggregator/ScopeAggregator.php index 3b8123b65..11a71654e 100644 --- a/src/Bundle/ChillCalendarBundle/Export/Aggregator/ScopeAggregator.php +++ b/src/Bundle/ChillCalendarBundle/Export/Aggregator/ScopeAggregator.php @@ -1,14 +1,14 @@ addSelect('IDENTITY(caluser.mainScope) as scope_aggregator'); - - $groupBy = $qb->getDQLPart('groupBy'); - - if (!empty($groupBy)) { - $qb->addGroupBy('scope_aggregator'); - } else { - $qb->groupBy('scope_aggregator'); - } + $qb->addGroupBy('scope_aggregator'); } public function applyOn(): string diff --git a/src/Bundle/ChillCalendarBundle/Export/Declarations.php b/src/Bundle/ChillCalendarBundle/Export/Declarations.php index 616d70a1a..0df90749c 100644 --- a/src/Bundle/ChillCalendarBundle/Export/Declarations.php +++ b/src/Bundle/ChillCalendarBundle/Export/Declarations.php @@ -1,14 +1,14 @@ getQuery()->getResult(AbstractQuery::HYDRATE_SCALAR); + return $query->getQuery()->getResult(AbstractQuery::HYDRATE_SCALAR); } public function getTitle(): string diff --git a/src/Bundle/ChillCalendarBundle/Export/Export/StatAppointmentAvgDuration.php b/src/Bundle/ChillCalendarBundle/Export/Export/StatAppointmentAvgDuration.php index 491cb38b9..50d8e2460 100644 --- a/src/Bundle/ChillCalendarBundle/Export/Export/StatAppointmentAvgDuration.php +++ b/src/Bundle/ChillCalendarBundle/Export/Export/StatAppointmentAvgDuration.php @@ -1,14 +1,14 @@ getQuery()->getResult(Query::HYDRATE_SCALAR); + return $query->getQuery()->getResult(Query::HYDRATE_SCALAR); } public function getTitle(): string diff --git a/src/Bundle/ChillCalendarBundle/Export/Export/StatAppointmentSumDuration.php b/src/Bundle/ChillCalendarBundle/Export/Export/StatAppointmentSumDuration.php index 286c73be5..ff5fc8592 100644 --- a/src/Bundle/ChillCalendarBundle/Export/Export/StatAppointmentSumDuration.php +++ b/src/Bundle/ChillCalendarBundle/Export/Export/StatAppointmentSumDuration.php @@ -1,14 +1,14 @@ getQuery()->getResult(Query::HYDRATE_SCALAR); + return $query->getQuery()->getResult(Query::HYDRATE_SCALAR); } public function getTitle(): string diff --git a/src/Bundle/ChillCalendarBundle/Export/Filter/AgentFilter.php b/src/Bundle/ChillCalendarBundle/Export/Filter/AgentFilter.php index 263b1e160..7c5d8e80e 100644 --- a/src/Bundle/ChillCalendarBundle/Export/Filter/AgentFilter.php +++ b/src/Bundle/ChillCalendarBundle/Export/Filter/AgentFilter.php @@ -1,14 +1,14 @@ course) { + if (null === $this->course) { return []; } diff --git a/src/Bundle/ChillDocStoreBundle/Entity/Document.php b/src/Bundle/ChillDocStoreBundle/Entity/Document.php index 0fd329ff8..2345aef61 100644 --- a/src/Bundle/ChillDocStoreBundle/Entity/Document.php +++ b/src/Bundle/ChillDocStoreBundle/Entity/Document.php @@ -1,14 +1,14 @@ exportFormStep($request, $export, $alias); - break; - case 'formatter': return $this->formatterFormStep($request, $export, $alias); - break; - case 'generate': return $this->forwardToGenerate($request, $export, $alias); - break; - default: throw $this->createNotFoundException("The given step '{$step}' is invalid"); } @@ -214,10 +209,8 @@ class ExportController extends AbstractController * @param string $alias * @param array $data the data from previous step. Required for steps 'formatter' and 'generate_formatter' * @param mixed $step - * - * @return \Symfony\Component\Form\Form */ - protected function createCreateFormExport($alias, $step, $data = []) + protected function createCreateFormExport($alias, $step, $data = []): FormInterface { /** @var \Chill\MainBundle\Export\ExportManager $exportManager */ $exportManager = $this->exportManager; @@ -475,8 +468,6 @@ class ExportController extends AbstractController * @param \Chill\MainBundle\Export\DirectExportInterface|\Chill\MainBundle\Export\ExportInterface $export * @param string $alias * - * @throws type - * * @return Response */ protected function selectCentersStep(Request $request, $export, $alias) @@ -543,6 +534,8 @@ class ExportController extends AbstractController } } } + + return ''; } /** diff --git a/src/Bundle/ChillMainBundle/Controller/LanguageController.php b/src/Bundle/ChillMainBundle/Controller/LanguageController.php index 4612a3728..4e72d8983 100644 --- a/src/Bundle/ChillMainBundle/Controller/LanguageController.php +++ b/src/Bundle/ChillMainBundle/Controller/LanguageController.php @@ -1,14 +1,14 @@ countryRepository = $countryRepository; diff --git a/src/Bundle/ChillMainBundle/Controller/PostalCodeController.php b/src/Bundle/ChillMainBundle/Controller/PostalCodeController.php index f38e0004b..91de40985 100644 --- a/src/Bundle/ChillMainBundle/Controller/PostalCodeController.php +++ b/src/Bundle/ChillMainBundle/Controller/PostalCodeController.php @@ -1,14 +1,14 @@ getUser(); - $form = $this->createForm(UserCurrentLocationType::class, $user) + $form = $this->createForm(Select2UserLocationType::class, $user) ->add('submit', SubmitType::class, ['label' => 'Save']) ->handleRequest($request); diff --git a/src/Bundle/ChillMainBundle/Controller/UserJobApiController.php b/src/Bundle/ChillMainBundle/Controller/UserJobApiController.php index 50b97809a..1b0dbbf5f 100644 --- a/src/Bundle/ChillMainBundle/Controller/UserJobApiController.php +++ b/src/Bundle/ChillMainBundle/Controller/UserJobApiController.php @@ -1,14 +1,14 @@ [ 'EXTRACT' => Extract::class, 'TO_CHAR' => ToChar::class, + 'AGE' => Age::class, ], ], 'hydrators' => [ diff --git a/src/Bundle/ChillMainBundle/DependencyInjection/CompilerPass/ACLFlagsCompilerPass.php b/src/Bundle/ChillMainBundle/DependencyInjection/CompilerPass/ACLFlagsCompilerPass.php index b8b3b4d85..40baccfc0 100644 --- a/src/Bundle/ChillMainBundle/DependencyInjection/CompilerPass/ACLFlagsCompilerPass.php +++ b/src/Bundle/ChillMainBundle/DependencyInjection/CompilerPass/ACLFlagsCompilerPass.php @@ -1,14 +1,14 @@ value2) { + return sprintf( + 'AGE(%s, %s)', + $this->value1->dispatch($sqlWalker), + $this->value2->dispatch($sqlWalker) + ); + } + + return sprintf( + 'AGE(%s)', + $this->value1->dispatch($sqlWalker), + ); + } + + public function parse(Parser $parser) + { + $parser->match(Lexer::T_IDENTIFIER); + $parser->match(Lexer::T_OPEN_PARENTHESIS); + + $this->value1 = $parser->SimpleArithmeticExpression(); + + $parser->match(Lexer::T_COMMA); + + $this->value2 = $parser->SimpleArithmeticExpression(); + + $parser->match(Lexer::T_CLOSE_PARENTHESIS); + } +} diff --git a/src/Bundle/ChillMainBundle/Doctrine/DQL/Extract.php b/src/Bundle/ChillMainBundle/Doctrine/DQL/Extract.php index 7d8809582..e224c2a0c 100644 --- a/src/Bundle/ChillMainBundle/Doctrine/DQL/Extract.php +++ b/src/Bundle/ChillMainBundle/Doctrine/DQL/Extract.php @@ -1,14 +1,14 @@ expr1->dispatch($sqlWalker), - $sqlWalker->walkInputParameter($this->expr2) + $this->expr2->dispatch($sqlWalker) ); } diff --git a/src/Bundle/ChillMainBundle/Doctrine/DQL/OverlapsI.php b/src/Bundle/ChillMainBundle/Doctrine/DQL/OverlapsI.php index 52b39e97f..29642dc15 100644 --- a/src/Bundle/ChillMainBundle/Doctrine/DQL/OverlapsI.php +++ b/src/Bundle/ChillMainBundle/Doctrine/DQL/OverlapsI.php @@ -1,14 +1,14 @@ format(self::FORMAT); } - throw ConversionException::conversionFailedInvalidType($value, $this->getName(), ['null', 'DateInterval']); + throw ConversionException::conversionFailedInvalidType($value, 'string', ['null', 'DateInterval']); } public function convertToPHPValue($value, AbstractPlatform $platform) @@ -80,7 +81,7 @@ class NativeDateIntervalType extends DateIntervalType protected function createConversionException($value, $exception = null) { - return ConversionException::conversionFailedFormat($value, $this->getName(), 'xx year xx mons xx days 01:02:03', $exception); + return ConversionException::conversionFailedFormat($value, 'string', 'xx year xx mons xx days 01:02:03', $exception); } private function convertEntry(&$strings) @@ -125,5 +126,7 @@ class NativeDateIntervalType extends DateIntervalType return $intervalSpec; } + + throw new LogicException(); } } diff --git a/src/Bundle/ChillMainBundle/Doctrine/Type/PointType.php b/src/Bundle/ChillMainBundle/Doctrine/Type/PointType.php index 1d44b2358..3f74c62a3 100644 --- a/src/Bundle/ChillMainBundle/Doctrine/Type/PointType.php +++ b/src/Bundle/ChillMainBundle/Doctrine/Type/PointType.php @@ -1,14 +1,14 @@ roleScopes; } + public function isActive(): bool + { + return $this->active; + } + + public function setActive(bool $active): Scope + { + $this->active = $active; + + return $this; + } + /** * @param $name * diff --git a/src/Bundle/ChillMainBundle/Entity/User.php b/src/Bundle/ChillMainBundle/Entity/User.php index 3c9bf7959..80a0b5b2a 100644 --- a/src/Bundle/ChillMainBundle/Entity/User.php +++ b/src/Bundle/ChillMainBundle/Entity/User.php @@ -1,14 +1,14 @@ postalCodeRepository = $postalCodeRepository; + } + + public function reverseTransform($value) + { + if (null === $value || trim('') === $value) { + return null; + } + + if (!is_int((int) $value)) { + throw new TransformationFailedException('Cannot transform ' . gettype($value)); + } + + return $this->postalCodeRepository->find((int) $value); + } + + public function transform($value) + { + if (null === $value) { + return null; + } + + if ($value instanceof PostalCode) { + return $value->getId(); + } + + throw new TransformationFailedException('Could not reverseTransform ' . gettype($value)); + } +} diff --git a/src/Bundle/ChillMainBundle/Form/Type/DataTransformer/ScopeTransformer.php b/src/Bundle/ChillMainBundle/Form/Type/DataTransformer/ScopeTransformer.php index 5f6c3ed65..5ae26ec79 100644 --- a/src/Bundle/ChillMainBundle/Form/Type/DataTransformer/ScopeTransformer.php +++ b/src/Bundle/ChillMainBundle/Form/Type/DataTransformer/ScopeTransformer.php @@ -1,14 +1,14 @@ postalCodeToIdTransformer = $postalCodeToIdTransformer; + } + + public function buildForm(FormBuilderInterface $builder, array $options) + { + $builder->addViewTransformer($this->postalCodeToIdTransformer); + } + + public function buildView(FormView $view, FormInterface $form, array $options) + { + $view->vars['uniqid'] = $view->vars['attr']['data-input-postal-code'] = uniqid('input_pick_postal_code_'); + } + + public function configureOptions(OptionsResolver $resolver) + { + $resolver + ->setDefault('class', PostalCode::class) + ->setDefault('multiple', false) + ->setAllowedTypes('multiple', ['bool']) + ->setDefault('compound', false); + } +} diff --git a/src/Bundle/ChillMainBundle/Form/Type/PickUserDynamicType.php b/src/Bundle/ChillMainBundle/Form/Type/PickUserDynamicType.php index 3bc4df436..2fbfdcf11 100644 --- a/src/Bundle/ChillMainBundle/Form/Type/PickUserDynamicType.php +++ b/src/Bundle/ChillMainBundle/Form/Type/PickUserDynamicType.php @@ -1,14 +1,14 @@ authorizationHelper = $authorizationHelper; - $this->tokenStorage = $tokenStorage; - $this->scopeRepository = $scopeRepository; $this->security = $security; $this->translatableStringHelper = $translatableStringHelper; } public function buildForm(FormBuilderInterface $builder, array $options) { - $items = $this->authorizationHelper->getReachableScopes( - $this->security->getUser(), - $options['role'] instanceof Role ? $options['role']->getRole() : $options['role'], - $options['center'] + $items = array_filter( + $this->authorizationHelper->getReachableScopes( + $this->security->getUser(), + $options['role'] instanceof Role ? $options['role']->getRole() : $options['role'], + $options['center'] + ), + static function (Scope $s) { return $s->isActive(); } ); + if (0 === count($items)) { + throw new RuntimeException('no scopes are reachable. This form should not be shown to user'); + } + if (1 !== count($items)) { $builder->add('scope', EntityType::class, [ 'class' => Scope::class, @@ -123,35 +111,4 @@ class ScopePickerType extends AbstractType ->setRequired('role') ->setAllowedTypes('role', ['string', Role::class]); } - - /** - * @param array|Center|Center[] $center - * @param string $role - * - * @return \Doctrine\ORM\QueryBuilder - */ - protected function buildAccessibleScopeQuery($center, $role) - { - $roles = $this->authorizationHelper->getParentRoles($role); - $roles[] = $role; - $centers = $center instanceof Center ? [$center] : $center; - - $qb = $this->scopeRepository->createQueryBuilder('s'); - $qb - // jointure to center - ->join('s.roleScopes', 'rs') - ->join('rs.permissionsGroups', 'pg') - ->join('pg.groupCenters', 'gc') - // add center constraint - ->where($qb->expr()->in('IDENTITY(gc.center)', ':centers')) - ->setParameter('centers', array_map(static fn (Center $c) => $c->getId(), $centers)) - // role constraints - ->andWhere($qb->expr()->in('rs.role', ':roles')) - ->setParameter('roles', $roles) - // user contraint - ->andWhere(':user MEMBER OF gc.users') - ->setParameter('user', $this->tokenStorage->getToken()->getUser()); - - return $qb; - } } diff --git a/src/Bundle/ChillMainBundle/Form/Type/Select2ChoiceType.php b/src/Bundle/ChillMainBundle/Form/Type/Select2ChoiceType.php index ae5ab075e..b427c603b 100644 --- a/src/Bundle/ChillMainBundle/Form/Type/Select2ChoiceType.php +++ b/src/Bundle/ChillMainBundle/Form/Type/Select2ChoiceType.php @@ -1,14 +1,14 @@ translatableStringHelper = $translatableStringHelper; + } + + public function buildForm(FormBuilderInterface $builder, array $options) + { + $builder->add('locationtype', EntityType::class, [ + 'class' => LocationType::class, + 'choice_label' => function (LocationType $type) { + return $this->translatableStringHelper->localize($type->getTitle()); + }, + 'placeholder' => 'Pick a location type', + 'required' => false, + 'label' => $options['label'], + 'label_attr' => $options['label_attr'], + 'multiple' => $options['multiple'], + 'attr' => ['class' => 'select2'], + ]); + } + + public function configureOptions(OptionsResolver $resolver) + { + $resolver + ->setDefault('label', 'Location type') + ->setDefault('label_attr', []) + ->setDefault('multiple', false) + ->setAllowedTypes('multiple', ['bool']); + } + + public function getBlockPrefix(): string + { + return 'select2_location_type_type'; + } +} diff --git a/src/Bundle/ChillMainBundle/Form/UserCurrentLocationType.php b/src/Bundle/ChillMainBundle/Form/Type/Select2UserLocationType.php similarity index 71% rename from src/Bundle/ChillMainBundle/Form/UserCurrentLocationType.php rename to src/Bundle/ChillMainBundle/Form/Type/Select2UserLocationType.php index e7ae27b3a..8fb100441 100644 --- a/src/Bundle/ChillMainBundle/Form/UserCurrentLocationType.php +++ b/src/Bundle/ChillMainBundle/Form/Type/Select2UserLocationType.php @@ -1,15 +1,15 @@ 'Pick a location', 'required' => false, + 'label' => $options['label'], + 'label_attr' => $options['label_attr'], + 'multiple' => $options['multiple'], 'attr' => ['class' => 'select2'], ]); } + + public function configureOptions(OptionsResolver $resolver) + { + $resolver + ->setDefault('label', 'Current location') + ->setDefault('label_attr', []) + ->setDefault('multiple', false) + ->setAllowedTypes('multiple', ['bool']); + } + + public function getBlockPrefix(): string + { + return 'select2_user_location_type'; + } } diff --git a/src/Bundle/ChillMainBundle/Form/Type/TranslatableStringFormType.php b/src/Bundle/ChillMainBundle/Form/Type/TranslatableStringFormType.php index 822ff0101..ee39ef75e 100644 --- a/src/Bundle/ChillMainBundle/Form/Type/TranslatableStringFormType.php +++ b/src/Bundle/ChillMainBundle/Form/Type/TranslatableStringFormType.php @@ -1,14 +1,14 @@ repository = $entityManager->getRepository(PostalCode::class); + $this->repository = $entityManager->getRepository($this->getClassName()); $this->entityManager = $entityManager; } @@ -51,20 +50,11 @@ final class PostalCodeRepository implements ObjectRepository return $this->repository->find($id, $lockMode, $lockVersion); } - /** - * @return PostalCode[] - */ public function findAll(): array { return $this->repository->findAll(); } - /** - * @param mixed|null $limit - * @param mixed|null $offset - * - * @return PostalCode[] - */ public function findBy(array $criteria, ?array $orderBy = null, $limit = null, $offset = null): array { return $this->repository->findBy($criteria, $orderBy, $limit, $offset); @@ -95,7 +85,7 @@ final class PostalCodeRepository implements ObjectRepository return $this->repository->findOneBy($criteria, $orderBy); } - public function getClassName() + public function getClassName(): string { return PostalCode::class; } diff --git a/src/Bundle/ChillMainBundle/Repository/PostalCodeRepositoryInterface.php b/src/Bundle/ChillMainBundle/Repository/PostalCodeRepositoryInterface.php new file mode 100644 index 000000000..fe3dee195 --- /dev/null +++ b/src/Bundle/ChillMainBundle/Repository/PostalCodeRepositoryInterface.php @@ -0,0 +1,42 @@ +repository->findAll(); } + public function findAllActive(): array + { + $qb = $this->repository->createQueryBuilder('s'); + + $qb->where('s.active = \'TRUE\''); + + return $qb->getQuery()->getResult(); + } + /** * @param mixed|null $limit * @param mixed|null $offset diff --git a/src/Bundle/ChillMainBundle/Repository/ScopeRepositoryInterface.php b/src/Bundle/ChillMainBundle/Repository/ScopeRepositoryInterface.php index e9de77018..3cfb6042d 100644 --- a/src/Bundle/ChillMainBundle/Repository/ScopeRepositoryInterface.php +++ b/src/Bundle/ChillMainBundle/Repository/ScopeRepositoryInterface.php @@ -1,14 +1,14 @@ repository->findAll(); } + public function findAllActive(): array + { + return $this->repository->findBy(['active' => true]); + } + /** * @param mixed|null $limit * @param mixed|null $offset @@ -49,12 +53,12 @@ class UserJobRepository implements ObjectRepository return $this->repository->findBy($criteria, $orderBy, $limit, $offset); } - public function findOneBy(array $criteria) + public function findOneBy(array $criteria): ?UserJob { return $this->repository->findOneBy($criteria); } - public function getClassName() + public function getClassName(): string { return UserJob::class; } diff --git a/src/Bundle/ChillMainBundle/Repository/UserJobRepositoryInterface.php b/src/Bundle/ChillMainBundle/Repository/UserJobRepositoryInterface.php new file mode 100644 index 000000000..a752f452b --- /dev/null +++ b/src/Bundle/ChillMainBundle/Repository/UserJobRepositoryInterface.php @@ -0,0 +1,42 @@ +', + components: { + PickPostalCode, + }, + data() { + return { + city: city, + } + }, + methods: { + onCitySelected(city) { + this.city = city; + input.value = city.id; + }, + onCityRemoved(city) { + this.city = null; + input.value = ''; + } + } + }) + .use(i18n) + .mount(el); +} + +function loadDynamicPickers(element) { + + let apps = element.querySelectorAll('[data-module="pick-postal-code"]'); + + apps.forEach(function(el) { + + const + uniqId = el.dataset.uniqid, + input = document.querySelector(`input[data-input-uniqid="${uniqId}"]`), + cityIdValue = input.value === '' ? null : input.value + ; + + if (cityIdValue !== null) { + makeFetch('GET', `/api/1.0/main/postal-code/${cityIdValue}.json`).then(city => { + loadOnePicker(el, input, uniqId, city); + }) + } else { + loadOnePicker(el, input, uniqId, null); + } + }); +} + +document.addEventListener('DOMContentLoaded', function(e) { + loadDynamicPickers(document) +}) diff --git a/src/Bundle/ChillMainBundle/Resources/public/vuejs/PickPostalCode/PickPostalCode.md b/src/Bundle/ChillMainBundle/Resources/public/vuejs/PickPostalCode/PickPostalCode.md new file mode 100644 index 000000000..501e96983 --- /dev/null +++ b/src/Bundle/ChillMainBundle/Resources/public/vuejs/PickPostalCode/PickPostalCode.md @@ -0,0 +1,29 @@ +# Pickpostalcode + +Allow to pick a postal code. + +In use with module `mod_pick_postal_code`, associated with `PickPostalCodeType` in php. + +## Usage + + `` + +## Props + +* `picked`: the city picked. A javascript object (a city). Null if empty. +* `country`: country to restraint search on picked. May be null. + +## Emits + +### `selectCity` + +When a city is onCitySelected. + +Argument: a js object, representing a city + +### `removeCity` + +When a city is removed. + + +Argument: a js object, representing a city diff --git a/src/Bundle/ChillMainBundle/Resources/public/vuejs/PickPostalCode/PickPostalCode.vue b/src/Bundle/ChillMainBundle/Resources/public/vuejs/PickPostalCode/PickPostalCode.vue new file mode 100644 index 000000000..d5e55dbbd --- /dev/null +++ b/src/Bundle/ChillMainBundle/Resources/public/vuejs/PickPostalCode/PickPostalCode.vue @@ -0,0 +1,107 @@ + + + diff --git a/src/Bundle/ChillMainBundle/Resources/public/vuejs/PickPostalCode/_PickPostalCode.scss b/src/Bundle/ChillMainBundle/Resources/public/vuejs/PickPostalCode/_PickPostalCode.scss new file mode 100644 index 000000000..09f5fd539 --- /dev/null +++ b/src/Bundle/ChillMainBundle/Resources/public/vuejs/PickPostalCode/_PickPostalCode.scss @@ -0,0 +1,3 @@ +.PickPostalCode { + +} diff --git a/src/Bundle/ChillMainBundle/Resources/public/vuejs/PickPostalCode/api.js b/src/Bundle/ChillMainBundle/Resources/public/vuejs/PickPostalCode/api.js new file mode 100644 index 000000000..d31dcc3f4 --- /dev/null +++ b/src/Bundle/ChillMainBundle/Resources/public/vuejs/PickPostalCode/api.js @@ -0,0 +1,43 @@ +import {makeFetch, fetchResults} from 'ChillMainAssets/lib/api/apiMethods'; + +/** + * Endpoint chill_api_single_postal_code__index + * method GET, get Cities Object + * @params {object} a country object + * @returns {Promise} a promise containing all Postal Code objects filtered with country + */ +const fetchCities = (country) => { + // warning: do not use fetchResults (in apiMethods): we need only a **part** of the results in the db + const params = new URLSearchParams({item_per_page: 100}); + + if (country !== null) { + params.append('country', country.id); + } + + return makeFetch('GET', `/api/1.0/main/postal-code.json?${params.toString()}`).then(r => Promise.resolve(r.results)); +}; + +/** + * Endpoint chill_main_postalcodeapi_search + * method GET, get Cities Object + * @params {string} search a search string + * @params {object} country a country object + * @params {AbortController} an abort controller + * @returns {Promise} a promise containing all Postal Code objects filtered with country and a search string + */ +const searchCities = (search, country, controller) => { + const url = '/api/1.0/main/postal-code/search.json?'; + const params = new URLSearchParams({q: search}); + + if (country !== null) { + Object.assign('country', country.id); + } + + return makeFetch('GET', url + params, null, {signal: controller.signal}) + .then(result => Promise.resolve(result.results)); +}; + +export { + fetchCities, + searchCities, +}; diff --git a/src/Bundle/ChillMainBundle/Resources/views/Export/new.html.twig b/src/Bundle/ChillMainBundle/Resources/views/Export/new.html.twig index ad49d9aa6..e1605a4c2 100644 --- a/src/Bundle/ChillMainBundle/Resources/views/Export/new.html.twig +++ b/src/Bundle/ChillMainBundle/Resources/views/Export/new.html.twig @@ -20,7 +20,12 @@ {% block title %}{{ export.title|trans }}{% endblock %} +{% block css %} + {{ encore_entry_link_tags('mod_pickentity_type') }} +{% endblock %} + {% block js %} + {{ encore_entry_script_tags('mod_pickentity_type') }} {{ encore_entry_script_tags('page_export') }} {% if export_alias == 'count_social_work_actions' %} {{ encore_entry_script_tags('vue_export_action_goal_result') }} diff --git a/src/Bundle/ChillMainBundle/Resources/views/Form/fields.html.twig b/src/Bundle/ChillMainBundle/Resources/views/Form/fields.html.twig index 1710a91b8..2b006fc4d 100644 --- a/src/Bundle/ChillMainBundle/Resources/views/Form/fields.html.twig +++ b/src/Bundle/ChillMainBundle/Resources/views/Form/fields.html.twig @@ -251,3 +251,9 @@
{% endblock %} + +{% block pick_postal_code_widget %} + {{ form_help(form)}} + +
+{% endblock %} diff --git a/src/Bundle/ChillMainBundle/Routing/Loader/ChillRoutesLoader.php b/src/Bundle/ChillMainBundle/Routing/Loader/ChillRoutesLoader.php index bc16929b7..112054ee3 100644 --- a/src/Bundle/ChillMainBundle/Routing/Loader/ChillRoutesLoader.php +++ b/src/Bundle/ChillMainBundle/Routing/Loader/ChillRoutesLoader.php @@ -1,14 +1,14 @@ getQueryBuilders() as $qb) { + foreach ($this->getFormData() as $data) { + yield [clone $qb, $data]; + } + } + } + /** * provide data for `testAlterQuery`. */ @@ -95,6 +107,28 @@ abstract class AbstractAggregatorTest extends KernelTestCase */ abstract public function getQueryBuilders(); + /** + * Compare aliases array before and after that aggregator alter query. + * + * @dataProvider dataProviderAliasDidNotDisappears + * + * @return void + */ + public function testAliasDidNotDisappears(QueryBuilder $qb, array $data) + { + $aliases = $qb->getAllAliases(); + + $this->getAggregator()->alterQuery($qb, $data); + + $alteredQuery = $qb->getAllAliases(); + + $this->assertGreaterThanOrEqual(count($aliases), count($alteredQuery)); + + foreach ($aliases as $alias) { + $this->assertContains($alias, $alteredQuery); + } + } + /** * test the alteration of query by the filter. * diff --git a/src/Bundle/ChillMainBundle/Test/Export/AbstractExportTest.php b/src/Bundle/ChillMainBundle/Test/Export/AbstractExportTest.php index 60d539573..0e5b56ae0 100644 --- a/src/Bundle/ChillMainBundle/Test/Export/AbstractExportTest.php +++ b/src/Bundle/ChillMainBundle/Test/Export/AbstractExportTest.php @@ -1,14 +1,14 @@ prophet = $this->getProphet(); } + /** + * provide data for `testAliasDidNotDisappears`. + */ + public function dataProviderAliasDidNotDisappears() + { + foreach ($this->getQueryBuilders() as $qb) { + foreach ($this->getFormData() as $data) { + yield [clone $qb, $data]; + } + } + } + public function dataProviderAlterQuery() { foreach ($this->getQueryBuilders() as $qb) { @@ -87,6 +99,28 @@ abstract class AbstractFilterTest extends KernelTestCase */ abstract public function getQueryBuilders(); + /** + * Compare aliases array before and after that filter alter query. + * + * @dataProvider dataProviderAliasDidNotDisappears + * + * @return void + */ + public function testAliasDidNotDisappears(QueryBuilder $qb, array $data) + { + $aliases = $qb->getAllAliases(); + + $this->getFilter()->alterQuery($qb, $data); + + $alteredQuery = $qb->getAllAliases(); + + $this->assertGreaterThanOrEqual(count($aliases), count($alteredQuery)); + + foreach ($aliases as $alias) { + $this->assertContains($alias, $alteredQuery); + } + } + /** * test the alteration of query by the filter. * diff --git a/src/Bundle/ChillMainBundle/Test/PrepareCenterTrait.php b/src/Bundle/ChillMainBundle/Test/PrepareCenterTrait.php index 9e4d6ea68..343c41180 100644 --- a/src/Bundle/ChillMainBundle/Test/PrepareCenterTrait.php +++ b/src/Bundle/ChillMainBundle/Test/PrepareCenterTrait.php @@ -1,14 +1,14 @@ entityManager = self::$container->get(EntityManagerInterface::class); + } + + public function generateQueries(): iterable + { + yield [ + 'SELECT AGE(a.validFrom, a.validTo) FROM ' . Address::class . ' a', + [], + ]; + + yield [ + 'SELECT AGE(:date0, :date1) FROM ' . Address::class . ' a', + [ + 'date0' => new DateTimeImmutable('now'), + 'date1' => new DateTimeImmutable('2020-01-01'), + ], + ]; + + yield [ + 'SELECT AGE(a.validFrom, :date1) FROM ' . Address::class . ' a', + [ + 'date1' => new DateTimeImmutable('now'), + ], + ]; + + yield [ + 'SELECT AGE(:date0, a.validFrom) FROM ' . Address::class . ' a', + [ + 'date0' => new DateTimeImmutable('now'), + ], + ]; + } + + /** + * @dataProvider generateQueries + */ + public function testWorking(string $dql, array $args) + { + $dql = $this->entityManager->createQuery($dql)->setMaxResults(3); + + foreach ($args as $key => $value) { + $dql->setParameter($key, $value); + } + + $results = $dql->getResult(); + + $this->assertIsArray($results); + } +} diff --git a/src/Bundle/ChillMainBundle/Tests/Doctrine/DQL/JsonbExistsInArrayTest.php b/src/Bundle/ChillMainBundle/Tests/Doctrine/DQL/JsonbExistsInArrayTest.php new file mode 100644 index 000000000..67c41d3d9 --- /dev/null +++ b/src/Bundle/ChillMainBundle/Tests/Doctrine/DQL/JsonbExistsInArrayTest.php @@ -0,0 +1,41 @@ +em = self::$container->get(EntityManagerInterface::class); + } + + public function testDQLFunctionWorks() + { + $result = $this->em + ->createQuery('SELECT JSONB_EXISTS_IN_ARRAY(u.attributes, :param) FROM ' . User::class . ' u') + ->setParameter('param', 'fr') + ->getResult(); + + $this->assertIsArray($result); + } +} diff --git a/src/Bundle/ChillMainBundle/Tests/Doctrine/Model/PointTest.php b/src/Bundle/ChillMainBundle/Tests/Doctrine/Model/PointTest.php index bcb5b2d26..01160604a 100644 --- a/src/Bundle/ChillMainBundle/Tests/Doctrine/Model/PointTest.php +++ b/src/Bundle/ChillMainBundle/Tests/Doctrine/Model/PointTest.php @@ -1,14 +1,14 @@ factory->createBuilder(FormType::class, ['postal_code' => null]); + $builder->add('postal_code', PickPostalCodeType::class); + $form = $builder->getForm(); + + $form->submit(['postal_code' => '1']); + + $this->assertTrue($form->isSynchronized()); + + $this->assertEquals(1, $form['postal_code']->getData()->getId()); + } + + protected function getExtensions() + { + $postalCodeRepository = $this->prophesize(PostalCodeRepositoryInterface::class); + $postalCodeRepository->find(Argument::any()) + ->will(static function ($args) { + $postalCode = new PostalCode(); + $reflectionClass = new ReflectionClass($postalCode); + $id = $reflectionClass->getProperty('id'); + $id->setAccessible(true); + $id->setValue($postalCode, (int) $args[0]); + + return $postalCode; + }); + + $type = new PickPostalCodeType( + new PostalCodeToIdTransformer( + $postalCodeRepository->reveal() + ) + ); + + return [ + new PreloadedExtension([$type], []), + ]; + } +} diff --git a/src/Bundle/ChillMainBundle/Tests/Form/Type/ScopePickerTypeTest.php b/src/Bundle/ChillMainBundle/Tests/Form/Type/ScopePickerTypeTest.php new file mode 100644 index 000000000..d64f68951 --- /dev/null +++ b/src/Bundle/ChillMainBundle/Tests/Form/Type/ScopePickerTypeTest.php @@ -0,0 +1,127 @@ +factory->create(ScopePickerType::class, null, [ + 'center' => new Center(), + 'role' => 'ONE_SCOPE', + ]); + + $view = $form->createView(); + + $this->assertContains('hidden', $view['scope']->vars['block_prefixes']); + } + + public function testBuildThreeScopesIsSuccessful() + { + $form = $this->factory->create(ScopePickerType::class, null, [ + 'center' => new Center(), + 'role' => 'THREE_SCOPE', + ]); + + $view = $form->createView(); + + $this->assertContains('entity', $view['scope']->vars['block_prefixes']); + } + + public function testBuildTwoScopesIsSuccessful() + { + $form = $this->factory->create(ScopePickerType::class, null, [ + 'center' => new Center(), + 'role' => 'TWO_SCOPE', + ]); + + $view = $form->createView(); + + $this->assertContains('entity', $view['scope']->vars['block_prefixes']); + } + + protected function getExtensions() + { + $user = new User(); + $role1Scope = 'ONE_SCOPE'; + $role2Scope = 'TWO_SCOPE'; + $role3Scope = 'THREE_SCOPE'; + $scopeA = (new Scope())->setName(['fr' => 'scope a']); + $scopeB = (new Scope())->setName(['fr' => 'scope b']); + $scopeC = (new Scope())->setName(['fr' => 'scope b'])->setActive(false); + + $authorizationHelper = $this->prophesize(AuthorizationHelperInterface::class); + $authorizationHelper->getReachableScopes($user, $role1Scope, Argument::any()) + ->willReturn([$scopeA]); + $authorizationHelper->getReachableScopes($user, $role2Scope, Argument::any()) + ->willReturn([$scopeA, $scopeB]); + $authorizationHelper->getReachableScopes($user, $role3Scope, Argument::any()) + ->willReturn([$scopeA, $scopeB, $scopeC]); + + $security = $this->prophesize(Security::class); + $security->getUser()->willReturn($user); + + $translatableStringHelper = $this->prophesize(TranslatableStringHelperInterface::class); + $translatableStringHelper->localize(Argument::type('array'))->will( + static function ($args) { return $args[0]['fr']; } + ); + + $type = new ScopePickerType( + $authorizationHelper->reveal(), + $security->reveal(), + $translatableStringHelper->reveal() + ); + + // add the mocks for creating EntityType + $entityManager = DoctrineTestHelper::createTestEntityManager(); + $em = $this->prophesize(EntityManagerInterface::class); + $em->getClassMetadata(Scope::class)->willReturn($entityManager->getClassMetadata(Scope::class)); + $em->contains(Argument::type(Scope::class))->willReturn(true); + $em->initializeObject(Argument::type(Scope::class))->will(static fn ($o) => $o); + $emRevealed = $em->reveal(); + $managerRegistry = $this->prophesize(ManagerRegistry::class); + $managerRegistry->getManager(Argument::any())->willReturn($emRevealed); + $managerRegistry->getManagerForClass(Scope::class)->willReturn($emRevealed); + + $entityType = $this->prophesize(EntityType::class); + $entityType->getParent()->willReturn(ChoiceType::class); + + return [ + new PreloadedExtension([$type], []), + new DoctrineOrmExtension($managerRegistry->reveal()), + ]; + } +} diff --git a/src/Bundle/ChillMainBundle/Tests/Notification/EventListener/PersistNotificationOnTerminateEventSubscriberTest.php b/src/Bundle/ChillMainBundle/Tests/Notification/EventListener/PersistNotificationOnTerminateEventSubscriberTest.php index 4c1b5c304..3939accc7 100644 --- a/src/Bundle/ChillMainBundle/Tests/Notification/EventListener/PersistNotificationOnTerminateEventSubscriberTest.php +++ b/src/Bundle/ChillMainBundle/Tests/Notification/EventListener/PersistNotificationOnTerminateEventSubscriberTest.php @@ -1,14 +1,14 @@ addSql('ALTER TABLE scopes DROP active'); + } + + public function getDescription(): string + { + return 'Allow a scope to be desactivated'; + } + + public function up(Schema $schema): void + { + $this->addSql('ALTER TABLE scopes ADD active BOOLEAN DEFAULT true NOT NULL'); + } +} diff --git a/src/Bundle/ChillMainBundle/translations/messages.fr.yml b/src/Bundle/ChillMainBundle/translations/messages.fr.yml index 36f793817..d14b4a7c1 100644 --- a/src/Bundle/ChillMainBundle/translations/messages.fr.yml +++ b/src/Bundle/ChillMainBundle/translations/messages.fr.yml @@ -227,6 +227,7 @@ never: jamais Create a new location: Créer une nouvelle localisation Location list: Liste des localisations Location type: Type de localisation +Pick a location type: Choisir un type de localisation Phonenumber1: Numéro de téléphone Phonenumber2: Autre numéro de téléphone Location configuration: Configuration des localisations diff --git a/src/Bundle/ChillPersonBundle/AccompanyingPeriod/Events/PersonAddressMoveEventSubscriber.php b/src/Bundle/ChillPersonBundle/AccompanyingPeriod/Events/PersonAddressMoveEventSubscriber.php index 04dfb25cc..666febe9d 100644 --- a/src/Bundle/ChillPersonBundle/AccompanyingPeriod/Events/PersonAddressMoveEventSubscriber.php +++ b/src/Bundle/ChillPersonBundle/AccompanyingPeriod/Events/PersonAddressMoveEventSubscriber.php @@ -1,14 +1,14 @@ getUser() !== $this->security->getUser() && null !== $period->getUser() && $period->getStep() !== AccompanyingPeriod::STEP_DRAFT + && !$period->isPreventUserIsChangedNotification() ) { $this->generateNotificationToUser($period); } diff --git a/src/Bundle/ChillPersonBundle/AccompanyingPeriod/SocialIssueConsistency/AccompanyingPeriodLinkedWithSocialIssuesEntityInterface.php b/src/Bundle/ChillPersonBundle/AccompanyingPeriod/SocialIssueConsistency/AccompanyingPeriodLinkedWithSocialIssuesEntityInterface.php index 566e05440..05b9fc210 100644 --- a/src/Bundle/ChillPersonBundle/AccompanyingPeriod/SocialIssueConsistency/AccompanyingPeriodLinkedWithSocialIssuesEntityInterface.php +++ b/src/Bundle/ChillPersonBundle/AccompanyingPeriod/SocialIssueConsistency/AccompanyingPeriodLinkedWithSocialIssuesEntityInterface.php @@ -1,14 +1,14 @@ handleRequest($request); $userFrom = $form['user']->getData(); + $postalCodes = $form['postal_code']->getData() instanceof PostalCode ? [$form['postal_code']->getData()] : []; $total = $this->accompanyingPeriodACLAwareRepository->countByUserOpenedAccompanyingPeriod($userFrom); $paginator = $this->paginatorFactory->create($total); $periods = $this->accompanyingPeriodACLAwareRepository - ->findByUserOpenedAccompanyingPeriod( + ->findByUserAndPostalCodesOpenedAccompanyingPeriod( $userFrom, + $postalCodes, ['openingDate' => 'ASC'], $paginator->getItemsPerPage(), $paginator->getCurrentPageFirstItemNumber() @@ -123,7 +127,7 @@ class ReassignAccompanyingPeriodController extends AbstractController $period = $this->courseRepository->find($periodId); if ($period->getUser() === $userFrom) { - $period->setUser($userTo); + $period->setUser($userTo, true); } } @@ -148,7 +152,9 @@ class ReassignAccompanyingPeriodController extends AbstractController { $data = [ 'user' => null, + 'postal_code' => null, ]; + $builder = $this->formFactory->createBuilder(FormType::class, $data, [ 'method' => 'get', 'csrf_protection' => false, ]); @@ -158,12 +164,17 @@ class ReassignAccompanyingPeriodController extends AbstractController 'label' => 'reassign.Current user', 'required' => false, 'help' => 'reassign.Choose a user and click on "Filter" to apply', + ]) + ->add('postal_code', PickPostalCodeType::class, [ + 'label' => 'reassign.Filter by postal code', + 'required' => false, + 'help' => 'reassign.Filter course which are located inside a postal code', ]); return $builder->getForm(); } - private function buildReassignForm(array $periodIds, ?User $userFrom): FormInterface + private function buildReassignForm(array $periodIds, ?User $userFrom = null): FormInterface { $defaultData = [ 'userFrom' => $userFrom, diff --git a/src/Bundle/ChillPersonBundle/Controller/RelationController.php b/src/Bundle/ChillPersonBundle/Controller/RelationController.php index 8f0c7fa44..7780b46c4 100644 --- a/src/Bundle/ChillPersonBundle/Controller/RelationController.php +++ b/src/Bundle/ChillPersonBundle/Controller/RelationController.php @@ -1,14 +1,14 @@ preventUserIsChangedNotification; + } + public function isRequestorAnonymous(): bool { return $this->requestorAnonymous; @@ -1372,11 +1379,12 @@ class AccompanyingPeriod implements return $this; } - public function setUser(?User $user): self + public function setUser(?User $user, bool $preventNotification = false): self { if ($this->user !== $user) { $this->userPrevious = $this->user; $this->userIsChanged = true; + $this->preventUserIsChangedNotification = $preventNotification; foreach ($this->userHistories as $history) { if (null === $history->getEndDate()) { diff --git a/src/Bundle/ChillPersonBundle/Entity/AccompanyingPeriod/AccompanyingPeriodLocationHistory.php b/src/Bundle/ChillPersonBundle/Entity/AccompanyingPeriod/AccompanyingPeriodLocationHistory.php index 1dcb5a1bf..8b2839636 100644 --- a/src/Bundle/ChillPersonBundle/Entity/AccompanyingPeriod/AccompanyingPeriodLocationHistory.php +++ b/src/Bundle/ChillPersonBundle/Entity/AccompanyingPeriod/AccompanyingPeriodLocationHistory.php @@ -1,14 +1,14 @@ id = substr(md5(uniqid()), 0, 7); + } + /** * Get id. */ diff --git a/src/Bundle/ChillPersonBundle/Entity/Person.php b/src/Bundle/ChillPersonBundle/Entity/Person.php index e21dbfbac..1134674df 100644 --- a/src/Bundle/ChillPersonBundle/Entity/Person.php +++ b/src/Bundle/ChillPersonBundle/Entity/Person.php @@ -1,14 +1,14 @@ participationsContainAccompanyingPeriod($accompanyingPeriod); if (!null === $participation) { - $participation->setEndDate(DateTimeImmutable::class); + $participation->setEndDate(new DateTime()); $this->accompanyingPeriodParticipations->removeElement($participation); } } @@ -1569,8 +1569,6 @@ class Person implements HasCenterInterface, TrackCreationInterface, TrackUpdateI */ public function setCenter(Center $center): self { - $this->center = $center; - $modification = new DateTimeImmutable('now'); foreach ($this->centerHistory as $centerHistory) { diff --git a/src/Bundle/ChillPersonBundle/Entity/Person/PersonCenterCurrent.php b/src/Bundle/ChillPersonBundle/Entity/Person/PersonCenterCurrent.php index 30de1f55a..6d67fbbbb 100644 --- a/src/Bundle/ChillPersonBundle/Entity/Person/PersonCenterCurrent.php +++ b/src/Bundle/ChillPersonBundle/Entity/Person/PersonCenterCurrent.php @@ -1,14 +1,14 @@ socialActions = new ArrayCollection(); } + /** + * @internal do use @see{SocialAction::addEvaluation} + */ public function addSocialAction(SocialAction $socialAction): self { if (!$this->socialActions->contains($socialAction)) { @@ -111,6 +114,11 @@ class Evaluation return $this->url; } + /** + * @return $this + * + * @internal do use @see{SocialAction::removeEvaluation} + */ public function removeSocialAction(SocialAction $socialAction): self { if ($this->socialActions->contains($socialAction)) { diff --git a/src/Bundle/ChillPersonBundle/Entity/SocialWork/Goal.php b/src/Bundle/ChillPersonBundle/Entity/SocialWork/Goal.php index 30abaa3ef..a51ba1a59 100644 --- a/src/Bundle/ChillPersonBundle/Entity/SocialWork/Goal.php +++ b/src/Bundle/ChillPersonBundle/Entity/SocialWork/Goal.php @@ -1,14 +1,14 @@ evaluations->contains($evaluation)) { $this->evaluations[] = $evaluation; + $evaluation->addSocialAction($this); } return $this; @@ -310,6 +311,7 @@ class SocialAction public function removeEvaluation(Evaluation $evaluation): self { $this->evaluations->removeElement($evaluation); + $evaluation->removeSocialAction($this); return $this; } diff --git a/src/Bundle/ChillPersonBundle/Entity/SocialWork/SocialIssue.php b/src/Bundle/ChillPersonBundle/Entity/SocialWork/SocialIssue.php index fb277f56c..06f05c91f 100644 --- a/src/Bundle/ChillPersonBundle/Entity/SocialWork/SocialIssue.php +++ b/src/Bundle/ChillPersonBundle/Entity/SocialWork/SocialIssue.php @@ -1,14 +1,14 @@ addSelect( - ' - (acp.closingDate - acp.openingDate +15) *12/365 - AS duration_aggregator' - ); + switch ($data['precision']) { + case 'day': + $qb->addSelect('(COALESCE(acp.closingDate, :now) - acp.openingDate) AS duration_aggregator'); - // TODO Pour avoir un interval plus précis (nécessaire ?): - // adapter la fonction extract pour pouvoir l'utiliser avec des intervals: extract(month from interval) - // et ajouter une fonction custom qui calcule plus précisément les intervals, comme doctrineum/date-interval - // https://packagist.org/packages/doctrineum/date-interval#3.1.0 (mais composer fait un conflit de dépendance) + break; - $qb->addGroupBy('duration_aggregator'); - $qb->addOrderBy('duration_aggregator'); + case 'week': + $qb->addSelect('(COALESCE(acp.closingDate, :now) - acp.openingDate) / 7 AS duration_aggregator'); + + break; + + case 'month': + $qb->addSelect('(EXTRACT (MONTH FROM AGE(COALESCE(acp.closingDate, :now), acp.openingDate)) * 12 + + EXTRACT (MONTH FROM AGE(COALESCE(acp.closingDate, :now), acp.openingDate))) AS duration_aggregator'); + + break; + + default: + throw new LogicException('precision not supported: ' . $data['precision']); + } + + $qb + ->setParameter('now', new DateTimeImmutable('now')) + ->addGroupBy('duration_aggregator') + ->addOrderBy('duration_aggregator'); } public function applyOn(): string @@ -55,25 +76,27 @@ final class DurationAggregator implements AggregatorInterface public function buildForm(FormBuilderInterface $builder) { - // no form + $builder->add('precision', ChoiceType::class, [ + 'choices' => array_combine(self::CHOICES, self::CHOICES), + 'label' => 'export.aggregator.course.duration.Precision', + 'choice_label' => static fn (string $c) => 'export.aggregator.course.duration.' . $c, + 'multiple' => false, + 'expanded' => true, + ]); } public function getLabels($key, array $values, $data) { - return function ($value): ?string { + return static function ($value) use ($data) { if ('_header' === $value) { - return 'Rounded month duration'; + return 'export.aggregator.course.duration.' . $data['precision']; } if (null === $value) { - return $this->translator->trans('current duration'); // when closingDate is null + return 0; } - if (0 === $value) { - return $this->translator->trans('duration 0 month'); - } - - return $value . $this->translator->trans(' months'); + return $value; }; } diff --git a/src/Bundle/ChillPersonBundle/Export/Aggregator/AccompanyingCourseAggregators/EmergencyAggregator.php b/src/Bundle/ChillPersonBundle/Export/Aggregator/AccompanyingCourseAggregators/EmergencyAggregator.php index 297faf049..02f9f5cd9 100644 --- a/src/Bundle/ChillPersonBundle/Export/Aggregator/AccompanyingCourseAggregators/EmergencyAggregator.php +++ b/src/Bundle/ChillPersonBundle/Export/Aggregator/AccompanyingCourseAggregators/EmergencyAggregator.php @@ -1,19 +1,20 @@ leftJoin('person.countryOfBirth', 'countryOfBirth'); // add group by - $groupBy = $qb->getDQLPart('groupBy'); - - if (!empty($groupBy)) { - $qb->addGroupBy('country_of_birth_aggregator'); - } else { - $qb->groupBy('country_of_birth_aggregator'); - } + $qb->addGroupBy('country_of_birth_aggregator'); } public function applyOn() diff --git a/src/Bundle/ChillPersonBundle/Export/Aggregator/PersonAggregators/GenderAggregator.php b/src/Bundle/ChillPersonBundle/Export/Aggregator/PersonAggregators/GenderAggregator.php index 3cfadc355..549992845 100644 --- a/src/Bundle/ChillPersonBundle/Export/Aggregator/PersonAggregators/GenderAggregator.php +++ b/src/Bundle/ChillPersonBundle/Export/Aggregator/PersonAggregators/GenderAggregator.php @@ -1,14 +1,14 @@ setParameter('date', $data['date_position']); $qb->addSelect('IDENTITY(householdmember.position) AS household_position_aggregator'); - - $groupBy = $qb->getDQLPart('groupBy'); - - if (!empty($groupBy)) { - $qb->addGroupBy('household_position_aggregator'); - } else { - $qb->groupBy('household_position_aggregator'); - } + $qb->addGroupBy('household_position_aggregator'); } public function applyOn() diff --git a/src/Bundle/ChillPersonBundle/Export/Aggregator/PersonAggregators/MaritalStatusAggregator.php b/src/Bundle/ChillPersonBundle/Export/Aggregator/PersonAggregators/MaritalStatusAggregator.php index 333523487..e20ecfb62 100644 --- a/src/Bundle/ChillPersonBundle/Export/Aggregator/PersonAggregators/MaritalStatusAggregator.php +++ b/src/Bundle/ChillPersonBundle/Export/Aggregator/PersonAggregators/MaritalStatusAggregator.php @@ -1,14 +1,14 @@ addSelect('personmarital.id as marital_status_aggregator'); - - $groupBy = $qb->getDQLPart('groupBy'); - - if (!empty($groupBy)) { - $qb->addGroupBy('marital_status_aggregator'); - } else { - $qb->groupBy('marital_status_aggregator'); - } + $qb->addGroupBy('marital_status_aggregator'); } public function applyOn() diff --git a/src/Bundle/ChillPersonBundle/Export/Aggregator/PersonAggregators/NationalityAggregator.php b/src/Bundle/ChillPersonBundle/Export/Aggregator/PersonAggregators/NationalityAggregator.php index eb58913c3..1eced58d3 100644 --- a/src/Bundle/ChillPersonBundle/Export/Aggregator/PersonAggregators/NationalityAggregator.php +++ b/src/Bundle/ChillPersonBundle/Export/Aggregator/PersonAggregators/NationalityAggregator.php @@ -1,14 +1,14 @@ leftJoin('person.nationality', 'nationality'); - - // add group by - $groupBy = $qb->getDQLPart('groupBy'); - - if (!empty($groupBy)) { - $qb->addGroupBy('nationality_aggregator'); - } else { - $qb->groupBy('nationality_aggregator'); - } + $qb->addGroupBy('nationality_aggregator'); } public function applyOn() diff --git a/src/Bundle/ChillPersonBundle/Export/Aggregator/SocialWorkAggregators/ActionTypeAggregator.php b/src/Bundle/ChillPersonBundle/Export/Aggregator/SocialWorkAggregators/ActionTypeAggregator.php index 38fd40071..fbdac5d40 100644 --- a/src/Bundle/ChillPersonBundle/Export/Aggregator/SocialWorkAggregators/ActionTypeAggregator.php +++ b/src/Bundle/ChillPersonBundle/Export/Aggregator/SocialWorkAggregators/ActionTypeAggregator.php @@ -1,14 +1,14 @@ getQuery()->getResult(Query::HYDRATE_SCALAR); + return $query->getQuery()->getResult(Query::HYDRATE_SCALAR); } public function getTitle(): string diff --git a/src/Bundle/ChillPersonBundle/Export/Export/CountEvaluation.php b/src/Bundle/ChillPersonBundle/Export/Export/CountEvaluation.php index 544734055..e62752d13 100644 --- a/src/Bundle/ChillPersonBundle/Export/Export/CountEvaluation.php +++ b/src/Bundle/ChillPersonBundle/Export/Export/CountEvaluation.php @@ -1,14 +1,14 @@ getQuery()->getResult(Query::HYDRATE_SCALAR); + return $query->getQuery()->getResult(Query::HYDRATE_SCALAR); } public function getTitle(): string diff --git a/src/Bundle/ChillPersonBundle/Export/Export/CountHousehold.php b/src/Bundle/ChillPersonBundle/Export/Export/CountHousehold.php index 2b358634f..0c838beff 100644 --- a/src/Bundle/ChillPersonBundle/Export/Export/CountHousehold.php +++ b/src/Bundle/ChillPersonBundle/Export/Export/CountHousehold.php @@ -1,14 +1,14 @@ getQuery()->getResult(Query::HYDRATE_SCALAR); + return $query->getQuery()->getResult(Query::HYDRATE_SCALAR); } public function getTitle(): string diff --git a/src/Bundle/ChillPersonBundle/Export/Export/CountPerson.php b/src/Bundle/ChillPersonBundle/Export/Export/CountPerson.php index c411fad2e..98708149a 100644 --- a/src/Bundle/ChillPersonBundle/Export/Export/CountPerson.php +++ b/src/Bundle/ChillPersonBundle/Export/Export/CountPerson.php @@ -1,14 +1,14 @@ getQuery()->getResult(Query::HYDRATE_SCALAR); + return $query->getQuery()->getResult(Query::HYDRATE_SCALAR); } public function getTitle() diff --git a/src/Bundle/ChillPersonBundle/Export/Export/CountPersonWithAccompanyingCourse.php b/src/Bundle/ChillPersonBundle/Export/Export/CountPersonWithAccompanyingCourse.php index df48fe7c6..7acbd09cf 100644 --- a/src/Bundle/ChillPersonBundle/Export/Export/CountPersonWithAccompanyingCourse.php +++ b/src/Bundle/ChillPersonBundle/Export/Export/CountPersonWithAccompanyingCourse.php @@ -1,14 +1,14 @@ getQuery()->getResult(Query::HYDRATE_SCALAR); + return $query->getQuery()->getResult(Query::HYDRATE_SCALAR); } public function getTitle(): string diff --git a/src/Bundle/ChillPersonBundle/Export/Export/CountSocialWorkActions.php b/src/Bundle/ChillPersonBundle/Export/Export/CountSocialWorkActions.php index caf6cdbc2..9333312fd 100644 --- a/src/Bundle/ChillPersonBundle/Export/Export/CountSocialWorkActions.php +++ b/src/Bundle/ChillPersonBundle/Export/Export/CountSocialWorkActions.php @@ -1,14 +1,14 @@ getQuery()->getResult(Query::HYDRATE_SCALAR); + return $query->getQuery()->getResult(Query::HYDRATE_SCALAR); } public function getTitle(): string diff --git a/src/Bundle/ChillPersonBundle/Export/Export/ListPerson.php b/src/Bundle/ChillPersonBundle/Export/Export/ListPerson.php index e1d8788a7..5f5d95034 100644 --- a/src/Bundle/ChillPersonBundle/Export/Export/ListPerson.php +++ b/src/Bundle/ChillPersonBundle/Export/Export/ListPerson.php @@ -1,14 +1,14 @@ getQuery()->getResult(Query::HYDRATE_SCALAR); + return $query->getQuery()->getResult(Query::HYDRATE_SCALAR); } public function getTitle(): string diff --git a/src/Bundle/ChillPersonBundle/Export/Filter/AccompanyingCourseFilters/ActiveOnDateFilter.php b/src/Bundle/ChillPersonBundle/Export/Filter/AccompanyingCourseFilters/ActiveOnDateFilter.php index b52b8b34a..7fa92c0ae 100644 --- a/src/Bundle/ChillPersonBundle/Export/Filter/AccompanyingCourseFilters/ActiveOnDateFilter.php +++ b/src/Bundle/ChillPersonBundle/Export/Filter/AccompanyingCourseFilters/ActiveOnDateFilter.php @@ -1,14 +1,14 @@ getDQLPart('where'); $clause = $qb->expr()->in('acp.administrativeLocation', ':locations'); - - if ($where instanceof Andx) { - $where->add($clause); - } else { - $where = $qb->expr()->andX($clause); - } - - $qb->add('where', $where); - $qb->setParameter('locations', $data['accepted_locations']); + $qb + ->andWhere($clause) + ->setParameter('locations', $data['accepted_locations']); } public function applyOn(): string @@ -57,13 +48,12 @@ class AdministrativeLocationFilter implements FilterInterface public function buildForm(FormBuilderInterface $builder) { - $builder->add('accepted_locations', EntityType::class, [ - 'class' => Location::class, - 'choice_label' => function (Location $l) { - return $l->getName() . ' (' . $this->translatableStringHelper->localize($l->getLocationType()->getTitle()) . ')'; - }, + $builder->add('accepted_locations', Select2UserLocationType::class, [ + 'label' => 'Accepted locations', + 'label_attr' => [ + //'class' => 'd-none' + ], 'multiple' => true, - 'expanded' => true, ]); } diff --git a/src/Bundle/ChillPersonBundle/Export/Filter/AccompanyingCourseFilters/ClosingMotiveFilter.php b/src/Bundle/ChillPersonBundle/Export/Filter/AccompanyingCourseFilters/ClosingMotiveFilter.php index 636524d04..00ea8210d 100644 --- a/src/Bundle/ChillPersonBundle/Export/Filter/AccompanyingCourseFilters/ClosingMotiveFilter.php +++ b/src/Bundle/ChillPersonBundle/Export/Filter/AccompanyingCourseFilters/ClosingMotiveFilter.php @@ -1,14 +1,14 @@ $v) { - if ($v === $data['accepted_confidentials']) { - $choice = $k; - } - } - return [ 'Filtered by confidential: only %confidential%', [ - '%confidential%' => $this->translator->trans($choice) - ] + '%confidential%' => $this->translator->trans( + $data['accepted_confidentials'] ? 'is confidential' : 'is not confidential' + ), + ], ]; } diff --git a/src/Bundle/ChillPersonBundle/Export/Filter/AccompanyingCourseFilters/EmergencyFilter.php b/src/Bundle/ChillPersonBundle/Export/Filter/AccompanyingCourseFilters/EmergencyFilter.php index b9c835080..afdb717f0 100644 --- a/src/Bundle/ChillPersonBundle/Export/Filter/AccompanyingCourseFilters/EmergencyFilter.php +++ b/src/Bundle/ChillPersonBundle/Export/Filter/AccompanyingCourseFilters/EmergencyFilter.php @@ -1,14 +1,14 @@ $v) { - if ($v === $data['accepted_emergency']) { - $choice = $k; - } - } - return [ 'Filtered by emergency: only %emergency%', [ - '%emergency%' => $this->translator->trans($choice), + '%emergency%' => $this->translator->trans( + $data['accepted_emergency'] ? 'is emergency' : 'is not emergency' + ), ], ]; } diff --git a/src/Bundle/ChillPersonBundle/Export/Filter/AccompanyingCourseFilters/EvaluationFilter.php b/src/Bundle/ChillPersonBundle/Export/Filter/AccompanyingCourseFilters/EvaluationFilter.php index 3b95261db..ec4a5abe7 100644 --- a/src/Bundle/ChillPersonBundle/Export/Filter/AccompanyingCourseFilters/EvaluationFilter.php +++ b/src/Bundle/ChillPersonBundle/Export/Filter/AccompanyingCourseFilters/EvaluationFilter.php @@ -1,14 +1,14 @@ $v) { - if ($v === $data['accepted_intensities']) { - $choice = $k; - } - } - return [ 'Filtered by intensity: only %intensity%', [ - '%intensity%' => $this->translator->trans($choice), + '%intensity%' => $this->translator->trans($data['accepted_intensities']), ], ]; } diff --git a/src/Bundle/ChillPersonBundle/Export/Filter/AccompanyingCourseFilters/OpenBetweenDatesFilter.php b/src/Bundle/ChillPersonBundle/Export/Filter/AccompanyingCourseFilters/OpenBetweenDatesFilter.php index 814819a57..5b8335c55 100644 --- a/src/Bundle/ChillPersonBundle/Export/Filter/AccompanyingCourseFilters/OpenBetweenDatesFilter.php +++ b/src/Bundle/ChillPersonBundle/Export/Filter/AccompanyingCourseFilters/OpenBetweenDatesFilter.php @@ -1,14 +1,14 @@ translatableStringHelper = $translatableStringHelper; $this->security = $security; + $this->translatableStringHelper = $translatableStringHelper; + $this->userJobRepository = $userJobRepository; } public function addRole(): ?string @@ -42,17 +47,11 @@ class CurrentUserJobFilter implements FilterInterface public function alterQuery(QueryBuilder $qb, $data) { - $where = $qb->getDQLPart('where'); - $clause = $qb->expr()->eq('acp.job', ':userjob'); - - if ($where instanceof Andx) { - $where->add($clause); - } else { - $where = $qb->expr()->andX($clause); - } - - $qb->add('where', $where); - $qb->setParameter('userjob', $this->getUserJob()); + $qb + ->andWhere( + $qb->expr()->in('acp.job', ':acp_user_job_filter_j') + ) + ->setParameter('acp_user_job_filter_j', $data['jobs']); } public function applyOn() @@ -62,14 +61,26 @@ class CurrentUserJobFilter implements FilterInterface public function buildForm(FormBuilderInterface $builder) { + $builder->add('jobs', EntityType::class, [ + 'class' => UserJob::class, + 'choices' => $this->userJobRepository->findAllActive(), + 'multiple' => true, + 'expanded' => true, + 'choice_label' => fn (UserJob $job) => $this->translatableStringHelper->localize($job->getLabel()), + 'label' => 'Job', + ]); } public function describeAction($data, $format = 'string') { return [ 'Filtered by user job: only %job%', [ - '%job%' => $this->translatableStringHelper->localize( - $this->getUserJob()->getLabel() + '%job%' => implode( + ', ', + array_map( + fn (UserJob $job) => $this->translatableStringHelper->localize($job->getLabel()), + $data['jobs']->toArray() + ) ), ], ]; diff --git a/src/Bundle/ChillPersonBundle/Export/Filter/AccompanyingCourseFilters/CurrentUserScopeFilter.php b/src/Bundle/ChillPersonBundle/Export/Filter/AccompanyingCourseFilters/UserScopeFilter.php similarity index 55% rename from src/Bundle/ChillPersonBundle/Export/Filter/AccompanyingCourseFilters/CurrentUserScopeFilter.php rename to src/Bundle/ChillPersonBundle/Export/Filter/AccompanyingCourseFilters/UserScopeFilter.php index 8e164d668..c079b2bec 100644 --- a/src/Bundle/ChillPersonBundle/Export/Filter/AccompanyingCourseFilters/CurrentUserScopeFilter.php +++ b/src/Bundle/ChillPersonBundle/Export/Filter/AccompanyingCourseFilters/UserScopeFilter.php @@ -1,39 +1,43 @@ translatableStringHelper = $translatableStringHelper; + $this->scopeRepository = $scopeRepository; $this->security = $security; + $this->translatableStringHelper = $translatableStringHelper; } public function addRole(): ?string @@ -43,21 +47,14 @@ class CurrentUserScopeFilter implements FilterInterface public function alterQuery(QueryBuilder $qb, $data) { - if (!in_array('acpscope', $qb->getAllAliases(), true)) { - $qb->join('acp.scopes', 'acpscope'); + foreach ($data['scopes'] as $key => $scope) { + /** @var Scope $scope */ + $qb + ->andWhere( + $qb->expr()->isMemberOf(':acp_scope_filter_s_' . $key, 'acp.scopes') + ) + ->setParameter('acp_scope_filter_s_' . $key, $scope); } - - $where = $qb->getDQLPart('where'); - $clause = $qb->expr()->eq('acpscope.id', ':userscope'); - - if ($where instanceof Andx) { - $where->add($clause); - } else { - $where = $qb->expr()->andX($clause); - } - - $qb->add('where', $where); - $qb->setParameter('userscope', $this->getUserMainScope()); } public function applyOn() @@ -67,14 +64,25 @@ class CurrentUserScopeFilter implements FilterInterface public function buildForm(FormBuilderInterface $builder) { + $builder->add('scopes', EntityType::class, [ + 'class' => Scope::class, + 'choices' => $this->scopeRepository->findAllActive(), + 'choice_label' => fn (Scope $s) => $this->translatableStringHelper->localize($s->getName()), + 'multiple' => true, + 'expanded' => true, + ]); } public function describeAction($data, $format = 'string') { return [ 'Filtered by user main scope: only %scope%', [ - '%scope%' => $this->translatableStringHelper->localize( - $this->getUserMainScope()->getName() + '%scope%' => implode( + ', ', + array_map( + fn (Scope $s) => $this->translatableStringHelper->localize($s->getName()), + $data['scopes']->toArray() + ) ), ], ]; diff --git a/src/Bundle/ChillPersonBundle/Export/Filter/EvaluationFilters/EvaluationTypeFilter.php b/src/Bundle/ChillPersonBundle/Export/Filter/EvaluationFilters/EvaluationTypeFilter.php index 74f6fef75..2a5c143c7 100644 --- a/src/Bundle/ChillPersonBundle/Export/Filter/EvaluationFilters/EvaluationTypeFilter.php +++ b/src/Bundle/ChillPersonBundle/Export/Filter/EvaluationFilters/EvaluationTypeFilter.php @@ -1,14 +1,14 @@ true, - 'is not specified' => false, + 'maxdate is specified' => true, + 'maxdate is not specified' => false, ]; private TranslatorInterface $translator; @@ -40,21 +39,13 @@ class MaxDateFilter implements FilterInterface public function alterQuery(QueryBuilder $qb, $data) { - $where = $qb->getDQLPart('where'); - if (true === $data['maxdate']) { - $clause = $qb->expr()->isNotNull('eval.maxDate'); + $clause = $qb->expr()->isNotNull('workeval.maxDate'); } else { - $clause = $qb->expr()->isNull('eval.maxDate'); + $clause = $qb->expr()->isNull('workeval.maxDate'); } - if ($where instanceof Andx) { - $where->add($clause); - } else { - $where = $qb->expr()->andX($clause); - } - - $qb->add('where', $where); + $qb->andWhere($clause); } public function applyOn(): string @@ -73,19 +64,15 @@ class MaxDateFilter implements FilterInterface public function describeAction($data, $format = 'string'): array { - foreach (self::MAXDATE_CHOICES as $k => $v) { - if ($v === $data['maxdate']) { - $choice = $k; - } - } - return ['Filtered by maxdate: only %choice%', [ - '%choice%' => $this->translator->trans($choice), + '%choice%' => $this->translator->trans( + $data['maxdate'] ? 'maxdate is specified' : 'maxdate is not specified' + ), ]]; } public function getTitle(): string { - return 'Filter by maxdate'; + return 'Filter evaluations by maxdate mention'; } } diff --git a/src/Bundle/ChillPersonBundle/Export/Filter/HouseholdFilters/CompositionFilter.php b/src/Bundle/ChillPersonBundle/Export/Filter/HouseholdFilters/CompositionFilter.php index 94b55b67c..9296717ce 100644 --- a/src/Bundle/ChillPersonBundle/Export/Filter/HouseholdFilters/CompositionFilter.php +++ b/src/Bundle/ChillPersonBundle/Export/Filter/HouseholdFilters/CompositionFilter.php @@ -1,14 +1,14 @@ expr()->andX( $qb->expr()->isNotNull('person.deathdate'), $qb->expr()->gt( diff --git a/src/Bundle/ChillPersonBundle/Export/Filter/PersonFilters/DeathdateFilter.php b/src/Bundle/ChillPersonBundle/Export/Filter/PersonFilters/DeathdateFilter.php index ba8e8c150..48749006d 100644 --- a/src/Bundle/ChillPersonBundle/Export/Filter/PersonFilters/DeathdateFilter.php +++ b/src/Bundle/ChillPersonBundle/Export/Filter/PersonFilters/DeathdateFilter.php @@ -1,14 +1,14 @@ implode( ', ', array_map( - function (GeographicalUnit $item) { - return $this->translatableStringHelper->localize($item->getLayer()->getName()) . ' > ' . $item->getUnitName(); - }, - $data['units']->toArray() - ) + function (GeographicalUnit $item) { + return $this->translatableStringHelper->localize($item->getLayer()->getName()) . ' > ' . $item->getUnitName(); + }, + $data['units']->toArray() + ) ), ], ]; diff --git a/src/Bundle/ChillPersonBundle/Export/Filter/PersonFilters/MaritalStatusFilter.php b/src/Bundle/ChillPersonBundle/Export/Filter/PersonFilters/MaritalStatusFilter.php index 5d136c0e6..a3d2260e3 100644 --- a/src/Bundle/ChillPersonBundle/Export/Filter/PersonFilters/MaritalStatusFilter.php +++ b/src/Bundle/ChillPersonBundle/Export/Filter/PersonFilters/MaritalStatusFilter.php @@ -1,14 +1,14 @@ add('id', TextType::class, [ - 'label' => 'Identifiant', - ]) ->add('name', TranslatableStringFormType::class, [ 'label' => 'Nom', ]); diff --git a/src/Bundle/ChillPersonBundle/Form/OriginType.php b/src/Bundle/ChillPersonBundle/Form/OriginType.php index e3c08b359..bd28b80e5 100644 --- a/src/Bundle/ChillPersonBundle/Form/OriginType.php +++ b/src/Bundle/ChillPersonBundle/Form/OriginType.php @@ -1,14 +1,14 @@ centerResolverDispatcher = $centerResolverDispatcher; } - public function buildQueryOpenedAccompanyingCourseByUser(?User $user) + /** + * @param array|PostalCode[] + * + * @return QueryBuilder + */ + public function buildQueryOpenedAccompanyingCourseByUser(?User $user, array $postalCodes = []) { $qb = $this->accompanyingPeriodRepository->createQueryBuilder('ap'); @@ -65,6 +76,37 @@ final class AccompanyingPeriodACLAwareRepository implements AccompanyingPeriodAC ->setParameter('now', new DateTime('now')) ->setParameter('draft', AccompanyingPeriod::STEP_DRAFT); + if ([] !== $postalCodes) { + $qb->join('ap.locationHistories', 'location_history') + ->leftJoin(PersonHouseholdAddress::class, 'person_address', Join::WITH, 'IDENTITY(location_history.personLocation) = IDENTITY(person_address.person)') + ->join( + Address::class, + 'address', + Join::WITH, + 'COALESCE(IDENTITY(location_history.addressLocation), IDENTITY(person_address.address)) = address.id' + ) + ->andWhere( + $qb->expr()->orX( + $qb->expr()->isNull('person_address'), + $qb->expr()->andX( + $qb->expr()->lte('person_address.validFrom', ':now'), + $qb->expr()->orX( + $qb->expr()->isNull('person_address.validTo'), + $qb->expr()->lt('person_address.validTo', ':now') + ) + ) + ) + ) + ->andWhere( + $qb->expr()->isNull('location_history.endDate') + ) + ->andWhere( + $qb->expr()->in('address.postcode', ':postal_codes') + ) + ->setParameter('now', new DateTimeImmutable('now'), Types::DATE_IMMUTABLE) + ->setParameter('postal_codes', $postalCodes); + } + return $qb; } @@ -77,6 +119,18 @@ final class AccompanyingPeriodACLAwareRepository implements AccompanyingPeriodAC return $qb->getQuery()->getSingleScalarResult(); } + public function countByUserAndPostalCodesOpenedAccompanyingPeriod(?User $user, array $postalCodes): int + { + if (null === $user) { + return 0; + } + + return $this->buildQueryOpenedAccompanyingCourseByUser($user, $postalCodes) + ->select('COUNT(ap)') + ->getQuery() + ->getSingleScalarResult(); + } + public function countByUserOpenedAccompanyingPeriod(?User $user): int { if (null === $user) { @@ -158,6 +212,24 @@ final class AccompanyingPeriodACLAwareRepository implements AccompanyingPeriodAC return $qb->getQuery()->getResult(); } + public function findByUserAndPostalCodesOpenedAccompanyingPeriod(?User $user, array $postalCodes, array $orderBy = [], int $limit = 0, int $offset = 50): array + { + if (null === $user) { + return []; + } + + $qb = $this->buildQueryOpenedAccompanyingCourseByUser($user); + + $qb->setFirstResult($offset) + ->setMaxResults($limit); + + foreach ($orderBy as $field => $direction) { + $qb->addOrderBy('ap.' . $field, $direction); + } + + return $qb->getQuery()->getResult(); + } + /** * @return array|AccompanyingPeriod[] */ diff --git a/src/Bundle/ChillPersonBundle/Repository/AccompanyingPeriodACLAwareRepositoryInterface.php b/src/Bundle/ChillPersonBundle/Repository/AccompanyingPeriodACLAwareRepositoryInterface.php index e8d0bd856..0cca1a5f4 100644 --- a/src/Bundle/ChillPersonBundle/Repository/AccompanyingPeriodACLAwareRepositoryInterface.php +++ b/src/Bundle/ChillPersonBundle/Repository/AccompanyingPeriodACLAwareRepositoryInterface.php @@ -1,16 +1,17 @@ buildQueryBySocialActionWithDescendants($action); $qb->select('g'); + $qb->andWhere( + $qb->expr()->orX( + $qb->expr()->isNull('g.desactivationDate'), + $qb->expr()->gt('g.desactivationDate', ':now') + ) + ) + ->setParameter('now', new DateTime('now')); + foreach ($orderBy as $sort => $order) { $qb->addOrderBy('g.' . $sort, $order); } diff --git a/src/Bundle/ChillPersonBundle/Repository/SocialWork/ResultRepository.php b/src/Bundle/ChillPersonBundle/Repository/SocialWork/ResultRepository.php index 744c42577..df73bde21 100644 --- a/src/Bundle/ChillPersonBundle/Repository/SocialWork/ResultRepository.php +++ b/src/Bundle/ChillPersonBundle/Repository/SocialWork/ResultRepository.php @@ -1,14 +1,14 @@ , - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . + * For the full copyright and license information, please view + * the LICENSE file that was distributed with this source code. */ namespace Chill\PersonBundle\Repository\SocialWork; diff --git a/src/Bundle/ChillPersonBundle/Resources/views/AccompanyingCourse/dispatch_list.html.twig b/src/Bundle/ChillPersonBundle/Resources/views/AccompanyingCourse/dispatch_list.html.twig index 88bdf80c3..8cb5ab59f 100644 --- a/src/Bundle/ChillPersonBundle/Resources/views/AccompanyingCourse/dispatch_list.html.twig +++ b/src/Bundle/ChillPersonBundle/Resources/views/AccompanyingCourse/dispatch_list.html.twig @@ -76,7 +76,7 @@
{% for period in periods %} {% include '@ChillPerson/AccompanyingPeriod/_list_item.html.twig' with {'period': period, - 'recordAction': m.period_actions(period), 'itemMeta': m.period_meta(period) } %} + 'recordAction': m.period_actions(period), 'itemMeta': m.period_meta(period), 'show_address': true } %} {% endfor %}
{% endif %} diff --git a/src/Bundle/ChillPersonBundle/Resources/views/AccompanyingPeriod/_list_item.html.twig b/src/Bundle/ChillPersonBundle/Resources/views/AccompanyingPeriod/_list_item.html.twig index cfa616988..6c7fbf7c0 100644 --- a/src/Bundle/ChillPersonBundle/Resources/views/AccompanyingPeriod/_list_item.html.twig +++ b/src/Bundle/ChillPersonBundle/Resources/views/AccompanyingPeriod/_list_item.html.twig @@ -113,6 +113,16 @@ {% endif %} + {% if show_address|default(false) and period.location is not null %} +
+

{{ 'Accompanying course location'|trans }}

+
+

+ {{ period.location|chill_entity_render_string }} +

+
+
+ {% endif %} {% endif %} diff --git a/src/Bundle/ChillPersonBundle/Resources/views/AccompanyingPeriod/reassign_list.html.twig b/src/Bundle/ChillPersonBundle/Resources/views/AccompanyingPeriod/reassign_list.html.twig index 63e25efeb..c1144512d 100644 --- a/src/Bundle/ChillPersonBundle/Resources/views/AccompanyingPeriod/reassign_list.html.twig +++ b/src/Bundle/ChillPersonBundle/Resources/views/AccompanyingPeriod/reassign_list.html.twig @@ -5,11 +5,13 @@ {% block js %} {{ encore_entry_script_tags('mod_set_referrer') }} {{ encore_entry_script_tags('mod_pickentity_type') }} + {{ encore_entry_script_tags('mod_pick_postal_code') }} {% endblock %} {% block css %} {{ encore_entry_link_tags('mod_set_referrer') }} {{ encore_entry_link_tags('mod_pickentity_type') }} + {{ encore_entry_link_tags('mod_pick_postal_code') }} {% endblock %} {% macro period_meta(period) %} @@ -48,6 +50,8 @@ {{ form_start(form) }} {{ form_label(form.user ) }} {{ form_widget(form.user, {'attr': {'class': 'select2'}}) }} + {{ form_label(form.postal_code) }} + {{ form_widget(form.postal_code) }}