Verified Commit 4ba0eff8 authored by godotislate's avatar godotislate
Browse files

fix: #3252278 Complete JSON:API's handling of field (including computed &...

fix: #3252278 Complete JSON:API's handling of field (including computed & empty fields) cache metadata

By: tivi22
By: bbrala
By: bradjones1
By: br0ken
By: jan.stoeckler
By: duivw
By: tstoeckler
By: godotislate
(cherry picked from commit 16b32971)
parent e59c0b01
Loading
Loading
Loading
Loading
Loading
+7 −0
Original line number Diff line number Diff line
@@ -2,6 +2,7 @@

namespace Drupal\jsonapi\Normalizer;

use Drupal\Core\Cache\CacheableDependencyInterface;
use Drupal\Core\Cache\CacheableMetadata;
use Drupal\Core\Entity\EntityFieldManagerInterface;
use Drupal\Core\Entity\EntityTypeManagerInterface;
@@ -243,6 +244,12 @@ protected function serializeField($field, array $context, $format) {
        $normalized_field = $this->serializer->normalize($field, $format, $context);
      }
      assert($normalized_field instanceof CacheableNormalization);

      // Add cacheability metadata if field item list provides some.
      if ($field instanceof CacheableDependencyInterface) {
        $normalized_field = $normalized_field->withCacheableDependency($field);
      }

      return $normalized_field->withCacheableDependency(CacheableMetadata::createFromObject($field_access_result));
    }
    else {
+6 −0
Original line number Diff line number Diff line
@@ -180,6 +180,9 @@ protected function getExpectedCacheContexts(?array $sparse_fieldset = NULL) {
    if ($sparse_fieldset === NULL || in_array('computed_test_cacheable_string_field', $sparse_fieldset)) {
      $cache_contexts = Cache::mergeContexts($cache_contexts, ['url.query_args']);
    }
    if ($sparse_fieldset === NULL || in_array('computed_test_cacheable_integer_field', $sparse_fieldset)) {
      $cache_contexts = Cache::mergeContexts($cache_contexts, ['headers:X-computed_test_cacheable_integer_field=1']);
    }

    return $cache_contexts;
  }
@@ -192,6 +195,9 @@ protected function getExpectedCacheTags(?array $sparse_fieldset = NULL) {
    if ($sparse_fieldset === NULL || in_array('computed_test_cacheable_string_field', $sparse_fieldset)) {
      $expected_cache_tags = Cache::mergeTags($expected_cache_tags, ['field:computed_test_cacheable_string_field']);
    }
    if ($sparse_fieldset === NULL || in_array('computed_test_cacheable_integer_field', $sparse_fieldset)) {
      $expected_cache_tags = Cache::mergeTags($expected_cache_tags, ['field:computed_test_cacheable_integer_field']);
    }

    return $expected_cache_tags;
  }
+1 −0
Original line number Diff line number Diff line
@@ -587,6 +587,7 @@ protected static function getExpectedCollectionCacheability(AccountInterface $ac
                    $cacheability->addCacheableDependency(CacheableMetadata::createFromObject($property));
                  }
                }
                $cacheability->addCacheableDependency(CacheableMetadata::createFromObject($field_item_list));
              }
            }
          }
+1 −1
Original line number Diff line number Diff line
@@ -28,7 +28,7 @@ protected function computeValue() {
    $value = \Drupal::state()->get('entity_test_computed_integer_value', 0);
    $item = $this->createItem(0, $value);
    $cacheability = (new CacheableMetadata())
      ->setCacheContexts(['url.query_args:computed_test_cacheable_integer_field'])
      ->setCacheContexts(['headers:X-computed_test_cacheable_integer_field=1'])
      ->setCacheTags(['field:computed_test_cacheable_integer_field'])
      ->setCacheMaxAge(31536000);
    $this->setCacheability($cacheability);
+3 −3
Original line number Diff line number Diff line
@@ -59,21 +59,21 @@ public function testFormatterComputedFieldCacheableMetadata(): void {
    $this->drupalGet($entity->toUrl('canonical')->toString());
    $field_item_selector = '.field--name-computed-test-cacheable-integer-field .field__item';
    $this->assertSession()->elementTextEquals('css', $field_item_selector, '2024');
    $this->assertSession()->responseHeaderContains('X-Drupal-Cache-Contexts', 'url.query_args:computed_test_cacheable_integer_field');
    $this->assertSession()->responseHeaderContains('X-Drupal-Cache-Contexts', 'headers:X-computed_test_cacheable_integer_field=1');
    $this->assertSession()->responseHeaderContains('X-Drupal-Cache-Tags', 'field:computed_test_cacheable_integer_field');
    $this->assertSession()->responseHeaderEquals('X-Drupal-Cache-Max-Age', "31536000");

    $this->state->set('entity_test_computed_integer_value', 2025);
    $this->drupalGet($entity->toUrl('canonical')->toString());
    $this->assertSession()->elementTextEquals('css', $field_item_selector, '2024');
    $this->assertSession()->responseHeaderContains('X-Drupal-Cache-Contexts', 'url.query_args:computed_test_cacheable_integer_field');
    $this->assertSession()->responseHeaderContains('X-Drupal-Cache-Contexts', 'headers:X-computed_test_cacheable_integer_field=1');
    $this->assertSession()->responseHeaderContains('X-Drupal-Cache-Tags', 'field:computed_test_cacheable_integer_field');
    $this->assertSession()->responseHeaderEquals('X-Drupal-Cache-Max-Age', "31536000");

    Cache::invalidateTags(['field:computed_test_cacheable_integer_field']);
    $this->drupalGet($entity->toUrl('canonical')->toString());
    $this->assertSession()->elementTextEquals('css', $field_item_selector, '2025');
    $this->assertSession()->responseHeaderContains('X-Drupal-Cache-Contexts', 'url.query_args:computed_test_cacheable_integer_field');
    $this->assertSession()->responseHeaderContains('X-Drupal-Cache-Contexts', 'headers:X-computed_test_cacheable_integer_field=1');
    $this->assertSession()->responseHeaderContains('X-Drupal-Cache-Tags', 'field:computed_test_cacheable_integer_field');
    $this->assertSession()->responseHeaderEquals('X-Drupal-Cache-Max-Age', "31536000");
  }