Problem/Motivation

When adding blocks as context reactions, the blocks from category "Inline blocks" throw ajax error:

TypeError: Drupal\Component\Utility\NestedArray::getValue(): Argument #1 ($array) must be of type array, null given, called in /app/docroot/core/lib/Drupal/Core/Field/WidgetBase.php on line 426 in Drupal\Component\Utility\NestedArray::getValue() (line 69 of /app/docroot/core/lib/Drupal/Component/Utility/NestedArray.php).

Steps to reproduce

Create custom block type, create context and try to add the Inline block as a context reaction.

Proposed resolution

There are two possible options here:
1. Resolve the issue and allow Inline blocks to be created as part of the Block reaction.
2. Remove Inline blocks from the available list.

If we go with option 2, solution is to use the core's getFilteredDefinitions method to get the list of available blocks like it is used in \Drupal\block\Controller\BlockLibraryController.

Remaining tasks

Determine if the module should support inline blocks or hide them from the list.

Comments

yivanov created an issue. See original summary.

yivanov’s picture

Issue summary: View changes
yivanov’s picture

StatusFileSize
new911 bytes

Replaced the getDefinitionsForContexts with getFilteredDefinitions and added "context" as consumer, which will allow then further filtering by other modules with following hooks:

hook_plugin_filter_TYPE_alter()
hook_plugin_filter_TYPE__CONSUMER_alter()
davidlordwinc’s picture

StatusFileSize
new3.41 KB
new2.31 KB

Here is a fix for option 1, supporting inline blocks instead of hiding them. On 5.0.0-rc2, inline blocks hit three defects in sequence. Each one is only visible after the previous one is fixed.

1. Validation crashes. This is the error in the summary. BlockFormBase::validateForm() validates the plugin with a new, empty FormState:

$settings = (new FormState())->setValues($form_state->getValue('settings'));

InlineBlock::blockValidate() validates a full block_content entity form and needs the complete form to flag widget errors, so WidgetBase::flagErrors() receives NULL. The throwaway state also drops the block_form_parents temporary value that blockSubmit() reads later. context-inline-block-validate-subformstate.patch uses SubformState::createForSubform(), as submitForm() in the same class already does. The loop that copied errors by hand is removed, because SubformState already reports them on the parent form with the right names.

2. Saving the context afterwards returns HTTP 500. This is the general problem of #3218342, where I posted the fix.

3. The block is saved but never renders. No error, nothing in the log. BlockContentAccessControlHandler forbids non-reusable block content without an access dependency: "Non-reusable blocks must set an access dependency for access control." Layout Builder sets the entity that owns the layout as the dependency. Context sets nothing. A context has no host entity: the block lives in the context's own configuration, and the context's conditions already decided that it belongs on the page. context-inline-block-access-dependency.patch adds ContextBlockAccessAllowed, modeled on core's LayoutPreviewAccessAllowed and allowing only view. Blocks::execute() assigns it when the plugin has no dependency yet.

With these two patches and the one in #3218342, an inline block can be created, the context can be saved, and the block renders for anonymous users. The configuration export carries the whole block in block_serialized, with block_revision_id: null, so it deploys with the context.

Steps to reproduce

  1. Enable context, context_ui, block_content and layout_builder, with a "basic" block type that has a body field.
  2. Create a context with any condition and a Blocks reaction.
  3. Click "Place block", choose "Basic block" in the Inline blocks category, fill in the title and the body, and click "Add block".
  4. Result: "Oops, something went wrong", and the TypeError from the summary in the log.

Tested on Drupal 11.3.11 with 5.0.0-rc2. Both patches apply cleanly to 5.x.