activityReasonCategoryRepository = $activityReasonCategoryRepository; $this->activityReasonRepository = $activityReasonRepository; $this->translatableStringHelper = $translatableStringHelper; } public function addRole() { return new Role(ActivityStatsVoter::STATS); } public function alterQuery(QueryBuilder $qb, $data) { // add select element if ('reasons' === $data['level']) { $elem = 'reasons.id'; $alias = 'activity_reasons_id'; } elseif ('categories' === $data['level']) { $elem = 'category.id'; $alias = 'activity_categories_id'; } else { throw new RuntimeException('The data provided are not recognized.'); } $qb->addSelect($elem . ' as ' . $alias); // make a jointure only if needed $join = $qb->getDQLPart('join'); if ( ( array_key_exists('activity', $join) && !$this->checkJoinAlreadyDefined($join['activity'], 'reasons') ) || (!array_key_exists('activity', $join)) ) { $qb->add( 'join', [ 'activity' => new Join(Join::INNER_JOIN, 'activity.reasons', 'reasons'), ], true ); } // join category if necessary if ('activity_categories_id' === $alias) { // add join only if needed if (!$this->checkJoinAlreadyDefined($qb->getDQLPart('join')['activity'], 'category')) { $qb->join('reasons.category', 'category'); } } // add the "group by" part $groupBy = $qb->getDQLPart('groupBy'); if (count($groupBy) > 0) { $qb->addGroupBy($alias); } else { $qb->groupBy($alias); } } public function applyOn(): string { return Declarations::ACTIVITY_PERSON; } public function buildForm(FormBuilderInterface $builder) { $builder->add( 'level', ChoiceType::class, [ 'choices' => [ 'By reason' => 'reasons', 'By category of reason' => 'categories', ], 'multiple' => false, 'expanded' => true, 'label' => "Reason's level", ] ); } public function getLabels($key, array $values, $data) { // for performance reason, we load data from db only once switch ($data['level']) { case 'reasons': $this->activityReasonRepository->findBy(['id' => $values]); break; case 'categories': $this->activityReasonCategoryRepository->findBy(['id' => $values]); break; default: throw new RuntimeException(sprintf("The level data '%s' is invalid.", $data['level'])); } return function ($value) use ($data) { if ('_header' === $value) { return 'reasons' === $data['level'] ? 'Group by reasons' : 'Group by categories of reason'; } switch ($data['level']) { case 'reasons': $r = $this->activityReasonRepository->find($value); return sprintf( '%s > %s', $this->translatableStringHelper->localize($r->getCategory()->getName()), $this->translatableStringHelper->localize($r->getName()) ); case 'categories': $c = $this->activityReasonCategoryRepository->find($value); return $this->translatableStringHelper->localize($c->getName()); } }; } public function getQueryKeys($data) { // add select element if ('reasons' === $data['level']) { return ['activity_reasons_id']; } if ('categories' === $data['level']) { return ['activity_categories_id']; } throw new RuntimeException('The data provided are not recognised.'); } public function getTitle() { return 'Aggregate by activity reason'; } public function validateForm($data, ExecutionContextInterface $context) { if (null === $data['level']) { $context ->buildViolation("The reasons's level should not be empty.") ->addViolation(); } } /** * Check if a join between Activity and another alias. * * @param Join[] $joins * @param string $alias the alias to search for * * @return bool */ private function checkJoinAlreadyDefined(array $joins, $alias) { foreach ($joins as $join) { if ($join->getAlias() === $alias) { return true; } } return false; } }