diff --git a/core/core.services.yml b/core/core.services.yml index 20b8651..8993e8b 100644 --- a/core/core.services.yml +++ b/core/core.services.yml @@ -297,7 +297,7 @@ services: arguments: ['@database'] router.builder: class: Drupal\Core\Routing\RouteBuilder - arguments: ['@router.dumper', '@lock', '@event_dispatcher', '@module_handler'] + arguments: ['@router.dumper', '@lock', '@event_dispatcher', '@module_handler', '@controller_resolver'] path.alias_manager.cached: class: Drupal\Core\CacheDecorator\AliasManagerCacheDecorator arguments: ['@path.alias_manager', '@cache.path'] diff --git a/core/lib/Drupal/Core/Routing/RouteBuilder.php b/core/lib/Drupal/Core/Routing/RouteBuilder.php index 45e1024..37122c8 100644 --- a/core/lib/Drupal/Core/Routing/RouteBuilder.php +++ b/core/lib/Drupal/Core/Routing/RouteBuilder.php @@ -8,6 +8,7 @@ namespace Drupal\Core\Routing; use Drupal\Component\Discovery\YamlDiscovery; +use Drupal\Core\Controller\ControllerResolverInterface; use Symfony\Component\EventDispatcher\EventDispatcherInterface; use Symfony\Component\Yaml\Parser; use Symfony\Component\Routing\RouteCollection; @@ -60,6 +61,13 @@ class RouteBuilder { protected $moduleHandler; /** + * The controller resolver. + * + * @var \Drupal\Core\Controller\ControllerResolverInterface + */ + protected $controllerResolver; + + /** * Construcs the RouteBuilder using the passed MatcherDumperInterface. * * @param \Drupal\Core\Routing\MatcherDumperInterface $dumper @@ -70,12 +78,15 @@ class RouteBuilder { * The event dispatcher to notify of routes. * @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler * The module handler. + * @param \Drupal\Core\Controller\ControllerResolverInterface $controller_resolver + * The controller resolver. */ - public function __construct(MatcherDumperInterface $dumper, LockBackendInterface $lock, EventDispatcherInterface $dispatcher, ModuleHandlerInterface $module_handler) { + public function __construct(MatcherDumperInterface $dumper, LockBackendInterface $lock, EventDispatcherInterface $dispatcher, ModuleHandlerInterface $module_handler, ControllerResolverInterface $controller_resolver) { $this->dumper = $dumper; $this->lock = $lock; $this->dispatcher = $dispatcher; $this->moduleHandler = $module_handler; + $this->controllerResolver = $controller_resolver; } /** @@ -98,6 +109,21 @@ public function rebuild() { foreach ($yaml_discovery->findAll() as $module => $routes) { $collection = new RouteCollection(); + $dynamic_routes = array(); + foreach ($routes as $name => $route_info) { + if (isset($route_info['provider'])) { + $route_info += array( + 'weight' => 0, + ); + // @todo Take into account $route_info['weight']. + $controller = $this->controllerResolver->getControllerFromDefinition($route_info['provider']); + $dynamic_routes += call_user_func($controller); + // Remove the dynamic route from the set. + unset($routes[$name]); + } + } + // Add any dynamic routes into the set to be processed. + $routes += $dynamic_routes; foreach ($routes as $name => $route_info) { $route_info += array( 'defaults' => array(), diff --git a/core/modules/field_ui/field_ui.routing.yml b/core/modules/field_ui/field_ui.routing.yml index 636d534..067dba6 100644 --- a/core/modules/field_ui/field_ui.routing.yml +++ b/core/modules/field_ui/field_ui.routing.yml @@ -4,3 +4,7 @@ field_ui.list: _entity_list: 'field_entity' requirements: _permission: 'administer content types' + +field_ui.*: + provider: '\Drupal\field_ui\Routing\RouteSubscriber::routes' + weight: -100 diff --git a/core/modules/field_ui/field_ui.services.yml b/core/modules/field_ui/field_ui.services.yml index 10752b0..1f4cebe 100644 --- a/core/modules/field_ui/field_ui.services.yml +++ b/core/modules/field_ui/field_ui.services.yml @@ -1,9 +1,4 @@ services: - field_ui.subscriber: - class: Drupal\field_ui\Routing\RouteSubscriber - arguments: ['@entity.manager', '@router.route_provider'] - tags: - - { name: event_subscriber } access_check.field_ui.view_mode: class: Drupal\field_ui\Access\ViewModeAccessCheck arguments: ['@entity.manager'] diff --git a/core/modules/field_ui/lib/Drupal/field_ui/Routing/RouteSubscriber.php b/core/modules/field_ui/lib/Drupal/field_ui/Routing/RouteSubscriber.php index 048630a..b1b3180 100644 --- a/core/modules/field_ui/lib/Drupal/field_ui/Routing/RouteSubscriber.php +++ b/core/modules/field_ui/lib/Drupal/field_ui/Routing/RouteSubscriber.php @@ -7,18 +7,16 @@ namespace Drupal\field_ui\Routing; +use Drupal\Core\DependencyInjection\ContainerInjectionInterface; use Drupal\Core\Entity\EntityManagerInterface; use Drupal\Core\Routing\RouteProviderInterface; -use Drupal\Core\Routing\RouteSubscriberBase; -use Drupal\Core\Routing\RoutingEvents; +use Symfony\Component\DependencyInjection\ContainerInterface; use Symfony\Component\Routing\Exception\RouteNotFoundException; -use Symfony\Component\Routing\Route; -use Symfony\Component\Routing\RouteCollection; /** * Subscriber for Field UI routes. */ -class RouteSubscriber extends RouteSubscriberBase { +class RouteSubscriber implements ContainerInjectionInterface { /** * The entity type manager @@ -50,110 +48,103 @@ public function __construct(EntityManagerInterface $manager, RouteProviderInterf /** * {@inheritdoc} */ - protected function routes(RouteCollection $collection) { + public static function create(ContainerInterface $container) { + return new static( + $container->get('entity.manager'), + $container->get('router.route_provider') + ); + } + + /** + * {@inheritdoc} + */ + public function routes() { + $routes = array(); foreach ($this->manager->getDefinitions() as $entity_type => $entity_info) { $defaults = array(); if ($entity_info['fieldable'] && isset($entity_info['links']['admin-form'])) { - // First try to get the route from the dynamic_routes collection. - if (!$entity_route = $collection->get($entity_info['links']['admin-form'])) { - // Then try to get the route from the route provider itself, checking - // all previous collections. - try { - $entity_route = $this->routeProvider->getRouteByName($entity_info['links']['admin-form']); - } - // If the route was not found, skip this entity type. - catch (RouteNotFoundException $e) { - continue; - } + // Try to get the route from the route provider itself, checking + // all previous collections. + try { + $entity_route = $this->routeProvider->getRouteByName($entity_info['links']['admin-form']); + } + // If the route was not found, skip this entity type. + catch (RouteNotFoundException $e) { + continue; } $path = $entity_route->getPath(); - $route = new Route( - "$path/fields/{field_instance}", - array('_form' => '\Drupal\field_ui\Form\FieldInstanceEditForm'), - array('_permission' => 'administer ' . $entity_type . ' fields') + $routes["field_ui.instance_edit_$entity_type"] = array( + 'path' => "$path/fields/{field_instance}", + 'defaults' => array('_form' => '\Drupal\field_ui\Form\FieldInstanceEditForm'), + 'requirements' => array('_permission' => 'administer ' . $entity_type . ' fields'), ); - $collection->add("field_ui.instance_edit_$entity_type", $route); - $route = new Route( - "$path/fields/{field_instance}/field", - array('_form' => '\Drupal\field_ui\Form\FieldEditForm'), - array('_permission' => 'administer ' . $entity_type . ' fields') + $routes["field_ui.field_edit_$entity_type"] = array( + 'path' => "$path/fields/{field_instance}/field", + 'defaults' => array('_form' => '\Drupal\field_ui\Form\FieldEditForm'), + 'requirements' => array('_permission' => 'administer ' . $entity_type . ' fields'), ); - $collection->add("field_ui.field_edit_$entity_type", $route); - $route = new Route( - "$path/fields/{field_instance}/delete", - array('_entity_form' => 'field_instance.delete'), - array('_permission' => 'administer ' . $entity_type . ' fields') + $routes["field_ui.delete_$entity_type"] = array( + 'path' => "$path/fields/{field_instance}/delete", + 'defaults' => array('_entity_form' => 'field_instance.delete'), + 'requirements' => array('_permission' => 'administer ' . $entity_type . ' fields'), ); - $collection->add("field_ui.delete_$entity_type", $route); // If the entity type has no bundles, use the entity type. $defaults['entity_type'] = $entity_type; if (empty($entity_info['entity_keys']['bundle'])) { $defaults['bundle'] = $entity_type; } - $route = new Route( - "$path/fields", - array( + + $routes["field_ui.overview_$entity_type"] = array( + 'path' => "$path/fields", + 'defaults' => array( '_form' => '\Drupal\field_ui\FieldOverview', '_title' => 'Manage fields', ) + $defaults, - array('_permission' => 'administer ' . $entity_type . ' fields') + 'requirements' => array('_permission' => 'administer ' . $entity_type . ' fields'), ); - $collection->add("field_ui.overview_$entity_type", $route); - $route = new Route( - "$path/form-display", - array( + $routes["field_ui.form_display_overview_$entity_type"] = array( + 'path' => "$path/form-display", + 'defaults' => array( '_form' => '\Drupal\field_ui\FormDisplayOverview', '_title' => 'Manage form display', ) + $defaults, - array('_field_ui_form_mode_access' => 'administer ' . $entity_type . ' form display') + 'requirements' => array('_field_ui_form_mode_access' => 'administer ' . $entity_type . ' form display'), ); - $collection->add("field_ui.form_display_overview_$entity_type", $route); - $route = new Route( - "$path/form-display/{form_mode_name}", - array( + $routes["field_ui.form_display_overview_form_mode_$entity_type"] = array( + 'path' => "$path/form-display/{form_mode_name}", + 'defaults' => array( '_form' => '\Drupal\field_ui\FormDisplayOverview', 'form_mode_name' => NULL, ) + $defaults, - array('_field_ui_form_mode_access' => 'administer ' . $entity_type . ' form display') + 'requirements' => array('_field_ui_form_mode_access' => 'administer ' . $entity_type . ' form display'), ); - $collection->add("field_ui.form_display_overview_form_mode_$entity_type", $route); - $route = new Route( - "$path/display", - array( + $routes["field_ui.display_overview_$entity_type"] = array( + 'path' => "$path/display", + 'defaults' => array( '_form' => '\Drupal\field_ui\DisplayOverview', '_title' => 'Manage display', ) + $defaults, - array('_field_ui_view_mode_access' => 'administer ' . $entity_type . ' display') + 'requirements' => array('_field_ui_view_mode_access' => 'administer ' . $entity_type . ' display'), ); - $collection->add("field_ui.display_overview_$entity_type", $route); - $route = new Route( - "$path/display/{view_mode_name}", - array( + $routes["field_ui.display_overview_view_mode_$entity_type"] = array( + 'path' => "$path/display/{view_mode_name}", + 'defaults' => array( '_form' => '\Drupal\field_ui\DisplayOverview', 'view_mode_name' => NULL, ) + $defaults, - array('_field_ui_view_mode_access' => 'administer ' . $entity_type . ' display') + 'requirements' => array('_field_ui_view_mode_access' => 'administer ' . $entity_type . ' display'), ); - $collection->add("field_ui.display_overview_view_mode_$entity_type", $route); } } - } - - /** - * {@inheritdoc} - */ - public static function getSubscribedEvents() { - $events = parent::getSubscribedEvents(); - $events[RoutingEvents::DYNAMIC] = array('onDynamicRoutes', -100); - return $events; + return $routes; } } diff --git a/core/modules/image/image.routing.yml b/core/modules/image/image.routing.yml index ae5e88f..5b4877b 100644 --- a/core/modules/image/image.routing.yml +++ b/core/modules/image/image.routing.yml @@ -62,3 +62,6 @@ image.effect_edit_form: _form: '\Drupal\image\Form\ImageEffectEditForm' requirements: _permission: 'administer image styles' + +image.*: + provider: '\Drupal\image\EventSubscriber\RouteSubscriber::routes' diff --git a/core/modules/image/image.services.yml b/core/modules/image/image.services.yml index d9c14c6..1447e03 100644 --- a/core/modules/image/image.services.yml +++ b/core/modules/image/image.services.yml @@ -1,8 +1,4 @@ services: - image.route_subscriber: - class: Drupal\image\EventSubscriber\RouteSubscriber - tags: - - { name: 'event_subscriber' } path_processor.image_styles: class: Drupal\image\PathProcessor\PathProcessorImageStyles tags: diff --git a/core/modules/image/lib/Drupal/image/EventSubscriber/RouteSubscriber.php b/core/modules/image/lib/Drupal/image/EventSubscriber/RouteSubscriber.php index 59fbb75..ca47101 100644 --- a/core/modules/image/lib/Drupal/image/EventSubscriber/RouteSubscriber.php +++ b/core/modules/image/lib/Drupal/image/EventSubscriber/RouteSubscriber.php @@ -7,34 +7,31 @@ namespace Drupal\image\EventSubscriber; -use Drupal\Core\Routing\RouteSubscriberBase; -use Symfony\Component\Routing\Route; -use Symfony\Component\Routing\RouteCollection; - /** * Defines a route subscriber to register a url for serving image styles. */ -class RouteSubscriber extends RouteSubscriberBase { +class RouteSubscriber { /** * {@inheritdoc} */ - protected function routes(RouteCollection $collection) { + public function routes() { // Generate image derivatives of publicly available files. If clean URLs are // disabled image derivatives will always be served through the menu system. // If clean URLs are enabled and the image derivative already exists, PHP // will be bypassed. $directory_path = file_stream_wrapper_get_instance_by_scheme('public')->getDirectoryPath(); - $route = new Route('/' . $directory_path . '/styles/{image_style}/{scheme}', - array( + $routes['image.style_public'] = array( + 'path' => '/' . $directory_path . '/styles/{image_style}/{scheme}', + 'defaults' => array( '_controller' => 'Drupal\image\Controller\ImageStyleDownloadController::deliver', ), - array( + 'requirements' => array( '_access' => 'TRUE', - ) + ), ); - $collection->add('image.style_public', $route); + return $routes; } } diff --git a/core/modules/search/lib/Drupal/search/Routing/SearchRouteSubscriber.php b/core/modules/search/lib/Drupal/search/Routing/SearchRouteSubscriber.php index dfb634c..3614f08 100644 --- a/core/modules/search/lib/Drupal/search/Routing/SearchRouteSubscriber.php +++ b/core/modules/search/lib/Drupal/search/Routing/SearchRouteSubscriber.php @@ -7,15 +7,14 @@ namespace Drupal\search\Routing; -use Drupal\Core\Routing\RouteSubscriberBase; +use Drupal\Core\DependencyInjection\ContainerInjectionInterface; use Drupal\search\SearchPluginManager; -use Symfony\Component\Routing\Route; -use Symfony\Component\Routing\RouteCollection; +use Symfony\Component\DependencyInjection\ContainerInterface; /** * Provides dynamic routes for search. */ -class SearchRouteSubscriber extends RouteSubscriberBase { +class SearchRouteSubscriber implements ContainerInjectionInterface { /** * The search plugin manager. @@ -37,22 +36,33 @@ public function __construct(SearchPluginManager $search_plugin_manager) { /** * {@inheritdoc} */ - protected function routes(RouteCollection $collection) { + public static function create(ContainerInterface $container) { + return new static( + $container->get('plugin.manager.search') + ); + } + + /** + * {@inheritdoc} + */ + public function routes() { + $routes = array(); foreach ($this->searchManager->getActiveDefinitions() as $plugin_id => $search_info) { - $path = 'search/' . $search_info['path'] . '/{keys}'; - $defaults = array( - '_content' => 'Drupal\search\Controller\SearchController::view', - 'plugin_id' => $plugin_id, - 'keys' => '', - ); - $requirements = array( - 'keys' => '.+', - '_search_plugin_view_access' => $plugin_id, - '_permission' => 'search content', + $routes["search.view_$plugin_id"] = array( + 'path' => 'search/' . $search_info['path'] . '/{keys}', + 'defaults' => array( + '_content' => 'Drupal\search\Controller\SearchController::view', + 'plugin_id' => $plugin_id, + 'keys' => '', + ), + 'requirements' => array( + 'keys' => '.+', + '_search_plugin_view_access' => $plugin_id, + '_permission' => 'search content', + ), ); - $route = new Route($path, $defaults, $requirements); - $collection->add('search.view_' . $plugin_id, $route); } + return $routes; } } diff --git a/core/modules/search/search.routing.yml b/core/modules/search/search.routing.yml index 21e481e..0d0f2b8 100644 --- a/core/modules/search/search.routing.yml +++ b/core/modules/search/search.routing.yml @@ -23,3 +23,6 @@ search.view: keys: '.+' _permission: 'search content' _search_access: 'TRUE' + +search.*: + provider: '\Drupal\search\Routing\SearchRouteSubscriber::routes' diff --git a/core/modules/search/search.services.yml b/core/modules/search/search.services.yml index 88f6ea9..31dc5c5 100644 --- a/core/modules/search/search.services.yml +++ b/core/modules/search/search.services.yml @@ -14,9 +14,3 @@ services: arguments: ['@plugin.manager.search'] tags: - { name: access_check } - - route_subscriber.search: - class: Drupal\search\Routing\SearchRouteSubscriber - arguments: ['@plugin.manager.search'] - tags: - - { name: event_subscriber } diff --git a/core/modules/system/tests/modules/entity_test/entity_test.routing.yml b/core/modules/system/tests/modules/entity_test/entity_test.routing.yml index 4bab92e..61d85eb 100644 --- a/core/modules/system/tests/modules/entity_test/entity_test.routing.yml +++ b/core/modules/system/tests/modules/entity_test/entity_test.routing.yml @@ -22,3 +22,6 @@ entity_test.render_no_view_mode: _entity_view: 'entity_test' requirements: _access: 'TRUE' + +entity_test.*: + provider: '\Drupal\entity_test\Routing\RouteSubscriber::routes' diff --git a/core/modules/system/tests/modules/entity_test/entity_test.services.yml b/core/modules/system/tests/modules/entity_test/entity_test.services.yml deleted file mode 100644 index 77855b8..0000000 --- a/core/modules/system/tests/modules/entity_test/entity_test.services.yml +++ /dev/null @@ -1,5 +0,0 @@ -services: - entity_test.subscriber: - class: Drupal\entity_test\Routing\RouteSubscriber - tags: - - { name: event_subscriber } diff --git a/core/modules/system/tests/modules/entity_test/lib/Drupal/entity_test/Routing/RouteSubscriber.php b/core/modules/system/tests/modules/entity_test/lib/Drupal/entity_test/Routing/RouteSubscriber.php index 91a43cd..38efcbd 100644 --- a/core/modules/system/tests/modules/entity_test/lib/Drupal/entity_test/Routing/RouteSubscriber.php +++ b/core/modules/system/tests/modules/entity_test/lib/Drupal/entity_test/Routing/RouteSubscriber.php @@ -7,46 +7,41 @@ namespace Drupal\entity_test\Routing; -use Drupal\Core\Routing\RouteSubscriberBase; -use Symfony\Component\Routing\Route; -use Symfony\Component\Routing\RouteCollection; - /** * Subscriber for Entity Test routes. */ -class RouteSubscriber extends RouteSubscriberBase { +class RouteSubscriber { /** * {@inheritdoc} */ - protected function routes(RouteCollection $collection) { + public function routes() { $types = entity_test_entity_types(); + $routes = array(); foreach ($types as $entity_type) { - $route = new Route( - "$entity_type/add", - array('_content' => '\Drupal\entity_test\Controller\EntityTestController::testAdd', 'entity_type' => $entity_type), - array('_permission' => 'administer entity_test content') + $routes["entity_test.add_$entity_type"] = array( + 'path' => "$entity_type/add", + 'defaults' => array('_content' => '\Drupal\entity_test\Controller\EntityTestController::testAdd', 'entity_type' => $entity_type), + 'requirements' => array('_permission' => 'administer entity_test content'), ); - $collection->add("entity_test.add_$entity_type", $route); - $route = new Route( - "$entity_type/manage/{" . $entity_type . '}', - array('_content' => '\Drupal\entity_test\Controller\EntityTestController::testEdit', '_entity_type' => $entity_type), - array('_permission' => 'administer entity_test content'), - array('parameters' => array( + $routes["entity_test.edit_$entity_type"] = array( + 'path' => "$entity_type/manage/{" . $entity_type . '}', + 'defaults' => array('_content' => '\Drupal\entity_test\Controller\EntityTestController::testEdit', '_entity_type' => $entity_type), + 'requirements' => array('_permission' => 'administer entity_test content'), + 'options' => array('parameters' => array( 'entity' => array('type' => 'entity:' . $entity_type), - )) + )), ); - $collection->add("entity_test.edit_$entity_type", $route); - $route = new Route( - "$entity_type/structure/{bundle}", - array('_content' => '\Drupal\entity_test\Controller\EntityTestController::testAdmin'), - array('_permission' => 'administer entity_test content') + $routes["entity_test.admin_$entity_type"] = array( + 'path' => "$entity_type/structure/{bundle}", + 'defaults' => array('_content' => '\Drupal\entity_test\Controller\EntityTestController::testAdmin'), + 'requirements' => array('_permission' => 'administer entity_test content'), ); - $collection->add("entity_test.admin_$entity_type", $route); } + return $routes; } }