diff --git a/CHANGELOG.md b/CHANGELOG.md index deb66aba9..90f4c2503 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,9 +11,13 @@ and this project adheres to ## Unreleased +* [person] prevent circular references in PersonDocGenNormalizer (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/527) +* [person] add maritalStatusComment to PersonDocGenNormalizer (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/582) * Load relationships without gender in french fixtures * Add command to remove old draft accompanying periods + + ## Test releases ### 2021-04-28 @@ -24,7 +28,6 @@ and this project adheres to * [Documents] Validate storedObject and allow for null data (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/565) * [parcours]: Comments can be unpinned + edit/delete for all users that are allowed to edit parcours (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/566) - ### 2021-04-26 * [Datepickers] datepickers fixed when using keyboard to enter date (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/545) diff --git a/src/Bundle/ChillPersonBundle/Serializer/Normalizer/PersonDocGenNormalizer.php b/src/Bundle/ChillPersonBundle/Serializer/Normalizer/PersonDocGenNormalizer.php index 89f01bf94..22ce96ab7 100644 --- a/src/Bundle/ChillPersonBundle/Serializer/Normalizer/PersonDocGenNormalizer.php +++ b/src/Bundle/ChillPersonBundle/Serializer/Normalizer/PersonDocGenNormalizer.php @@ -23,6 +23,7 @@ use Chill\PersonBundle\Repository\Relationships\RelationshipRepository; use Chill\PersonBundle\Templating\Entity\PersonRenderInterface; use DateTimeInterface; use Doctrine\Common\Collections\ArrayCollection; +use Doctrine\Common\DataFixtures\Exception\CircularReferenceException; use libphonenumber\PhoneNumber; use Symfony\Component\Serializer\Exception\UnexpectedValueException; use Symfony\Component\Serializer\Normalizer\AbstractNormalizer; @@ -31,6 +32,7 @@ use Symfony\Component\Serializer\Normalizer\NormalizerAwareInterface; use Symfony\Component\Serializer\Normalizer\NormalizerAwareTrait; use Symfony\Contracts\Translation\TranslatorInterface; +use function array_key_exists; use function array_map; use function implode; use function in_array; @@ -42,6 +44,8 @@ class PersonDocGenNormalizer implements { use NormalizerAwareTrait; + private const CIRCULAR_KEY = 'person:circular'; + private PersonRenderInterface $personRender; private RelationshipRepository $relationshipRepository; @@ -68,6 +72,16 @@ class PersonDocGenNormalizer implements public function normalize($person, $format = null, array $context = []) { + try { + $context = $this->addCircularToContext($person, $context); + } catch (CircularReferenceException $circularReferenceException) { + return [ + 'isNull' => true, + 'isCircular' => true, + 'text' => '', + ]; + } + /** @var Person $person */ $dateContext = $context; $dateContext['docgen:expects'] = DateTimeInterface::class; @@ -114,6 +128,7 @@ class PersonDocGenNormalizer implements 'gender' => $this->translator->trans($person->getGender()), 'maritalStatus' => null !== ($ms = $person->getMaritalStatus()) ? $this->translatableStringHelper->localize($ms->getName()) : '', 'maritalStatusDate' => $this->normalizer->normalize($person->getMaritalStatusDate(), $format, $dateContext), + 'maritalStatusComment' => $this->normalizer->normalize($person->getMaritalStatusComment(), $format, $dateContext), 'email' => $person->getEmail(), 'firstPhoneNumber' => $this->normalizer->normalize($person->getPhonenumber() ?? $person->getMobilenumber(), $format, $phonenumberContext), 'fixPhoneNumber' => $this->normalizer->normalize($person->getPhonenumber(), $format, $phonenumberContext), @@ -123,7 +138,7 @@ class PersonDocGenNormalizer implements 'memo' => $person->getMemo(), 'numberOfChildren' => (string) $person->getNumberOfChildren(), 'address' => $this->normalizer->normalize($person->getCurrentPersonAddress(), $format, $addressContext), - //'resources' => $this->normalizer->normalize($person->getResources(), $format, $personResourceContext), + 'resources' => $this->normalizer->normalize($person->getResources(), $format, $personResourceContext), ]; if ($context['docgen:person:with-household'] ?? false) { @@ -177,6 +192,37 @@ class PersonDocGenNormalizer implements ); } + private function addCircularToContext($person, $context) + { + if (null === $person) { + $key = 'n'; + } else { + $key = spl_object_hash($person); + } + + if (!array_key_exists(self::CIRCULAR_KEY, $context)) { + $context[self::CIRCULAR_KEY] = [$key]; + + return $context; + } + + $occurences = array_reduce($context[self::CIRCULAR_KEY], static function ($carry, $item) use ($key) { + if ($key === $item) { + ++$carry; + } + + return $carry; + }, 0); + + if (2 <= $occurences) { + throw new CircularReferenceException(); + } + + $context[self::CIRCULAR_KEY][] = $key; + + return $context; + } + private function hasGroup($context, string $group): bool { $groups = $context[AbstractNormalizer::GROUPS] ?? [];