Problem/Motivation

FieldBlock::getFormatterOptions() is intended to limit the Formatter select to formatters that apply to the selected field, but the current applicability check never works.

$definition = $this->formatterPluginManager->getDefinition($id, FALSE);
$formatter_plugin_class = $definition['class'] ?? NULL;
$applicable = $formatter_plugin_class instanceof FormatterInterface && $formatter_plugin_class::isApplicable($field_definition);
if ($applicable) {
  unset($options[$id]);
}

$definition['class'] is a class-name string, so the instanceof check is always FALSE. The condition is also inverted and would remove applicable formatters rather than inapplicable ones.

FormatterPluginManager::getOptions() only filters by field type, so formatters with additional applicability requirements are still offered.

For example, on a Drupal 11 standard install:

  • An entity reference field pointing to nodes offers the "Author" and "RSS category" formatters, even though those only apply to references to users and taxonomy terms respectively.
  • A plain string field can offer the "User name" formatter, which only applies to the user name base field.

Selecting one of these saves a formatter that cannot render the field. Core then silently falls back to the field type's default formatter, so the rendered block does not match its configuration.

Steps to reproduce

  1. Install Field as Block on a standard install.
  2. Add an entity reference field to the Article content type that references Content.
  3. Go to Block layout and place a "Content field" block.
  4. Select the new reference field.
  5. Observe that the Formatter select includes "Author" and "RSS category", neither of which applies to a field referencing nodes.

Proposed resolution

Filter out formatter plugins that are not applicable to the field definition, following the same approach used by core:

foreach (array_keys($options) as $id) {
  $definition = $this->formatterPluginManager->getDefinition($id, FALSE);
  $formatter_plugin_class = $definition['class'] ?? NULL;

  if (
    is_subclass_of($formatter_plugin_class, FormatterInterface::class)
    && !$formatter_plugin_class::isApplicable($field_definition)
  ) {
    unset($options[$id]);
  }
}

Add functional test coverage for the formatter options shown on the block configuration form.

Remaining tasks

  • Review the MR.

User interface changes

The Formatter select no longer lists formatters that do not apply to the selected field.

Existing blocks configured with an inapplicable formatter are unchanged. The formatter is no longer offered when editing the block, and core continues to fall back to the field type's default formatter when rendering existing configuration.

Issue fork fieldblock-3615375

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:

Comments

joelpittet created an issue. See original summary.

  • joelpittet committed 60cc2e08 on 8.x-2.x
    fix: #3615375 Formatter select offers formatters that do not apply to...
joelpittet’s picture

Status: Active » Fixed

Now that this issue is closed, review the contribution record.

As a contributor, attribute any organization that helped you, or if you volunteered your own time.

Maintainers, credit people who helped resolve this issue.

Status: Fixed » Closed (fixed)

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