Problem/Motivation

Normally, when creating block plugins, one can return an #attributes from the build() method. If that happens, the attributes are being added to the block's wrapper.

It looks like this logic is located here: https://git.drupalcode.org/project/drupal/blob/8.8.x/core/modules/block/...

It doesn't work if the block has been put inside the layout, through the layout_builder. I consider it a bug, as anyone would expect the same behavior here, and it will surely break some custom plugin blocks relying on this feature.

Proposed resolution

Apply the same logic inside the BlockComponentRenderArray as it is in the BlockViewBuilder, to make #attributes work with the layout_builder.

Remaining tasks

Review the patch.

API changes

If anyone used #attributes to put attributes in the content of their block, instead of the block's wrapper, this change will probably break something for him. The weight of this issue is reduced by the fact, that this person would have to create this block plugin only to work in the layout builder, as outside of it, he would quickly notice that it doesn't work as expected.

Issue fork drupal-3077734

Command icon Show commands

Start within a Git clone of the project using the version control instructions.

Or, if you do not have SSH keys set up on git.drupalcode.org:

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

Luke_Nuke created an issue. See original summary.

Luke_Nuke’s picture

I attached two patches. One with test, testing the buggy scenario, which should fail. And the fix, also containing the same test, but it should pass it.

The last submitted patch, 2: plugin-block-attributes-test-3077734-2.patch, failed testing. View results

Luke_Nuke’s picture

Improved patch. I added the same checks that can be find in BlockViewBuilder. BTW There is something very wrong, that this logic is basically copied from another class. Some DRY issue is here.

tim.plunkett’s picture

Issue tags: +Blocks-Layouts, +Needs tests

Agreed with the concerns of #4

Version: 8.8.x-dev » 8.9.x-dev

Drupal 8.8.0-alpha1 will be released the week of October 14th, 2019, which means new developments and disruptive changes should now be targeted against the 8.9.x-dev branch. (Any changes to 8.9.x will also be committed to 9.0.x in preparation for Drupal 9’s release, but some changes like significant feature additions will be deferred to 9.1.x.). For more information see the Drupal 8 and 9 minor version schedule and the Allowed changes during the Drupal 8 and 9 release cycles.

Petr Illek’s picture

I've recreated/rerolled the patch against 8.9.x as it wasn't working for 8.8.x-rc1.

Status: Needs review » Needs work

The last submitted patch, 7: plugin-block-attributes-fix-3077734-6.patch, failed testing. View results
- codesniffer_fixes.patch Interdiff of automated coding standards fixes only.

kyberman’s picture

I tested the latest patch and it solves my problem. It would be great to have that merged.

We are facing missing attributes placed by entity_class_formatter module implementation (using hook_entity_view_alter() to set attributes), when custom blocks are inserted into Layout Builder. As a workaround, I created a patch to transfer missing attributes, but it's not really a general solution: https://www.drupal.org/project/entity_class_formatter/issues/3108054

hash6’s picture

Assigned: Unassigned » hash6
kyberman’s picture

Status: Needs work » Needs review
FileSize
4.74 KB

Patch inside comment #7 failed only because the test block plugin was in the wrong folder.
Here is a fixed patch against 8.9.x.

tim.plunkett’s picture

Title: Plugin blocks cannot set their own attributes when put in the layout. » Plugin blocks cannot set their own attributes when put in the layout
Assigned: hash6 » Unassigned
Issue tags: -Needs tests

Thanks for the patch!

  1. +++ b/core/modules/layout_builder/src/EventSubscriber/BlockComponentRenderArray.php
    @@ -124,9 +124,29 @@ public function onBuildRender(SectionComponentBuildRenderArrayEvent $event) {
    +      if ($content !== NULL && !Element::isEmpty($content)) {
    

    The result of BlockPluginInterface::build() is always an array, and isEmpty() is already called above, this whole line can be

    if (!$is_content_empty) {
    
  2. +++ b/core/modules/layout_builder/src/EventSubscriber/BlockComponentRenderArray.php
    @@ -124,9 +124,29 @@ public function onBuildRender(SectionComponentBuildRenderArrayEvent $event) {
    +        // Place the $content returned by the block plugin into a 'content' child
    +        // element, as a way to allow the plugin to have complete control of its
    +        // properties and rendering (for instance, its own #theme) without
    +        // conflicting with the properties used above, or alternate ones used by
    +        // alternate block rendering approaches in contrib (for instance, Panels).
    +        // However, the use of a child element is an implementation detail of this
    +        // particular block rendering approach. Semantically, the content returned
    +        // by the plugin "is the" block, and in particular, #attributes
    +        // is information about the *entire* block. Therefore, we must move this
    +        // property from $content and merge them into the top-level element.
    

    This comment needs to be rewrapped. References to specific contrib modules should be removed. Mixing styles like "is the" and *entire* is odd, neither are found in core AFAIK.

  3. +++ b/core/modules/layout_builder/src/EventSubscriber/BlockComponentRenderArray.php
    @@ -124,9 +124,29 @@ public function onBuildRender(SectionComponentBuildRenderArrayEvent $event) {
    +        foreach (['#attributes'] as $property) {
    

    Why the foreach loop for a single property? Is this expected to be expanded later?

  4. +++ b/core/modules/layout_builder/tests/src/Functional/LayoutBuilderTest.php
    @@ -580,6 +580,34 @@ public function testPluginDependencies() {
    +   * Tests if plugins can provide custom attributes, just like outside of the layout_builder.
    

    Shorten to 80 char. Remove everything after the , and clarify that it is testing a block plugin?

kyberman’s picture

Thank you Tim for your guidance! Firstly it was only a quick fix.

I'm also thinking about merging the existing values there (if available), rather than destroying them. What do you think?

  if (isset($content['#attributes'])) {
-   $build['#attributes'] = $content['#attributes'];
+   $build['#attributes'] = array_merge_recursive($build['#attributes'], $content['#attributes']);
    unset($content['#attributes']);
  }

Version: 8.9.x-dev » 9.1.x-dev

Drupal 8.9.0-beta1 was released on March 20, 2020. 8.9.x is the final, long-term support (LTS) minor release of Drupal 8, which means new developments and disruptive changes should now be targeted against the 9.1.x-dev branch. For more information see the Drupal 8 and 9 minor version schedule and the Allowed changes during the Drupal 8 and 9 release cycles.

tim.plunkett’s picture

Status: Needs review » Needs work

Please include an interdiff when making changes to an existing patch, to help others review your changes.

This issue seems similar to #3135899: Layout Builder does not seem to work with Entity Class Formatter and #3072231: Custom blocks break layout builder module - Quick Edit could not associate the rendered entity field markup, perhaps they can be combined?

Grayle’s picture

Just a combo patch of this issue and this one: https://www.drupal.org/project/drupal/issues/3020876

Both change the same lines, so uploaded combo patch here for composer. Please ignore, has no bearing on the issue at hand. Just need it now.

kkalashnikov’s picture

Patch #13 is successfully applied for Drupal 9.1.

@kyberman, It would be helpful for reviewing if you will update interdiff.

Version: 9.1.x-dev » 9.2.x-dev

Drupal 9.1.0-alpha1 will be released the week of October 19, 2020, which means new developments and disruptive changes should now be targeted for the 9.2.x-dev branch. For more information see the Drupal 9 minor version schedule and the Allowed changes during the Drupal 9 release cycle.

mohit_aghera’s picture

Combining both the patches here in case someone needs it.
https://www.drupal.org/project/drupal/issues/3020876#comment-14051592

I think we can take forward the other issue and may be close to this one.

volkswagenchick’s picture

Adding NorthAmerica2021 and Easy Out of the Box tags for visibility.
DrupalCon NA is April 12-16 with a focus on EOOTB on Wednesday, April 14.
Thanks

Suresh Prabhu Parkala’s picture

Status: Needs work » Needs review
FileSize
4.61 KB

Just a re-roll against the latest 9.2.x.

Version: 9.2.x-dev » 9.3.x-dev

Drupal 9.2.0-alpha1 will be released the week of May 3, 2021, which means new developments and disruptive changes should now be targeted for the 9.3.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

brentgees made their first commit to this issue’s fork.

brentg’s picture

Status: Needs review » Needs work

Quickly rerolled the patch for 9.3, tests probably needs adapting since a lot on this has changed in the other issue

Version: 9.3.x-dev » 9.4.x-dev

Drupal 9.3.0-rc1 was released on November 26, 2021, which means new developments and disruptive changes should now be targeted for the 9.4.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

BramDriesen’s picture

The merge request applies cleanly on 9.3.0. Not sure what is needed to get this to RTBC.

mohit_aghera’s picture

Status: Needs work » Needs review
tim.plunkett’s picture

Version: 9.4.x-dev » 9.5.x-dev

Drupal 9.4.0-alpha1 was released on May 6, 2022, which means new developments and disruptive changes should now be targeted for the 9.5.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

Version: 9.5.x-dev » 10.1.x-dev

Drupal 9.5.0-beta2 and Drupal 10.0.0-beta2 were released on September 29, 2022, which means new developments and disruptive changes should now be targeted for the 10.1.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

smustgrave’s picture

Status: Needs review » Needs work
Issue tags: +Needs Review Queue Initiative

As mentioned in #29 the MR seems to be missing some files. And there is an open thread on the 1 file added.

nginex made their first commit to this issue’s fork.

nginex’s picture

Status: Needs work » Needs review
FileSize
2.67 KB

I've removed duplciate for this line below.

$build['content'] = $content;

Besides, the tests from #13 are already in drupal core 9.3.x, so that's why you don't see new files in the MR.

I've also created a static patch for those who does not like when patch from MR does not apply anymore due to new commits.

smustgrave’s picture

Status: Needs review » Needs work

So if the tests were already added and they didn't catch this bug then I think the tests may not have been covering this bug. So we will need a failing test case to show this is still an issue I believe.

nginex’s picture

@smustgrave, you can check #3077734-2: Plugin blocks cannot set their own attributes when put in the layout comment, there are two patches, first patch contains only tests without the fix and it failed, second patch contains the fix + tests and it successed.

Would you expect to have one more test scenario that will fail, something like this?

$assert_session->elementNotExists('css', '.attribute-test-class');
$assert_session->elementNotExists('css', '[custom-attribute=test]');
$assert_session->elementNotExists('css', 'div[data-contextual-id*="layout_builder_test"]');

So if the fix is not working then test will be passed.

I'm not sure what else we can add here

BramDriesen’s picture

Status: Needs work » Needs review

I think #2 was just overlooked. Setting it back to NR for that matter.

smustgrave’s picture

Status: Needs review » Needs work

The test-only patch from #2

One file is already in drupal core
The other is not but also contains deprecated function calls.

The MR and patch #34 do not contain any tests. Would expect a full patch to contain the tests also.

nginex’s picture

Status: Needs work » Needs review

@smustgrave, you can find that the tests exist and already commited in 9.2.x, 9.3.x almost 2 years ago.

#3020876-68: Contextual links of reusable content blocks are not displayed when rendering entities built via Layout Builder,

that's why you can't see tests in the MR.

smustgrave’s picture

Then the tests weren't covering this bug or they would be failing on without this fix. So either this is a non issue now or we need new tests.

nginex’s picture

smustgrave’s picture

Can you see if the fix from that one solves the problem here? Could be the same issue and just 2 different approaches being taken.

smustgrave’s picture

Posted in the #bugsmash channel on slack too

nginex’s picture

It's indeed seems like a duplicate of #3020876: Contextual links of reusable content blocks are not displayed when rendering entities built via Layout Builder, the only difference is that here we have an extra condition

if (!$is_content_empty) { }

Honestly, that extra condition does not affect on functionality, at least the tests that cover block attributes change from #3020876: Contextual links of reusable content blocks are not displayed when rendering entities built via Layout Builder are passed.

I would closed this as duplicate, but I need one more confirmation of this theory

smustgrave’s picture

Status: Needs review » Closed (duplicate)

Looking at this again I do think it's a duplicate. Closing this out for the other and will move over credit.

Thanks!