Code owners
Assign users and groups as approvers for specific file changes. Learn more.
ResourceObjectNormalizer.php 4.00 KiB
<?php
namespace Drupal\jsonapi\Normalizer;
use Drupal\Core\Cache\CacheableMetadata;
use Drupal\Core\Field\FieldItemListInterface;
use Drupal\jsonapi\JsonApiResource\ResourceObject;
use Drupal\jsonapi\Normalizer\Value\CacheableNormalization;
use Drupal\jsonapi\Normalizer\Value\CacheableOmission;
/**
* 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.
*
* @see https://www.drupal.org/project/jsonapi/issues/3032787
* @see jsonapi.api.php
*/
class ResourceObjectNormalizer extends NormalizerBase {
/**
* {@inheritdoc}
*/
protected $supportedInterfaceOrClass = ResourceObject::class;
/**
* {@inheritdoc}
*/
public function supportsDenormalization($data, $type, $format = NULL) {
return FALSE;
}
/**
* {@inheritdoc}
*/
public function normalize($object, $format = NULL, array $context = []) {
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);
}
$normalizer_values = [];
foreach ($fields as $field_name => $field) {
$in_sparse_fieldset = in_array($field_name, $field_names);
// Omit fields not listed in sparse fieldsets.
if (!$in_sparse_fieldset) {
continue;
}
$normalizer_values[$field_name] = $this->serializeField($field, $context, $format);
}
$relationship_field_names = array_keys($resource_type->getRelatableResourceTypes());
return CacheableNormalization::aggregate([
'type' => CacheableNormalization::permanent($resource_type->getTypeName()),
'id' => CacheableNormalization::permanent($object->getId()),
'attributes' => CacheableNormalization::aggregate(array_diff_key($normalizer_values, array_flip($relationship_field_names)))->omitIfEmpty(),
'relationships' => CacheableNormalization::aggregate(array_intersect_key($normalizer_values, array_flip($relationship_field_names)))->omitIfEmpty(),
'links' => $this->serializer->normalize($object->getLinks(), $format, $context)->omitIfEmpty(),
])->withCacheableDependency($object);
}
/**
* 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'], TRUE);
if (!$field_access_result->isAllowed()) {
return new CacheableOmission(CacheableMetadata::createFromObject($field_access_result));
}
$normalized_field = $this->serializer->normalize($field, $format, $context);
assert($normalized_field instanceof CacheableNormalization);
return $normalized_field->withCacheableDependency(CacheableMetadata::createFromObject($field_access_result));
}
else {
// Config "fields" in this case are arrays or primitives and do not need
// to be normalized.
return CacheableNormalization::permanent($field);
}
}
}