Issue #2090509 by yched, swentel, Wim Leers: Optimize entity_get_render_display() for the case of 'multiple entity view'.
parent
51d9879c22
commit
9c88b1afce
|
@ -569,62 +569,6 @@ function entity_get_display($entity_type, $bundle, $view_mode) {
|
|||
return $display;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the entity view display used to render an entity.
|
||||
*
|
||||
* Depending on the configuration of the view mode for the bundle, this can be
|
||||
* either the display object associated to the view mode, or the 'default'
|
||||
* display.
|
||||
*
|
||||
* This function should only be used internally when rendering an entity. When
|
||||
* assigning suggested display options for a component in a given view mode,
|
||||
* entity_get_display() should be used instead, in order to avoid inadvertently
|
||||
* modifying the output of other view modes that might happen to use the
|
||||
* 'default' display too. Those options will then be effectively applied only
|
||||
* if the view mode is configured to use them.
|
||||
*
|
||||
* @param \Drupal\Core\Entity\EntityInterface $entity
|
||||
* The entity being rendered.
|
||||
* @param string $view_mode
|
||||
* The view mode being rendered.
|
||||
*
|
||||
* @return \Drupal\Core\Entity\Display\EntityViewDisplayInterface
|
||||
* The entity view display that should be used to render the entity.
|
||||
*
|
||||
* @see entity_get_display().
|
||||
*/
|
||||
function entity_get_render_display(EntityInterface $entity, $view_mode) {
|
||||
$entity_type = $entity->getEntityTypeId();
|
||||
$bundle = $entity->bundle();
|
||||
$render_view_mode = 'default';
|
||||
|
||||
// Fall back to the default display if the display for the view mode does
|
||||
// not exist or is disabled.
|
||||
if ($view_mode != 'default') {
|
||||
$ids = array(
|
||||
'default' => $entity_type . '.' . $bundle . '.default',
|
||||
$view_mode => $entity_type . '.' . $bundle . '.' . $view_mode,
|
||||
);
|
||||
$entity_displays = entity_load_multiple('entity_view_display', $ids);
|
||||
if (isset($entity_displays[$ids[$view_mode]]) && $entity_displays[$ids[$view_mode]]->status()) {
|
||||
$render_view_mode = $view_mode;
|
||||
}
|
||||
}
|
||||
|
||||
$display = entity_get_display($entity_type, $bundle, $render_view_mode);
|
||||
$display->originalMode = $view_mode;
|
||||
|
||||
// Let modules alter the display.
|
||||
$display_context = array(
|
||||
'entity_type' => $entity_type,
|
||||
'bundle' => $bundle,
|
||||
'view_mode' => $view_mode,
|
||||
);
|
||||
drupal_alter('entity_view_display', $display, $display_context);
|
||||
|
||||
return $display;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the entity form display associated to a bundle and form mode.
|
||||
*
|
||||
|
@ -681,59 +625,6 @@ function entity_get_form_display($entity_type, $bundle, $form_mode) {
|
|||
return $entity_form_display;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the entity form display used to render an entity form.
|
||||
*
|
||||
* This function should only be used internally when rendering an entity form.
|
||||
* When assigning suggested form display options for a component in a given form
|
||||
* mode, entity_get_form_display() should be used instead, in order to avoid
|
||||
* inadvertently modifying the output of other form modes that might happen to
|
||||
* use the 'default' form display too. Those options will then be effectively
|
||||
* applied only if the form mode is configured to use them.
|
||||
*
|
||||
* @param \Drupal\Core\Entity\EntityInterface $entity
|
||||
* The entity for which the form is being rendered.
|
||||
* @param string $form_mode
|
||||
* The form mode being rendered.
|
||||
*
|
||||
* @return \Drupal\Core\Entity\Display\EntityFormDisplayInterface
|
||||
* The entity form display object that should be used to render the entity
|
||||
* form.
|
||||
*
|
||||
* @see entity_get_form_display().
|
||||
*/
|
||||
function entity_get_render_form_display(EntityInterface $entity, $form_mode) {
|
||||
$entity_type = $entity->getEntityTypeId();
|
||||
$bundle = $entity->bundle();
|
||||
$render_form_mode = 'default';
|
||||
|
||||
// Look at the default form display and form display for the view mode, and
|
||||
// fallback to the former if the latter does not exist is disabled.
|
||||
if ($form_mode != 'default') {
|
||||
$ids = array(
|
||||
'default' => $entity_type . '.' . $bundle . '.default',
|
||||
$form_mode => $entity_type . '.' . $bundle . '.' . $form_mode,
|
||||
);
|
||||
$entity_form_displays = entity_load_multiple('entity_form_display', $ids);
|
||||
if (isset($entity_form_displays[$ids[$form_mode]]) && $entity_form_displays[$ids[$form_mode]]->status()) {
|
||||
$render_form_mode = $form_mode;
|
||||
}
|
||||
}
|
||||
|
||||
$form_display = entity_get_form_display($entity_type, $bundle, $render_form_mode);
|
||||
$form_display->originalMode = $form_mode;
|
||||
|
||||
// Let modules alter the form display.
|
||||
$form_display_context = array(
|
||||
'entity_type' => $entity_type,
|
||||
'bundle' => $bundle,
|
||||
'form_mode' => $form_mode,
|
||||
);
|
||||
drupal_alter('entity_form_display', $form_display, $form_display_context);
|
||||
|
||||
return $form_display;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generic access callback for entity pages.
|
||||
*
|
||||
|
|
|
@ -10,6 +10,7 @@ namespace Drupal\Core\Entity;
|
|||
use Drupal\Core\Entity\Display\EntityFormDisplayInterface;
|
||||
use Drupal\Core\Form\FormBase;
|
||||
use Drupal\Core\Extension\ModuleHandlerInterface;
|
||||
use Drupal\entity\Entity\EntityFormDisplay;
|
||||
|
||||
/**
|
||||
* Base class for entity form controllers.
|
||||
|
@ -121,7 +122,7 @@ class EntityFormController extends FormBase implements EntityFormControllerInter
|
|||
// Prepare the entity to be presented in the entity form.
|
||||
$this->prepareEntity();
|
||||
|
||||
$form_display = entity_get_render_form_display($this->entity, $this->getOperation());
|
||||
$form_display = EntityFormDisplay::collectRenderDisplay($this->entity, $this->getOperation());
|
||||
$this->setFormDisplay($form_display, $form_state);
|
||||
|
||||
// Invoke the prepare form hooks.
|
||||
|
|
|
@ -9,9 +9,9 @@ namespace Drupal\Core\Entity;
|
|||
|
||||
use Drupal\Core\Cache\Cache;
|
||||
use Drupal\Core\Entity\Display\EntityViewDisplayInterface;
|
||||
use Drupal\Core\Extension\ModuleHandlerInterface;
|
||||
use Drupal\Core\Language\Language;
|
||||
use Drupal\Core\Language\LanguageManagerInterface;
|
||||
use Drupal\entity\Entity\EntityViewDisplay;
|
||||
use Symfony\Component\DependencyInjection\ContainerInterface;
|
||||
|
||||
/**
|
||||
|
@ -193,7 +193,6 @@ class EntityViewBuilder extends EntityControllerBase implements EntityController
|
|||
|
||||
// Build the view modes and display objects.
|
||||
$view_modes = array();
|
||||
$displays = array();
|
||||
$context = array('langcode' => $langcode);
|
||||
foreach ($entities as $key => $entity) {
|
||||
$bundle = $entity->bundle();
|
||||
|
@ -208,14 +207,10 @@ class EntityViewBuilder extends EntityControllerBase implements EntityController
|
|||
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) {
|
||||
$displays[$mode] = EntityViewDisplay::collectRenderDisplays($view_mode_entities, $mode);
|
||||
$this->buildContent($view_mode_entities, $displays[$mode], $mode, $langcode);
|
||||
}
|
||||
|
||||
|
|
|
@ -7,13 +7,14 @@
|
|||
|
||||
namespace Drupal\edit\Form;
|
||||
|
||||
use Drupal\Core\Form\FormBase;
|
||||
use Symfony\Component\DependencyInjection\ContainerInterface;
|
||||
use Drupal\Core\Entity\EntityInterface;
|
||||
use Drupal\Core\Entity\EntityStorageControllerInterface;
|
||||
use Drupal\Core\Extension\ModuleHandlerInterface;
|
||||
use Drupal\user\TempStoreFactory;
|
||||
use Drupal\Core\Entity\EntityChangedInterface;
|
||||
use Drupal\Core\Extension\ModuleHandlerInterface;
|
||||
use Drupal\Core\Form\FormBase;
|
||||
use Drupal\entity\Entity\EntityFormDisplay;
|
||||
use Drupal\user\TempStoreFactory;
|
||||
use Symfony\Component\DependencyInjection\ContainerInterface;
|
||||
|
||||
/**
|
||||
* Builds and process a form for editing a single entity field.
|
||||
|
@ -128,7 +129,7 @@ class EditFieldForm extends FormBase {
|
|||
|
||||
// @todo Allow the usage of different form modes by exposing a hook and the
|
||||
// UI for them.
|
||||
$form_state['form_display'] = entity_get_render_form_display($entity, 'default');
|
||||
$form_state['form_display'] = EntityFormDisplay::collectRenderDisplay($entity, 'default');
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -11,7 +11,7 @@ use Drupal\Component\Plugin\PluginManagerInterface;
|
|||
use Drupal\Core\Entity\EntityInterface;
|
||||
use Drupal\Core\Field\FieldItemListInterface;
|
||||
use Drupal\edit\Access\EditEntityFieldAccessCheckInterface;
|
||||
use Drupal\field\FieldInstanceInterface;
|
||||
use Drupal\entity\Entity\EntityViewDisplay;
|
||||
|
||||
/**
|
||||
* Generates in-place editing metadata for an entity field.
|
||||
|
@ -78,7 +78,7 @@ class MetadataGenerator implements MetadataGeneratorInterface {
|
|||
}
|
||||
|
||||
// Early-return if no editor is available.
|
||||
$formatter_id = entity_get_render_display($entity, $view_mode)->getRenderer($field_name)->getPluginId();
|
||||
$formatter_id = EntityViewDisplay::collectRenderDisplay($entity, $view_mode)->getRenderer($field_name)->getPluginId();
|
||||
$editor_id = $this->editorSelector->getEditor($formatter_id, $items);
|
||||
if (!isset($editor_id)) {
|
||||
return array('access' => FALSE);
|
||||
|
|
|
@ -35,6 +35,83 @@ class EntityFormDisplay extends EntityDisplayBase implements EntityFormDisplayIn
|
|||
*/
|
||||
protected $displayContext = 'form';
|
||||
|
||||
/**
|
||||
* Returns the entity_form_display object used to build an entity form.
|
||||
*
|
||||
* Depending on the configuration of the form mode for the entity bundle, this
|
||||
* can be either the display object associated to the form mode, or the
|
||||
* 'default' display.
|
||||
*
|
||||
* This method should only be used internally when rendering an entity form.
|
||||
* When assigning suggested display options for a component in a given form
|
||||
* mode, entity_get_form_display() should be used instead, in order to avoid
|
||||
* inadvertently modifying the output of other form modes that might happen to
|
||||
* use the 'default' display too. Those options will then be effectively
|
||||
* applied only if the form mode is configured to use them.
|
||||
*
|
||||
* hook_entity_form_display_alter() is invoked on each display, allowing 3rd
|
||||
* party code to alter the display options held in the display before they are
|
||||
* used to generate render arrays.
|
||||
*
|
||||
* @param \Drupal\Core\Entity\EntityInterface $entity
|
||||
* The entity for which the form is being built.
|
||||
* @param string $form_mode
|
||||
* The form mode.
|
||||
*
|
||||
* @return \Drupal\Core\Entity\Display\EntityFormDisplayInterface
|
||||
* The display object that should be used to build the entity form.
|
||||
*
|
||||
* @see entity_get_form_display()
|
||||
* @see hook_entity_form_display_alter()
|
||||
*/
|
||||
public static function collectRenderDisplay($entity, $form_mode) {
|
||||
$entity_type = $entity->getEntityTypeId();
|
||||
$bundle = $entity->bundle();
|
||||
|
||||
// Check the existence and status of:
|
||||
// - the display for the form mode,
|
||||
// - the 'default' display.
|
||||
if ($form_mode != 'default') {
|
||||
$candidate_ids[] = $entity_type . '.' . $bundle . '.' . $form_mode;
|
||||
}
|
||||
$candidate_ids[] = $entity_type . '.' . $bundle . '.default';
|
||||
$results = \Drupal::entityQuery('entity_form_display')
|
||||
->condition('id', $candidate_ids)
|
||||
->condition('status', TRUE)
|
||||
->execute();
|
||||
|
||||
// Load the first valid candidate display, if any.
|
||||
$storage = \Drupal::entityManager()->getStorageController('entity_form_display');
|
||||
foreach ($candidate_ids as $candidate_id) {
|
||||
if (isset($results[$candidate_id])) {
|
||||
$display = $storage->load($candidate_id);
|
||||
break;
|
||||
}
|
||||
}
|
||||
// Else create a fresh runtime object.
|
||||
if (empty($display)) {
|
||||
$display = $storage->create(array(
|
||||
'targetEntityType' => $entity_type,
|
||||
'bundle' => $bundle,
|
||||
'mode' => $form_mode,
|
||||
'status' => TRUE,
|
||||
));
|
||||
}
|
||||
|
||||
// Let the display know which form mode was originally requested.
|
||||
$display->originalMode = $form_mode;
|
||||
|
||||
// Let modules alter the display.
|
||||
$display_context = array(
|
||||
'entity_type' => $entity_type,
|
||||
'bundle' => $bundle,
|
||||
'form_mode' => $form_mode,
|
||||
);
|
||||
\Drupal::moduleHandler()->alter('entity_form_display', $display, $display_context);
|
||||
|
||||
return $display;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
|
||||
namespace Drupal\entity\Entity;
|
||||
|
||||
use Drupal\Component\Utility\NestedArray;
|
||||
use Drupal\Core\Entity\Display\EntityViewDisplayInterface;
|
||||
use Drupal\entity\EntityDisplayBase;
|
||||
|
||||
|
@ -35,6 +36,131 @@ class EntityViewDisplay extends EntityDisplayBase implements EntityViewDisplayIn
|
|||
*/
|
||||
protected $displayContext = 'view';
|
||||
|
||||
/**
|
||||
* Returns the display objects used to render a set of entities.
|
||||
*
|
||||
* Depending on the configuration of the view mode for each bundle, this can
|
||||
* be either the display object associated to the view mode, or the 'default'
|
||||
* display.
|
||||
*
|
||||
* This method should only be used internally when rendering an entity. When
|
||||
* assigning suggested display options for a component in a given view mode,
|
||||
* entity_get_display() should be used instead, in order to avoid
|
||||
* inadvertently modifying the output of other view modes that might happen to
|
||||
* use the 'default' display too. Those options will then be effectively
|
||||
* applied only if the view mode is configured to use them.
|
||||
*
|
||||
* hook_entity_view_display_alter() is invoked on each display, allowing 3rd
|
||||
* party code to alter the display options held in the display before they are
|
||||
* used to generate render arrays.
|
||||
*
|
||||
* @param \Drupal\Core\Entity\EntityInterface[] $entities
|
||||
* The entities being rendered. They should all be of the same entity type.
|
||||
* @param string $view_mode
|
||||
* The view mode being rendered.
|
||||
*
|
||||
* @return \Drupal\Core\Entity\Display\EntityViewDisplayInterface[]
|
||||
* The display objects to use to render the entities, keyed by entity
|
||||
* bundle.
|
||||
*
|
||||
* @see entity_get_display()
|
||||
* @see hook_entity_view_display_alter()
|
||||
*/
|
||||
public static function collectRenderDisplays($entities, $view_mode) {
|
||||
if (empty($entities)) {
|
||||
return array();
|
||||
}
|
||||
|
||||
// Collect entity type and bundles.
|
||||
$entity_type = current($entities)->getEntityTypeId();
|
||||
$bundles = array();
|
||||
foreach ($entities as $entity) {
|
||||
$bundles[$entity->bundle()] = TRUE;
|
||||
}
|
||||
$bundles = array_keys($bundles);
|
||||
|
||||
// For each bundle, check the existence and status of:
|
||||
// - the display for the view mode,
|
||||
// - the 'default' display.
|
||||
$candidate_ids = array();
|
||||
foreach ($bundles as $bundle) {
|
||||
if ($view_mode != 'default') {
|
||||
$candidate_ids[$bundle][] = $entity_type . '.' . $bundle . '.' . $view_mode;
|
||||
}
|
||||
$candidate_ids[$bundle][] = $entity_type . '.' . $bundle . '.default';
|
||||
}
|
||||
$results = \Drupal::entityQuery('entity_view_display')
|
||||
->condition('id', NestedArray::mergeDeepArray($candidate_ids))
|
||||
->condition('status', TRUE)
|
||||
->execute();
|
||||
|
||||
// For each bundle, select the first valid candidate display, if any.
|
||||
$load_ids = array();
|
||||
foreach ($bundles as $bundle) {
|
||||
foreach ($candidate_ids[$bundle] as $candidate_id) {
|
||||
if (isset($results[$candidate_id])) {
|
||||
$load_ids[$bundle] = $candidate_id;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Load the selected displays.
|
||||
$storage = \Drupal::entityManager()->getStorageController('entity_view_display');
|
||||
$displays = $storage->loadMultiple($load_ids);
|
||||
|
||||
$displays_by_bundle = array();
|
||||
foreach ($bundles as $bundle) {
|
||||
// Use the selected display if any, or create a fresh runtime object.
|
||||
if (isset($load_ids[$bundle])) {
|
||||
$display = $displays[$load_ids[$bundle]];
|
||||
}
|
||||
else {
|
||||
$display = $storage->create(array(
|
||||
'targetEntityType' => $entity_type,
|
||||
'bundle' => $bundle,
|
||||
'mode' => $view_mode,
|
||||
'status' => TRUE,
|
||||
));
|
||||
}
|
||||
|
||||
// Let the display know which view mode was originally requested.
|
||||
$display->originalMode = $view_mode;
|
||||
|
||||
// Let modules alter the display.
|
||||
$display_context = array(
|
||||
'entity_type' => $entity_type,
|
||||
'bundle' => $bundle,
|
||||
'view_mode' => $view_mode,
|
||||
);
|
||||
\Drupal::moduleHandler()->alter('entity_view_display', $display, $display_context);
|
||||
|
||||
$displays_by_bundle[$bundle] = $display;
|
||||
}
|
||||
|
||||
return $displays_by_bundle;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the display object used to render an entity.
|
||||
*
|
||||
* See the collectRenderDisplays() method for details.
|
||||
*
|
||||
* @param \Drupal\Core\Entity\EntityInterface $entity
|
||||
* The entity being rendered.
|
||||
* @param string $view_mode
|
||||
* The view mode.
|
||||
*
|
||||
* @return \Drupal\Core\Entity\Display\EntityViewDisplayInterface
|
||||
* The display object that should be used to render the entity.
|
||||
*
|
||||
* @see \Drupal\entity\Entity\EntityDisplay::collectRenderDisplays()
|
||||
*/
|
||||
public static function collectRenderDisplay($entity, $view_mode) {
|
||||
$displays = static::collectRenderDisplays(array($entity), $view_mode);
|
||||
return $displays[$entity->bundle()];
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
use Drupal\Core\Entity\ContentEntityInterface;
|
||||
use Drupal\Core\Entity\EntityInterface;
|
||||
use Drupal\Core\Template\Attribute;
|
||||
use Drupal\entity\Entity\EntityViewDisplay;
|
||||
|
||||
/*
|
||||
* Load all public Field API functions. Drupal currently has no
|
||||
|
@ -428,7 +429,7 @@ function field_view_field(ContentEntityInterface $entity, $field_name, $display_
|
|||
// Get the formatter object.
|
||||
if (is_string($display_options)) {
|
||||
$view_mode = $display_options;
|
||||
$formatter = entity_get_render_display($entity, $view_mode)->getRenderer($field_name);
|
||||
$formatter = EntityViewDisplay::collectRenderDisplay($entity, $view_mode)->getRenderer($field_name);
|
||||
}
|
||||
else {
|
||||
$view_mode = '_custom';
|
||||
|
|
Loading…
Reference in New Issue