diff --git a/core/lib/Drupal/Core/Entity/EntityViewBuilder.php b/core/lib/Drupal/Core/Entity/EntityViewBuilder.php index fb19c4e..7b8f993 100644 --- a/core/lib/Drupal/Core/Entity/EntityViewBuilder.php +++ b/core/lib/Drupal/Core/Entity/EntityViewBuilder.php @@ -12,6 +12,7 @@ use Drupal\Core\Extension\ModuleHandlerInterface; use Drupal\Core\Language\Language; use Drupal\Core\Language\LanguageManagerInterface; +use Drupal\Core\Render\Element; use Symfony\Component\DependencyInjection\ContainerInterface; /** @@ -132,12 +133,20 @@ public function buildContent(array $entities, array $displays, $view_mode, $lang * * @return array */ - protected function getBuildDefaults(EntityInterface $entity, $view_mode, $langcode) { - $return = array( + protected function getBuildDefaults(EntityInterface $entity, $view_mode = 'full', $langcode) { + $that = $this; + // Create a closure that uses the current execution context object as its + // invocation object. + $callback = function ($elements) use ($that) { + return $that->entityViewBuilderPreRender($elements); + }; + + $build = array( '#theme' => $this->entityType, "#{$this->entityType}" => $entity, '#view_mode' => $view_mode, '#langcode' => $langcode, + '#pre_render' => array($callback), ); // Cache the rendered output if permitted by the view mode and global entity @@ -154,7 +163,51 @@ protected function getBuildDefaults(EntityInterface $entity, $view_mode, $langco ); } - return $return; + return $build; + } + + /** + * Performs pre-render tasks on an entity view. + * + * This function is assigned as a #pre_render callback in + * \Drupal\Core\Entity\EntityViewBuilder::getBuildDefaults(). + * + * @param array $elements + * A structured array containing build information and context for an + * entity view. + * + * @see drupal_render() + */ + public function entityViewBuilderPreRender(array $elements) { + $build = array(); + $entity = $elements['#entity']; + $bundle = $entity->bundle(); + $view_hook = "{$this->entityType}_view"; + $display = $elements['#display']; + $view_mode = $elements['#view_mode']; + $langcode = $elements['#langcode']; + + \Drupal::moduleHandler()->invokeAll($view_hook, array($entity, $display, $view_mode, $langcode)); + \Drupal::moduleHandler()->invokeAll('entity_view', array($entity, $display, $view_mode, $langcode)); + + $this->buildContent(array($entity), array($bundle => $display), $view_mode, $langcode); + + $build = $entity->content; + // We don't need duplicate rendering info in $entity->content. + unset($entity->content); + + $this->alterBuild($build, $entity, $display, $view_mode, $langcode); + + // Assign the weights configured in the display. + foreach ($display->getComponents() as $name => $options) { + if (isset($build[$name])) { + $build[$name]['#weight'] = $options['weight']; + } + } + + // Allow modules to modify the render array. + \Drupal::moduleHandler()->alter(array($view_hook, 'entity_view'), $build, $entity, $display); + return $build; } /** @@ -180,7 +233,7 @@ protected function alterBuild(array &$build, EntityInterface $entity, EntityView */ public function view(EntityInterface $entity, $view_mode = 'full', $langcode = NULL) { $buildList = $this->viewMultiple(array($entity), $view_mode, $langcode); - return $buildList[0]; + return $buildList; } /** @@ -192,11 +245,12 @@ public function viewMultiple(array $entities = array(), $view_mode = 'full', $la } // Build the view modes and display objects. - $view_modes = array(); - $displays = array(); $context = array('langcode' => $langcode); + $build = array('#sorted' => TRUE); + $view_hook = "{$this->entityType}_view"; + $weight = 0; + foreach ($entities as $key => $entity) { - $bundle = $entity->bundle(); // Ensure that from now on we are dealing with the proper translation // object. @@ -206,46 +260,23 @@ public function viewMultiple(array $entities = array(), $view_mode = 'full', $la // Allow modules to change the view mode. $entity_view_mode = $view_mode; drupal_alter('entity_view_mode', $entity_view_mode, $entity, $context); - // Store entities for rendering by view_mode. - $view_modes[$entity_view_mode][$entity->id()] = $entity; - - // Get the corresponding display settings. - if (!isset($displays[$entity_view_mode][$bundle])) { - $displays[$entity_view_mode][$bundle] = entity_get_render_display($entity, $entity_view_mode); - } - } - - foreach ($view_modes as $mode => $view_mode_entities) { - $this->buildContent($view_mode_entities, $displays[$mode], $mode, $langcode); - } - - $view_hook = "{$this->entityType}_view"; - $build = array('#sorted' => TRUE); - $weight = 0; - foreach ($entities as $key => $entity) { $entity_view_mode = isset($entity->content['#view_mode']) ? $entity->content['#view_mode'] : $view_mode; - $display = $displays[$entity_view_mode][$entity->bundle()]; - module_invoke_all($view_hook, $entity, $display, $entity_view_mode, $langcode); - module_invoke_all('entity_view', $entity, $display, $entity_view_mode, $langcode); - $build[$key] = $entity->content; - // We don't need duplicate rendering info in $entity->content. - unset($entity->content); + // Get the corresponding display settings. + $display = entity_get_render_display($entity, $entity_view_mode); + + //$build[$key] = $entity->content; + $build[$key] = array( + '#entity' => $entity, + '#view_mode' => $entity_view_mode, + '#display' => $display, + '#langcode' => $langcode, + ); + // Set defaults for #pre_render. $build[$key] += $this->getBuildDefaults($entity, $entity_view_mode, $langcode); - $this->alterBuild($build[$key], $entity, $display, $entity_view_mode, $langcode); - - // Assign the weights configured in the display. - foreach ($display->getComponents() as $name => $options) { - if (isset($build[$key][$name])) { - $build[$key][$name]['#weight'] = $options['weight']; - } - } $build[$key]['#weight'] = $weight++; - - // Allow modules to modify the render array. - drupal_alter(array($view_hook, 'entity_view'), $build[$key], $entity, $display); } return $build;