filterStatsByCenters = $parameterBag->get('chill_main')['acl']['filter_stats_by_center']; } public function generate(string $exportAlias, array $configuration, ?User $byUser = null): FormattedExportGeneration { $data = $this->configNormalizer->denormalizeConfig($exportAlias, $configuration); $export = $this->exportManager->getExport($exportAlias); $centers = $this->filterCenters($byUser, $data['centers']['centers'], $data['centers']['regroupments'], $export); $context = new ExportGenerationContext($byUser); if ($export instanceof DirectExportInterface) { $generatedExport = $export->generate( $this->buildCenterReachableScopes($centers), $data['export'], $context, ); if ($generatedExport instanceof Response) { trigger_deprecation('chill-project/chill-bundles', '3.10', 'DirectExportInterface should not return a %s instance, but a %s instance', Response::class, FormattedExportGeneration::class); return new FormattedExportGeneration($generatedExport->getContent(), $generatedExport->headers->get('Content-Type')); } return $generatedExport; } $query = $export->initiateQuery( $this->retrieveUsedModifiers($data), $this->buildCenterReachableScopes($centers), $data['export'], $context, ); if ($query instanceof \Doctrine\ORM\NativeQuery) { // throw an error if the export require other modifier, which is // not allowed when the export return a `NativeQuery` if (\count($export->supportsModifiers()) > 0) { throw new \LogicException("The export with alias `{$exportAlias}` return ".'a `\Doctrine\ORM\NativeQuery` and supports modifiers, which is not allowed. Either the method `supportsModifiers` should return an empty array, or return a `Doctrine\ORM\QueryBuilder`'); } } elseif ($query instanceof QueryBuilder) { // handle filters $this->handleFilters($query, $data[ExportType::FILTER_KEY], $context); // handle aggregators $this->handleAggregators($query, $data[ExportType::AGGREGATOR_KEY], $context); $this->logger->notice('[export] will execute this qb in export', [ 'dql' => $query->getDQL(), ]); } else { throw new \UnexpectedValueException('The method `intiateQuery` should return a `\Doctrine\ORM\NativeQuery` or a `Doctrine\ORM\QueryBuilder` object.'); } $result = $export->getResult($query, $data['export'], $context); $formatter = $this->exportManager->getFormatter($data['pick_formatter']); $filtersData = []; $aggregatorsData = []; if ($query instanceof QueryBuilder) { foreach ($this->exportConfigProcessor->retrieveUsedAggregators($data[ExportType::AGGREGATOR_KEY]) as $alias => $aggregator) { $aggregatorsData[$alias] = $data[ExportType::AGGREGATOR_KEY][$alias]['form']; } foreach ($this->exportConfigProcessor->retrieveUsedFilters($data[ExportType::FILTER_KEY]) as $alias => $filter) { $filtersData[$alias] = $data[ExportType::FILTER_KEY][$alias]['form']; } } /* @phpstan-ignore-next-line the method "generate" is not yet implemented on all formatters */ if (method_exists($formatter, 'generate')) { return $formatter->generate( $result, $data['formatter'], $exportAlias, $data['export'], $filtersData, $aggregatorsData, $context, ); } trigger_deprecation('chill-project/chill-bundles', '3.10', '%s should implements the "generate" method', FormatterInterface::class); /* @phpstan-ignore-next-line this is a deprecated method that we must still call */ $generatedExport = $formatter->getResponse( $result, $data['formatter'], $exportAlias, $data['export'], $filtersData, $aggregatorsData, $context, ); return new FormattedExportGeneration($generatedExport->getContent(), $generatedExport->headers->get('content-type')); } private function filterCenters(User $byUser, array $centers, array $regroupements, ExportInterface|DirectExportInterface $export): array { if (!$this->filterStatsByCenters) { return $this->centerRepository->findActive(); } $authorizedCenters = new ArrayCollection($this->authorizationHelper->getReachableCenters($byUser, $export->requiredRole())); if ($authorizedCenters->isEmpty()) { throw new UnauthorizedGenerationException('No authorized centers'); } $wantedCenters = $this->centerRegroupementResolver->resolveCenters($regroupements, $centers); $resolvedCenters = []; foreach ($wantedCenters as $wantedCenter) { if ($authorizedCenters->contains($wantedCenter)) { $resolvedCenters[] = $wantedCenter; } } if ([] == $resolvedCenters) { throw new UnauthorizedGenerationException('No common centers between wanted centers and authorized centers'); } return $resolvedCenters; } /** * parse the data to retrieve the used filters and aggregators. * * @return list */ private function retrieveUsedModifiers(mixed $data): array { if (null === $data) { return []; } $usedTypes = array_merge( $this->retrieveUsedFiltersType($data[ExportType::FILTER_KEY]), $this->retrieveUsedAggregatorsType($data[ExportType::AGGREGATOR_KEY]), ); return array_values(array_unique($usedTypes)); } /** * Retrieve the filter used in this export. * * @return list an array with types */ private function retrieveUsedFiltersType(mixed $data): array { if (null === $data) { return []; } $usedTypes = []; foreach ($this->exportConfigProcessor->retrieveUsedFilters($data) as $filter) { if (!\in_array($filter->applyOn(), $usedTypes, true)) { $usedTypes[] = $filter->applyOn(); } } return $usedTypes; } /** * @return string[] */ private function retrieveUsedAggregatorsType(mixed $data): array { if (null === $data) { return []; } $usedTypes = []; foreach ($this->exportConfigProcessor->retrieveUsedAggregators($data) as $alias => $aggregator) { if (!\in_array($aggregator->applyOn(), $usedTypes, true)) { $usedTypes[] = $aggregator->applyOn(); } } return $usedTypes; } /** * Alter the query with selected aggregators. */ private function handleAggregators( QueryBuilder $qb, array $data, ExportGenerationContext $context, ): void { foreach ($this->exportConfigProcessor->retrieveUsedAggregators($data) as $alias => $aggregator) { $formData = $data[$alias]; $aggregator->alterQuery($qb, $formData['form'], $context); } } /** * alter the query with selected filters. */ private function handleFilters( QueryBuilder $qb, mixed $data, ExportGenerationContext $context, ): void { foreach ($this->exportConfigProcessor->retrieveUsedFilters($data) as $alias => $filter) { $formData = $data[$alias]; $filter->alterQuery($qb, $formData['form'], $context); } } /** * build the array required for defining centers and circles in the initiate * queries of ExportElementsInterfaces. * * @param list
$centers */ private function buildCenterReachableScopes(array $centers) { return array_map(static fn (Center $center) => ['center' => $center, 'circles' => []], $centers); } }