Skip to content
Snippets Groups Projects
Commit fa1b5ba5 authored by Alex Pott's avatar Alex Pott
Browse files

Issue #2346763 by yched, msonnabaum: Improve views field rendering performance...

Issue #2346763 by yched, msonnabaum: Improve views field rendering performance by caching entity display objects.
parent 09ed9450
No related branches found
No related tags found
No related merge requests found
......@@ -9,13 +9,13 @@
use Drupal\Core\Cache\Cache;
use Drupal\Core\Entity\Display\EntityViewDisplayInterface;
use Drupal\Core\Entity\Entity\EntityViewDisplay;
use Drupal\Core\Field\FieldItemInterface;
use Drupal\Core\Field\FieldItemListInterface;
use Drupal\Core\Language\LanguageInterface;
use Drupal\Core\Language\LanguageManagerInterface;
use Drupal\Core\TypedData\TranslatableInterface;
use Drupal\Core\Render\Element;
use Drupal\Core\Entity\Entity\EntityViewDisplay;
use Symfony\Component\DependencyInjection\ContainerInterface;
/**
......@@ -60,6 +60,15 @@ class EntityViewBuilder extends EntityHandlerBase implements EntityHandlerInterf
*/
protected $languageManager;
/**
* The EntityViewDisplay objects created for individual field rendering.
*
* @see \Drupal\Core\Entity\EntityViewBuilder::getSingleFieldDisplay()
*
* @param \Drupal\Core\Entity\Display\EntityViewDisplayInterface[]
*/
protected $singleFieldDisplays;
/**
* Constructs a new EntityViewBuilder.
*
......@@ -393,32 +402,11 @@ protected function isViewModeCacheable($view_mode) {
* {@inheritdoc}
*/
public function viewField(FieldItemListInterface $items, $display_options = array()) {
$output = array();
$entity = $items->getEntity();
$field_name = $items->getFieldDefinition()->getName();
$display = $this->getSingleFieldDisplay($entity, $field_name, $display_options);
// Get the display object.
if (is_string($display_options)) {
$view_mode = $display_options;
$display = EntityViewDisplay::collectRenderDisplay($entity, $view_mode);
// Hide all fields except the current one.
foreach (array_keys($entity->getFieldDefinitions()) as $name) {
if ($name != $field_name) {
$display->removeComponent($name);
}
}
}
else {
$view_mode = '_custom';
$display = entity_create('entity_view_display', array(
'targetEntityType' => $entity->getEntityTypeId(),
'bundle' => $entity->bundle(),
'mode' => $view_mode,
'status' => TRUE,
));
$display->setComponent($field_name, $display_options);
}
$output = array();
$build = $display->build($entity);
if (isset($build[$field_name])) {
$output = $build[$field_name];
......@@ -451,4 +439,50 @@ public function viewFieldItem(FieldItemInterface $item, $display = array()) {
return $output;
}
/**
* Returns an EntityViewDisplay for rendering an individual field.
*
* @param \Drupal\Core\Entity\EntityInterface $entity
* The entity.
* @param string $field_name
* The field name.
* @param string|array $display_options
* The display options passed to the viewField() method.
*
* @return \Drupal\Core\Entity\Display\EntityViewDisplayInterface
*/
protected function getSingleFieldDisplay($entity, $field_name, $display_options) {
if (is_string($display_options)) {
// View mode: use the Display configured for the view mode.
$view_mode = $display_options;
$display = EntityViewDisplay::collectRenderDisplay($entity, $view_mode);
// Hide all fields except the current one.
foreach (array_keys($entity->getFieldDefinitions()) as $name) {
if ($name != $field_name) {
$display->removeComponent($name);
}
}
}
else {
// Array of custom display options: use a runtime Display for the
// '_custom' view mode. Persist the displays created, to reduce the number
// of objects (displays and formatter plugins) created when rendering a
// series of fields individually for cases such as views tables.
$entity_type_id = $entity->getEntityTypeId();
$bundle = $entity->bundle();
$key = $entity_type_id . ':' . $bundle . ':' . $field_name . ':' . crc32(serialize($display_options));
if (!isset($this->singleFieldDisplays[$key])) {
$this->singleFieldDisplays[$key] = EntityViewDisplay::create(array(
'targetEntityType' => $entity_type_id,
'bundle' => $bundle,
'mode' => '_custom',
'status' => TRUE,
))->setComponent($field_name, $display_options);
}
$display = $this->singleFieldDisplays[$key];
}
return $display;
}
}
......@@ -106,7 +106,7 @@ public function resetCache(array $entities = NULL);
*
* @param \Drupal\Core\Field\FieldItemListInterface $items
* FieldItemList containing the values to be displayed.
* @param array $display_options
* @param string|array $display_options
* Can be either:
* - The name of a view mode. The field will be displayed according to the
* display settings specified for this view mode in the $field
......@@ -137,7 +137,7 @@ public function viewField(FieldItemListInterface $items, $display_options = arra
*
* @param \Drupal\Core\Field\FieldItemInterface $item
* FieldItem to be displayed.
* @param array $display_options
* @param string|array $display_options
* Can be either the name of a view mode, or an array of display settings.
* See EntityViewBuilderInterface::viewField() for more information.
*
......
......@@ -740,10 +740,6 @@ public function getItems(ResultRow $values) {
'type' => $this->options['type'],
'settings' => $this->options['settings'],
'label' => 'hidden',
// Pass the View object in the display so that fields can act on it.
'views_view' => $this->view,
'views_field' => $this,
'views_row_id' => $values->index,
);
$render_array = $entity->get($this->definition['field_name'])->view($display);
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment