You are here

public function LayoutBuilderIntegration::entityViewAlter in Drupal 10

Alters the entity view build for Layout Builder compatibility.

When rendering fields outside of normal view modes, Quick Edit requires that modules identify themselves with a view mode ID in the format [module_name]-[information the module needs to rerender], as prescribed by hook_quickedit_render_field().

Parameters

array $build: The built entity render array.

\Drupal\Core\Entity\EntityInterface $entity: The entity.

\Drupal\Core\Entity\Display\EntityViewDisplayInterface $display: The entity view display.

See also

hook_quickedit_render_field()

layout_builder_quickedit_render_field()

File

core/modules/quickedit/src/LayoutBuilderIntegration.php, line 97

Class

LayoutBuilderIntegration
Helper methods for Layout Builder module integration.

Namespace

Drupal\quickedit

Code

public function entityViewAlter(array &$build, EntityInterface $entity, EntityViewDisplayInterface $display) {
  if (!$entity instanceof FieldableEntityInterface || !isset($build['_layout_builder'])) {
    return;
  }
  $build['#cache']['contexts'][] = 'user.permissions';
  if (!$this->currentUser
    ->hasPermission('access in-place editing')) {
    return;
  }
  $cacheable_metadata = CacheableMetadata::createFromRenderArray($build);
  $section_list = $this->sectionStorageManager
    ->findByContext([
    'display' => EntityContext::fromEntity($display),
    'entity' => EntityContext::fromEntity($entity),
    'view_mode' => new Context(new ContextDefinition('string'), $display
      ->getMode()),
  ], $cacheable_metadata);
  $cacheable_metadata
    ->applyTo($build);
  if (empty($section_list)) {
    return;
  }

  // Create a hash of the sections and use it in the unique Quick Edit view
  // mode ID. Any changes to the sections will result in a different hash,
  // forcing Quick Edit's JavaScript to recognize any changes and retrieve
  // up-to-date metadata.
  $sections_hash = hash('sha256', serialize($section_list
    ->getSections()));

  // Track each component by their plugin ID, delta, region, and UUID.
  $plugin_ids_to_update = [];
  foreach (Element::children($build['_layout_builder']) as $delta) {
    $section = $build['_layout_builder'][$delta];
    if (!Element::isEmpty($section)) {

      /** @var \Drupal\Core\Layout\LayoutDefinition $layout */
      $layout = $section['#layout'];
      $regions = $layout
        ->getRegionNames();
      foreach ($regions as $region) {
        if (isset($section[$region])) {
          foreach ($section[$region] as $uuid => $component) {
            if (isset($component['#plugin_id']) && $this
              ->supportQuickEditOnComponent($component, $entity)) {
              $plugin_ids_to_update[$component['#plugin_id']][$delta][$region][$uuid] = $uuid;
            }
          }
        }
      }
    }
  }

  // @todo Remove when https://www.drupal.org/node/3041850 is resolved.
  $plugin_ids_to_update = array_filter($plugin_ids_to_update, function ($info) {

    // Delta, region, and UUID each count as one.
    return count($info, COUNT_RECURSIVE) === 3;
  });
  $plugin_ids_to_update = NestedArray::mergeDeepArray($plugin_ids_to_update, TRUE);
  foreach ($plugin_ids_to_update as $delta => $regions) {
    foreach ($regions as $region => $uuids) {
      foreach ($uuids as $uuid => $component) {
        $build['_layout_builder'][$delta][$region][$uuid]['content']['#view_mode'] = static::getViewModeId($entity, $display, $delta, $uuid, $sections_hash);
      }
    }
  }

  // Alter the Quick Edit view mode ID of all fields outside of the Layout
  // Builder sections to force Quick Edit to request to the field metadata.
  // @todo Remove this logic in https://www.drupal.org/project/node/2966136.
  foreach (Element::children($build) as $field_name) {
    if ($field_name !== '_layout_builder') {
      $field_build =& $build[$field_name];
      if (isset($field_build['#view_mode'])) {
        $field_build['#view_mode'] = "layout_builder-{$display->getMode()}-non_component-{$sections_hash}";
      }
    }
  }
}