Issue #2498849 by catch, dawehner: Entity view controller title rendering is expensive

8.0.x
Alex Pott 2015-06-05 20:04:08 +01:00
parent 2f370af9c5
commit 4fb37aa1ff
4 changed files with 31 additions and 100 deletions

View File

@ -56,6 +56,31 @@ class EntityViewController implements ContainerInjectionInterface {
);
}
/**
* Pre-render callback to build the page title.
*
* @param array $page
* A page render array.
*
* @return array
* The changed page render array.
*/
public function buildTitle(array $page) {
$entity_type = $page['#entity_type'];
$entity = $page['#' . $entity_type];
// If the entity's label is rendered using a field formatter, set the
// rendered title field formatter as the page title instead of the default
// plain text title. This allows attributes set on the field to propagate
// correctly (e.g. RDFa, in-place editing).
if ($entity instanceof FieldableEntityInterface) {
$label_field = $entity->getEntityType()->getKey('label');
if (isset($page[$label_field])) {
$page['#title'] = $this->renderer->render($page[$label_field]);
}
}
return $page;
}
/**
* Provides a page to render a single entity.
*
@ -78,22 +103,9 @@ class EntityViewController implements ContainerInjectionInterface {
->getViewBuilder($_entity->getEntityTypeId())
->view($_entity, $view_mode, $langcode);
// If the entity's label is rendered using a field formatter, set the
// rendered title field formatter as the page title instead of the default
// plain text title. This allows attributes set on the field to propagate
// correctly (e.g. RDFa, in-place editing).
if ($_entity instanceof FieldableEntityInterface) {
$label_field = $_entity->getEntityType()->getKey('label');
if ($label_field && $_entity->getFieldDefinition($label_field)->getDisplayOptions('view')) {
// We must render the label field, because rendering the entity may be
// a cache hit, in which case we can't extract the rendered label field
// from the $page renderable array.
$build = $this->entityManager->getTranslationFromContext($_entity)
->get($label_field)
->view($view_mode);
$page['#title'] = $this->renderer->render($build);
}
}
$page['#pre_render'][] = [$this, 'buildTitle'];
$page['#entity_type'] = $_entity->getEntityTypeId();
return $page;
}

View File

@ -21,15 +21,12 @@ class NodePreviewController extends EntityViewController {
*/
public function view(EntityInterface $node_preview, $view_mode_id = 'full', $langcode = NULL) {
$node_preview->preview_view_mode = $view_mode_id;
$build = array('nodes' => parent::view($node_preview, $view_mode_id));
$build = parent::view($node_preview, $view_mode_id);
$build['#attached']['library'][] = 'node/drupal.node.preview';
$build['#title'] = $build['nodes']['#title'];
unset($build['nodes']['#title']);
// Don't render cache previews.
unset($build['nodes']['#cache']);
unset($build['#cache']);
foreach ($node_preview->uriRelationships() as $rel) {
// Set the node path as the canonical URL to prevent duplicate content.

View File

@ -20,10 +20,7 @@ class NodeViewController extends EntityViewController {
* {@inheritdoc}
*/
public function view(EntityInterface $node, $view_mode = 'full', $langcode = NULL) {
$build = array('nodes' => parent::view($node));
$build['#title'] = $build['nodes']['#title'];
unset($build['nodes']['#title']);
$build = parent::view($node);
foreach ($node->uriRelationships() as $rel) {
// Set the node path as the canonical URL to prevent duplicate content.

View File

@ -1,75 +0,0 @@
<?php
/**
* @file
* Contains \Drupal\Tests\Core\Entity\Controller\EntityViewControllerTest.
*/
namespace Drupal\Tests\Core\Entity\Controller;
use Drupal\Core\Entity\Controller\EntityViewController;
use Drupal\Tests\UnitTestCase;
/**
* @coversDefaultClass \Drupal\Core\Entity\Controller\EntityViewController
* @group Entity
*/
class EntityViewControllerTest extends UnitTestCase{
/**
* Tests the enhancer method.
*
* @see \Drupal\Core\Entity\Controller\EntityViewController::view()
*/
public function testView() {
// Mock a view builder.
$render_controller = $this->getMockBuilder('Drupal\entity_test\EntityTestViewBuilder')
->disableOriginalConstructor()
->getMock();
$render_controller->expects($this->any())
->method('view')
->will($this->returnValue('Output from rendering the entity'));
// Mock an entity manager.
$entity_manager = $this->getMock('Drupal\Core\Entity\EntityManagerInterface');
$entity_manager->expects($this->any())
->method('getViewBuilder')
->will($this->returnValue($render_controller));
// Mock the 'entity_test' entity type.
$entity_type = $this->getMockBuilder('Drupal\Core\Entity\ContentEntityType')
->disableOriginalConstructor()
->getMock();
$entity_type->expects($this->once())
->method('getKey')
->with('label')
->will($this->returnValue('name'));
// Mock the 'name' field's definition.
$field_definition = $this->getMock('Drupal\Core\Field\BaseFieldDefinition');
$field_definition->expects($this->any())
->method('getDisplayOptions')
->with('view')
->will($this->returnValue(NULL));
// Mock an 'entity_test' entity.
$entity = $this->getMockBuilder('Drupal\entity_test\Entity\EntityTest')
->disableOriginalConstructor()
->getMock();
$entity->expects($this->once())
->method('getEntityType')
->will($this->returnValue($entity_type));
$entity->expects($this->any())
->method('getFieldDefinition')
->with('name')
->will($this->returnValue($field_definition));
// Initialize the controller to test.
$controller = new EntityViewController($entity_manager, $this->getMock('Drupal\Core\Render\RendererInterface'));
// Test the view method.
$this->assertEquals($controller->view($entity, 'full'), 'Output from rendering the entity');
}
}