personRender = $personRender; $this->relationshipRepository = $relationshipRepository; $this->translator = $translator; $this->translatableStringHelper = $translatableStringHelper; $this->summaryBudget = $summaryBudget; } 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; $addressContext = array_merge($context, ['docgen:expects' => Address::class]); $phonenumberContext = array_merge($context, ['docgen:expects' => PhoneNumber::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 => function ($object, $format, $context) { return $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 function (PersonAltName $altName) { return $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), ]; 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', '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; } }