Code Coverage |
||||||||||||||||
Lines |
Branches |
Paths |
Functions and Methods |
Classes and Traits |
||||||||||||
| Total | |
0.00% |
0 / 41 |
|
0.00% |
0 / 20 |
|
0.00% |
0 / 16 |
|
0.00% |
0 / 7 |
CRAP | |
0.00% |
0 / 1 |
| DisplayBuilderRoutes | |
0.00% |
0 / 41 |
|
0.00% |
0 / 20 |
|
0.00% |
0 / 16 |
|
0.00% |
0 / 7 |
240 | |
0.00% |
0 / 1 |
| __construct | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
| create | |
0.00% |
0 / 4 |
|
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
| getSubscribedEvents | |
0.00% |
0 / 3 |
|
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
| onAlterRoutes | |
0.00% |
0 / 2 |
|
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
| buildRoutes | |
0.00% |
0 / 8 |
|
0.00% |
0 / 8 |
|
0.00% |
0 / 5 |
|
0.00% |
0 / 1 |
20 | |||
| buildDisplayBuilderRoute | |
0.00% |
0 / 20 |
|
0.00% |
0 / 7 |
|
0.00% |
0 / 6 |
|
0.00% |
0 / 1 |
20 | |||
| getEntityTypes | |
0.00% |
0 / 3 |
|
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
12 | |||
| 1 | <?php |
| 2 | |
| 3 | declare(strict_types=1); |
| 4 | |
| 5 | namespace Drupal\display_builder_entity_view\Routing; |
| 6 | |
| 7 | use Drupal\Component\Utility\NestedArray; |
| 8 | use Drupal\Core\Entity\EntityTypeInterface; |
| 9 | use Drupal\Core\Entity\EntityTypeManagerInterface; |
| 10 | use Drupal\Core\Entity\FieldableEntityInterface; |
| 11 | use Drupal\Core\Extension\ModuleHandlerInterface; |
| 12 | use Drupal\Core\Routing\RouteBuildEvent; |
| 13 | use Drupal\Core\Routing\RoutingEvents; |
| 14 | use Drupal\display_builder_entity_view\Controller\EntityViewController; |
| 15 | use Symfony\Component\DependencyInjection\ContainerInterface; |
| 16 | use Symfony\Component\EventDispatcher\EventSubscriberInterface; |
| 17 | use Symfony\Component\Routing\Route; |
| 18 | use Symfony\Component\Routing\RouteCollection; |
| 19 | |
| 20 | /** |
| 21 | * Provides routes for the Display Builder UI. |
| 22 | * |
| 23 | * @internal |
| 24 | * Tagged services are internal. |
| 25 | */ |
| 26 | final 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 | } |
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.
| 31 | public function __construct( |
| 32 | private EntityTypeManagerInterface $entityTypeManager, |
| 33 | private ModuleHandlerInterface $module_handler, |
| 34 | ) {} |
| 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; |
| 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 | } |
| 39 | public static function create(ContainerInterface $container): static { |
| 40 | return new self( |
| 41 | $container->get('entity_type.manager'), |
| 42 | $container->get('module_handler'), |
| 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 | }); |
| 50 | $events = []; |
| 51 | // Run after \Drupal\field_ui\Routing\RouteSubscriber. |
| 52 | $events[RoutingEvents::ALTER] = ['onAlterRoutes', -110]; |
| 53 | |
| 54 | return $events; |
| 63 | public function onAlterRoutes(RouteBuildEvent $event): void { |
| 64 | $collection = $event->getRouteCollection(); |
| 65 | $this->buildRoutes($collection); |
| 66 | } |
| 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'); |