[person] prevent circular references in PersonDocGenNormalizer

This commit is contained in:
nobohan 2022-04-29 10:54:56 +02:00
parent 4675525225
commit 671950708c
2 changed files with 46 additions and 1 deletions

View File

@ -11,7 +11,8 @@ and this project adheres to
## Unreleased
<!-- write down unreleased development here -->
* [person] add maritalStatusComment to PersonDocGenNormalizer (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/582s)
* [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)
* [main] avoid address reference search on undefined post code (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/561)
* [person] prevent duplicate relationship in filiation/household graph (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/560)

View File

@ -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;
@ -52,6 +53,8 @@ class PersonDocGenNormalizer implements
private TranslatorInterface $translator;
private const CIRCULAR_KEY = 'person:circular';
public function __construct(
PersonRenderInterface $personRender,
RelationshipRepository $relationshipRepository,
@ -68,6 +71,17 @@ 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;
@ -178,6 +192,36 @@ 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], 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] ?? [];