Issue #2091411 by damiankloip, dawehner: Provide an easier mechanism for a route definition wrapped by module_exists().
parent
9ced9d5a3a
commit
f366930462
|
@ -320,6 +320,11 @@ services:
|
|||
tags:
|
||||
- { name: paramconverter }
|
||||
arguments: ['@entity.manager']
|
||||
route_subscriber.module:
|
||||
class: Drupal\Core\EventSubscriber\ModuleRouteSubscriber
|
||||
tags:
|
||||
- { name: event_subscriber }
|
||||
arguments: ['@module_handler']
|
||||
route_subscriber.entity:
|
||||
class: Drupal\Core\EventSubscriber\EntityRouteAlterSubscriber
|
||||
tags:
|
||||
|
|
|
@ -0,0 +1,98 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\Core\EventSubscriber\ModuleRouteSubscriber.
|
||||
*/
|
||||
|
||||
namespace Drupal\Core\EventSubscriber;
|
||||
|
||||
use Drupal\Core\Extension\ModuleHandlerInterface;
|
||||
use Drupal\Core\Routing\RouteBuildEvent;
|
||||
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
|
||||
use Drupal\Core\Routing\RoutingEvents;
|
||||
|
||||
/**
|
||||
* A route subscriber to remove routes that depend on modules being enabled.
|
||||
*/
|
||||
class ModuleRouteSubscriber implements EventSubscriberInterface {
|
||||
|
||||
/**
|
||||
* The module handler.
|
||||
*
|
||||
* @var \Drupal\Core\Extension\ModuleHandlerInterface
|
||||
*/
|
||||
protected $moduleHandler;
|
||||
|
||||
/**
|
||||
* Constructs a ModuleRouteSubscriber object.
|
||||
*
|
||||
* @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler
|
||||
* The module handler.
|
||||
*/
|
||||
public function __construct(ModuleHandlerInterface $module_handler) {
|
||||
$this->moduleHandler = $module_handler;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static function getSubscribedEvents() {
|
||||
$events[RoutingEvents::ALTER] = 'removeRoutes';
|
||||
return $events;
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes any routes that have an unmet module dependency.
|
||||
*
|
||||
* @param \Drupal\Core\Routing\RouteBuildEvent $event
|
||||
* The route building event.
|
||||
*/
|
||||
public function removeRoutes(RouteBuildEvent $event) {
|
||||
$collection = $event->getRouteCollection();
|
||||
|
||||
foreach ($collection as $name => $route) {
|
||||
if ($route->hasRequirement('_module_dependencies')) {
|
||||
$modules = $route->getRequirement('_module_dependencies');
|
||||
|
||||
$explode_and = $this->explodeString($modules, '+');
|
||||
if (count($explode_and) > 1) {
|
||||
foreach ($explode_and as $module) {
|
||||
// If any moduleExists() call returns FALSE, remove the route and
|
||||
// move on to the next.
|
||||
if (!$this->moduleHandler->moduleExists($module)) {
|
||||
$collection->remove($name);
|
||||
continue 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
// OR condition, exploding on ',' character.
|
||||
foreach ($this->explodeString($modules, ',') as $module) {
|
||||
if ($this->moduleHandler->moduleExists($module)) {
|
||||
continue 2;
|
||||
}
|
||||
}
|
||||
// If no modules are found, and we get this far, remove the route.
|
||||
$collection->remove($name);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Explodes a string based on a separator.
|
||||
*
|
||||
* @param string $string
|
||||
* The string to explode.
|
||||
* @param string $separator
|
||||
* The string separator to explode with.
|
||||
*
|
||||
* @return array
|
||||
* An array of exploded (and trimmed) values.
|
||||
*/
|
||||
protected function explodeString($string, $separator = ',') {
|
||||
return array_filter(array_map('trim', explode($separator, $string)));
|
||||
}
|
||||
|
||||
}
|
|
@ -75,3 +75,11 @@ comment.bundle:
|
|||
_title_callback: 'Drupal\comment\Controller\AdminController::bundleTitle'
|
||||
requirements:
|
||||
_access: 'FALSE'
|
||||
|
||||
comment.node_redirect:
|
||||
path: '/comment/{node}/reply'
|
||||
defaults:
|
||||
_controller: 'Drupal\comment\Controller\CommentController::redirectNode'
|
||||
requirements:
|
||||
_entity_access: 'node.view'
|
||||
_module_dependencies: 'node'
|
||||
|
|
|
@ -5,12 +5,6 @@ services:
|
|||
- { name: breadcrumb_builder, priority: 100 }
|
||||
arguments: ['@string_translation', '@entity.manager']
|
||||
|
||||
comment.subscriber:
|
||||
class: Drupal\comment\Routing\RouteSubscriber
|
||||
arguments: ['@module_handler']
|
||||
tags:
|
||||
- { name: event_subscriber }
|
||||
|
||||
comment.manager:
|
||||
class: Drupal\comment\CommentManager
|
||||
arguments: ['@field.info', '@entity.manager']
|
||||
|
|
|
@ -1,64 +0,0 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\comment\Routing\RouteSubscriber.
|
||||
*/
|
||||
|
||||
namespace Drupal\comment\Routing;
|
||||
|
||||
use Drupal\Core\Routing\RouteBuildEvent;
|
||||
use Drupal\Core\Routing\RoutingEvents;
|
||||
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
|
||||
use Symfony\Component\Routing\Route;
|
||||
use Drupal\Core\Extension\ModuleHandlerInterface;
|
||||
|
||||
/**
|
||||
* Defines a route subscriber for the comment module.
|
||||
*/
|
||||
class RouteSubscriber implements EventSubscriberInterface {
|
||||
|
||||
/**
|
||||
* The module handler service.
|
||||
*
|
||||
* @var \Drupal\Core\Extension\ModuleHandlerInterface
|
||||
*/
|
||||
protected $moduleHandler;
|
||||
|
||||
/**
|
||||
* Constructs a RouteSubscriber object.
|
||||
*
|
||||
* @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler
|
||||
* The module handler service.
|
||||
*/
|
||||
public function __construct(ModuleHandlerInterface $module_handler) {
|
||||
$this->moduleHandler = $module_handler;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static function getSubscribedEvents() {
|
||||
$events[RoutingEvents::DYNAMIC] = 'routes';
|
||||
return $events;
|
||||
}
|
||||
|
||||
/**
|
||||
* If node module is present, adds the legacy /comment/{node}/reply route.
|
||||
*
|
||||
* @param \Drupal\Core\Routing\RouteBuildEvent $event
|
||||
* The route build event.
|
||||
*/
|
||||
public function routes(RouteBuildEvent $event) {
|
||||
$collection = $event->getRouteCollection();
|
||||
if ($this->moduleHandler->moduleExists('node')) {
|
||||
$route = new Route(
|
||||
"/comment/{node}/reply",
|
||||
array('_controller' => 'Drupal\comment\Controller\CommentController::redirectNode'),
|
||||
array('_entity_access' => 'node.view')
|
||||
);
|
||||
$collection->add('comment_node_redirect', $route);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -27,3 +27,12 @@ dblog.access_denied:
|
|||
_content: '\Drupal\dblog\Controller\DbLogController::accessDenied'
|
||||
requirements:
|
||||
_permission: 'access site reports'
|
||||
|
||||
dblog.search:
|
||||
path: '/admin/reports/search'
|
||||
defaults:
|
||||
_content: '\Drupal\dblog\Controller\DbLogController::search'
|
||||
_title: 'Top search phrases'
|
||||
requirements:
|
||||
_module_dependencies: 'search'
|
||||
_permission: 'access site reports'
|
||||
|
|
|
@ -1,6 +0,0 @@
|
|||
services:
|
||||
dblog.route_subscriber:
|
||||
class: Drupal\dblog\Routing\RouteSubscriber
|
||||
arguments: ['@module_handler']
|
||||
tags:
|
||||
- { name: event_subscriber}
|
|
@ -1,73 +0,0 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\dblog\Routing\RouteSubscriber.
|
||||
*/
|
||||
|
||||
namespace Drupal\dblog\Routing;
|
||||
|
||||
use Drupal\Core\Extension\ModuleHandlerInterface;
|
||||
use Drupal\Core\Routing\RouteBuildEvent;
|
||||
use Drupal\Core\Routing\RoutingEvents;
|
||||
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
|
||||
use Symfony\Component\Routing\Route;
|
||||
|
||||
/**
|
||||
* Provides dynamic routes for dblog.
|
||||
*/
|
||||
class RouteSubscriber implements EventSubscriberInterface {
|
||||
|
||||
/**
|
||||
* The module handler.
|
||||
*
|
||||
* @var \Drupal\Core\Extension\ModuleHandlerInterface
|
||||
*/
|
||||
protected $moduleHandler;
|
||||
|
||||
/**
|
||||
* Creates a new RouteSubscriber.
|
||||
*
|
||||
* @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler
|
||||
* The module handler.
|
||||
*/
|
||||
public function __construct(ModuleHandlerInterface $module_handler) {
|
||||
$this->moduleHandler = $module_handler;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static function getSubscribedEvents() {
|
||||
$events[RoutingEvents::DYNAMIC] = 'routes';
|
||||
return $events;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate dynamic routes for various dblog pages.
|
||||
*
|
||||
* @param \Drupal\Core\Routing\RouteBuildEvent $event
|
||||
* The route building event.
|
||||
*
|
||||
* @return \Symfony\Component\Routing\RouteCollection
|
||||
* The route collection that contains the new dynamic route.
|
||||
*/
|
||||
public function routes(RouteBuildEvent $event) {
|
||||
$collection = $event->getRouteCollection();
|
||||
if ($this->moduleHandler->moduleExists('search')) {
|
||||
// The block entity listing page.
|
||||
$route = new Route(
|
||||
'admin/reports/search',
|
||||
array(
|
||||
'_content' => '\Drupal\dblog\Controller\DbLogController::search',
|
||||
'_title' => 'Top search phrases',
|
||||
),
|
||||
array(
|
||||
'_permission' => 'access site reports',
|
||||
)
|
||||
);
|
||||
$collection->add('dblog.search', $route);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,100 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\Tests\Core\EventSubscriber\ModuleRouteSubscriberTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\Tests\Core\EventSubscriber;
|
||||
|
||||
use Drupal\Core\Routing\RouteBuildEvent;
|
||||
use Drupal\Tests\UnitTestCase;
|
||||
use Drupal\Core\EventSubscriber\ModuleRouteSubscriber;
|
||||
use Symfony\Component\Routing\RouteCollection;
|
||||
use Symfony\Component\Routing\Route;
|
||||
|
||||
/**
|
||||
* Tests the ModuleRouteSubscriber class.
|
||||
*
|
||||
* @group Drupal
|
||||
*
|
||||
* @see \Drupal\Core\EventSubscriber\ModuleRouteSubscriber
|
||||
*/
|
||||
class ModuleRouteSubscriberTest extends UnitTestCase {
|
||||
|
||||
/**
|
||||
* The mock module handler.
|
||||
*
|
||||
* @var Drupal\Core\Extension\ModuleHandlerInterface|\PHPUnit_Framework_MockObject_MockObject
|
||||
*/
|
||||
protected $moduleHandler;
|
||||
|
||||
public static function getInfo() {
|
||||
return array(
|
||||
'name' => 'Module route subscriber',
|
||||
'description' => 'Unit test the \Drupal\Core\EventSubscriber\ModuleRouteSubscriber class.',
|
||||
'group' => 'System'
|
||||
);
|
||||
}
|
||||
|
||||
public function setUp() {
|
||||
$this->moduleHandler = $this->getMock('Drupal\Core\Extension\ModuleHandlerInterface');
|
||||
|
||||
$value_map = array(
|
||||
array('enabled', TRUE),
|
||||
array('disabled', FALSE),
|
||||
);
|
||||
|
||||
$this->moduleHandler->expects($this->any())
|
||||
->method('moduleExists')
|
||||
->will($this->returnValueMap($value_map));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that removeRoute() removes routes when the module is not enabled.
|
||||
*
|
||||
* @dataProvider testRemoveRouteProvider
|
||||
*
|
||||
* @param string $route_name
|
||||
* The machine name for the route.
|
||||
* @param array $requirements
|
||||
* An array of requirements to use for the route.
|
||||
* @param bool $removed
|
||||
* Whether or not the route is expected to be removed from the collection.
|
||||
*/
|
||||
public function testRemoveRoute($route_name, array $requirements, $removed) {
|
||||
$collection = new RouteCollection();
|
||||
$route = new Route('', array(), $requirements);
|
||||
$collection->add($route_name, $route);
|
||||
|
||||
$event = new RouteBuildEvent($collection, 'test');
|
||||
$route_subscriber = new ModuleRouteSubscriber($this->moduleHandler);
|
||||
$route_subscriber->removeRoutes($event);
|
||||
|
||||
if ($removed) {
|
||||
$this->assertNull($collection->get($route_name));
|
||||
}
|
||||
else {
|
||||
$this->assertInstanceOf('Symfony\Component\Routing\Route', $collection->get($route_name));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Data provider for testRemoveRoute().
|
||||
*/
|
||||
public function testRemoveRouteProvider() {
|
||||
return array(
|
||||
array('enabled', array('_module_dependencies' => 'enabled'), FALSE),
|
||||
array('disabled', array('_module_dependencies' => 'disabled'), TRUE),
|
||||
array('enabled_or', array('_module_dependencies' => 'disabled,enabled'), FALSE),
|
||||
array('enabled_or', array('_module_dependencies' => 'enabled,disabled'), FALSE),
|
||||
array('disabled_or', array('_module_dependencies' => 'disabled,disabled'), TRUE),
|
||||
array('enabled_and', array('_module_dependencies' => 'enabled+enabled'), FALSE),
|
||||
array('enabled_and', array('_module_dependencies' => 'enabled+disabled'), TRUE),
|
||||
array('enabled_and', array('_module_dependencies' => 'disabled+enabled'), TRUE),
|
||||
array('disabled_and', array('_module_dependencies' => 'disabled+disabled'), TRUE),
|
||||
array('no_dependencies', array(), FALSE),
|
||||
);
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in New Issue