Issue #1875970 by yched, swentel: Pass EntityDisplay objects to the whole entity_view() callstack.

8.0.x
webchick 2013-01-08 11:16:16 -08:00
parent f2e25f6097
commit 97c3ee2be9
27 changed files with 279 additions and 247 deletions

View File

@ -180,8 +180,11 @@ function hook_entity_query_alter(\Drupal\Core\Entity\Query\QueryInterface $query
/**
* Act on entities being assembled before rendering.
*
* @param Drupal\Core\Entity\EntityInterface $entity
* @param \Drupal\Core\Entity\EntityInterface $entity
* The entity object.
* @param \Drupal\entity\Plugin\Core\Entity\EntityDisplay $display
* The entity_display object holding the display options configured for the
* entity components.
* @param $view_mode
* The view mode the entity is rendered in.
* @param $langcode
@ -196,12 +199,16 @@ function hook_entity_query_alter(\Drupal\Core\Entity\Query\QueryInterface $query
* @see hook_node_view()
* @see hook_user_view()
*/
function hook_entity_view(Drupal\Core\Entity\EntityInterface $entity, $view_mode, $langcode) {
$entity->content['my_additional_field'] = array(
'#markup' => $additional_field,
'#weight' => 10,
'#theme' => 'mymodule_my_additional_field',
);
function hook_entity_view(\Drupal\Core\Entity\EntityInterface $entity, \Drupal\entity\Plugin\Core\Entity\EntityDisplay $display, $view_mode, $langcode) {
// Only do the extra work if the component is configured to be displayed.
// This assumes a 'mymodule_addition' extra field has been defined for the
// entity bundle in hook_field_extra_fields().
if ($display->getComponent('mymodule_addition')) {
$entity->content['mymodule_addition'] = array(
'#markup' => mymodule_addition($entity),
'#theme' => 'mymodule_my_additional_field',
);
}
}
/**
@ -221,6 +228,9 @@ function hook_entity_view(Drupal\Core\Entity\EntityInterface $entity, $view_mode
* A renderable array representing the entity content.
* @param Drupal\Core\Entity\EntityInterface $entity
* The entity object being rendered.
* @param \Drupal\entity\Plugin\Core\Entity\EntityDisplay $display
* The entity_display object holding the display options configured for the
* entity components.
*
* @see hook_entity_view()
* @see hook_comment_view_alter()
@ -228,7 +238,7 @@ function hook_entity_view(Drupal\Core\Entity\EntityInterface $entity, $view_mode
* @see hook_taxonomy_term_view_alter()
* @see hook_user_view_alter()
*/
function hook_entity_view_alter(&$build, Drupal\Core\Entity\EntityInterface $entity) {
function hook_entity_view_alter(&$build, Drupal\Core\Entity\EntityInterface $entity, \Drupal\entity\Plugin\Core\Entity\EntityDisplay $display) {
if ($build['#view_mode'] == 'full' && isset($build['an_additional_field'])) {
// Change its weight.
$build['an_additional_field']['#weight'] = -10;
@ -245,17 +255,33 @@ function hook_entity_view_alter(&$build, Drupal\Core\Entity\EntityInterface $ent
* view. Only use this if attaching the data during the entity loading phase
* is not appropriate, for example when attaching other 'entity' style objects.
*
* @param array $entities
* The entities keyed by entity ID.
* @param string $entity_type
* The type of entities being viewed (i.e. node, user, comment).
* @param array $entities
* The entities keyed by entity ID.
* @param array $display
* The array of entity_display objects holding the display options configured
* for the entity components, keyed by bundle name.
* @param string $view_mode
* The view mode.
*/
function hook_entity_prepare_view($entities, $entity_type) {
function hook_entity_prepare_view($entity_type, array $entities, array $displays, $view_mode) {
// Load a specific node into the user object for later theming.
if (!empty($entities) && $entity_type == 'user') {
$nodes = mymodule_get_user_nodes(array_keys($entities));
foreach ($entities as $uid => $entity) {
$entity->user_node = $nodes[$uid];
// Only do the extra work if the component is configured to be
// displayed. This assumes a 'mymodule_addition' extra field has been
// defined for the entity bundle in hook_field_extra_fields().
$ids = array();
foreach ($entities as $id => $entity) {
if ($displays[$entity->bundle()]->getComponent('mymodule_addition')) {
$ids[] = $id;
}
}
if ($ids) {
$nodes = mymodule_get_user_nodes($ids);
foreach ($ids as $id) {
$entities[$id]->user_node = $nodes[$id];
}
}
}
}

View File

@ -662,29 +662,6 @@ function entity_get_render_display(EntityInterface $entity, $view_mode) {
return $display;
}
/**
* Adjusts weights and visibility of components in displayed entities.
*
* This is used as a #pre_render callback.
*/
function _entity_view_pre_render($elements) {
$display = $elements['#entity_display'];
$extra_fields = field_info_extra_fields($display->targetEntityType, $display->bundle, 'display');
foreach (array_keys($extra_fields) as $name) {
if (isset($elements[$name]) && (!isset($elements[$name]['#access']) || $elements[$name]['#access'])) {
if ($options = $display->getComponent($name)) {
$elements[$name]['#weight'] = $options['weight'];
}
else {
$elements[$name]['#access'] = FALSE;
}
}
}
return $elements;
}
/**
* Returns the entity query object for this entity type.
*

View File

@ -6,6 +6,7 @@
*/
namespace Drupal\Core\Entity;
use Drupal\entity\Plugin\Core\Entity\EntityDisplay;
/**
* Base class for entity view controllers.
@ -26,54 +27,16 @@ class EntityRenderController implements EntityRenderControllerInterface {
/**
* Implements Drupal\Core\Entity\EntityRenderControllerInterface::buildContent().
*/
public function buildContent(array $entities = array(), $view_mode = 'full', $langcode = NULL) {
// Allow modules to change the view mode.
$context = array('langcode' => $langcode);
$view_modes = array();
$displays = array();
public function buildContent(array $entities, array $displays, $view_mode, $langcode = NULL) {
field_attach_prepare_view($this->entityType, $entities, $displays, $langcode);
module_invoke_all('entity_prepare_view', $this->entityType, $entities, $displays, $view_mode);
foreach ($entities as $entity) {
// Remove previously built content, if exists.
$entity->content = array();
drupal_alter('entity_view_mode', $view_mode, $entity, $context);
$entity->content['#view_mode'] = $view_mode;
$view_modes[$view_mode][$entity->id()] = $entity;
$bundle = $entity->bundle();
// Load the corresponding display settings if not stored yet.
if (!isset($displays[$view_mode][$bundle])) {
// Get the display object to use for rendering the entity..
$display = entity_get_render_display($entity, $view_mode);
// Let modules alter the display.
// Note: if config entities get a static cache at some point, the
// objects should be cloned before running drupal_alter().
$display_context = array(
'entity_type' => $this->entityType,
'bundle' => $bundle,
'view_mode' => $view_mode,
);
drupal_alter('entity_display', $display, $display_context);
$displays[$view_mode][$bundle] = $display;
}
// Assigning weights to 'extra fields' is done in a pre_render callback.
$entity->content['#pre_render'] = array('_entity_view_pre_render');
$entity->content['#entity_display'] = $displays[$view_mode][$bundle];
}
// Prepare and build field content, grouped by view mode.
foreach ($view_modes as $view_mode => $view_mode_entities) {
field_attach_prepare_view($this->entityType, $view_mode_entities, $displays[$view_mode], $langcode);
module_invoke_all('entity_prepare_view', $view_mode_entities, $this->entityType);
foreach ($view_mode_entities as $entity) {
$entity->content += field_attach_view($entity, $displays[$view_mode][$entity->bundle()], $langcode);
}
$entity->content = array(
'#view_mode' => $view_mode,
);
$entity->content += field_attach_view($entity, $displays[$entity->bundle()], $langcode);
}
}
@ -105,15 +68,18 @@ class EntityRenderController implements EntityRenderControllerInterface {
*
* @param array $build
* The render array that is being created.
* @param Drupal\Core\Entity\EntityInterface $entity
* @param \Drupal\Core\Entity\EntityInterface $entity
* The entity to be prepared.
* @param \Drupal\entity\Plugin\Core\Entity\EntityDisplay $display
* The entity_display object holding the display options configured for
* the entity components.
* @param string $view_mode
* The view mode that should be used to prepare the entity.
* @param string $langcode
* (optional) For which language the entity should be prepared, defaults to
* the current content language.
*/
protected function alterBuild(array &$build, EntityInterface $entity, $view_mode, $langcode = NULL) { }
protected function alterBuild(array &$build, EntityInterface $entity, EntityDisplay $display, $view_mode, $langcode = NULL) { }
/**
* Implements Drupal\Core\Entity\EntityRenderControllerInterface::view().
@ -130,26 +96,68 @@ class EntityRenderController implements EntityRenderControllerInterface {
if (!isset($langcode)) {
$langcode = language(LANGUAGE_TYPE_CONTENT)->langcode;
}
$this->buildContent($entities, $view_mode, $langcode);
// Build the view modes and display objects.
$view_modes = array();
$displays = array();
$context = array('langcode' => $langcode);
foreach ($entities as $entity) {
$bundle = $entity->bundle();
// 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;
// Load the corresponding display settings if not stored yet.
if (!isset($displays[$entity_view_mode][$bundle])) {
// Get the display object for this bundle and view mode.
$display = entity_get_render_display($entity, $entity_view_mode);
// Let modules alter the display.
$display_context = array(
'entity_type' => $this->entityType,
'bundle' => $bundle,
'view_mode' => $entity_view_mode,
);
drupal_alter('entity_display', $display, $display_context);
$displays[$entity_view_mode][$bundle] = $display;
}
}
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;
module_invoke_all($view_hook, $entity, $entity_view_mode, $langcode);
module_invoke_all('entity_view', $entity, $entity_view_mode, $langcode);
$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);
$build[$key] += $this->getBuildDefaults($entity, $entity_view_mode, $langcode);
$this->alterBuild($build[$key], $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 structured entity.
drupal_alter(array($view_hook, 'entity_view'), $build[$key], $entity);
// Allow modules to modify the render array.
drupal_alter(array($view_hook, 'entity_view'), $build[$key], $entity, $display);
}
return $build;

View File

@ -11,13 +11,17 @@ namespace Drupal\Core\Entity;
* Defines a common interface for entity view controller classes.
*/
interface EntityRenderControllerInterface {
/**
* Build the structured $content property on the entity.
*
* @param array $entities
* The entities, implementing EntityInterface, whose content is being built.
* @param array $displays
* The array of entity_display objects holding the display options
* configured for the entity components, keyed by bundle name.
* @param string $view_mode
* (optional) The view mode that should be used to build the entity.
* The view mode in which the entity is being viewed.
* @param string $langcode
* (optional) For which language the entity should be build, defaults to
* the current content language.
@ -25,7 +29,7 @@ interface EntityRenderControllerInterface {
* @return array
* The content array.
*/
public function buildContent(array $entities = array(), $view_mode = 'full', $langcode = NULL);
public function buildContent(array $entities, array $displays, $view_mode, $langcode = NULL);
/**
* Returns the render array for the provided entity.

View File

@ -6,6 +6,7 @@
*/
use Drupal\node\Plugin\Core\Entity\Node;
use Drupal\entity\Plugin\Core\Entity\EntityDisplay;
use Drupal\Core\Template\Attribute;
/**
@ -776,7 +777,7 @@ function book_node_load($nodes, $types) {
/**
* Implements hook_node_view().
*/
function book_node_view(Node $node, $view_mode) {
function book_node_view(Node $node, EntityDisplay $display, $view_mode) {
if ($view_mode == 'full') {
if (!empty($node->book['bid']) && empty($node->in_preview)) {
$node->content['book_navigation'] = array(

View File

@ -64,8 +64,11 @@ function hook_comment_load(Drupal\comment\Comment $comments) {
/**
* Act on a comment that is being assembled before rendering.
*
* @param Drupal\comment\Comment $comment
* @param \Drupal\comment\Plugin\Core\Entity\Comment $comment $comment
* Passes in the comment the action is being performed on.
* @param \Drupal\entity\Plugin\Core\Entity\EntityDisplay $display
* The entity_display object holding the display options configured for the
* comment components.
* @param $view_mode
* View mode, e.g. 'full', 'teaser'...
* @param $langcode
@ -73,9 +76,16 @@ function hook_comment_load(Drupal\comment\Comment $comments) {
*
* @see hook_entity_view()
*/
function hook_comment_view(Drupal\comment\Comment $comment, $view_mode, $langcode) {
// how old is the comment
$comment->time_ago = time() - $comment->changed;
function hook_comment_view(\Drupal\comment\Plugin\Core\Entity\Comment $comment, \Drupal\entity\Plugin\Core\Entity\EntityDisplay $display, $view_mode, $langcode) {
// Only do the extra work if the component is configured to be displayed.
// This assumes a 'mymodule_addition' extra field has been defined for the
// node type in hook_field_extra_fields().
if ($display->getComponent('mymodule_addition')) {
$comment->content['mymodule_addition'] = array(
'#markup' => mymodule_addition($comment),
'#theme' => 'mymodule_my_additional_field',
);
}
}
/**
@ -93,13 +103,16 @@ function hook_comment_view(Drupal\comment\Comment $comment, $view_mode, $langcod
*
* @param $build
* A renderable array representing the comment.
* @param Drupal\comment\Comment $comment
* @param \Drupal\comment\Plugin\Core\Entity\Comment $comment
* The comment being rendered.
* @param \Drupal\entity\Plugin\Core\Entity\EntityDisplay $display
* The entity_display object holding the display options configured for the
* comment components.
*
* @see comment_view()
* @see hook_entity_view_alter()
*/
function hook_comment_view_alter(&$build, Drupal\comment\Comment $comment) {
function hook_comment_view_alter(&$build, \Drupal\comment\Plugin\Core\Entity\Comment $comment, \Drupal\entity\Plugin\Core\Entity\EntityDisplay $display) {
// Check for the existence of a field added by another module.
if ($build['#view_mode'] == 'full' && isset($build['an_additional_field'])) {
// Change its weight.

View File

@ -10,6 +10,7 @@
*/
use Drupal\node\Plugin\Core\Entity\Node;
use Drupal\entity\Plugin\Core\Entity\EntityDisplay;
use Drupal\file\Plugin\Core\Entity\File;
use Drupal\Core\Entity\EntityInterface;
use Symfony\Component\HttpFoundation\Request;
@ -566,7 +567,7 @@ function theme_comment_block($variables) {
/**
* Implements hook_node_view().
*/
function comment_node_view(Node $node, $view_mode) {
function comment_node_view(Node $node, EntityDisplay $display, $view_mode) {
$links = array();
if ($node->comment != COMMENT_NODE_HIDDEN) {

View File

@ -9,6 +9,7 @@ namespace Drupal\comment;
use Drupal\Core\Entity\EntityInterface;
use Drupal\Core\Entity\EntityRenderController;
use Drupal\entity\Plugin\Core\Entity\EntityDisplay;
/**
* Render controller for comments.
@ -21,7 +22,7 @@ class CommentRenderController extends EntityRenderController {
* In addition to modifying the content key on entities, this implementation
* will also set the node key which all comments carry.
*/
public function buildContent(array $entities = array(), $view_mode = 'full', $langcode = NULL) {
public function buildContent(array $entities, array $displays, $view_mode, $langcode = NULL) {
$return = array();
if (empty($entities)) {
return $return;
@ -30,7 +31,7 @@ class CommentRenderController extends EntityRenderController {
// Attach user account.
user_attach_accounts($entities);
parent::buildContent($entities, $view_mode, $langcode);
parent::buildContent($entities, $displays, $view_mode, $langcode);
// Load all nodes of all comments at once.
$nids = array();
@ -67,8 +68,8 @@ class CommentRenderController extends EntityRenderController {
/**
* Overrides Drupal\Core\Entity\EntityRenderController::alterBuild().
*/
protected function alterBuild(array &$build, EntityInterface $comment, $view_mode, $langcode = NULL) {
parent::alterBuild($build, $comment, $view_mode, $langcode);
protected function alterBuild(array &$build, EntityInterface $comment, EntityDisplay $display, $view_mode, $langcode = NULL) {
parent::alterBuild($build, $comment, $display, $view_mode, $langcode);
if (empty($comment->in_preview)) {
$prefix = '';
$is_threaded = isset($comment->divs)
@ -95,4 +96,5 @@ class CommentRenderController extends EntityRenderController {
}
}
}
}

View File

@ -18,19 +18,17 @@ class MessageRenderController extends EntityRenderController {
/**
* Overrides Drupal\Core\Entity\EntityRenderController::buildContent().
*/
public function buildContent(array $entities = array(), $view_mode = 'full', $langcode = NULL) {
parent::buildContent($entities, $view_mode, $langcode);
public function buildContent(array $entities, array $displays, $view_mode, $langcode = NULL) {
parent::buildContent($entities, $displays, $view_mode, $langcode);
foreach ($entities as $entity) {
// Add the message extra field, if enabled.
$entity_view_mode = $entity->content['#view_mode'];
$fields = field_extra_fields_get_display($entity, $entity_view_mode);
if (!empty($entity->message) && !empty($fields['message']['visible'])) {
$display = $displays[$entity->bundle()];
if (!empty($entity->message) && $display->getComponent('message')) {
$entity->content['message'] = array(
'#type' => 'item',
'#title' => t('Message'),
'#markup' => check_plain($entity->message),
'#weight' => $fields['message']['weight'],
);
}
}

View File

@ -721,33 +721,6 @@ function field_view_mode_settings($entity_type, $bundle) {
return $cache[$entity_type][$bundle];
}
/**
* Returns the display options to use for pseudo-fields in a given view mode.
*
* @todo Remove when all steps in the view callstack receive the
* entity_display.
*
* @param \Drupal\Core\Entity\EntityInterface $entity
* The entity.
* @param $view_mode
* The view mode.
*
* @return
* The display options to be used when viewing the entity's pseudo-fields in
* the view mode.
*/
function field_extra_fields_get_display(EntityInterface $entity, $view_mode) {
$entity_display = entity_get_render_display($entity, $view_mode);
$extra_fields = field_info_extra_fields($entity->entityType(), $entity->bundle(), 'display');
$options = array();
foreach ($extra_fields as $name => $value) {
$options[$name] = $entity_display->getComponent($name);
}
return $options;
}
/**
* Pre-render callback: Adjusts weights and visibility of non-field elements.
*/

View File

@ -38,13 +38,6 @@ abstract class FormatterBase extends PluginSettingsBase implements FormatterInte
*/
protected $settings;
/**
* The formatter weight.
*
* @var int
*/
protected $weight;
/**
* The label display setting.
*
@ -71,20 +64,17 @@ abstract class FormatterBase extends PluginSettingsBase implements FormatterInte
* The field instance to which the formatter is associated.
* @param array $settings
* The formatter settings.
* @param int $weight
* The formatter weight.
* @param string $label
* The formatter label display setting.
* @param string $view_mode
* The view mode.
*/
public function __construct($plugin_id, DiscoveryInterface $discovery, $instance, array $settings, $weight, $label, $view_mode) {
public function __construct($plugin_id, DiscoveryInterface $discovery, $instance, array $settings, $label, $view_mode) {
parent::__construct(array(), $plugin_id, $discovery);
$this->instance = $instance;
$this->field = field_info_field($instance['field_name']);
$this->settings = $settings;
$this->weight = $weight;
$this->label = $label;
$this->viewMode = $view_mode;
}
@ -103,7 +93,6 @@ abstract class FormatterBase extends PluginSettingsBase implements FormatterInte
$entity_type = $entity->entityType();
$info = array(
'#theme' => 'field',
'#weight' => $this->weight,
'#title' => $instance['label'],
'#access' => field_access('view', $field, $entity->entityType(), $entity),
'#label_display' => $this->label,

View File

@ -19,6 +19,6 @@ class FormatterFactory extends DefaultFactory {
*/
public function createInstance($plugin_id, array $configuration) {
$plugin_class = $this->getPluginClass($plugin_id);
return new $plugin_class($plugin_id, $this->discovery, $configuration['instance'], $configuration['settings'], $configuration['weight'], $configuration['label'], $configuration['view_mode']);
return new $plugin_class($plugin_id, $this->discovery, $configuration['instance'], $configuration['settings'], $configuration['label'], $configuration['view_mode']);
}
}

View File

@ -62,8 +62,6 @@ class FormatterPluginManager extends PluginManagerBase {
* requested formatter is not available.
* - settings: (array) Settings specific to the formatter. Each setting
* defaults to the default value specified in the formatter definition.
* - weight: (float) The weight to assign to the renderable element.
* Defaults to 0.
*
* @return \Drupal\field\Plugin\Type\Formatter\FormatterInterface
* A formatter object.
@ -113,7 +111,6 @@ class FormatterPluginManager extends PluginManagerBase {
$configuration += array(
'label' => 'above',
'settings' => array(),
'weight' => 0,
);
// If no formatter is specified, use the default formatter.
if (!isset($configuration['type'])) {

View File

@ -38,7 +38,6 @@ class LegacyFormatter extends FormatterBase {
$instance['display'][$this->viewMode] = array(
'type' => $this->getPluginId(),
'settings' => $this->getSettings(),
'weight' => $this->weight,
'label' => $this->label,
);
@ -62,7 +61,6 @@ class LegacyFormatter extends FormatterBase {
$instance['display'][$this->viewMode] = array(
'type' => $this->getPluginId(),
'settings' => $this->getSettings(),
'weight' => $this->weight,
'label' => $this->label,
);
@ -88,7 +86,6 @@ class LegacyFormatter extends FormatterBase {
$display = array(
'type' => $this->getPluginId(),
'settings' => $this->getSettings(),
'weight' => $this->weight,
'label' => $this->label,
);
$displays = array();
@ -111,7 +108,6 @@ class LegacyFormatter extends FormatterBase {
$display = array(
'type' => $this->getPluginId(),
'settings' => $this->getSettings(),
'weight' => $this->weight,
'label' => $this->label,
);

View File

@ -7,6 +7,7 @@
use Drupal\Core\Entity\EntityInterface;
use Drupal\node\Plugin\Core\Entity\Node;
use Drupal\entity\Plugin\Core\Entity\EntityDisplay;
use Drupal\taxonomy\Plugin\Core\Entity\Term;
/**
@ -254,7 +255,7 @@ function _forum_node_check_node_type(Node $node) {
/**
* Implements hook_node_view().
*/
function forum_node_view(Node $node, $view_mode) {
function forum_node_view(Node $node, EntityDisplay $display, $view_mode) {
$vid = config('forum.settings')->get('vocabulary');
$vocabulary = taxonomy_vocabulary_load($vid);
if (_forum_node_check_node_type($node)) {

View File

@ -9,6 +9,7 @@ namespace Drupal\node;
use Drupal\Core\Entity\EntityInterface;
use Drupal\Core\Entity\EntityRenderController;
use Drupal\entity\Plugin\Core\Entity\EntityDisplay;
/**
* Render controller for nodes.
@ -18,7 +19,7 @@ class NodeRenderController extends EntityRenderController {
/**
* Overrides Drupal\Core\Entity\EntityRenderController::buildContent().
*/
public function buildContent(array $entities = array(), $view_mode = 'full', $langcode = NULL) {
public function buildContent(array $entities, array $displays, $view_mode, $langcode = NULL) {
$return = array();
if (empty($entities)) {
return $return;
@ -27,15 +28,16 @@ class NodeRenderController extends EntityRenderController {
// Attach user account.
user_attach_accounts($entities);
parent::buildContent($entities, $view_mode, $langcode);
parent::buildContent($entities, $displays, $view_mode, $langcode);
foreach ($entities as $key => $entity) {
$entity_view_mode = $entity->content['#view_mode'];
$bundle = $entity->bundle();
$display = $displays[$bundle];
// The 'view' hook can be implemented to overwrite the default function
// to display nodes.
if (node_hook($entity->bundle(), 'view')) {
$entity = node_invoke($entity, 'view', $entity_view_mode, $langcode);
if (node_hook($bundle, 'view')) {
$entity = node_invoke($entity, 'view', $display, $view_mode, $langcode);
}
$entity->content['links'] = array(
@ -47,7 +49,7 @@ class NodeRenderController extends EntityRenderController {
// Always display a read more link on teasers because we have no way
// to know when a teaser view is different than a full view.
$links = array();
if ($entity_view_mode == 'teaser') {
if ($view_mode == 'teaser') {
$node_title_stripped = strip_tags($entity->label());
$links['node-readmore'] = array(
'title' => t('Read more<span class="element-invisible"> about @title</span>', array(
@ -69,22 +71,23 @@ class NodeRenderController extends EntityRenderController {
);
// Add Language field text element to node render array.
$entity->content['language'] = array(
'#type' => 'item',
'#title' => t('Language'),
'#markup' => language_name($langcode),
'#weight' => 0,
'#prefix' => '<div id="field-language-display">',
'#suffix' => '</div>'
);
if ($display->getComponent('language')) {
$entity->content['language'] = array(
'#type' => 'item',
'#title' => t('Language'),
'#markup' => language_name($langcode),
'#prefix' => '<div id="field-language-display">',
'#suffix' => '</div>'
);
}
}
}
/**
* Overrides Drupal\Core\Entity\EntityRenderController::alterBuild().
*/
protected function alterBuild(array &$build, EntityInterface $entity, $view_mode, $langcode = NULL) {
parent::alterBuild($build, $entity, $view_mode, $langcode);
protected function alterBuild(array &$build, EntityInterface $entity, EntityDisplay $display, $view_mode, $langcode = NULL) {
parent::alterBuild($build, $entity, $display, $view_mode, $langcode);
// Add contextual links for this node, except when the node is already being
// displayed on its own page. Modules may alter this behavior (for example,
// to restrict contextual links to certain view modes) by implementing

View File

@ -30,8 +30,7 @@ class NodeBuildContentTest extends NodeTestBase {
$node->content['test_content_property'] = array(
'#value' => $this->randomString(),
);
$nodes = array($node);
$content = entity_render_controller('node')->buildContent($nodes);
$content = node_view($node);
// If the property doesn't exist it means the node->content was rebuilt.
$this->assertFalse(isset($content['test_content_property']), 'Node content was emptied prior to being built.');

View File

@ -831,11 +831,14 @@ function hook_node_submit(Drupal\node\Node $node, $form, &$form_state) {
* the RSS item generated for this node.
* For details on how this is used, see node_feed().
*
* @param Drupal\node\Node $node
* @param \Drupal\node\Plugin\Core\Entity\Node $node
* The node that is being assembled for rendering.
* @param $view_mode
* @param \Drupal\entity\Plugin\Core\Entity\EntityDisplay $display
* The entity_display object holding the display options configured for the
* node components.
* @param string $view_mode
* The $view_mode parameter from node_view().
* @param $langcode
* @param string $langcode
* The language code used for rendering.
*
* @see forum_node_view()
@ -844,12 +847,16 @@ function hook_node_submit(Drupal\node\Node $node, $form, &$form_state) {
*
* @ingroup node_api_hooks
*/
function hook_node_view(Drupal\node\Node $node, $view_mode, $langcode) {
$node->content['my_additional_field'] = array(
'#markup' => $additional_field,
'#weight' => 10,
'#theme' => 'mymodule_my_additional_field',
);
function hook_node_view(\Drupal\node\Plugin\Core\Entity\Node $node, \Drupal\entity\Plugin\Core\Entity\EntityDisplay $display, $view_mode, $langcode) {
// Only do the extra work if the component is configured to be displayed.
// This assumes a 'mymodule_addition' extra field has been defined for the
// node type in hook_field_extra_fields().
if ($display->getComponent('mymodule_addition')) {
$node->content['mymodule_addition'] = array(
'#markup' => mymodule_addition($node),
'#theme' => 'mymodule_my_additional_field',
);
}
}
/**
@ -867,15 +874,18 @@ function hook_node_view(Drupal\node\Node $node, $view_mode, $langcode) {
*
* @param $build
* A renderable array representing the node content.
* @param Drupal\node\Node $node
* @param \Drupal\node\Plugin\Core\Entity\Node $node
* The node being rendered.
* @param \Drupal\entity\Plugin\Core\Entity\EntityDisplay $display
* The entity_display object holding the display options configured for the
* node components.
*
* @see node_view()
* @see hook_entity_view_alter()
*
* @ingroup node_api_hooks
*/
function hook_node_view_alter(&$build, Drupal\node\Node $node) {
function hook_node_view_alter(&$build, \Drupal\node\Plugin\Core\Entity\Node $node, \Drupal\entity\Plugin\Core\Entity\EntityDisplay $display) {
if ($build['#view_mode'] == 'full' && isset($build['an_additional_field'])) {
// Change its weight.
$build['an_additional_field']['#weight'] = -10;
@ -1279,8 +1289,11 @@ function hook_validate(Drupal\node\Node $node, $form, &$form_state) {
* that the node type module can define a custom method for display, or add to
* the default display.
*
* @param Drupal\node\Node $node
* @param \Drupal\node\Plugin\Core\Entity\Node $node
* The node to be displayed, as returned by node_load().
* @param \Drupal\entity\Plugin\Core\Entity\EntityDisplay $display
* The entity_display object holding the display options configured for the
* node components.
* @param $view_mode
* View mode, e.g. 'full', 'teaser', ...
*
@ -1297,7 +1310,7 @@ function hook_validate(Drupal\node\Node $node, $form, &$form_state) {
*
* @ingroup node_api_hooks
*/
function hook_view(Drupal\node\Node $node, $view_mode) {
function hook_view(\Drupal\node\Plugin\Core\Entity\Node $node, \Drupal\entity\Plugin\Core\Entity\EntityDisplay $display, $view_mode) {
if ($view_mode == 'full' && node_is_page($node)) {
$breadcrumb = array();
$breadcrumb[] = l(t('Home'), NULL);
@ -1306,10 +1319,15 @@ function hook_view(Drupal\node\Node $node, $view_mode) {
drupal_set_breadcrumb($breadcrumb);
}
$node->content['myfield'] = array(
'#markup' => theme('mymodule_myfield', $node->myfield),
'#weight' => 1,
);
// Only do the extra work if the component is configured to be displayed.
// This assumes a 'mymodule_addition' extra field has been defined for the
// node type in hook_field_extra_fields().
if ($display->getComponent('mymodule_addition')) {
$node->content['mymodule_addition'] = array(
'#markup' => mymodule_addition($node),
'#theme' => 'mymodule_my_additional_field',
);
}
return $node;
}

View File

@ -9,6 +9,7 @@
*/
use Drupal\node\Plugin\Core\Entity\Node;
use Drupal\entity\Plugin\Core\Entity\EntityDisplay;
/**
* Implements hook_node_load().
@ -29,7 +30,7 @@ function node_test_node_load($nodes, $types) {
/**
* Implements hook_node_view().
*/
function node_test_node_view(Node $node, $view_mode) {
function node_test_node_view(Node $node, EntityDisplay $display, $view_mode) {
if ($view_mode == 'rss') {
// Add RSS elements and namespaces when building the RSS feed.
$node->rss_elements[] = array(

View File

@ -7,6 +7,7 @@
use Drupal\Core\Entity\EntityInterface;
use Drupal\node\Plugin\Core\Entity\Node;
use Drupal\entity\Plugin\Core\Entity\EntityDisplay;
/**
* Implements hook_help().
@ -641,14 +642,13 @@ function poll_block_latest_poll_view(Node $node) {
*
* @see poll_view_results()
*/
function poll_view($node, $view_mode) {
global $user;
$output = '';
function poll_view($node, EntityDisplay $display, $view_mode) {
if (!empty($node->allowvotes) && empty($node->show_results)) {
$node->content['poll_view_voting'] = drupal_get_form('poll_view_voting', $node);
if ($display->getComponent('poll_view_voting')) {
$node->content['poll_view_voting'] = drupal_get_form('poll_view_voting', $node);
}
}
else {
elseif ($display->getComponent('poll_view_results')) {
$node->content['poll_view_results'] = array('#markup' => poll_view_results($node, $view_mode));
}
return $node;

View File

@ -6,6 +6,7 @@
*/
use Drupal\node\Plugin\Core\Entity\Node;
use Drupal\entity\Plugin\Core\Entity\EntityDisplay;
/**
* Implements hook_help().
@ -101,7 +102,7 @@ function statistics_permission() {
/**
* Implements hook_node_view().
*/
function statistics_node_view(Node $node, $view_mode) {
function statistics_node_view(Node $node, EntityDisplay $display, $view_mode) {
if (!empty($node->nid) && $view_mode == 'full' && node_is_page($node) && empty($node->in_preview)) {
$node->content['#attached']['library'][] = array('statistics', 'drupal.statistics');
$settings = array('data' => array('nid' => $node->nid), 'url' => url(drupal_get_path('module', 'statistics') . '/statistics.php'));

View File

@ -8,6 +8,7 @@
*/
use Drupal\taxonomy\Plugin\Core\Entity\Term;
use Drupal\entity\Plugin\Core\Entity\EntityDisplay;
/**
* Implements hook_taxonomy_term_load().
@ -61,7 +62,7 @@ function taxonomy_test_taxonomy_term_delete(Term $term) {
/**
* Implements hook_taxonomy_term_view().
*/
function taxonomy_test_taxonomy_term_view($term, $view_mode, $langcode) {
function taxonomy_test_taxonomy_term_view(Term $term, EntityDisplay $display, $view_mode, $langcode) {
if ($view_mode == 'full') {
$term->content['taxonomy_test_term_view_check'] = array(
'#prefix' => '<div>',
@ -75,7 +76,7 @@ function taxonomy_test_taxonomy_term_view($term, $view_mode, $langcode) {
/**
* Implements hook_entity_view().
*/
function taxonomy_test_entity_view($entity, $view_mode, $langcode) {
function taxonomy_test_entity_view($entity, EntityDisplay $display, $view_mode, $langcode) {
if ($entity->entityType() == 'taxonomy_term' && $view_mode == 'full') {
$entity->content['taxonomy_test_entity_view_check'] = array(
'#prefix' => '<div>',

View File

@ -9,6 +9,7 @@ namespace Drupal\taxonomy;
use Drupal\Core\Entity\EntityInterface;
use Drupal\Core\Entity\EntityRenderController;
use Drupal\entity\Plugin\Core\Entity\EntityDisplay;
/**
* Render controller for taxonomy terms.
@ -18,17 +19,15 @@ class TermRenderController extends EntityRenderController {
/**
* Overrides Drupal\Core\Entity\EntityRenderController::buildContent().
*/
public function buildContent(array $entities = array(), $view_mode = 'full', $langcode = NULL) {
parent::buildContent($entities, $view_mode, $langcode);
public function buildContent(array $entities, array $displays, $view_mode, $langcode = NULL) {
parent::buildContent($entities, $displays, $view_mode, $langcode);
foreach ($entities as $entity) {
// Add the description if enabled.
$entity_view_mode = $entity->content['#view_mode'];
$display = field_extra_fields_get_display($entity, $entity_view_mode);
if (!empty($entity->description) && !empty($display['description'])) {
$display = $displays[$entity->bundle()];
if (!empty($entity->description) && $display->getComponent('description')) {
$entity->content['description'] = array(
'#markup' => check_markup($entity->description, $entity->format, '', TRUE),
'#weight' => $display['description']['weight'],
'#prefix' => '<div class="taxonomy-term-description">',
'#suffix' => '</div>',
);
@ -36,6 +35,9 @@ class TermRenderController extends EntityRenderController {
}
}
/**
* Overrides \Drupal\Core\Entity\EntityRenderController::getBuildDefaults().
*/
protected function getBuildDefaults(EntityInterface $entity, $view_mode, $langcode) {
$return = parent::getBuildDefaults($entity, $view_mode, $langcode);
@ -46,8 +48,12 @@ class TermRenderController extends EntityRenderController {
return $return;
}
protected function alterBuild(array &$build, EntityInterface $entity, $view_mode, $langcode = NULL) {
parent::alterBuild($build, $entity, $view_mode, $langcode);
/**
* Overrides \Drupal\Core\Entity\EntityRenderController::alterBuild().
*/
protected function alterBuild(array &$build, EntityInterface $entity, EntityDisplay $display, $view_mode, $langcode = NULL) {
parent::alterBuild($build, $entity, $display, $view_mode, $langcode);
$build['#attached']['css'][] = drupal_get_path('module', 'taxonomy') . '/taxonomy.css';
}
}

View File

@ -231,8 +231,11 @@ function hook_taxonomy_term_delete(Drupal\taxonomy\Term $term) {
* structure of $term->content is a renderable array as expected by
* drupal_render().
*
* @param $term
* @param \Drupal\taxonomy\Plugin\Core\Entity\Term $term
* The term that is being assembled for rendering.
* @param \Drupal\entity\Plugin\Core\Entity\EntityDisplay $display
* The entity_display object holding the display options configured for the
* term components.
* @param $view_mode
* The $view_mode parameter from taxonomy_term_view().
* @param $langcode
@ -240,12 +243,16 @@ function hook_taxonomy_term_delete(Drupal\taxonomy\Term $term) {
*
* @see hook_entity_view()
*/
function hook_taxonomy_term_view($term, $view_mode, $langcode) {
$term->content['my_additional_field'] = array(
'#markup' => $additional_field,
'#weight' => 10,
'#theme' => 'mymodule_my_additional_field',
);
function hook_taxonomy_term_view(\Drupal\taxonomy\Plugin\Core\Entity\Term $term, \Drupal\entity\Plugin\Core\Entity\EntityDisplay $display, $view_mode, $langcode) {
// Only do the extra work if the component is configured to be displayed.
// This assumes a 'mymodule_addition' extra field has been defined for the
// vocabulary in hook_field_extra_fields().
if ($display->getComponent('mymodule_addition')) {
$term->content['mymodule_addition'] = array(
'#markup' => mymodule_addition($term),
'#theme' => 'mymodule_my_additional_field',
);
}
}
/**
@ -263,12 +270,15 @@ function hook_taxonomy_term_view($term, $view_mode, $langcode) {
*
* @param $build
* A renderable array representing the taxonomy term content.
* @param Drupal\taxonomy\Term $term
* @param \Drupal\taxonomy\Plugin\Core\Entity\Term $term
* The taxonomy term being rendered.
* @param \Drupal\entity\Plugin\Core\Entity\EntityDisplay $display
* The entity_display object holding the display options configured for the
* term components.
*
* @see hook_entity_view_alter()
*/
function hook_taxonomy_term_view_alter(&$build, Drupal\taxonomy\Term $term) {
function hook_taxonomy_term_view_alter(&$build, \Drupal\taxonomy\Plugin\Core\Entity\Term $term, \Drupal\entity\Plugin\Core\Entity\EntityDisplay $display) {
if ($build['#view_mode'] == 'full' && isset($build['an_additional_field'])) {
// Change its weight.
$build['an_additional_field']['#weight'] = -10;

View File

@ -20,6 +20,7 @@
*/
use Drupal\node\Plugin\Core\Entity\Node;
use Drupal\entity\Plugin\Core\Entity\EntityDisplay;
/**
* Implements hook_help().
@ -248,7 +249,7 @@ function translation_form_node_form_alter(&$form, &$form_state) {
* translation set. If no language provider is enabled, "fall back" to simple
* links built through the result of translation_node_get_translations().
*/
function translation_node_view(Node $node, $view_mode) {
function translation_node_view(Node $node, EntityDisplay $display, $view_mode) {
// If the site has no translations or is not multilingual we have no content
// translation links to display.
if (isset($node->tnid) && language_multilingual() && $translations = translation_node_get_translations($node->tnid)) {

View File

@ -331,8 +331,11 @@ function hook_user_logout($account) {
* The module should format its custom additions for display and add them to the
* $account->content array.
*
* @param $account
* @param \Drupal\user\Plugin\Core\Entity\User $account
* The user object on which the operation is being performed.
* @param \Drupal\entity\Plugin\Core\Entity\EntityDisplay $display
* The entity_display object holding the display options configured for the
* user components.
* @param $view_mode
* View mode, e.g. 'full'.
* @param $langcode
@ -341,21 +344,16 @@ function hook_user_logout($account) {
* @see hook_user_view_alter()
* @see hook_entity_view()
*/
function hook_user_view($account, $view_mode, $langcode) {
if (!isset($account->content['summary'])) {
$account->content['summary'] = array();
function hook_user_view(\Drupal\user\Plugin\Core\Entity\User $account, \Drupal\entity\Plugin\Core\Entity\EntityDisplay $display, $view_mode, $langcode) {
// Only do the extra work if the component is configured to be displayed.
// This assumes a 'mymodule_addition' extra field has been defined for the
// user entity type in hook_field_extra_fields().
if ($display->getComponent('mymodule_addition')) {
$account->content['mymodule_addition'] = array(
'#markup' => mymodule_addition($account),
'#theme' => 'mymodule_my_additional_field',
);
}
$account->content['summary'] += array(
'#type' => 'user_profile_category',
'#title' => t('History'),
'#attributes' => array('class' => array('user-member')),
'#weight' => 5,
);
$account->content['summary']['member_for'] = array(
'#type' => 'user_profile_item',
'#title' => t('Member for'),
'#markup' => format_interval(REQUEST_TIME - $account->created),
);
}
/**
@ -373,13 +371,16 @@ function hook_user_view($account, $view_mode, $langcode) {
*
* @param $build
* A renderable array representing the user.
* @param Drupal\user\User $account
* @param \Drupal\user\Plugin\Core\Entity\User $account
* The user account being rendered.
* @param \Drupal\entity\Plugin\Core\Entity\EntityDisplay $display
* The entity_display object holding the display options configured for the
* user components.
*
* @see user_view()
* @see hook_entity_view_alter()
*/
function hook_user_view_alter(&$build, Drupal\user\User $account) {
function hook_user_view_alter(&$build, \Drupal\user\Plugin\Core\Entity\User $account, \Drupal\entity\Plugin\Core\Entity\EntityDisplay $display) {
// Check for the existence of a field added by another module.
if (isset($build['an_additional_field'])) {
// Change its weight.

View File

@ -2,7 +2,10 @@
use Drupal\Core\Database\Query\SelectInterface;
use Drupal\Core\Entity\EntityInterface;
use Drupal\comment\Plugin\Core\Entity\Comment;
use Drupal\entity\Plugin\Core\Entity\EntityDisplay;
use Drupal\file\Plugin\Core\Entity\File;
use Drupal\user\Plugin\Core\Entity\User;
use Drupal\Core\Template\Attribute;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
@ -151,7 +154,8 @@ function user_label($entity_type, $entity) {
/**
* Populates $entity->account for each prepared entity.
*
* Called by hook_entity_prepare_view() implementations.
* Called by Drupal\Core\Entity\EntityRenderControllerInterface::buildContent()
* implementations.
*
* @param array $entities
* The entities keyed by entity ID.
@ -583,13 +587,14 @@ function user_search_execute($keys = NULL, $conditions = NULL) {
/**
* Implements hook_user_view().
*/
function user_user_view($account) {
$account->content['member_for'] = array(
'#type' => 'item',
'#title' => t('Member for'),
'#markup' => format_interval(REQUEST_TIME - $account->created),
'#weight' => 5,
);
function user_user_view(User $account, EntityDisplay $display) {
if ($display->getComponent('member_for')) {
$account->content['member_for'] = array(
'#type' => 'item',
'#title' => t('Member for'),
'#markup' => format_interval(REQUEST_TIME - $account->created),
);
}
}
/**
@ -2381,7 +2386,7 @@ function user_build_filter_query(SelectInterface $query) {
/**
* Implements hook_comment_view().
*/
function user_comment_view($comment) {
function user_comment_view(Comment $comment, EntityDisplay $display) {
if (config('user.settings')->get('signatures') && !empty($comment->signature)) {
// @todo This alters and replaces the original object value, so a
// hypothetical process of loading, viewing, and saving will hijack the