Code Coverage
 
Lines
Branches
Paths
Functions and Methods
Classes and Traits
Total
0.00% covered (danger)
0.00%
0 / 27
0.00% covered (danger)
0.00%
0 / 19
0.00% covered (danger)
0.00%
0 / 14
0.00% covered (danger)
0.00%
0 / 4
CRAP
0.00% covered (danger)
0.00%
0 / 1
TemplateOverride
0.00% covered (danger)
0.00%
0 / 27
0.00% covered (danger)
0.00%
0 / 19
0.00% covered (danger)
0.00%
0 / 14
0.00% covered (danger)
0.00%
0 / 4
132
0.00% covered (danger)
0.00%
0 / 1
 __construct
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 entityView
0.00% covered (danger)
0.00%
0 / 3
0.00% covered (danger)
0.00%
0 / 3
0.00% covered (danger)
0.00%
0 / 2
0.00% covered (danger)
0.00%
0 / 1
6
 suggestionsAlter
0.00% covered (danger)
0.00%
0 / 6
0.00% covered (danger)
0.00%
0 / 7
0.00% covered (danger)
0.00%
0 / 6
0.00% covered (danger)
0.00%
0 / 1
20
 themeRegistryAlter
0.00% covered (danger)
0.00%
0 / 17
0.00% covered (danger)
0.00%
0 / 8
0.00% covered (danger)
0.00%
0 / 5
0.00% covered (danger)
0.00%
0 / 1
20
1<?php
2
3declare(strict_types=1);
4
5namespace Drupal\display_builder_entity_view\Hook;
6
7use Drupal\Core\Entity\ContentEntityTypeInterface;
8use Drupal\Core\Entity\Display\EntityViewDisplayInterface;
9use Drupal\Core\Entity\EntityInterface;
10use Drupal\Core\Entity\EntityTypeManagerInterface;
11use Drupal\Core\Extension\ModuleExtensionList;
12use Drupal\Core\Hook\Attribute\Hook;
13use Drupal\Core\Hook\Order\Order;
14use Drupal\display_builder_entity_view\Entity\DisplayBuilderEntityDisplayInterface;
15
16/**
17 * Hook implementations to override entity template.
18 */
19class TemplateOverride {
20
21  /**
22   * Key to store info for template override.
23   */
24  public const KEY = 'display_builder_entity_view';
25
26  public function __construct(
27    protected ModuleExtensionList $moduleExtensionList,
28    protected EntityTypeManagerInterface $entityTypeManager,
29  ) {}
30
31  /**
32   * Implements hook_entity_view().
33   *
34   * @param array $build
35   *   The renderable array representing the entity content.
36   * @param \Drupal\Core\Entity\EntityInterface $entity
37   *   The entity being viewed.
38   * @param \Drupal\Core\Entity\Display\EntityViewDisplayInterface $display
39   *   The display configuration entity to be used to build the entity.
40   * @param string $view_mode
41   *   The view mode in which the entity is being viewed.
42   *
43   * phpcs:disable Generic.CodeAnalysis.UnusedFunctionParameter.FoundAfterLastUsed
44   */
45  #[Hook('entity_view')]
46  public function entityView(array &$build, EntityInterface $entity, EntityViewDisplayInterface $display, string $view_mode): void {
47    if (!$display instanceof DisplayBuilderEntityDisplayInterface) {
48      return;
49    }
50
51    // @todo Is isDisplayBuilderEnabled enough?
52    $build['#' . $this::KEY] = $display->isDisplayBuilderEnabled();
53  }
54
55  /**
56   * Implements hook_theme_suggestions_alter().
57   *
58   * @param array $suggestions
59   *   An array of theme hook suggestions.
60   * @param array $variables
61   *   An array of variables to pass to the theme function or template.
62   * @param string $hook
63   *   The name of the theme hook being invoked.
64   */
65  #[Hook('theme_suggestions_alter', order: Order::Last)]
66  public function suggestionsAlter(array &$suggestions, array $variables, string $hook): void {
67    $key = '#' . $this::KEY;
68
69    if (!isset($variables['elements'][$key]) || empty($variables['elements'][$key])) {
70      return;
71    }
72
73    if (isset($variables['theme_hook_original'])) {
74      // CommentViewBuilder overrides #theme to a compound suggestion like
75      // 'comment__FIELD_NAME__CONTENT_BUNDLE'.
76      // Extract the base entity type ID (first segment) so the registered
77      // suggestion 'comment__display_builder' is always used.
78      $base_hook = \explode('__', $variables['theme_hook_original'])[0];
79      $suggestions[] = $base_hook . '__display_builder';
80    }
81  }
82
83  /**
84   * Implements hook_theme_registry_alter().
85   *
86   * Add entry for display builder suggestion.
87   */
88  #[Hook('theme_registry_alter')]
89  public function themeRegistryAlter(array &$theme_registry): void {
90    $modulePath = $this->moduleExtensionList->getPath('display_builder_entity_view');
91    $templatePath = $modulePath . '/templates';
92    $entityDefinitions = $this->entityTypeManager->getDefinitions();
93
94    foreach ($entityDefinitions as $entityTypeId => $entityType) {
95      if (!$entityType instanceof ContentEntityTypeInterface) {
96        continue;
97      }
98
99      if (!isset($theme_registry[$entityTypeId])) {
100        continue;
101      }
102
103      $theme_registry[$entityTypeId . '__display_builder'] = [
104        // @todo Does the base hook always match the entity type ID?
105        'base hook' => $entityTypeId,
106        'path' => $templatePath,
107        'preprocess functions' => ['display_builder_entity_view_preprocess_entity'],
108        'render element' => 'elements',
109        'template' => 'entity',
110        'theme path' => $modulePath,
111        'type' => 'base_theme_engine',
112      ];
113    }
114  }
115
116}