diff --git a/core/modules/jsonapi/src/EventSubscriber/ResourceObjectNormalizationCacher.php b/core/modules/jsonapi/src/EventSubscriber/ResourceObjectNormalizationCacher.php index 45572b25da71..9c651caba2de 100644 --- a/core/modules/jsonapi/src/EventSubscriber/ResourceObjectNormalizationCacher.php +++ b/core/modules/jsonapi/src/EventSubscriber/ResourceObjectNormalizationCacher.php @@ -143,6 +143,7 @@ class ResourceObjectNormalizationCacher implements EventSubscriberInterface { // Merge the entity's cacheability metadata with that of the normalization // parts, so that RenderCache can take care of cache redirects for us. CacheableMetadata::createFromObject($object) + ->merge(static::mergeCacheableDependencies($normalization_parts[static::RESOURCE_CACHE_SUBSET_BASE])) ->merge(static::mergeCacheableDependencies($normalization_parts[static::RESOURCE_CACHE_SUBSET_FIELDS])) ->applyTo($data_as_render_array); diff --git a/core/modules/jsonapi/tests/src/Kernel/EventSubscriber/ResourceObjectNormalizerCacherTest.php b/core/modules/jsonapi/tests/src/Kernel/EventSubscriber/ResourceObjectNormalizerCacherTest.php new file mode 100644 index 000000000000..409cd783a20a --- /dev/null +++ b/core/modules/jsonapi/tests/src/Kernel/EventSubscriber/ResourceObjectNormalizerCacherTest.php @@ -0,0 +1,95 @@ +resourceTypeRepository = $this->container->get('jsonapi.resource_type.repository'); + $this->serializer = $this->container->get('jsonapi.serializer'); + $this->cacher = $this->container->get('jsonapi.normalization_cacher'); + } + + /** + * Tests that link normalization cache information is not lost. + * + * @see https://www.drupal.org/project/drupal/issues/3077287 + */ + public function testLinkNormalizationCacheability() { + $user = User::create([ + 'name' => $this->randomMachineName(), + 'pass' => $this->randomString(), + ]); + $resource_type = $this->resourceTypeRepository->get($user->getEntityTypeId(), $user->bundle()); + $resource_object = ResourceObject::createFromEntity($resource_type, $user); + $cache_tag_to_invalidate = 'link_normalization'; + $normalized_links = $this->serializer + ->normalize($resource_object->getLinks(), 'api_json') + ->withCacheableDependency((new CacheableMetadata())->addCacheTags([$cache_tag_to_invalidate])); + assert($normalized_links instanceof CacheableNormalization); + $normalization_parts = [ + ResourceObjectNormalizationCacher::RESOURCE_CACHE_SUBSET_BASE => [ + 'type' => CacheableNormalization::permanent($resource_object->getTypeName()), + 'id' => CacheableNormalization::permanent($resource_object->getId()), + 'links' => $normalized_links, + ], + ResourceObjectNormalizationCacher::RESOURCE_CACHE_SUBSET_FIELDS => [], + ]; + $this->cacher->saveOnTerminate($resource_object, $normalization_parts); + $event = $this->prophesize(PostResponseEvent::class); + $this->cacher->onTerminate($event->reveal()); + $this->assertNotFalse((bool) $this->cacher->get($resource_object)); + Cache::invalidateTags([$cache_tag_to_invalidate]); + $this->assertFalse((bool) $this->cacher->get($resource_object)); + } + +}