Code Coverage
 
Lines
Branches
Paths
Functions and Methods
Classes and Traits
Total
0.00% covered (danger)
0.00%
0 / 37
0.00% covered (danger)
0.00%
0 / 19
0.00% covered (danger)
0.00%
0 / 15
0.00% covered (danger)
0.00%
0 / 6
CRAP
0.00% covered (danger)
0.00%
0 / 1
DisplayBuilderRoutes
0.00% covered (danger)
0.00%
0 / 37
0.00% covered (danger)
0.00%
0 / 19
0.00% covered (danger)
0.00%
0 / 15
0.00% covered (danger)
0.00%
0 / 6
182
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
 getSubscribedEvents
0.00% covered (danger)
0.00%
0 / 3
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
 onAlterRoutes
0.00% covered (danger)
0.00%
0 / 2
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
 buildRoutes
0.00% covered (danger)
0.00%
0 / 8
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
 buildDisplayBuilderRoute
0.00% covered (danger)
0.00%
0 / 20
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
 getEntityTypes
0.00% covered (danger)
0.00%
0 / 3
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
6
1<?php
2
3declare(strict_types=1);
4
5namespace Drupal\display_builder_entity_view\Routing;
6
7use Drupal\Component\Utility\NestedArray;
8use Drupal\Core\DependencyInjection\AutowireTrait;
9use Drupal\Core\Entity\EntityTypeInterface;
10use Drupal\Core\Entity\EntityTypeManagerInterface;
11use Drupal\Core\Extension\ModuleHandlerInterface;
12use Drupal\Core\Routing\RouteBuildEvent;
13use Drupal\Core\Routing\RoutingEvents;
14use Drupal\display_builder\DisplayBuilderHelpers;
15use Drupal\display_builder_entity_view\Controller\EntityViewController;
16use Symfony\Component\EventDispatcher\EventSubscriberInterface;
17use Symfony\Component\Routing\Route;
18use Symfony\Component\Routing\RouteCollection;
19
20/**
21 * Provides routes for the Display Builder UI.
22 *
23 * @internal
24 *   Tagged services are internal.
25 */
26final class DisplayBuilderRoutes implements EventSubscriberInterface {
27
28  use AutowireTrait;
29
30  /**
31   * {@inheritdoc}
32   */
33  public function __construct(
34    private EntityTypeManagerInterface $entityTypeManager,
35    private ModuleHandlerInterface $module_handler,
36  ) {}
37
38  /**
39   * {@inheritdoc}
40   */
41  public static function getSubscribedEvents(): array {
42    $events = [];
43    // Run after \Drupal\field_ui\Routing\RouteSubscriber.
44    $events[RoutingEvents::ALTER] = ['onAlterRoutes', -110];
45
46    return $events;
47  }
48
49  /**
50   * Alters existing routes for a specific collection.
51   *
52   * @param \Drupal\Core\Routing\RouteBuildEvent $event
53   *   The route build event.
54   */
55  public function onAlterRoutes(RouteBuildEvent $event): void {
56    $collection = $event->getRouteCollection();
57    $this->buildRoutes($collection);
58  }
59
60  /**
61   * Build Display Builder routes for each existing entity view display.
62   *
63   * @param \Symfony\Component\Routing\RouteCollection $collection
64   *   The route collection to add the routes to.
65   */
66  private function buildRoutes(RouteCollection $collection): void {
67    if (!$this->module_handler->moduleExists('field_ui')) {
68      return;
69    }
70
71    foreach ($this->getEntityTypes() as $entity_type_id => $entity_type) {
72      // Try to get the route from the current collection.
73      if (!$entity_route = $collection->get($entity_type->get('field_ui_base_route'))) {
74        continue;
75      }
76      $route_name = 'display_builder_entity_view.' . $entity_type_id;
77      $route = $this->buildDisplayBuilderRoute($entity_type, $entity_route);
78      $collection->add($route_name, $route);
79    }
80  }
81
82  /**
83   * Build a Display Builder route from an existing Entity View Display route.
84   *
85   * @param \Drupal\Core\Entity\EntityTypeInterface $entity_type
86   *   The entity type for which to build the route.
87   * @param \Symfony\Component\Routing\Route $entity_route
88   *   The existing entity view display route.
89   *
90   * @return \Symfony\Component\Routing\Route
91   *   The new route for the Display Builder.
92   */
93  private function buildDisplayBuilderRoute(EntityTypeInterface $entity_type, Route $entity_route): Route {
94    $path = $entity_route->getPath() . '/display/{view_mode_name}/display-builder';
95
96    $defaults = [];
97    $entity_type_id = $entity_type->id();
98    $defaults['entity_type_id'] = $entity_type_id;
99
100    // If the entity type has no bundles and it doesn't use {bundle} in its
101    // admin path, use the entity type.
102    if (!\str_contains($path, '{bundle}')) {
103      if (!$entity_type->hasKey('bundle')) {
104        $defaults['bundle'] = $entity_type_id;
105      }
106      else {
107        $defaults['bundle_key'] = $entity_type->getBundleEntityType();
108      }
109    }
110
111    $requirements = [];
112    $requirements['_field_ui_view_mode_access'] = 'administer ' . $entity_type_id . ' display';
113
114    $options = $entity_route->getOptions();
115    $options['_admin_route'] = FALSE;
116
117    // @todo add the display builder access check
118    // $requirements['_display_builder_access'] = 'view';
119    // Trigger the display builder RouteEnhancer.
120    $parameters = [];
121    // Merge the passed in options in after parameters.
122    $options = NestedArray::mergeDeep(['parameters' => $parameters], $options);
123
124    $defaults['_controller'] = EntityViewController::class . '::getBuilder';
125    $defaults['_title_callback'] = EntityViewController::class . '::title';
126    $route = (new Route($path))->setDefaults($defaults)->setRequirements($requirements)->setOptions($options);
127
128    // Set field_ui.route_enhancer to run on the manage layout form?
129    if (isset($defaults['bundle_key'])) {
130      $route->setOption('_field_ui', TRUE)->setDefault('bundle', '');
131    }
132
133    return $route;
134  }
135
136  /**
137   * Returns an array of relevant entity types.
138   *
139   * @return \Drupal\Core\Entity\EntityTypeInterface[]
140   *   An array of entity types.
141   */
142  private function getEntityTypes(): array {
143    return \array_filter($this->entityTypeManager->getDefinitions(), static function (EntityTypeInterface $entity_type) {
144      return DisplayBuilderHelpers::isDisplayBuilderEntityType($entity_type) && $entity_type->get('field_ui_base_route');
145    });
146  }
147
148}

Branches

Below are the source code lines that represent each code branch as identified by Xdebug. Please note a branch is not necessarily coterminous with a line, a line may contain multiple branches and therefore show up more than once. Please also be aware that some branches may be implicit rather than explicit, e.g. an if statement always has an else as part of its logical flow even if you didn't write one.

DisplayBuilderRoutes->__construct
34    private EntityTypeManagerInterface $entityTypeManager,
35    private ModuleHandlerInterface $module_handler,
36  ) {}
DisplayBuilderRoutes->buildDisplayBuilderRoute
93  private function buildDisplayBuilderRoute(EntityTypeInterface $entity_type, Route $entity_route): Route {
94    $path = $entity_route->getPath() . '/display/{view_mode_name}/display-builder';
95
96    $defaults = [];
97    $entity_type_id = $entity_type->id();
98    $defaults['entity_type_id'] = $entity_type_id;
99
100    // If the entity type has no bundles and it doesn't use {bundle} in its
101    // admin path, use the entity type.
102    if (!\str_contains($path, '{bundle}')) {
103      if (!$entity_type->hasKey('bundle')) {
103      if (!$entity_type->hasKey('bundle')) {
104        $defaults['bundle'] = $entity_type_id;
107        $defaults['bundle_key'] = $entity_type->getBundleEntityType();
108      }
109    }
110
111    $requirements = [];
111    $requirements = [];
112    $requirements['_field_ui_view_mode_access'] = 'administer ' . $entity_type_id . ' display';
113
114    $options = $entity_route->getOptions();
115    $options['_admin_route'] = FALSE;
116
117    // @todo add the display builder access check
118    // $requirements['_display_builder_access'] = 'view';
119    // Trigger the display builder RouteEnhancer.
120    $parameters = [];
121    // Merge the passed in options in after parameters.
122    $options = NestedArray::mergeDeep(['parameters' => $parameters], $options);
123
124    $defaults['_controller'] = EntityViewController::class . '::getBuilder';
125    $defaults['_title_callback'] = EntityViewController::class . '::title';
126    $route = (new Route($path))->setDefaults($defaults)->setRequirements($requirements)->setOptions($options);
127
128    // Set field_ui.route_enhancer to run on the manage layout form?
129    if (isset($defaults['bundle_key'])) {
130      $route->setOption('_field_ui', TRUE)->setDefault('bundle', '');
131    }
132
133    return $route;
133    return $route;
134  }
DisplayBuilderRoutes->buildRoutes
66  private function buildRoutes(RouteCollection $collection): void {
67    if (!$this->module_handler->moduleExists('field_ui')) {
68      return;
71    foreach ($this->getEntityTypes() as $entity_type_id => $entity_type) {
71    foreach ($this->getEntityTypes() as $entity_type_id => $entity_type) {
71    foreach ($this->getEntityTypes() as $entity_type_id => $entity_type) {
72      // Try to get the route from the current collection.
73      if (!$entity_route = $collection->get($entity_type->get('field_ui_base_route'))) {
74        continue;
71    foreach ($this->getEntityTypes() as $entity_type_id => $entity_type) {
72      // Try to get the route from the current collection.
73      if (!$entity_route = $collection->get($entity_type->get('field_ui_base_route'))) {
74        continue;
75      }
76      $route_name = 'display_builder_entity_view.' . $entity_type_id;
71    foreach ($this->getEntityTypes() as $entity_type_id => $entity_type) {
72      // Try to get the route from the current collection.
73      if (!$entity_route = $collection->get($entity_type->get('field_ui_base_route'))) {
74        continue;
75      }
76      $route_name = 'display_builder_entity_view.' . $entity_type_id;
77      $route = $this->buildDisplayBuilderRoute($entity_type, $entity_route);
78      $collection->add($route_name, $route);
79    }
80  }
DisplayBuilderRoutes->getEntityTypes
143    return \array_filter($this->entityTypeManager->getDefinitions(), static function (EntityTypeInterface $entity_type) {
144      return DisplayBuilderHelpers::isDisplayBuilderEntityType($entity_type) && $entity_type->get('field_ui_base_route');
145    });
146  }
DisplayBuilderRoutes->getSubscribedEvents
42    $events = [];
43    // Run after \Drupal\field_ui\Routing\RouteSubscriber.
44    $events[RoutingEvents::ALTER] = ['onAlterRoutes', -110];
45
46    return $events;
47  }
DisplayBuilderRoutes->onAlterRoutes
55  public function onAlterRoutes(RouteBuildEvent $event): void {
56    $collection = $event->getRouteCollection();
57    $this->buildRoutes($collection);
58  }
{closure:/var/www/html/web/modules/custom/display_builder/modules/display_builder_entity_view/src/Routing/DisplayBuilderRoutes.php:143-145}
143    return \array_filter($this->entityTypeManager->getDefinitions(), static function (EntityTypeInterface $entity_type) {
144      return DisplayBuilderHelpers::isDisplayBuilderEntityType($entity_type) && $entity_type->get('field_ui_base_route');
144      return DisplayBuilderHelpers::isDisplayBuilderEntityType($entity_type) && $entity_type->get('field_ui_base_route');
144      return DisplayBuilderHelpers::isDisplayBuilderEntityType($entity_type) && $entity_type->get('field_ui_base_route');
145    });