src/Normalizer/FieldNormalizer.php | 4 +--- src/Normalizer/RelationshipNormalizer.php | 12 +++++++++--- src/Normalizer/Value/FieldNormalizerValue.php | 14 +++++--------- src/Normalizer/Value/RelationshipNormalizerValue.php | 10 +++++----- .../src/Unit/Normalizer/Value/FieldNormalizerValueTest.php | 8 ++------ 5 files changed, 22 insertions(+), 26 deletions(-) diff --git a/src/Normalizer/FieldNormalizer.php b/src/Normalizer/FieldNormalizer.php index 4d57dd6..98d8ed8 100644 --- a/src/Normalizer/FieldNormalizer.php +++ b/src/Normalizer/FieldNormalizer.php @@ -3,7 +3,6 @@ namespace Drupal\jsonapi\Normalizer; use Drupal\Component\Assertion\Inspector; -use Drupal\Core\Cache\CacheableMetadata; use Drupal\Core\Field\EntityReferenceFieldItemList; use Drupal\Core\Field\FieldDefinitionInterface; use Drupal\Core\Field\FieldItemListInterface; @@ -51,8 +50,7 @@ class FieldNormalizer extends NormalizerBase implements DenormalizerInterface { $cardinality = $field->getFieldDefinition() ->getFieldStorageDefinition() ->getCardinality(); - $cacheability = CacheableMetadata::createFromObject($access); - return new FieldNormalizerValue($cacheability, $normalized_field_items, $cardinality, $property_type); + return new FieldNormalizerValue($access, $normalized_field_items, $cardinality, $property_type); } else { return new NullFieldNormalizerValue($access, $property_type); diff --git a/src/Normalizer/RelationshipNormalizer.php b/src/Normalizer/RelationshipNormalizer.php index 0bf90cf..3c32d6c 100644 --- a/src/Normalizer/RelationshipNormalizer.php +++ b/src/Normalizer/RelationshipNormalizer.php @@ -2,7 +2,7 @@ namespace Drupal\jsonapi\Normalizer; -use Drupal\Core\Cache\CacheableMetadata; +use Drupal\Core\Access\AccessResult; use Drupal\Core\Entity\EntityFieldManagerInterface; use Drupal\Core\Entity\EntityInterface; use Drupal\Core\Entity\EntityRepositoryInterface; @@ -200,8 +200,14 @@ class RelationshipNormalizer extends NormalizerBase implements DenormalizerInter 'link_manager' => $this->linkManager, 'resource_type' => $resource_type, ]; - $cacheability = CacheableMetadata::createFromObject($relationship); - return new RelationshipNormalizerValue($cacheability, $normalizer_items, $cardinality, $link_context); + // If this is called, access to the Relationship field is allowed. The + // cacheability of the access result is carried by the Relationship value + // object. Therefore, we can safely construct an access result object here. + // Access to the targeted related resources will be checked separately. + // @see \Drupal\jsonapi\Normalizer\EntityReferenceFieldNormalizer::normalize() + // @see \Drupal\jsonapi\Normalizer\RelationshipItemNormalizer::normalize() + $relationship_access = AccessResult::allowed()->addCacheableDependency($relationship); + return new RelationshipNormalizerValue($relationship_access, $normalizer_items, $cardinality, $link_context); } /** diff --git a/src/Normalizer/Value/FieldNormalizerValue.php b/src/Normalizer/Value/FieldNormalizerValue.php index c51074c..295cb44 100644 --- a/src/Normalizer/Value/FieldNormalizerValue.php +++ b/src/Normalizer/Value/FieldNormalizerValue.php @@ -2,7 +2,7 @@ namespace Drupal\jsonapi\Normalizer\Value; -use Drupal\Core\Cache\CacheableDependencyInterface; +use Drupal\Core\Access\AccessResultInterface; use Drupal\Core\Cache\CacheableDependencyTrait; /** @@ -39,12 +39,8 @@ class FieldNormalizerValue implements FieldNormalizerValueInterface { /** * Instantiate a FieldNormalizerValue object. * - * @param \Drupal\Core\Cache\CacheableDependencyInterface $field_cacheability - * The cacheability of the normalized field. This cacheability is not part - * of $values because field item list is normalized by Drupal core's - * serialization system, which was never designed with cacheability in mind. - * FieldNormalizer::normalize() must catch the out-of-band bubbled - * cacheability and then passes it to this value object. + * @param \Drupal\Core\Access\AccessResultInterface $field_access_result + * The field access result. * @param \Drupal\jsonapi\Normalizer\Value\FieldItemNormalizerValue[] $values * The normalized result. * @param int $cardinality @@ -52,9 +48,9 @@ class FieldNormalizerValue implements FieldNormalizerValueInterface { * @param string $property_type * The property type of the field: 'attributes' or 'relationships'. */ - public function __construct(CacheableDependencyInterface $field_cacheability, array $values, $cardinality, $property_type) { + public function __construct(AccessResultInterface $field_access_result, array $values, $cardinality, $property_type) { assert($property_type === 'attributes' || $property_type === 'relationships'); - $this->setCacheability(static::mergeCacheableDependencies(array_merge([$field_cacheability], $values))); + $this->setCacheability(static::mergeCacheableDependencies(array_merge([$field_access_result], $values))); $this->values = $values; $this->cardinality = $cardinality; diff --git a/src/Normalizer/Value/RelationshipNormalizerValue.php b/src/Normalizer/Value/RelationshipNormalizerValue.php index 637e827..0b81a0a 100644 --- a/src/Normalizer/Value/RelationshipNormalizerValue.php +++ b/src/Normalizer/Value/RelationshipNormalizerValue.php @@ -2,7 +2,7 @@ namespace Drupal\jsonapi\Normalizer\Value; -use Drupal\Core\Cache\CacheableDependencyInterface; +use Drupal\Core\Access\AccessResultInterface; /** * Helps normalize relationships in compliance with the JSON API spec. @@ -42,8 +42,8 @@ class RelationshipNormalizerValue extends FieldNormalizerValue { /** * Instantiate a EntityReferenceNormalizerValue object. * - * @param \Drupal\Core\Cache\CacheableDependencyInterface $relationship_cacheability - * The cacheability of the relationship. + * @param \Drupal\Core\Access\AccessResultInterface $relationship_access_result + * The relationship access result. * @param RelationshipItemNormalizerValue[] $values * The normalized result. * @param int $cardinality @@ -52,7 +52,7 @@ class RelationshipNormalizerValue extends FieldNormalizerValue { * All the objects and variables needed to generate the links for this * relationship. */ - public function __construct(CacheableDependencyInterface $relationship_cacheability, array $values, $cardinality, array $link_context) { + public function __construct(AccessResultInterface $relationship_access_result, array $values, $cardinality, array $link_context) { $this->hostEntityId = $link_context['host_entity_id']; $this->fieldName = $link_context['field_name']; $this->linkManager = $link_context['link_manager']; @@ -62,7 +62,7 @@ class RelationshipNormalizerValue extends FieldNormalizerValue { throw new \RuntimeException(sprintf('Unexpected normalizer item value for this %s.', get_called_class())); } }); - parent::__construct($relationship_cacheability, $values, $cardinality, 'relationships'); + parent::__construct($relationship_access_result, $values, $cardinality, 'relationships'); } /** diff --git a/tests/src/Unit/Normalizer/Value/FieldNormalizerValueTest.php b/tests/src/Unit/Normalizer/Value/FieldNormalizerValueTest.php index 8094e7b..5014c86 100644 --- a/tests/src/Unit/Normalizer/Value/FieldNormalizerValueTest.php +++ b/tests/src/Unit/Normalizer/Value/FieldNormalizerValueTest.php @@ -2,7 +2,7 @@ namespace Drupal\Tests\jsonapi\Unit\Normalizer\Value; -use Drupal\Core\Cache\CacheableMetadata; +use Drupal\Core\Access\AccessResult; use Drupal\Core\DependencyInjection\ContainerBuilder; use Drupal\jsonapi\Normalizer\Value\FieldItemNormalizerValue; use Drupal\jsonapi\Normalizer\Value\FieldNormalizerValue; @@ -45,11 +45,7 @@ class FieldNormalizerValueTest extends UnitTestCase { * @dataProvider rasterizeValueProvider */ public function testRasterizeValue($values, $cardinality, $expected) { - $cacheability = new CacheableMetadata(); - $cacheability->addCacheContexts(['user']); - $cacheability->addCacheTags(['field:foo']); - $cacheability->setCacheMaxAge(8000); - $object = new FieldNormalizerValue($cacheability, $values, $cardinality, 'attributes'); + $object = new FieldNormalizerValue(AccessResult::allowed()->cachePerUser()->addCacheTags(['field:foo']), $values, $cardinality, 'attributes'); $this->assertEquals($expected, $object->rasterizeValue()); $this->assertSame(['ccfoo', 'user'], $object->getCacheContexts()); $this->assertSame(['ctfoo', 'field:foo'], $object->getCacheTags());