mirror of
https://gitlab.com/Chill-Projet/chill-bundles.git
synced 2025-06-07 18:44:08 +00:00
248 lines
10 KiB
PHP
248 lines
10 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
/*
|
|
* Chill is a software for social workers
|
|
*
|
|
* For the full copyright and license information, please view
|
|
* the LICENSE file that was distributed with this source code.
|
|
*/
|
|
|
|
namespace Chill\PersonBundle\Serializer\Normalizer;
|
|
|
|
use Chill\BudgetBundle\Service\Summary\SummaryBudgetInterface;
|
|
use Chill\DocGeneratorBundle\Serializer\Helper\NormalizeNullValueHelper;
|
|
use Chill\MainBundle\Entity\Address;
|
|
use Chill\MainBundle\Entity\Center;
|
|
use Chill\MainBundle\Entity\Civility;
|
|
use Chill\MainBundle\Templating\TranslatableStringHelper;
|
|
use Chill\PersonBundle\Entity\Household\Household;
|
|
use Chill\PersonBundle\Entity\Person;
|
|
use Chill\PersonBundle\Entity\PersonAltName;
|
|
use Chill\PersonBundle\Repository\Relationships\RelationshipRepository;
|
|
use Chill\PersonBundle\Templating\Entity\PersonRenderInterface;
|
|
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;
|
|
use Symfony\Component\Serializer\Normalizer\ContextAwareNormalizerInterface;
|
|
use Symfony\Component\Serializer\Normalizer\NormalizerAwareInterface;
|
|
use Symfony\Component\Serializer\Normalizer\NormalizerAwareTrait;
|
|
use Symfony\Contracts\Translation\TranslatorInterface;
|
|
|
|
class PersonDocGenNormalizer implements
|
|
ContextAwareNormalizerInterface,
|
|
NormalizerAwareInterface
|
|
{
|
|
use NormalizerAwareTrait;
|
|
|
|
private const CIRCULAR_KEY = 'person:circular';
|
|
|
|
public function __construct(private readonly PersonRenderInterface $personRender, private readonly RelationshipRepository $relationshipRepository, private readonly TranslatorInterface $translator, private readonly TranslatableStringHelper $translatableStringHelper, private readonly SummaryBudgetInterface $summaryBudget) {}
|
|
|
|
public function normalize($person, $format = null, array $context = [])
|
|
{
|
|
try {
|
|
$context = $this->addCircularToContext($person, $context);
|
|
} catch (CircularReferenceException) {
|
|
return [
|
|
'isNull' => true,
|
|
'isCircular' => true,
|
|
'text' => '',
|
|
];
|
|
}
|
|
|
|
/** @var Person $person */
|
|
$dateContext = $context;
|
|
$dateContext['docgen:expects'] = \DateTimeInterface::class;
|
|
$addressContext = array_merge($context, ['docgen:expects' => Address::class]);
|
|
$phonenumberContext = array_merge($context, ['docgen:expects' => PhoneNumber::class]);
|
|
$centerContext = array_merge($context, ['docgen:expects' => Center::class]);
|
|
$personResourceContext = array_merge($context, [
|
|
'docgen:expects' => Person\PersonResource::class,
|
|
// we simplify the list of attributes for the embedded persons
|
|
AbstractNormalizer::GROUPS => ['docgen:read'],
|
|
// when a person reference the same person... take care of circular references
|
|
AbstractNormalizer::CIRCULAR_REFERENCE_HANDLER => fn ($object, $format, $context) => $this->normalizer->normalize(null, $format, $context),
|
|
]);
|
|
|
|
if (null === $person) {
|
|
return $this->normalizeNullValue($format, $context);
|
|
}
|
|
|
|
if (!$person instanceof Person) {
|
|
throw new UnexpectedValueException();
|
|
}
|
|
|
|
$data = [
|
|
'type' => 'person',
|
|
'id' => $person->getId(),
|
|
'isNull' => false,
|
|
'civility' => $this->normalizer->normalize($person->getCivility(), $format, array_merge($context, ['docgen:expects' => Civility::class])),
|
|
'firstName' => $person->getFirstName(),
|
|
'lastName' => $person->getLastName(),
|
|
'altNames' => \implode(
|
|
', ',
|
|
\array_map(
|
|
static fn (PersonAltName $altName) => $altName->getLabel(),
|
|
$person->getAltNames()->toArray()
|
|
)
|
|
),
|
|
'text' => $this->personRender->renderString($person, []),
|
|
'age' => (int) $person->getAge(),
|
|
'birthdate' => $this->normalizer->normalize($person->getBirthdate(), $format, $dateContext),
|
|
'deathdate' => $this->normalizer->normalize($person->getDeathdate(), $format, $dateContext),
|
|
'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),
|
|
'mobilePhoneNumber' => $this->normalizer->normalize($person->getMobilenumber(), $format, $phonenumberContext),
|
|
'nationality' => null !== ($c = $person->getNationality()) ? $this->translatableStringHelper->localize($c->getName()) : '',
|
|
'placeOfBirth' => $person->getPlaceOfBirth(),
|
|
'memo' => $person->getMemo(),
|
|
'numberOfChildren' => (string) $person->getNumberOfChildren(),
|
|
'address' => $this->normalizer->normalize($person->getCurrentPersonAddress(), $format, $addressContext),
|
|
'resources' => $this->normalizer->normalize($person->getResources(), $format, $personResourceContext),
|
|
'center' => $this->normalizer->normalize($person->getCenter(), $format, $centerContext),
|
|
];
|
|
|
|
if ($context['docgen:person:with-household'] ?? false) {
|
|
$data['household'] = $this->normalizer->normalize(
|
|
$person->getCurrentHousehold(),
|
|
$format,
|
|
array_merge($context, [
|
|
'docgen:expects' => Household::class,
|
|
'docgen:person:with-household' => false,
|
|
'docgen:person:with-relations' => false,
|
|
'docgen:person:with-budget' => false,
|
|
])
|
|
);
|
|
}
|
|
|
|
if ($context['docgen:person:with-relations'] ?? false) {
|
|
$data['relations'] = $this->normalizer->normalize(
|
|
new ArrayCollection($this->relationshipRepository->findByPerson($person)),
|
|
$format,
|
|
array_merge($context, [
|
|
'docgen:person:with-household' => false,
|
|
'docgen:person:with-relation' => false,
|
|
'docgen:relationship:counterpart' => $person,
|
|
'docgen:person:with-budget' => false,
|
|
])
|
|
);
|
|
}
|
|
|
|
if ($context['docgen:person:with-budget'] ?? false) {
|
|
$data['budget']['person'] = $this->summaryBudget->getSummaryForPerson($person);
|
|
|
|
if ($context['docgen:person:with-household'] ?? false) {
|
|
$data['budget']['household'] = $this->summaryBudget->getSummaryForHousehold($person->getCurrentHousehold());
|
|
}
|
|
}
|
|
|
|
return $data;
|
|
}
|
|
|
|
public function supportsNormalization($data, $format = null, array $context = [])
|
|
{
|
|
if ('docgen' !== $format) {
|
|
return false;
|
|
}
|
|
|
|
return
|
|
$data instanceof Person
|
|
|| (
|
|
null === $data
|
|
&& Person::class === ($context['docgen:expects'] ?? null)
|
|
);
|
|
}
|
|
|
|
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] ?? [];
|
|
|
|
if (\is_string($groups)) {
|
|
$groups = [$groups];
|
|
}
|
|
|
|
return \in_array($group, $groups, true);
|
|
}
|
|
|
|
private function normalizeNullValue(string $format, array $context)
|
|
{
|
|
$normalizer = new NormalizeNullValueHelper($this->normalizer, 'type', 'person');
|
|
|
|
$attributes = [
|
|
'id', 'firstName', 'lastName', 'age', 'altNames', 'text',
|
|
'center' => Center::class,
|
|
'civility' => Civility::class,
|
|
'birthdate' => \DateTimeInterface::class,
|
|
'deathdate' => \DateTimeInterface::class,
|
|
'gender', 'maritalStatus',
|
|
'maritalStatusDate' => \DateTimeInterface::class,
|
|
'maritalStatusComment',
|
|
'email', 'firstPhoneNumber', 'fixPhoneNumber', 'mobilePhoneNumber', 'nationality',
|
|
'placeOfBirth', 'memo', 'numberOfChildren',
|
|
'address' => Address::class,
|
|
];
|
|
|
|
if ($context['docgen:person:with-household'] ?? false) {
|
|
$attributes['household'] = Household::class;
|
|
}
|
|
|
|
$data = $normalizer->normalize($attributes, $format, $context);
|
|
|
|
$data['resources'] = [];
|
|
|
|
if ($context['docgen:person:with-relations'] ?? false) {
|
|
$data['relations'] = [];
|
|
}
|
|
|
|
if ($context['docgen:person:with-budget'] ?? false) {
|
|
$data['budget']['person'] = $this->summaryBudget->getSummaryForPerson(null);
|
|
|
|
if ($context['docgen:person:with-household'] ?? false) {
|
|
$data['budget']['household'] = $this->summaryBudget->getSummaryForHousehold(null);
|
|
}
|
|
}
|
|
|
|
return $data;
|
|
}
|
|
}
|