`, * donc l'INTERFACE. Le serializer ne sait pas denormaliser un IRI vers une * interface (« Could not denormalize object of type SiteInterface[] ») ; on * resout l'IRI via l'IriConverter (qui retourne le Site mappe a la route) sans * importer la classe Site du module Sites — la regle ABSOLUE n°1 (pas d'import * cross-module) reste respectee : dependance au seul contrat Shared + API Platform. * * En lecture (normalisation), aucun probleme : l'objet reel EST un Site, * ressource a part entiere, serialise en IRI par le normalizer standard. */ final class SiteReferenceDenormalizer implements DenormalizerInterface { public function __construct( private readonly IriConverterInterface $iriConverter, ) {} public function denormalize(mixed $data, string $type, ?string $format = null, array $context = []): ?SiteInterface { if (!is_string($data) || '' === $data) { return null; } // getResourceFromIri leve une exception sur IRI invalide -> 400, ce qui // est le comportement attendu pour une reference cassee. $resource = $this->iriConverter->getResourceFromIri($data); // IRI syntaxiquement valide mais pointant sur une autre ressource : on // refuse explicitement plutot que de retourner null silencieusement. if (!$resource instanceof SiteInterface) { throw new UnexpectedValueException(sprintf( 'L\'IRI "%s" ne référence pas un site.', $data, )); } return $resource; } public function supportsDenormalization(mixed $data, string $type, ?string $format = null, array $context = []): bool { // Support base sur le seul type cible : l'ArrayDenormalizer (collection // `SiteInterface[]`) interroge le support en passant le TABLEAU complet // comme $data avant de deleguer element par element. Tester // is_string($data) ici casserait la chaine pour les collections. return SiteInterface::class === $type; } /** * @return array */ public function getSupportedTypes(?string $format): array { return [SiteInterface::class => true]; } }