diff --git a/core/lib/Drupal/Core/Entity/Display/EntityViewDisplayInterface.php b/core/lib/Drupal/Core/Entity/Display/EntityViewDisplayInterface.php index 8c7433c..3771d81 100644 --- a/core/lib/Drupal/Core/Entity/Display/EntityViewDisplayInterface.php +++ b/core/lib/Drupal/Core/Entity/Display/EntityViewDisplayInterface.php @@ -8,7 +8,6 @@ namespace Drupal\Core\Entity\Display; use Drupal\Core\Entity\FieldableEntityInterface; -use Drupal\Core\Field\FieldDefinitionInterface; /** * Provides a common interface for entity view displays. @@ -52,39 +51,4 @@ public function build(FieldableEntityInterface $entity); */ public function buildMultiple(array $entities); - /** - * Returns a renderable array for the specified field. - * - * @param \Drupal\Core\Entity\FieldableEntityInterface $entity - * The entity being displayed. - * @param \Drupal\Core\Field\FieldDefinitionInterface $field_definition - * The definition of the field to be displayed. - * @param string $type - * The formatter type. - * @param array $settings - * The formatter settings. - * - * @return array - * A renderable array for the field. - */ - public function buildField(FieldableEntityInterface $entity, FieldDefinitionInterface $field_definition, $type, $settings); - - /** - * Returns a renderable array for the specified field of a set of entities. - * - * @param \Drupal\Core\Entity\FieldableEntityInterface[] $entities - * The entities being displayed. - * @param \Drupal\Core\Field\FieldDefinitionInterface $field_definition - * The definition of the field to be displayed. - * @param string $type - * The formatter type. - * @param array $settings - * The formatter settings. - * - * @return array - * A renderable array for the field, indexed by the same keys as the - * $entities array parameter. - */ - public function buildFieldMultiple(array $entities, FieldDefinitionInterface $field_definition, $type, $settings); - } diff --git a/core/lib/Drupal/Core/Entity/Entity/EntityViewDisplay.php b/core/lib/Drupal/Core/Entity/Entity/EntityViewDisplay.php index f55f1c2..6712fb5 100644 --- a/core/lib/Drupal/Core/Entity/Entity/EntityViewDisplay.php +++ b/core/lib/Drupal/Core/Entity/Entity/EntityViewDisplay.php @@ -9,12 +9,10 @@ use Drupal\Component\Utility\NestedArray; use Drupal\Core\Entity\Display\EntityViewDisplayInterface; -use Drupal\Core\Entity\EntityDisplayBase; use Drupal\Core\Entity\EntityDisplayPluginCollection; use Drupal\Core\Entity\EntityStorageInterface; use Drupal\Core\Entity\FieldableEntityInterface; -use Drupal\Core\Field\FieldDefinitionInterface; -use Drupal\Core\Field\FormatterInterface; +use Drupal\Core\Entity\EntityDisplayBase; /** * Configuration entity that contains display options for all components of a @@ -227,9 +225,25 @@ public function buildMultiple(array $entities) { // Run field formatters. foreach ($this->getComponents() as $name => $options) { if ($formatter = $this->getRenderer($name)) { - foreach ($this->formatFieldMultiple($entities, $name, $formatter) as $key => $build) { - $build_list[$key][$name] = $build; - }; + // Group items across all entities and pass them to the formatter's + // prepareView() method. + $grouped_items = array(); + foreach ($entities as $id => $entity) { + $items = $entity->get($name); + $items->filterEmptyItems(); + $grouped_items[$id] = $items; + } + $formatter->prepareView($grouped_items); + + // Then let the formatter build the output for each entity. + foreach ($entities as $id => $entity) { + $items = $grouped_items[$id]; + /** @var \Drupal\Core\Access\AccessResultInterface $field_access */ + $field_access = $items->access('view', NULL, TRUE); + $build_list[$id][$name] = $field_access->isAllowed() ? $formatter->view($items) : []; + // Apply the field access cacheability metadata to the render array. + $this->renderer->addDependency($build_list[$id][$name], $field_access); + } } } @@ -254,76 +268,6 @@ public function buildMultiple(array $entities) { } /** - * Formats a field for multiple entities. - * - * @param \Drupal\Core\Entity\FieldableEntityInterface[] $entities - * The entities being displayed. - * @param string $field_name - * The name of the field to be formatted. - * @param \Drupal\Core\Field\FormatterInterface $formatter - * The field formatter to be used. - * - * @return array - * A renderable array, indexed by the same keys as the $entities array - * parameter. - */ - protected function formatFieldMultiple(array $entities, $field_name, FormatterInterface $formatter) { - $build_list = []; - - // Group items across all entities and pass them to the formatter's - // prepareView() method. - $grouped_items = []; - foreach ($entities as $index => $entity) { - $items = $entity->get($field_name); - $items->filterEmptyItems(); - $grouped_items[$index] = $items; - } - $formatter->prepareView($grouped_items); - - // Then let the formatter build the output for each entity. - foreach ($entities as $index => $entity) { - /** @var \Drupal\Core\Field\FieldItemListInterface $items */ - $items = $grouped_items[$index]; - $field_access = $items->access('view', NULL, TRUE); - $build_list[$index] = $field_access->isAllowed() ? $formatter->view($items) : []; - // Apply the field access cacheability metadata to the render array. - $this->renderer->addDependency($build_list[$index], $field_access); - } - - return $build_list; - } - - /** - * {@inheritdoc} - */ - public function buildField(FieldableEntityInterface $entity, FieldDefinitionInterface $field_definition, $type, $settings) { - $build_list = $this->buildFieldMultiple([$entity], $field_definition, $type, $settings); - return reset($build_list); - } - - /** - * {@inheritdoc} - */ - public function buildFieldMultiple(array $entities, FieldDefinitionInterface $field_definition, $type, $settings) { - $options = [ - 'field_definition' => $field_definition, - 'configuration' => array( - 'type' => $type, - 'settings' => $settings, - 'label' => 'hidden', - 'weight' => 0, - ), - 'view_mode' => static::CUSTOM_MODE, - ]; - /** @var \Drupal\Core\Field\FormatterInterface $formatter */ - if ($formatter = $this->pluginManager->getInstance($options)) { - return $this->formatFieldMultiple($entities, $field_definition->getName(), $formatter); - } - - return []; - } - - /** * {@inheritdoc} */ public function getPluginCollections() { diff --git a/core/modules/views/src/Entity/Render/EntityFieldRenderer.php b/core/modules/views/src/Entity/Render/EntityFieldRenderer.php index 1d004b1..08ebac2 100644 --- a/core/modules/views/src/Entity/Render/EntityFieldRenderer.php +++ b/core/modules/views/src/Entity/Render/EntityFieldRenderer.php @@ -134,35 +134,48 @@ protected function buildFields(array $values) { $fields_by_relationship[$field->options['relationship']][$field_id] = $field; } - // For each relationship and each result row, collect the entities to - // display, fetch the right translation, and group them by bundle. - $entities = []; + // Handle each relationship target separately, since they all operate on + // a different set of entities. foreach ($fields_by_relationship as $relationhip_id => $fields) { - $entities[$relationhip_id] = []; + // For each result row, collect the entities to display, fetch the right + // translation, and group them by bundle. + $entities_by_bundles = []; $field = current($fields); foreach ($values as $result_row) { $entity = $field->getEntity($result_row); - $entities[$relationhip_id][$entity->bundle()][$result_row->index] = $this->getEntityTranslation($entity, $result_row); + $entities_by_bundles[$entity->bundle()][$result_row->index] = $this->getEntityTranslation($entity, $result_row); } - foreach ($entities[$relationhip_id] as $bundle => $bundle_entities) { - // Create the Display. - $display = new EntityViewDisplay([ - 'targetEntityType' => $this->getEntityTypeId(), - 'bundle' => $bundle, - 'status' => TRUE, - ], 'entity_view_display'); - foreach ($fields as $field_id => $field) { - $display->setComponent($field->definition['field_name'], [ - 'type' => $field->options['type'], - 'settings' => $field->options['settings'], - ]); + // Build "layers" @todo explain + $layers = []; + foreach ($fields as $field_id => $field) { + $index = 0; + while (isset($layers[$index][$field->definition['field_name']])) { + $index++; } - // Let the Display do the rendering. - $display_build = $display->buildMultiple($bundle_entities); - foreach ($display_build as $row_index => $entity_build) { + $layers[$index][$field_id] = $field; + } + + foreach ($layers as $fields) { + foreach ($entities_by_bundles as $bundle => $bundle_entities) { + // Create the Display. + $display = new EntityViewDisplay([ + 'targetEntityType' => $this->getEntityTypeId(), + 'bundle' => $bundle, + 'status' => TRUE, + ], 'entity_view_display'); foreach ($fields as $field_id => $field) { - $build[$row_index][$field_id] = $entity_build[$field->definition['field_name']]; + $display->setComponent($field->definition['field_name'], [ + 'type' => $field->options['type'], + 'settings' => $field->options['settings'], + ]); + } + // Let the Display do the rendering. + $display_build = $display->buildMultiple($bundle_entities); + foreach ($display_build as $row_index => $entity_build) { + foreach ($fields as $field_id => $field) { + $build[$row_index][$field_id] = $entity_build[$field->definition['field_name']]; + } } } }