Commit f3669304 authored by alexpott's avatar alexpott

Issue #2091411 by damiankloip, dawehner: Provide an easier mechanism for a...

Issue #2091411 by damiankloip, dawehner: Provide an easier mechanism for a route definition wrapped by module_exists().
parent 9ced9d5a
......@@ -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:
......
......@@ -2,21 +2,20 @@
/**
* @file
* Contains \Drupal\dblog\Routing\RouteSubscriber.
* Contains \Drupal\Core\EventSubscriber\ModuleRouteSubscriber.
*/
namespace Drupal\dblog\Routing;
namespace Drupal\Core\EventSubscriber;
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;
use Drupal\Core\Routing\RoutingEvents;
/**
* Provides dynamic routes for dblog.
* A route subscriber to remove routes that depend on modules being enabled.
*/
class RouteSubscriber implements EventSubscriberInterface {
class ModuleRouteSubscriber implements EventSubscriberInterface {
/**
* The module handler.
......@@ -26,7 +25,7 @@ class RouteSubscriber implements EventSubscriberInterface {
protected $moduleHandler;
/**
* Creates a new RouteSubscriber.
* Constructs a ModuleRouteSubscriber object.
*
* @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler
* The module handler.
......@@ -39,35 +38,61 @@ public function __construct(ModuleHandlerInterface $module_handler) {
* {@inheritdoc}
*/
public static function getSubscribedEvents() {
$events[RoutingEvents::DYNAMIC] = 'routes';
$events[RoutingEvents::ALTER] = 'removeRoutes';
return $events;
}
/**
* Generate dynamic routes for various dblog pages.
* Removes any routes that have an unmet module dependency.
*
* @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) {
public function removeRoutes(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);
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']
<?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'
services:
dblog.route_subscriber:
class: Drupal\dblog\Routing\RouteSubscriber
arguments: ['@module_handler']
tags:
- { name: event_subscriber}
<?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),
);
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment