1<?php 2 3namespace Drupal\Core\Entity\Controller; 4 5use Drupal\Core\DependencyInjection\ContainerInjectionInterface; 6use Drupal\Core\Entity\EntityInterface; 7use Drupal\Core\Entity\EntityTypeManagerInterface; 8use Drupal\Core\Entity\FieldableEntityInterface; 9use Drupal\Core\Security\TrustedCallbackInterface; 10use Drupal\Core\Render\RendererInterface; 11use Symfony\Component\DependencyInjection\ContainerInterface; 12 13/** 14 * Defines a generic controller to render a single entity. 15 */ 16class EntityViewController implements ContainerInjectionInterface, TrustedCallbackInterface { 17 18 /** 19 * The entity type manager. 20 * 21 * @var \Drupal\Core\Entity\EntityTypeManagerInterface 22 */ 23 protected $entityTypeManager; 24 25 /** 26 * The renderer service. 27 * 28 * @var \Drupal\Core\Render\RendererInterface 29 */ 30 protected $renderer; 31 32 /** 33 * Creates an EntityViewController object. 34 * 35 * @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager 36 * The entity type manager. 37 * @param \Drupal\Core\Render\RendererInterface $renderer 38 * The renderer service. 39 */ 40 public function __construct(EntityTypeManagerInterface $entity_type_manager, RendererInterface $renderer) { 41 $this->entityTypeManager = $entity_type_manager; 42 $this->renderer = $renderer; 43 } 44 45 /** 46 * {@inheritdoc} 47 */ 48 public static function create(ContainerInterface $container) { 49 return new static( 50 $container->get('entity_type.manager'), 51 $container->get('renderer') 52 ); 53 } 54 55 /** 56 * Pre-render callback to build the page title. 57 * 58 * @param array $page 59 * A page render array. 60 * 61 * @return array 62 * The changed page render array. 63 */ 64 public function buildTitle(array $page) { 65 $entity_type = $page['#entity_type']; 66 $entity = $page['#' . $entity_type]; 67 // If the entity's label is rendered using a field formatter, set the 68 // rendered title field formatter as the page title instead of the default 69 // plain text title. This allows attributes set on the field to propagate 70 // correctly (e.g. RDFa, in-place editing). 71 if ($entity instanceof FieldableEntityInterface) { 72 $label_field = $entity->getEntityType()->getKey('label'); 73 if (isset($page[$label_field])) { 74 $page['#title'] = $this->renderer->render($page[$label_field]); 75 } 76 } 77 return $page; 78 } 79 80 /** 81 * Provides a page to render a single entity. 82 * 83 * @param \Drupal\Core\Entity\EntityInterface $_entity 84 * The Entity to be rendered. Note this variable is named $_entity rather 85 * than $entity to prevent collisions with other named placeholders in the 86 * route. 87 * @param string $view_mode 88 * (optional) The view mode that should be used to display the entity. 89 * Defaults to 'full'. 90 * 91 * @return array 92 * A render array as expected by 93 * \Drupal\Core\Render\RendererInterface::render(). 94 */ 95 public function view(EntityInterface $_entity, $view_mode = 'full') { 96 $page = $this->entityTypeManager 97 ->getViewBuilder($_entity->getEntityTypeId()) 98 ->view($_entity, $view_mode); 99 100 $page['#pre_render'][] = [$this, 'buildTitle']; 101 $page['#entity_type'] = $_entity->getEntityTypeId(); 102 $page['#' . $page['#entity_type']] = $_entity; 103 104 return $page; 105 } 106 107 /** 108 * {@inheritdoc} 109 */ 110 public static function trustedCallbacks() { 111 return ['buildTitle']; 112 } 113 114 /** 115 * Provides a page to render a single entity revision. 116 * 117 * @param \Drupal\Core\Entity\EntityInterface $_entity_revision 118 * The Entity to be rendered. Note this variable is named $_entity_revision 119 * rather than $entity to prevent collisions with other named placeholders 120 * in the route. 121 * @param string $view_mode 122 * (optional) The view mode that should be used to display the entity. 123 * Defaults to 'full'. 124 * 125 * @return array 126 * A render array. 127 */ 128 public function viewRevision(EntityInterface $_entity_revision, $view_mode = 'full') { 129 return $this->view($_entity_revision, $view_mode); 130 } 131 132} 133