Code Coverage
 
Lines
Branches
Paths
Functions and Methods
Classes and Traits
Total
0.00% covered (danger)
0.00%
0 / 36
0.00% covered (danger)
0.00%
0 / 11
0.00% covered (danger)
0.00%
0 / 9
0.00% covered (danger)
0.00%
0 / 5
CRAP
0.00% covered (danger)
0.00%
0 / 1
OverridesRoutes
0.00% covered (danger)
0.00%
0 / 36
0.00% covered (danger)
0.00%
0 / 11
0.00% covered (danger)
0.00%
0 / 9
0.00% covered (danger)
0.00%
0 / 5
56
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 / 12
0.00% covered (danger)
0.00%
0 / 7
0.00% covered (danger)
0.00%
0 / 5
0.00% covered (danger)
0.00%
0 / 1
12
 buildSingleRoute
0.00% covered (danger)
0.00%
0 / 18
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
1<?php
2
3declare(strict_types=1);
4
5namespace Drupal\display_builder_entity_view\Routing;
6
7use Drupal\Core\DependencyInjection\AutowireTrait;
8use Drupal\Core\Entity\EntityTypeManagerInterface;
9use Drupal\Core\Routing\RouteBuildEvent;
10use Drupal\Core\Routing\RoutingEvents;
11use Drupal\display_builder_entity_view\Controller\EntityViewOverridesController;
12use Drupal\display_builder_entity_view\Entity\EntityViewDisplay;
13use Symfony\Component\EventDispatcher\EventSubscriberInterface;
14use Symfony\Component\Routing\Route;
15use Symfony\Component\Routing\RouteCollection;
16
17/**
18 * Provides routes for the Display Builder UI.
19 *
20 * @internal
21 *   Tagged services are internal.
22 */
23final class OverridesRoutes implements EventSubscriberInterface {
24
25  use AutowireTrait;
26
27  /**
28   * {@inheritdoc}
29   */
30  public function __construct(
31    private EntityTypeManagerInterface $entityTypeManager,
32  ) {}
33
34  /**
35   * {@inheritdoc}
36   */
37  public static function getSubscribedEvents(): array {
38    $events = [];
39    // Run after \Drupal\field_ui\Routing\RouteSubscriber.
40    $events[RoutingEvents::ALTER] = ['onAlterRoutes', -110];
41
42    return $events;
43  }
44
45  /**
46   * Alters existing routes for a specific collection.
47   *
48   * @param \Drupal\Core\Routing\RouteBuildEvent $event
49   *   The route build event.
50   */
51  public function onAlterRoutes(RouteBuildEvent $event): void {
52    $collection = $event->getRouteCollection();
53    $this->buildRoutes($collection);
54  }
55
56  /**
57   * Build routes for each display overrides.
58   *
59   * @param \Symfony\Component\Routing\RouteCollection $collection
60   *   The route collection to add the routes to.
61   */
62  private function buildRoutes(RouteCollection $collection): void {
63    $display_infos = EntityViewDisplay::getDisplayInfos($this->entityTypeManager);
64
65    foreach ($display_infos as $entity_type_id => $display_info) {
66      $entity_type = $this->entityTypeManager->getDefinition($entity_type_id);
67      $canonical = $entity_type->getLinkTemplate('canonical');
68
69      $path = \sprintf('%s/display', $canonical);
70      $forward_route = $this->buildSingleRoute($entity_type_id, $path, 'getFirstBuilder', 'checkFirstBuilderAccess');
71      $collection->add("entity.{$entity_type_id}.display_builder.forward", $forward_route);
72
73      foreach (\array_keys($display_info['modes']) as $view_mode) {
74        $path = \sprintf('%s/display/%s', $canonical, $view_mode);
75        $override_route = $this->buildSingleRoute($entity_type_id, $path, 'getBuilder', 'checkAccess');
76        $override_route->addDefaults(['view_mode_name' => $view_mode]);
77        $collection->add("entity.{$entity_type_id}.display_builder.{$view_mode}", $override_route);
78      }
79    }
80  }
81
82  /**
83   * Build single display overrides route.
84   *
85   * @param string $entity_type_id
86   *   The entity type ID.
87   * @param string $path
88   *   The path for the route.
89   * @param string $controller
90   *   The controller method to call.
91   * @param string $custom_access
92   *   The custom access check method.
93   *
94   * @return \Symfony\Component\Routing\Route
95   *   The built route.
96   */
97  private function buildSingleRoute(string $entity_type_id, string $path, string $controller, string $custom_access): Route {
98    $defaults = [
99      '_controller' => EntityViewOverridesController::class . '::' . $controller,
100      '_title_callback' => EntityViewOverridesController::class . '::title',
101      'entity_type_id' => $entity_type_id,
102    ];
103    $requirements = [
104      '_entity_access' => "{$entity_type_id}.update",
105      '_custom_access' => EntityViewOverridesController::class . '::' . $custom_access,
106    ];
107    $main_options = [
108      'parameters' => [
109        $entity_type_id => ['type' => 'entity:' . $entity_type_id],
110      ],
111    ];
112
113    return (new Route($path))
114      ->setDefaults($defaults)
115      ->setRequirements($requirements)
116      ->setOptions($main_options);
117  }
118
119}