class EntityReferenceFieldNormalizer

Same name in other branches
  1. 9 core/modules/jsonapi/src/Normalizer/EntityReferenceFieldNormalizer.php \Drupal\jsonapi\Normalizer\EntityReferenceFieldNormalizer
  2. 8.9.x core/modules/jsonapi/src/Normalizer/EntityReferenceFieldNormalizer.php \Drupal\jsonapi\Normalizer\EntityReferenceFieldNormalizer
  3. 11.x core/modules/jsonapi/src/Normalizer/EntityReferenceFieldNormalizer.php \Drupal\jsonapi\Normalizer\EntityReferenceFieldNormalizer

Normalizer class specific for entity reference field objects.

@internal JSON:API maintains no PHP API since its API is the HTTP API. This class may change at any time and this will break any dependencies on it.

Hierarchy

Expanded class hierarchy of EntityReferenceFieldNormalizer

See also

https://www.drupal.org/project/drupal/issues/3032787

jsonapi.api.php

File

core/modules/jsonapi/src/Normalizer/EntityReferenceFieldNormalizer.php, line 25

Namespace

Drupal\jsonapi\Normalizer
View source
class EntityReferenceFieldNormalizer extends FieldNormalizer {
    
    /**
     * {@inheritdoc}
     */
    public function normalize($field, $format = NULL, array $context = []) : array|string|int|float|bool|\ArrayObject|null {
        assert($field instanceof EntityReferenceFieldItemListInterface);
        // Build the relationship object based on the Entity Reference and normalize
        // that object instead.
        $resource_identifiers = array_filter(ResourceIdentifier::toResourceIdentifiers($field->filterEmptyItems()), function (ResourceIdentifierInterface $resource_identifier) {
            return !$resource_identifier->getResourceType()
                ->isInternal();
        });
        $normalized_items = CacheableNormalization::aggregate($this->serializer
            ->normalize($resource_identifiers, $format, $context));
        assert($context['resource_object'] instanceof ResourceObject);
        $resource_relationship = $context['resource_object']->getResourceType()
            ->getFieldByInternalName($field->getName());
        assert($resource_relationship instanceof ResourceTypeRelationship);
        $link_cacheability = new CacheableMetadata();
        $links = array_map(function (Url $link) use ($link_cacheability) {
            $href = $link->setAbsolute()
                ->toString(TRUE);
            $link_cacheability->addCacheableDependency($href);
            return [
                'href' => $href->getGeneratedUrl(),
            ];
        }, static::getRelationshipLinks($context['resource_object'], $resource_relationship));
        $data_normalization = $normalized_items->getNormalization();
        $normalization = [
            // Empty 'to-one' relationships must be NULL.
            // Empty 'to-many' relationships must be an empty array.
            // @link http://jsonapi.org/format/#document-resource-object-linkage
'data' => $resource_relationship->hasOne() ? array_shift($data_normalization) : $data_normalization,
        ];
        if (!empty($links)) {
            $normalization['links'] = $links;
        }
        return (new CacheableNormalization($normalized_items, $normalization))->withCacheableDependency($link_cacheability);
    }
    
    /**
     * Gets the links for the relationship.
     *
     * @param \Drupal\jsonapi\JsonApiResource\ResourceObject $relationship_context
     *   The JSON:API resource object context of the relationship.
     * @param \Drupal\jsonapi\ResourceType\ResourceTypeRelationship $resource_relationship
     *   The resource type relationship field.
     *
     * @return array
     *   The relationship's links.
     */
    public static function getRelationshipLinks(ResourceObject $relationship_context, ResourceTypeRelationship $resource_relationship) {
        $resource_type = $relationship_context->getResourceType();
        if ($resource_type->isInternal() || !$resource_type->isLocatable()) {
            return [];
        }
        $public_field_name = $resource_relationship->getPublicName();
        $relationship_route_name = Routes::getRouteName($resource_type, "{$public_field_name}.relationship.get");
        $links = [
            'self' => Url::fromRoute($relationship_route_name, [
                'entity' => $relationship_context->getId(),
            ]),
        ];
        if (static::hasNonInternalResourceType($resource_type->getRelatableResourceTypesByField($public_field_name))) {
            $related_route_name = Routes::getRouteName($resource_type, "{$public_field_name}.related");
            $links['related'] = Url::fromRoute($related_route_name, [
                'entity' => $relationship_context->getId(),
            ]);
        }
        if ($resource_type->isVersionable()) {
            $version_query_parameter = [
                JsonApiSpec::VERSION_QUERY_PARAMETER => $relationship_context->getVersionIdentifier(),
            ];
            $links['self']->setOption('query', $version_query_parameter);
            if (isset($links['related'])) {
                $links['related']->setOption('query', $version_query_parameter);
            }
        }
        return $links;
    }
    
    /**
     * Determines if a given list of resource types contains a non-internal type.
     *
     * @param \Drupal\jsonapi\ResourceType\ResourceType[] $resource_types
     *   The JSON:API resource types to evaluate.
     *
     * @return bool
     *   FALSE if every resource type is internal, TRUE otherwise.
     */
    protected static function hasNonInternalResourceType(array $resource_types) {
        foreach ($resource_types as $resource_type) {
            if (!$resource_type->isInternal()) {
                return TRUE;
            }
        }
        return FALSE;
    }
    
    /**
     * {@inheritdoc}
     */
    public function getSupportedTypes(?string $format) : array {
        return [
            EntityReferenceFieldItemListInterface::class => TRUE,
        ];
    }

}

Members

Title Sort descending Modifiers Object type Summary Overriden Title Overrides
CacheableNormalizerInterface::SERIALIZATION_CONTEXT_CACHEABILITY constant Name of key for bubbling cacheability metadata via serialization context.
EntityReferenceFieldNormalizer::getRelationshipLinks public static function Gets the links for the relationship.
EntityReferenceFieldNormalizer::getSupportedTypes public function Overrides FieldNormalizer::getSupportedTypes
EntityReferenceFieldNormalizer::hasNonInternalResourceType protected static function Determines if a given list of resource types contains a non-internal type.
EntityReferenceFieldNormalizer::normalize public function Overrides FieldNormalizer::normalize
FieldNormalizer::denormalize public function
FieldNormalizer::hasCacheableSupportsMethod public function Overrides NormalizerBase::hasCacheableSupportsMethod
FieldNormalizer::normalizeFieldItems protected function Helper function to normalize field items.
NormalizerBase::$format protected property List of formats which supports (de-)normalization. Overrides NormalizerBase::$format
NormalizerBase::addCacheableDependency protected function Adds cacheability if applicable.
NormalizerBase::checkFormat protected function Checks if the provided format is supported by this normalizer. Overrides NormalizerBase::checkFormat
NormalizerBase::rasterizeValueRecursive protected static function Rasterizes a value recursively.
NormalizerBase::supportsDenormalization public function Implements \Symfony\Component\Serializer\Normalizer\DenormalizerInterface::supportsDenormalization() 1
NormalizerBase::supportsNormalization public function 1

Buggy or inaccurate documentation? Please file an issue. Need support? Need help programming? Connect with the Drupal community.