diff --git a/src/Bundle/ChillMainBundle/Controller/ExportController.php b/src/Bundle/ChillMainBundle/Controller/ExportController.php
index 04c771365..70d7f10a8 100644
--- a/src/Bundle/ChillMainBundle/Controller/ExportController.php
+++ b/src/Bundle/ChillMainBundle/Controller/ExportController.php
@@ -25,6 +25,7 @@ use Chill\MainBundle\Form\Type\Export\FormatterType;
use Chill\MainBundle\Form\Type\Export\PickCenterType;
use Chill\MainBundle\Repository\SavedExportOrExportGenerationRepository;
use Chill\MainBundle\Security\Authorization\SavedExportVoter;
+use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\EntityManagerInterface;
use Psr\Log\LoggerInterface;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
@@ -117,7 +118,7 @@ class ExportController extends AbstractController
$options = match ($step) {
'export', 'generate_export' => [
'export_alias' => $alias,
- 'picked_centers' => $exportManager->getPickedCenters($data['centers'] ?? []),
+ 'picked_centers' => $this->exportFormHelper->getPickedCenters($data),
],
'formatter', 'generate_formatter' => [
'export_alias' => $alias,
@@ -337,9 +338,15 @@ class ExportController extends AbstractController
if ($this->filterStatsByCenters) {
$formCenters = $this->createCreateFormExport($alias, 'generate_centers', [], null);
$formCenters->submit($dataCenters);
- $dataCenters = $formCenters->getData();
+ $dataAsCollection = $formCenters->getData()['centers'];
+ $centers = $dataAsCollection['centers'];
+ $regroupments = $dataAsCollection['regroupments'];
+ $dataCenters = [
+ 'centers' => $centers instanceof Collection ? $centers->toArray() : $centers,
+ 'regroupments' => $regroupments instanceof Collection ? $regroupments->toArray() : $regroupments,
+ ];
} else {
- $dataCenters = ['centers' => []];
+ $dataCenters = ['centers' => [], 'regroupments' => []];
}
$formExport = $this->createCreateFormExport($alias, 'generate_export', $dataCenters, null);
@@ -358,7 +365,7 @@ class ExportController extends AbstractController
}
return [
- 'centers' => $dataCenters['centers'],
+ 'centers' => ['centers' => $dataCenters['centers'], 'regroupments' => $dataCenters['regroupments'] ?? []],
'export' => $dataExport['export']['export'] ?? [],
'filters' => $dataExport['export']['filters'] ?? [],
'aggregators' => $dataExport['export']['aggregators'] ?? [],
@@ -401,7 +408,7 @@ class ExportController extends AbstractController
false === $exportManager->isGrantedForElement(
$export,
null,
- $exportManager->getPickedCenters($data['centers'])
+ $this->exportFormHelper->getPickedCenters($data['centers']),
)
) {
throw $this->createAccessDeniedException('you do not have access to this export for those centers');
@@ -411,7 +418,7 @@ class ExportController extends AbstractController
'centers_step_raw',
$request->request->all()
);
- $this->session->set('centers_step', $data);
+ $this->session->set('centers_step', $data['centers']);
return $this->redirectToRoute('chill_main_export_new', [
'step' => $this->getNextStep('centers', $export),
diff --git a/src/Bundle/ChillMainBundle/Entity/Regroupment.php b/src/Bundle/ChillMainBundle/Entity/Regroupment.php
index 389eceb31..d28784210 100644
--- a/src/Bundle/ChillMainBundle/Entity/Regroupment.php
+++ b/src/Bundle/ChillMainBundle/Entity/Regroupment.php
@@ -102,4 +102,22 @@ class Regroupment
return $this;
}
+
+ /**
+ * Return true if the given center is contained into this regroupment.
+ */
+ public function containsCenter(Center $center): bool
+ {
+ return $this->centers->contains($center);
+ }
+
+ /**
+ * Return true if at least one of the given centers is contained into this regroupment.
+ *
+ * @param list
$centers
+ */
+ public function containsAtLeastOneCenter(array $centers): bool
+ {
+ return array_reduce($centers, fn (bool $carry, Center $center) => $carry || $this->containsCenter($center), false);
+ }
}
diff --git a/src/Bundle/ChillMainBundle/Export/Exception/ExportGenerationException.php b/src/Bundle/ChillMainBundle/Export/Exception/ExportGenerationException.php
new file mode 100644
index 000000000..0c06c4a7d
--- /dev/null
+++ b/src/Bundle/ChillMainBundle/Export/Exception/ExportGenerationException.php
@@ -0,0 +1,14 @@
+, export: array{form: array, version: int}, filters: array, version: int}>, aggregators: array, version: int}>, pick_formatter: string, formatter: array{form: array, version: int}}
+ * @phpstan-type NormalizedData array{centers: array{centers: list, regroupments: list}, export: array{form: array, version: int}, filters: array, version: int}>, aggregators: array, version: int}>, pick_formatter: string, formatter: array{form: array, version: int}}
*/
class ExportConfigNormalizer
{
public function __construct(
private readonly ExportManager $exportManager,
private readonly CenterRepositoryInterface $centerRepository,
+ private readonly RegroupmentRepository $regroupmentRepository,
) {}
/**
@@ -42,10 +45,10 @@ class ExportConfigNormalizer
],
];
- $serialized['centers'] = array_values(
- array_map(static fn (Center $center) => $center->getId(), $formData['centers'])
- );
-
+ $serialized['centers'] = [
+ 'centers' => array_values(array_map(static fn (Center $center) => $center->getId(), $formData['centers']['centers'] ?? [])),
+ 'regroupments' => array_values(array_map(static fn (Regroupment $group) => $group->getId(), $formData['centers']['regroupments'] ?? [])),
+ ];
$filtersSerialized = [];
foreach ($formData[ExportType::FILTER_KEY] as $alias => $filterData) {
@@ -116,7 +119,10 @@ class ExportConfigNormalizer
'aggregators' => $aggregatorsConfig,
'pick_formatter' => $serializedData['pick_formatter'],
'formatter' => $formater->denormalizeFormData($serializedData['formatter']['form'], $serializedData['formatter']['version']),
- 'centers' => array_filter(array_map(fn (int $id) => $this->centerRepository->find($id), $serializedData['centers']), fn ($item) => null !== $item),
+ 'centers' => [
+ 'centers' => array_values(array_filter(array_map(fn (int $id) => $this->centerRepository->find($id), $serializedData['centers']['centers']), fn ($item) => null !== $item)),
+ 'regroupments' => array_values(array_filter(array_map(fn (int $id) => $this->regroupmentRepository->find($id), $serializedData['centers']['regroupments']), fn ($item) => null !== $item)),
+ ],
];
}
}
diff --git a/src/Bundle/ChillMainBundle/Export/ExportFormHelper.php b/src/Bundle/ChillMainBundle/Export/ExportFormHelper.php
index f2c015351..faccbf0f3 100644
--- a/src/Bundle/ChillMainBundle/Export/ExportFormHelper.php
+++ b/src/Bundle/ChillMainBundle/Export/ExportFormHelper.php
@@ -11,11 +11,14 @@ declare(strict_types=1);
namespace Chill\MainBundle\Export;
+use Chill\MainBundle\Entity\Center;
use Chill\MainBundle\Entity\ExportGeneration;
use Chill\MainBundle\Entity\SavedExport;
use Chill\MainBundle\Form\Type\Export\ExportType;
use Chill\MainBundle\Form\Type\Export\FilterType;
use Chill\MainBundle\Security\Authorization\AuthorizationHelperForCurrentUserInterface;
+use Chill\MainBundle\Service\Regroupement\CenterRegroupementResolver;
+use Doctrine\Common\Collections\Collection;
final readonly class ExportFormHelper
{
@@ -23,12 +26,13 @@ final readonly class ExportFormHelper
private AuthorizationHelperForCurrentUserInterface $authorizationHelper,
private ExportManager $exportManager,
private ExportConfigNormalizer $configNormalizer,
+ private CenterRegroupementResolver $centerRegroupementResolver,
) {}
public function getDefaultData(string $step, DirectExportInterface|ExportInterface $export, array $options = []): array
{
return match ($step) {
- 'centers', 'generate_centers' => ['centers' => $this->authorizationHelper->getReachableCenters($export->requiredRole())],
+ 'centers', 'generate_centers' => ['centers' => $this->authorizationHelper->getReachableCenters($export->requiredRole()), 'regroupments' => []],
'export', 'generate_export' => ['export' => $this->getDefaultDataStepExport($export, $options)],
'formatter', 'generate_formatter' => ['formatter' => $this->getDefaultDataStepFormatter($options)],
default => throw new \LogicException('step not allowed : '.$step),
@@ -132,4 +136,24 @@ final readonly class ExportFormHelper
'formatter' => $data['formatter'],
];
}
+
+ /**
+ * Get the Center picked by the user for this export. The data are
+ * extracted from the PickCenterType data.
+ *
+ * @param array $data the data as given by the @see{Chill\MainBundle\Form\Type\Export\PickCenterType}
+ *
+ * @return list
+ */
+ public function getPickedCenters(array $data): array
+ {
+ if (!array_key_exists('centers', $data) || !array_key_exists('regroupments', $data)) {
+ throw new \RuntimeException('array has not the expected shape');
+ }
+
+ $centers = $data['centers'] instanceof Collection ? $data['centers']->toArray() : $data['centers'];
+ $regroupments = $data['regroupments'] instanceof Collection ? $data['regroupments']->toArray() : $data['regroupments'];
+
+ return $this->centerRegroupementResolver->resolveCenters(dump($regroupments), dump($centers));
+ }
}
diff --git a/src/Bundle/ChillMainBundle/Export/ExportGenerator.php b/src/Bundle/ChillMainBundle/Export/ExportGenerator.php
index f1a4d386b..20b87ebe9 100644
--- a/src/Bundle/ChillMainBundle/Export/ExportGenerator.php
+++ b/src/Bundle/ChillMainBundle/Export/ExportGenerator.php
@@ -13,7 +13,11 @@ namespace Chill\MainBundle\Export;
use Chill\MainBundle\Entity\Center;
use Chill\MainBundle\Entity\User;
+use Chill\MainBundle\Export\Exception\UnauthorizedGenerationException;
use Chill\MainBundle\Form\Type\Export\ExportType;
+use Chill\MainBundle\Security\Authorization\AuthorizationHelperInterface;
+use Chill\MainBundle\Service\Regroupement\CenterRegroupementResolver;
+use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\ORM\QueryBuilder;
use Psr\Log\LoggerInterface;
use Symfony\Component\HttpFoundation\Response;
@@ -27,14 +31,17 @@ final readonly class ExportGenerator
private ExportManager $exportManager,
private ExportConfigNormalizer $configNormalizer,
private LoggerInterface $logger,
+ private AuthorizationHelperInterface $authorizationHelper,
+ private CenterRegroupementResolver $centerRegroupementResolver,
) {}
public function generate(string $exportAlias, array $configuration, ?User $byUser = null): FormattedExportGeneration
{
$data = $this->configNormalizer->denormalizeConfig($exportAlias, $configuration);
- $centers = $data['centers'];
-
$export = $this->exportManager->getExport($exportAlias);
+
+ $centers = $this->filterCenters($byUser, $data['centers']['centers'], $data['centers']['regroupments'], $export);
+
$context = new ExportGenerationContext($byUser);
if ($export instanceof DirectExportInterface) {
@@ -94,6 +101,7 @@ final readonly class ExportGenerator
}
}
+ /** @phpstan-ignore-next-line the method "generate" is not yet implemented on all formatters */
if (method_exists($formatter, 'generate')) {
return $formatter->generate(
$result,
@@ -119,6 +127,29 @@ final readonly class ExportGenerator
return new FormattedExportGeneration($generatedExport->getContent(), $generatedExport->headers->get('content-type'));
}
+ private function filterCenters(User $byUser, array $centers, array $regroupements, ExportInterface|DirectExportInterface $export): array
+ {
+ $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.
*
diff --git a/src/Bundle/ChillMainBundle/Export/ExportManager.php b/src/Bundle/ChillMainBundle/Export/ExportManager.php
index c723bba68..fbc81caa3 100644
--- a/src/Bundle/ChillMainBundle/Export/ExportManager.php
+++ b/src/Bundle/ChillMainBundle/Export/ExportManager.php
@@ -348,19 +348,6 @@ class ExportManager
}
}
- /**
- * Get the Center picked by the user for this export. The data are
- * extracted from the PickCenterType data.
- *
- * @param array $data the data from a PickCenterType
- *
- * @return \Chill\MainBundle\Entity\Center[] the picked center
- */
- public function getPickedCenters(array $data): array
- {
- return $data;
- }
-
/**
* get the aggregators types used in the form export data.
*
diff --git a/src/Bundle/ChillMainBundle/Form/DataMapper/ExportPickCenterDataMapper.php b/src/Bundle/ChillMainBundle/Form/DataMapper/ExportPickCenterDataMapper.php
deleted file mode 100644
index 2a19c8e0b..000000000
--- a/src/Bundle/ChillMainBundle/Form/DataMapper/ExportPickCenterDataMapper.php
+++ /dev/null
@@ -1,56 +0,0 @@
- $form */
- $form = iterator_to_array($forms);
-
- $form['center']->setData($viewData);
-
- // NOTE: we do not map back the regroupments
- }
-
- public function mapFormsToData(\Traversable $forms, &$viewData): void
- {
- /** @var array $forms */
- $forms = iterator_to_array($forms);
-
- $centers = [];
-
- foreach ($forms['center']->getData() as $center) {
- $centers[spl_object_hash($center)] = $center;
- }
-
- if (\array_key_exists('regroupment', $forms)) {
- /** @var Regroupment $regroupment */
- foreach ($forms['regroupment']->getData() as $regroupment) {
- foreach ($regroupment->getCenters() as $center) {
- $centers[spl_object_hash($center)] = $center;
- }
- }
- }
-
- $viewData = array_values($centers);
- }
-}
diff --git a/src/Bundle/ChillMainBundle/Form/Type/Export/PickCenterType.php b/src/Bundle/ChillMainBundle/Form/Type/Export/PickCenterType.php
index fa8caf488..9196b05c0 100644
--- a/src/Bundle/ChillMainBundle/Form/Type/Export/PickCenterType.php
+++ b/src/Bundle/ChillMainBundle/Form/Type/Export/PickCenterType.php
@@ -14,9 +14,9 @@ namespace Chill\MainBundle\Form\Type\Export;
use Chill\MainBundle\Entity\Center;
use Chill\MainBundle\Entity\Regroupment;
use Chill\MainBundle\Export\ExportManager;
-use Chill\MainBundle\Form\DataMapper\ExportPickCenterDataMapper;
use Chill\MainBundle\Repository\RegroupmentRepository;
use Chill\MainBundle\Security\Authorization\AuthorizationHelperForCurrentUserInterface;
+use Chill\MainBundle\Service\Regroupement\RegroupementFiltering;
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
@@ -27,27 +27,26 @@ use Symfony\Component\OptionsResolver\OptionsResolver;
*/
final class PickCenterType extends AbstractType
{
- public const CENTERS_IDENTIFIERS = 'c';
-
public function __construct(
private readonly ExportManager $exportManager,
private readonly RegroupmentRepository $regroupmentRepository,
private readonly AuthorizationHelperForCurrentUserInterface $authorizationHelper,
+ private readonly RegroupementFiltering $regroupementFiltering,
) {}
public function buildForm(FormBuilderInterface $builder, array $options)
{
$export = $this->exportManager->getExport($options['export_alias']);
$centers = $this->authorizationHelper->getReachableCenters(
- $export->requiredRole()
+ $export->requiredRole(),
);
$centersActive = array_filter($centers, fn (Center $c) => $c->getIsActive());
// order alphabetically
- usort($centersActive, fn (Center $a, Center $b) => $a->getCenter() <=> $b->getName());
+ usort($centersActive, fn (Center $a, Center $b) => $a->getName() <=> $b->getName());
- $builder->add('center', EntityType::class, [
+ $builder->add('centers', EntityType::class, [
'class' => Center::class,
'choices' => $centersActive,
'label' => 'center',
@@ -56,18 +55,22 @@ final class PickCenterType extends AbstractType
'choice_label' => static fn (Center $c) => $c->getName(),
]);
- if (\count($this->regroupmentRepository->findAllActive()) > 0) {
- $builder->add('regroupment', EntityType::class, [
+ $groups = $this->regroupementFiltering
+ ->filterContainsAtLeastOneCenter($this->regroupmentRepository->findAllActive(), $centersActive);
+
+ // order alphabetically
+ usort($groups, fn (Regroupment $a, Regroupment $b) => $a->getName() <=> $b->getName());
+
+ if (\count($groups) > 0) {
+ $builder->add('regroupments', EntityType::class, [
'class' => Regroupment::class,
'label' => 'regroupment',
'multiple' => true,
'expanded' => true,
- 'choices' => $this->regroupmentRepository->findAllActive(),
+ 'choices' => $groups,
'choice_label' => static fn (Regroupment $r) => $r->getName(),
]);
}
-
- $builder->setDataMapper(new ExportPickCenterDataMapper());
}
public function configureOptions(OptionsResolver $resolver)
diff --git a/src/Bundle/ChillMainBundle/Resources/views/Export/new_centers_step.html.twig b/src/Bundle/ChillMainBundle/Resources/views/Export/new_centers_step.html.twig
index 2e2dc0ec6..42d2d4574 100644
--- a/src/Bundle/ChillMainBundle/Resources/views/Export/new_centers_step.html.twig
+++ b/src/Bundle/ChillMainBundle/Resources/views/Export/new_centers_step.html.twig
@@ -40,15 +40,15 @@
{{ 'Center'|trans }}
- {{ form_widget(form.centers.center) }}
+ {{ form_widget(form.centers.centers) }}
- {% if form.centers.regroupment is defined %}
+ {% if form.centers.regroupments is defined %}
{{ 'Pick aggregated centers'|trans }}
- {{ form_widget(form.centers.regroupment) }}
+ {{ form_widget(form.centers.regroupments) }}
{% endif %}
diff --git a/src/Bundle/ChillMainBundle/Service/Regroupement/CenterRegroupementResolver.php b/src/Bundle/ChillMainBundle/Service/Regroupement/CenterRegroupementResolver.php
new file mode 100644
index 000000000..9f1813c5c
--- /dev/null
+++ b/src/Bundle/ChillMainBundle/Service/Regroupement/CenterRegroupementResolver.php
@@ -0,0 +1,44 @@
+ $groups
+ * @param list $centers
+ *
+ * @return list
+ */
+ public function resolveCenters(array $groups, array $centers = []): array
+ {
+ $centersByHash = [];
+
+ foreach ($groups as $group) {
+ foreach ($group->getCenters() as $center) {
+ $centersByHash[spl_object_hash($center)] = $center;
+ }
+ }
+
+ foreach ($centers as $center) {
+ $centersByHash[spl_object_hash($center)] = $center;
+ }
+
+ return array_values($centersByHash);
+ }
+}
diff --git a/src/Bundle/ChillMainBundle/Service/Regroupement/RegroupementFiltering.php b/src/Bundle/ChillMainBundle/Service/Regroupement/RegroupementFiltering.php
new file mode 100644
index 000000000..76e4a892a
--- /dev/null
+++ b/src/Bundle/ChillMainBundle/Service/Regroupement/RegroupementFiltering.php
@@ -0,0 +1,37 @@
+ $group->containsAtLeastOneCenter($centers)),
+ );
+ }
+}
diff --git a/src/Bundle/ChillMainBundle/Tests/Export/ExportConfigNormalizerTest.php b/src/Bundle/ChillMainBundle/Tests/Export/ExportConfigNormalizerTest.php
index cf4518ccb..276e4e6ee 100644
--- a/src/Bundle/ChillMainBundle/Tests/Export/ExportConfigNormalizerTest.php
+++ b/src/Bundle/ChillMainBundle/Tests/Export/ExportConfigNormalizerTest.php
@@ -66,7 +66,7 @@ class ExportConfigNormalizerTest extends TestCase
$center->getId()->willReturn(10);
$formData = [
- 'centers' => [$center->reveal()],
+ 'centers' => ['centers' => [$center->reveal()]],
'export' => ['test' => '0'],
'filters' => [
'filterEnabled' => ['enabled' => true, 'form' => ['test' => '0']],
@@ -82,6 +82,7 @@ class ExportConfigNormalizerTest extends TestCase
$expected = [
'export' => ['form' => ['test' => '0'], 'version' => 1],
+ 'centers' => ['centers' => [10], 'regroupments' => []],
'filters' => [
'filtersEnabled' => ['enabled' => true, 'form' => ['test' => '0'], 'version' => 1],
'filterDisabled' => ['enabled' => false],
@@ -95,7 +96,6 @@ class ExportConfigNormalizerTest extends TestCase
'form' => ['test' => '0'],
'version' => 1,
],
- 'centers' => [10],
];
$exportConfigNormalizer = new ExportConfigNormalizer($exportManager->reveal(), $this->prophesize(CenterRepositoryInterface::class)->reveal());
@@ -137,7 +137,7 @@ class ExportConfigNormalizerTest extends TestCase
$centerRepository->find(10)->willReturn($center = new Center());
$serialized = [
- 'centers' => [10],
+ 'centers' => ['regroupments' => [], 'centers' => [10]],
'export' => ['form' => ['test' => '0'], 'version' => 1],
'filters' => [
'filterEnabled' => ['enabled' => true, 'form' => ['test' => '0'], 'version' => 1],
@@ -166,7 +166,7 @@ class ExportConfigNormalizerTest extends TestCase
],
'pick_formatter' => 'xlsx',
'formatter' => ['test' => '0'],
- 'centers' => [$center],
+ 'centers' => ['centers' => [$center], 'regroupments' => []],
];
$exportConfigNormalizer = new ExportConfigNormalizer($exportManager->reveal(), $centerRepository->reveal());
@@ -209,7 +209,7 @@ class ExportConfigNormalizerTest extends TestCase
$center->getId()->willReturn(10);
$formData = [
- 'centers' => [$center->reveal()],
+ 'centers' => ['centers' => [$center->reveal()]],
'export' => [],
'filters' => [
'filterEnabled' => ['enabled' => true, 'form' => []],
@@ -225,6 +225,7 @@ class ExportConfigNormalizerTest extends TestCase
$expected = [
'export' => ['form' => [], 'version' => 1],
+ 'centers' => ['centers' => [10], 'regroupments' => []],
'filters' => [
'filtersEnabled' => ['enabled' => true, 'form' => [], 'version' => 1],
'filterDisabled' => ['enabled' => false],
@@ -238,7 +239,6 @@ class ExportConfigNormalizerTest extends TestCase
'form' => [],
'version' => 1,
],
- 'centers' => [10],
];
$exportConfigNormalizer = new ExportConfigNormalizer($exportManager->reveal(), $this->prophesize(CenterRepositoryInterface::class)->reveal());
@@ -280,7 +280,7 @@ class ExportConfigNormalizerTest extends TestCase
$centerRepository->find(10)->willReturn($center = new Center());
$serialized = [
- 'centers' => [10],
+ 'centers' => ['centers' => [10], 'regroupments' => []],
'export' => ['form' => [], 'version' => 1],
'filters' => [
'filterEnabled' => ['enabled' => true, 'form' => [], 'version' => 1],
@@ -309,7 +309,7 @@ class ExportConfigNormalizerTest extends TestCase
],
'pick_formatter' => 'xlsx',
'formatter' => [],
- 'centers' => [$center],
+ 'centers' => ['centers' => [$center], 'regroupments' => []],
];
$exportConfigNormalizer = new ExportConfigNormalizer($exportManager->reveal(), $centerRepository->reveal());
diff --git a/src/Bundle/ChillMainBundle/Tests/Export/ExportGeneratorTest.php b/src/Bundle/ChillMainBundle/Tests/Export/ExportGeneratorTest.php
index 3f4d51059..94c29ab90 100644
--- a/src/Bundle/ChillMainBundle/Tests/Export/ExportGeneratorTest.php
+++ b/src/Bundle/ChillMainBundle/Tests/Export/ExportGeneratorTest.php
@@ -12,6 +12,7 @@ declare(strict_types=1);
namespace Chill\MainBundle\Tests\Export;
use Chill\MainBundle\Entity\Center;
+use Chill\MainBundle\Entity\Regroupment;
use Chill\MainBundle\Entity\User;
use Chill\MainBundle\Export\AggregatorInterface;
use Chill\MainBundle\Export\DirectExportInterface;
@@ -23,6 +24,8 @@ use Chill\MainBundle\Export\ExportManager;
use Chill\MainBundle\Export\FilterInterface;
use Chill\MainBundle\Export\FormattedExportGeneration;
use Chill\MainBundle\Export\FormatterInterface;
+use Chill\MainBundle\Security\Authorization\AuthorizationHelperInterface;
+use Chill\MainBundle\Service\Regroupement\CenterRegroupementResolver;
use Doctrine\ORM\NativeQuery;
use Doctrine\ORM\QueryBuilder;
use PHPUnit\Framework\TestCase;
@@ -54,7 +57,7 @@ class ExportGeneratorTest extends TestCase
],
'pick_formatter' => 'xlsx',
'formatter' => $formatterData = ['key' => 'form4'],
- 'centers' => [$centerA = new Center(), $centerB = new Center()],
+ 'centers' => ['centers' => [$centerA = new Center()], 'regroupments' => [(new Regroupment())->addCenter($centerB = new Center())]],
];
$user = new User();
@@ -70,11 +73,30 @@ class ExportGeneratorTest extends TestCase
// required methods
$export->initiateQuery(
['tagada', 'tsointsoin'],
- [['center' => $centerA, 'circles' => []], ['center' => $centerB, 'circles' => []]],
+ Argument::that(function ($arg) use ($centerB, $centerA) {
+ if (!is_array($arg)) {
+ return false;
+ }
+ if (2 !== count($arg)) {
+ return false;
+ }
+
+ foreach ($arg as $item) {
+ if ([] !== $item['circles']) {
+ return false;
+ }
+ if (!in_array($item['center'], [$centerA, $centerB], true)) {
+ return false;
+ }
+ }
+
+ return true;
+ }),
['key' => 'form1'],
)->shouldBeCalled()->willReturn($query->reveal());
$export->getResult($query->reveal(), $formExportData, Argument::that(static fn (ExportGenerationContext $context) => $context->byUser === $user))
->shouldBeCalled()->willReturn([['result0' => '0']]);
+ $export->requiredRole()->willReturn('dummy_role');
$filter->alterQuery($query->reveal(), $formFilterData, Argument::that(static fn (ExportGenerationContext $context) => $context->byUser === $user))
->shouldBeCalled();
@@ -105,7 +127,10 @@ class ExportGeneratorTest extends TestCase
$exportManager->hasAggregator('disabled_aggregator')->willReturn(true);
$exportManager->getFormatter('xlsx')->willReturn($formatter->reveal());
- $generator = new ExportGenerator($exportManager->reveal(), $exportConfigNormalizer->reveal(), new NullLogger());
+ $authorizationHelper = $this->prophesize(AuthorizationHelperInterface::class);
+ $authorizationHelper->getReachableCenters($user, 'dummy_role')->willReturn([$centerA, $centerB]);
+
+ $generator = new ExportGenerator($exportManager->reveal(), $exportConfigNormalizer->reveal(), new NullLogger(), $authorizationHelper->reveal(), new CenterRegroupementResolver());
$actual = $generator->generate('dummy', $initialData, $user);
@@ -123,7 +148,7 @@ class ExportGeneratorTest extends TestCase
'aggregators' => [],
'pick_formatter' => 'xlsx',
'formatter' => $formatterData = ['key' => 'form4'],
- 'centers' => [$centerA = new Center(), $centerB = new Center()],
+ 'centers' => ['centers' => [$centerA = new Center(), $centerB = new Center()], 'regroupments' => []],
];
$user = new User();
@@ -141,6 +166,7 @@ class ExportGeneratorTest extends TestCase
$export->getResult($query->reveal(), $formExportData, Argument::that(static fn (ExportGenerationContext $context) => $context->byUser === $user))
->shouldBeCalled()->willReturn([['result0' => '0']]);
$export->supportsModifiers()->willReturn([]);
+ $export->requiredRole()->willReturn('dummy_role');
$formatter->generate(
[['result0' => '0']],
@@ -160,7 +186,10 @@ class ExportGeneratorTest extends TestCase
$exportManager->getExport('dummy')->willReturn($export->reveal());
$exportManager->getFormatter('xlsx')->willReturn($formatter->reveal());
- $generator = new ExportGenerator($exportManager->reveal(), $exportConfigNormalizer->reveal(), new NullLogger());
+ $authorizationHelper = $this->prophesize(AuthorizationHelperInterface::class);
+ $authorizationHelper->getReachableCenters($user, 'dummy_role')->willReturn([$centerA, $centerB]);
+
+ $generator = new ExportGenerator($exportManager->reveal(), $exportConfigNormalizer->reveal(), new NullLogger(), $authorizationHelper->reveal(), new CenterRegroupementResolver());
$actual = $generator->generate('dummy', $initialData, $user);
diff --git a/src/Bundle/ChillMainBundle/Tests/Services/Regroupement/CenterRegroupementResolverTest.php b/src/Bundle/ChillMainBundle/Tests/Services/Regroupement/CenterRegroupementResolverTest.php
new file mode 100644
index 000000000..4f7c2431f
--- /dev/null
+++ b/src/Bundle/ChillMainBundle/Tests/Services/Regroupement/CenterRegroupementResolverTest.php
@@ -0,0 +1,78 @@
+resolveCenters($groups, $centers);
+
+ self::assertEquals(count($expected), count($actual));
+
+ foreach ($expected as $center) {
+ self::assertContains($center, $actual);
+ }
+ }
+
+ public static function provideData(): iterable
+ {
+ $centerA = new Center();
+ $centerB = new Center();
+ $centerC = new Center();
+ $centerD = new Center();
+
+ $groupA = new Regroupment();
+ $groupA->addCenter($centerA)->addCenter($centerB);
+
+ $groupB = new Regroupment();
+ $groupB->addCenter($centerA)->addCenter($centerB)->addCenter($centerC);
+
+ yield [
+ [$groupA],
+ [],
+ [$centerA, $centerB],
+ ];
+
+ yield [
+ [$groupA, $groupB],
+ [],
+ [$centerA, $centerB, $centerC],
+ ];
+
+ yield [
+ [$groupA, $groupB],
+ [$centerB, $centerD],
+ [$centerA, $centerB, $centerC, $centerD],
+ ];
+ }
+}
diff --git a/src/Bundle/ChillMainBundle/Tests/Services/Regroupement/RegroupementFilteringTest.php b/src/Bundle/ChillMainBundle/Tests/Services/Regroupement/RegroupementFilteringTest.php
new file mode 100644
index 000000000..f6976054f
--- /dev/null
+++ b/src/Bundle/ChillMainBundle/Tests/Services/Regroupement/RegroupementFilteringTest.php
@@ -0,0 +1,96 @@
+filterContainsAtLeastOneCenter($groups, $centers);
+
+ self::assertEquals(count($expected), count($actual));
+ self::assertTrue(array_is_list($actual));
+
+ foreach ($expected as $center) {
+ self::assertContains($center, $actual);
+ }
+ }
+
+ public static function provideDataForFilterContainsAtLeastOnCenter(): iterable
+ {
+
+ $centerA = new Center();
+ $centerB = new Center();
+ $centerC = new Center();
+ $centerD = new Center();
+
+ $groupA = new Regroupment();
+ $groupA->addCenter($centerA)->addCenter($centerB);
+
+ $groupB = new Regroupment();
+ $groupB->addCenter($centerA)->addCenter($centerB)->addCenter($centerC);
+
+ $groupC = new Regroupment();
+ $groupC->addCenter($centerA)->addCenter($centerD);
+
+ yield [
+ [$groupA, $groupB],
+ [],
+ [],
+ ];
+
+ yield [
+ [$groupA, $groupB],
+ [$centerA, $centerB, $centerC],
+ [$groupA, $groupB],
+ ];
+
+ yield [
+ [$groupA, $groupC],
+ [$centerD],
+ [$groupC],
+ ];
+
+ yield [
+ [$groupA],
+ [$centerB, $centerD],
+ [$groupA],
+ ];
+
+ yield [
+ [$groupA],
+ [new Center()],
+ [],
+ ];
+
+ }
+}