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