class ResourceObjectNormalizer
Same name in other branches
- 9 core/modules/jsonapi/src/Normalizer/ResourceObjectNormalizer.php \Drupal\jsonapi\Normalizer\ResourceObjectNormalizer
- 8.9.x core/modules/jsonapi/src/Normalizer/ResourceObjectNormalizer.php \Drupal\jsonapi\Normalizer\ResourceObjectNormalizer
- 11.x core/modules/jsonapi/src/Normalizer/ResourceObjectNormalizer.php \Drupal\jsonapi\Normalizer\ResourceObjectNormalizer
Converts the JSON:API module ResourceObject into a JSON:API array structure.
@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
- class \Drupal\serialization\Normalizer\NormalizerBase implements \Symfony\Component\Serializer\SerializerAwareInterface, \Drupal\serialization\Normalizer\CacheableNormalizerInterface uses \Symfony\Component\Serializer\SerializerAwareTrait
- class \Drupal\jsonapi\Normalizer\NormalizerBase extends \Drupal\serialization\Normalizer\NormalizerBase
- class \Drupal\jsonapi\Normalizer\ResourceObjectNormalizer extends \Drupal\jsonapi\Normalizer\NormalizerBase
- class \Drupal\jsonapi\Normalizer\NormalizerBase extends \Drupal\serialization\Normalizer\NormalizerBase
Expanded class hierarchy of ResourceObjectNormalizer
See also
https://www.drupal.org/project/drupal/issues/3032787
1 string reference to 'ResourceObjectNormalizer'
- jsonapi.services.yml in core/
modules/ jsonapi/ jsonapi.services.yml - core/modules/jsonapi/jsonapi.services.yml
1 service uses ResourceObjectNormalizer
File
-
core/
modules/ jsonapi/ src/ Normalizer/ ResourceObjectNormalizer.php, line 23
Namespace
Drupal\jsonapi\NormalizerView source
class ResourceObjectNormalizer extends NormalizerBase {
/**
* The entity normalization cacher.
*
* @var \Drupal\jsonapi\EventSubscriber\ResourceObjectNormalizationCacher
*/
protected $cacher;
/**
* Constructs a ResourceObjectNormalizer object.
*
* @param \Drupal\jsonapi\EventSubscriber\ResourceObjectNormalizationCacher $cacher
* The entity normalization cacher.
*/
public function __construct(ResourceObjectNormalizationCacher $cacher) {
$this->cacher = $cacher;
}
/**
* {@inheritdoc}
*/
public function supportsDenormalization($data, string $type, ?string $format = NULL, array $context = []) : bool {
return FALSE;
}
/**
* {@inheritdoc}
*/
public function normalize($object, $format = NULL, array $context = []) : array|string|int|float|bool|\ArrayObject|null {
assert($object instanceof ResourceObject);
// If the fields to use were specified, only output those field values.
$context['resource_object'] = $object;
$resource_type = $object->getResourceType();
$resource_type_name = $resource_type->getTypeName();
$fields = $object->getFields();
// Get the bundle ID of the requested resource. This is used to determine if
// this is a bundle level resource or an entity level resource.
if (!empty($context['sparse_fieldset'][$resource_type_name])) {
$field_names = $context['sparse_fieldset'][$resource_type_name];
}
else {
$field_names = array_keys($fields);
}
$normalization_parts = $this->getNormalization($field_names, $object, $format, $context);
// Keep only the requested fields (the cached normalization gradually grows
// to the complete set of fields).
$fields = $normalization_parts[ResourceObjectNormalizationCacher::RESOURCE_CACHE_SUBSET_FIELDS];
$field_normalizations = array_intersect_key($fields, array_flip($field_names));
$relationship_field_names = array_keys($resource_type->getRelatableResourceTypes());
$attributes = array_diff_key($field_normalizations, array_flip($relationship_field_names));
$relationships = array_intersect_key($field_normalizations, array_flip($relationship_field_names));
$entity_normalization = array_filter($normalization_parts[ResourceObjectNormalizationCacher::RESOURCE_CACHE_SUBSET_BASE] + [
'attributes' => CacheableNormalization::aggregate($attributes)->omitIfEmpty(),
'relationships' => CacheableNormalization::aggregate($relationships)->omitIfEmpty(),
]);
return CacheableNormalization::aggregate($entity_normalization)->withCacheableDependency($object);
}
/**
* Normalizes an entity using the given fieldset.
*
* @param string[] $field_names
* The field names to normalize (the sparse fieldset, if any).
* @param \Drupal\jsonapi\JsonApiResource\ResourceObject $object
* The resource object to partially normalize.
* @param string $format
* The format in which the normalization will be encoded.
* @param array $context
* Context options for the normalizer.
*
* @return array
* An array with two key-value pairs:
* - 'base': array, the base normalization of the entity, that does not
* depend on which sparse fieldset was requested.
* - 'fields': CacheableNormalization for all requested fields.
*
* @see ::normalize()
*/
protected function getNormalization(array $field_names, ResourceObject $object, $format = NULL, array $context = []) {
$cached_normalization_parts = $this->cacher
->get($object);
$normalizer_values = $cached_normalization_parts !== FALSE ? $cached_normalization_parts : static::buildEmptyNormalization($object);
$fields =& $normalizer_values[ResourceObjectNormalizationCacher::RESOURCE_CACHE_SUBSET_FIELDS];
$non_cached_fields = array_diff_key($object->getFields(), $fields);
$non_cached_requested_fields = array_intersect_key($non_cached_fields, array_flip($field_names));
foreach ($non_cached_requested_fields as $field_name => $field) {
$fields[$field_name] = $this->serializeField($field, $context, $format);
}
// Add links if missing.
$base =& $normalizer_values[ResourceObjectNormalizationCacher::RESOURCE_CACHE_SUBSET_BASE];
$base['links'] = $base['links'] ?? $this->serializer
->normalize($object->getLinks(), $format, $context)
->omitIfEmpty();
if (!empty($non_cached_requested_fields)) {
$this->cacher
->saveOnTerminate($object, $normalizer_values);
}
return $normalizer_values;
}
/**
* Builds the empty normalization structure for cache misses.
*
* @param \Drupal\jsonapi\JsonApiResource\ResourceObject $object
* The resource object being normalized.
*
* @return array
* The normalization structure as defined in ::getNormalization().
*
* @see ::getNormalization()
*/
protected static function buildEmptyNormalization(ResourceObject $object) {
return [
ResourceObjectNormalizationCacher::RESOURCE_CACHE_SUBSET_BASE => [
'type' => CacheableNormalization::permanent($object->getResourceType()
->getTypeName()),
'id' => CacheableNormalization::permanent($object->getId()),
],
ResourceObjectNormalizationCacher::RESOURCE_CACHE_SUBSET_FIELDS => [],
];
}
/**
* Serializes a given field.
*
* @param mixed $field
* The field to serialize.
* @param array $context
* The normalization context.
* @param string $format
* The serialization format.
*
* @return \Drupal\jsonapi\Normalizer\Value\CacheableNormalization
* The normalized value.
*/
protected function serializeField($field, array $context, $format) {
// Only content entities contain FieldItemListInterface fields. Since config
// entities do not have "real" fields and therefore do not have field access
// restrictions.
if ($field instanceof FieldItemListInterface) {
$field_access_result = $field->access('view', $context['account'] ?? NULL, TRUE);
if (!$field_access_result->isAllowed()) {
return new CacheableOmission(CacheableMetadata::createFromObject($field_access_result));
}
if ($field instanceof EntityReferenceFieldItemListInterface) {
// Build the relationship object based on the entity reference and
// normalize that object instead.
assert(!empty($context['resource_object']) && $context['resource_object'] instanceof ResourceObject);
$resource_object = $context['resource_object'];
$relationship = Relationship::createFromEntityReferenceField($resource_object, $field);
$normalized_field = $this->serializer
->normalize($relationship, $format, $context);
}
else {
$normalized_field = $this->serializer
->normalize($field, $format, $context);
}
assert($normalized_field instanceof CacheableNormalization);
return $normalized_field->withCacheableDependency(CacheableMetadata::createFromObject($field_access_result));
}
else {
// @todo Replace this workaround after https://www.drupal.org/node/3043245
// or remove the need for this in https://www.drupal.org/node/2942975.
// See \Drupal\layout_builder\Normalizer\LayoutEntityDisplayNormalizer.
if (is_a($context['resource_object']->getResourceType()
->getDeserializationTargetClass(), 'Drupal\\layout_builder\\Entity\\LayoutBuilderEntityViewDisplay', TRUE) && $context['resource_object']->getField('third_party_settings') === $field) {
unset($field['layout_builder']['sections']);
}
// Config "fields" in this case are arrays or primitives and do not need
// to be normalized.
return CacheableNormalization::permanent($field);
}
}
/**
* {@inheritdoc}
*/
public function hasCacheableSupportsMethod() : bool {
@trigger_error(__METHOD__ . '() is deprecated in drupal:10.1.0 and is removed from drupal:11.0.0. Use getSupportedTypes() instead. See https://www.drupal.org/node/3359695', E_USER_DEPRECATED);
return TRUE;
}
/**
* {@inheritdoc}
*/
public function getSupportedTypes(?string $format) : array {
return [
ResourceObject::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. | |||
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::supportsNormalization | public | function | 1 | ||
ResourceObjectNormalizer::$cacher | protected | property | The entity normalization cacher. | ||
ResourceObjectNormalizer::buildEmptyNormalization | protected static | function | Builds the empty normalization structure for cache misses. | ||
ResourceObjectNormalizer::getNormalization | protected | function | Normalizes an entity using the given fieldset. | ||
ResourceObjectNormalizer::getSupportedTypes | public | function | Overrides NormalizerBase::getSupportedTypes | ||
ResourceObjectNormalizer::hasCacheableSupportsMethod | public | function | Overrides NormalizerBase::hasCacheableSupportsMethod | ||
ResourceObjectNormalizer::normalize | public | function | |||
ResourceObjectNormalizer::serializeField | protected | function | Serializes a given field. | ||
ResourceObjectNormalizer::supportsDenormalization | public | function | Implements \Symfony\Component\Serializer\Normalizer\DenormalizerInterface::supportsDenormalization() | Overrides NormalizerBase::supportsDenormalization | |
ResourceObjectNormalizer::__construct | public | function | Constructs a ResourceObjectNormalizer object. |
Buggy or inaccurate documentation? Please file an issue. Need support? Need help programming? Connect with the Drupal community.