Problem/Motivation

The block_field formatters don't propagate the access cacheability metadata properly.

This can cause problems, for example, if the referenced block is automatically generated (as a derivative) from an entity that can be unpublished. In such cases, when you unpublish the entity the cache should be invalidated but it doesn't.

Proposed resolution

Simply apply the cacheability metadata from the access object to the render array when appropriate on the formatter classes.

CommentFileSizeAuthor
#27 interdiff-26-27.txt3.49 KBsardara
#27 3114053-27.patch13.33 KBsardara
#26 interdiff-25-26.txt8.14 KBsardara
#26 3114053-26.patch13.38 KBsardara
#25 interdiff.txt11.44 KBpaulocs
#25 3114053-25.patch5.23 KBpaulocs
#22 3114053-22.patch14.52 KBpaulocs
#21 3114053-21.patch6.4 KBpaulocs
#18 interdiff_16_18.txt1.71 KBieguskiza
#18 interdiff_16_18-test-only.txt1.71 KBieguskiza
#18 3114053-18-3068281.patch14.49 KBieguskiza
#18 3114053-18.patch13.29 KBieguskiza
#18 3114053-18-test-only.patch11.54 KBieguskiza
#16 interdiff_15_16.txt502 bytesieguskiza
#16 interdiff_15-16-test-only.txt502 bytesieguskiza
#16 3114053-16-3068281.patch14.46 KBieguskiza
#16 3114053-16.patch13.25 KBieguskiza
#16 3114053-16-test-only.patch11.51 KBieguskiza
#15 interdiff_11_15.patch2.47 KBieguskiza
#15 interdiff_11_15-test-only.txt2.47 KBieguskiza
#15 3114053-15-3068281.patch14.46 KBieguskiza
#15 3114053-15.patch13.26 KBieguskiza
#15 3114053-15-test-only.patch11.51 KBieguskiza
#12 3114053-12-3068281.patch14.67 KBieguskiza
#11 interdiff_6_11-test-only.txt5.23 KBieguskiza
#11 interdiff_6_11.txt5.23 KBieguskiza
#11 3114053-11-3068281.patch14.71 KBieguskiza
#11 3114053-11.patch13.47 KBieguskiza
#11 3114053-11-test-only.patch11.72 KBieguskiza
#6 interdiff_5_6.txt2.87 KBieguskiza
#6 interdiff_5_6-test-only.txt2.87 KBieguskiza
#6 3114053-6.patch13.21 KBieguskiza
#6 3114053-6-test-only.patch11.46 KBieguskiza
#5 interdiff_3_5.txt4.43 KBieguskiza
#5 3114053-5.patch11.85 KBieguskiza
#5 3114053-5-test-only.patch10.1 KBieguskiza
#2 3114053-2.patch12.72 KBieguskiza
#2 3114053-2-test-only.patch10.97 KBieguskiza
Support from Acquia helps fund testing for Drupal Acquia logo

Comments

ieguskiza created an issue. See original summary.

Chewie’s picture

I have tested this patch together with https://www.drupal.org/project/block_field/issues/3114056
Fix and tests looks good!
Just 2 questions:
- Why we didn't include this fix also in these changes (https://www.drupal.org/project/block_field/issues/3114056) issue for make testing simpler.
- little question regarding this part:

+++ b/tests/src/Kernel/BlockFieldFormatterTest.php
@@ -0,0 +1,102 @@
+    // Use Classy theme for testing markup output.
+    \Drupal::service('theme_installer')->install(['classy']);
+    $this->config('system.theme')->set('default', 'classy')->save();
+    $this->installEntitySchema('entity_test');
+    // Grant the 'view test entity' permission.
+    $this->installConfig(['user']);
+    Role::load(RoleInterface::ANONYMOUS_ID)
+      ->grantPermission('view test entity')
+      ->save();
+
+    // The label formatter rendering generates links, so build the router.
+    $this->container->get('router.builder')->rebuild();

Are we really need this part of setUp()?

Chewie’s picture

+++ b/tests/modules/block_field_access_test/src/Plugin/Block/BlockFieldAccessTestBlock.php
@@ -0,0 +1,36 @@
+namespace Drupal\block_field_access_test\Plugin\Block;

Maybe it is simpler to use the existing test module 'block_field_test' and implement the plugin in the existing one.

ieguskiza’s picture

I took your comments into account @chewie and provided a new set of patches.

ieguskiza’s picture

It was mentioned to me that we should also make sure the tags are propagated if the access is denied. I made some adjustments to the kernel test to take this into consideration. I attach the new patches with the interdiffs.

Chewie’s picture

Changes looks good.
But first should be merged this issue: https://www.drupal.org/project/block_field/issues/3068281

sardara’s picture

  1. +++ b/tests/src/Functional/BlockFieldTest.php
    @@ -29,6 +30,13 @@ class BlockFieldTest extends BrowserTestBase {
    +
    

    Nit: remove empty line.

  2. +++ b/tests/src/Functional/BlockFieldTest.php
    @@ -70,6 +79,15 @@ class BlockFieldTest extends BrowserTestBase {
    +    $element = $this->getSession()->getPage()->find('css', $selector);
    

    $element is not used.

  3. +++ b/tests/src/Functional/BlockFieldTest.php
    @@ -70,6 +79,15 @@ class BlockFieldTest extends BrowserTestBase {
    +    // Check that a referenced block that is no longer available is not visible.
    

    The comment could be improved, the block is still available, it's just unpublished.

  4. +++ b/tests/src/Functional/BlockFieldTest.php
    @@ -114,6 +132,26 @@ class BlockFieldTest extends BrowserTestBase {
    +    // When the blocks is not available anonymous users can't see it.
    

    Again, let's talk about visibility/published and not availability.

  5. +++ b/tests/src/Functional/BlockFieldTest.php
    @@ -114,6 +132,26 @@ class BlockFieldTest extends BrowserTestBase {
    +    // enabling it and checking if it is available for anonymous users.
    

    Same here.

  6. +++ b/tests/src/Kernel/BlockFieldFormatterTest.php
    @@ -0,0 +1,112 @@
    +  protected $entityType = 'entity_test';
    

    I don't think we should use class properties for these. For example, in the test method you end up creating a local variable for $fieldName, which outlines how we don't need these. Let's just use the strings around.

  7. +++ b/tests/modules/block_field_test/src/Plugin/Block/BlockFieldAccessTestBlock.php
    @@ -0,0 +1,65 @@
    +      '#markup' => '<div> Custom access tag. </div>>',
    

    Nit: double > at the end.

  8. +++ b/tests/modules/block_field_test/src/Plugin/Block/BlockFieldAccessTestBlock.php
    @@ -0,0 +1,65 @@
    +    return AccessResult::allowedif($this->configuration['access'])->addCacheTags(['custom_tag']);
    

    AllowedIf (capital I)

  9. +++ b/tests/src/Kernel/BlockFieldFormatterTest.php
    @@ -0,0 +1,112 @@
    +      $this->assertEqual($build['#cache']['tags'], ['custom_tag']);
    

    assertEquals()

  10. +++ b/tests/src/Kernel/BlockFieldFormatterTest.php
    @@ -0,0 +1,112 @@
    +      $this->assertEqual($build['#cache']['tags'], ['custom_tag']);
    

    assertEquals()

  11. +++ b/tests/src/Kernel/BlockFieldFormatterTest.php
    @@ -0,0 +1,112 @@
    +    }
    

    Nit: empty line after function closing bracket.

  12. +++ b/tests/src/Kernel/BlockFieldFormatterTest.php
    @@ -0,0 +1,112 @@
    +
    

    Nit: remove empty line.

  13. +++ b/tests/src/Kernel/BlockFieldFormatterTest.php
    @@ -0,0 +1,112 @@
    +      $renderer->renderRoot($build);
    

    To make sure that our block is working well, let's assert that the rendered markup contains or doesn't contain the label.
    In order to render the block properly, make sure to include the block module in the list of modules above.
    Also, add an extra message in the loops assertions to understand on which formatter they would be failing.

We could have used the block_content module to make this test, but I have noticed that the block label formatter would return only one cache tag (block_content:) while the other formatter would return also the list cache tag. We can keep our custom block for ease of test.

sardara’s picture

Status: Needs review » Needs work
sardara’s picture

Since the tests cannot be green unless #3068281: BlockFieldLabelFormatter CacheableMetadata::createFromRenderArray points to incorrect array is merged first, add here a patch that includes the other one too, so we see the tests are green.

ieguskiza’s picture

Hi @sardara,
thanks for the input. I fixed all the comments you had and as you proposed I add a new patch that merges the two solutions to showcase everything being green.

ieguskiza’s picture

Reupload of the patch that contains both solutions using the backwards compatible code.

ieguskiza’s picture

Status: Needs work » Needs review
sardara’s picture

Status: Needs review » Needs work
+++ b/tests/src/Kernel/BlockFieldFormatterTest.php
@@ -0,0 +1,102 @@
+  protected $fieldName = 'field_test';

Let's remove also this property, like the others.
There are also some double empty lines, let's clear those and for me we are good to go.

ieguskiza’s picture

Status: Needs work » Needs review
FileSize
11.51 KB
13.26 KB
14.46 KB
2.47 KB
2.47 KB

Fixed the latest comments, attached are all the patches and interdiffs.

sardara’s picture

Status: Needs review » Needs work
  1. +++ b/tests/src/Kernel/BlockFieldFormatterTest.php
    @@ -0,0 +1,91 @@
    +   */
    

    We can use @inheritdoc here.

  2. +++ b/tests/src/Kernel/BlockFieldFormatterTest.php
    @@ -0,0 +1,91 @@
    +  protected function setUp() {
    

    Missing @inheritdoc.

  3. +++ b/tests/src/Kernel/BlockFieldFormatterTest.php
    @@ -0,0 +1,91 @@
    +   * Assert access tags are propagated.
    

    Let's use "Tests that block access cache metadata is propagated".
    Also the method name, let's use "testBlockAccessCacheMetadata" or similar.

  4. +++ b/tests/src/Kernel/BlockFieldFormatterTest.php
    @@ -0,0 +1,91 @@
    +      // Assert block contents are properly rendered.
    

    We are asserting that they are not rendered here.

  5. +++ b/tests/src/Functional/BlockFieldTest.php
    @@ -70,6 +78,14 @@ class BlockFieldTest extends BrowserTestBase {
    +
    

    Double empty line.

ieguskiza’s picture

sardara’s picture

Assigned: ieguskiza » Unassigned
Status: Needs review » Reviewed & tested by the community

Good for me! Moving to RTBC.

Berdir’s picture

Status: Reviewed & tested by the community » Needs work

This will need a an update after the Drupal 9 patch has been committed.

paulocs’s picture

Status: Needs work » Needs review
FileSize
6.4 KB

Patch re-rolled.

paulocs’s picture

Patch #21 is wrong.

Attaching new one.

Berdir’s picture

Status: Needs review » Needs work

Looks good to me, great test coverage. However, it already needs another reroll due to the coding standard changes I think.

Berdir’s picture

This also contained the fix for #3068281: BlockFieldLabelFormatter CacheableMetadata::createFromRenderArray points to incorrect array but I think without test coverage for that unlike the other issue, so I committed that one, another thing to check when rerolling.

paulocs’s picture

Status: Needs work » Needs review
FileSize
5.23 KB
11.44 KB

Attached a new patch.

sardara’s picture

Latest uploaded re-roll is missing some of the original test coverage.

sardara’s picture

Missed the coding standards fixes.

paulocs’s picture

Status: Needs review » Reviewed & tested by the community

Patch looks good to me!

  • paulocs committed 9d4b676 on 8.x-1.x authored by sardara
    Issue #3114053 by ieguskiza, paulocs, sardara, Berdir, Chewie: Access...
paulocs’s picture

Status: Reviewed & tested by the community » Fixed

Fixed in dev branch.

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.