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