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

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
31  public function __construct(
32    private EntityTypeManagerInterface $entityTypeManager,
33    private ModuleHandlerInterface $module_handler,
34  ) {}
DisplayBuilderRoutes->buildDisplayBuilderRoute
101  private function buildDisplayBuilderRoute(EntityTypeInterface $entity_type, Route $entity_route): Route {
102    $path = $entity_route->getPath() . '/display/{view_mode_name}/display-builder';
103
104    $defaults = [];
105    $entity_type_id = $entity_type->id();
106    $defaults['entity_type_id'] = $entity_type_id;
107
108    // If the entity type has no bundles and it doesn't use {bundle} in its
109    // admin path, use the entity type.
110    if (!\str_contains($path, '{bundle}')) {
111      if (!$entity_type->hasKey('bundle')) {
111      if (!$entity_type->hasKey('bundle')) {
112        $defaults['bundle'] = $entity_type_id;
115        $defaults['bundle_key'] = $entity_type->getBundleEntityType();
116      }
117    }
118
119    $requirements = [];
119    $requirements = [];
120    $requirements['_field_ui_view_mode_access'] = 'administer ' . $entity_type_id . ' display';
121
122    $options = $entity_route->getOptions();
123    $options['_admin_route'] = FALSE;
124
125    // @todo add the display builder access check
126    // $requirements['_display_builder_access'] = 'view';
127    // Trigger the display builder RouteEnhancer.
128    $parameters = [];
129    // Merge the passed in options in after parameters.
130    $options = NestedArray::mergeDeep(['parameters' => $parameters], $options);
131
132    $defaults['_controller'] = EntityViewController::class . '::getBuilder';
133    $defaults['_title_callback'] = EntityViewController::class . '::title';
134    $route = (new Route($path))->setDefaults($defaults)->setRequirements($requirements)->setOptions($options);
135
136    // Set field_ui.route_enhancer to run on the manage layout form?
137    if (isset($defaults['bundle_key'])) {
138      $route->setOption('_field_ui', TRUE)->setDefault('bundle', '');
139    }
140
141    return $route;
141    return $route;
DisplayBuilderRoutes->buildRoutes
74  private function buildRoutes(RouteCollection $collection): void {
75    if (!$this->module_handler->moduleExists('field_ui')) {
76      return;
79    foreach ($this->getEntityTypes() as $entity_type_id => $entity_type) {
79    foreach ($this->getEntityTypes() as $entity_type_id => $entity_type) {
79    foreach ($this->getEntityTypes() as $entity_type_id => $entity_type) {
80      // Try to get the route from the current collection.
81      if (!$entity_route = $collection->get($entity_type->get('field_ui_base_route'))) {
82        continue;
79    foreach ($this->getEntityTypes() as $entity_type_id => $entity_type) {
80      // Try to get the route from the current collection.
81      if (!$entity_route = $collection->get($entity_type->get('field_ui_base_route'))) {
82        continue;
83      }
84      $route_name = 'display_builder_entity_view.' . $entity_type_id;
79    foreach ($this->getEntityTypes() as $entity_type_id => $entity_type) {
80      // Try to get the route from the current collection.
81      if (!$entity_route = $collection->get($entity_type->get('field_ui_base_route'))) {
82        continue;
83      }
84      $route_name = 'display_builder_entity_view.' . $entity_type_id;
85      $route = $this->buildDisplayBuilderRoute($entity_type, $entity_route);
86      $collection->add($route_name, $route);
87    }
88  }
DisplayBuilderRoutes->create
39  public static function create(ContainerInterface $container): static {
40    return new self(
41      $container->get('entity_type.manager'),
42      $container->get('module_handler'),
DisplayBuilderRoutes->getEntityTypes
151    return \array_filter($this->entityTypeManager->getDefinitions(), static function (EntityTypeInterface $entity_type) {
152      return $entity_type->entityClassImplements(FieldableEntityInterface::class) && $entity_type->hasViewBuilderClass() && $entity_type->get('field_ui_base_route');
153    });
DisplayBuilderRoutes->getSubscribedEvents
50    $events = [];
51    // Run after \Drupal\field_ui\Routing\RouteSubscriber.
52    $events[RoutingEvents::ALTER] = ['onAlterRoutes', -110];
53
54    return $events;
DisplayBuilderRoutes->onAlterRoutes
63  public function onAlterRoutes(RouteBuildEvent $event): void {
64    $collection = $event->getRouteCollection();
65    $this->buildRoutes($collection);
66  }
{closure:/var/www/html/web/modules/custom/display_builder/modules/display_builder_entity_view/src/Routing/DisplayBuilderRoutes.php:151-153}
151    return \array_filter($this->entityTypeManager->getDefinitions(), static function (EntityTypeInterface $entity_type) {
152      return $entity_type->entityClassImplements(FieldableEntityInterface::class) && $entity_type->hasViewBuilderClass() && $entity_type->get('field_ui_base_route');
152      return $entity_type->entityClassImplements(FieldableEntityInterface::class) && $entity_type->hasViewBuilderClass() && $entity_type->get('field_ui_base_route');
152      return $entity_type->entityClassImplements(FieldableEntityInterface::class) && $entity_type->hasViewBuilderClass() && $entity_type->get('field_ui_base_route');
152      return $entity_type->entityClassImplements(FieldableEntityInterface::class) && $entity_type->hasViewBuilderClass() && $entity_type->get('field_ui_base_route');