diff --git a/core/lib/Drupal/Core/EventSubscriber/AccessSubscriber.php b/core/lib/Drupal/Core/EventSubscriber/AccessSubscriber.php index e6f6eb8..553fb3c 100644 --- a/core/lib/Drupal/Core/EventSubscriber/AccessSubscriber.php +++ b/core/lib/Drupal/Core/EventSubscriber/AccessSubscriber.php @@ -52,7 +52,16 @@ public function onKernelRequestAccessCheck(GetResponseEvent $event) { return; } - $access = $this->accessManager->check($request->attributes->get(RouteObjectInterface::ROUTE_OBJECT), $request); + // Wrap this in a try/catch to ensure the '_controller_request' attribute + // can always be removed. + try { + $access = $this->accessManager->check($request->attributes->get(RouteObjectInterface::ROUTE_OBJECT), $request); + } + catch (\Exception $e) { + $request->attributes->remove('_controller_request'); + throw $e; + } + if (!$access) { throw new AccessDeniedHttpException(); } diff --git a/core/lib/Drupal/Core/RouteProcessor/RouteProcessorManager.php b/core/lib/Drupal/Core/RouteProcessor/RouteProcessorManager.php index 42261cb..43071be 100644 --- a/core/lib/Drupal/Core/RouteProcessor/RouteProcessorManager.php +++ b/core/lib/Drupal/Core/RouteProcessor/RouteProcessorManager.php @@ -10,7 +10,10 @@ use Symfony\Component\Routing\Route; /** - * Class RouteProcessorManager. + * Route processor manager. + * + * Holds an array of route processor objects and uses them to sequentially + * process an outbound route, in order of processor priority. */ class RouteProcessorManager implements OutboundRouteProcessorInterface { diff --git a/core/tests/Drupal/Tests/Core/Access/CsrfAccessCheckTest.php b/core/tests/Drupal/Tests/Core/Access/CsrfAccessCheckTest.php index 2b08b97..bfe40a3 100644 --- a/core/tests/Drupal/Tests/Core/Access/CsrfAccessCheckTest.php +++ b/core/tests/Drupal/Tests/Core/Access/CsrfAccessCheckTest.php @@ -16,6 +16,9 @@ /** * Tests the CSRF access checker.. * + * @group Drupal + * @group Access + * * @see \Drupal\Core\Access\CsrfAccessCheck */ class CsrfAccessCheckTest extends UnitTestCase { diff --git a/core/tests/Drupal/Tests/Core/Access/RouteProcessorCsrfTest.php b/core/tests/Drupal/Tests/Core/Access/RouteProcessorCsrfTest.php index 06d0b9c..681df29 100644 --- a/core/tests/Drupal/Tests/Core/Access/RouteProcessorCsrfTest.php +++ b/core/tests/Drupal/Tests/Core/Access/RouteProcessorCsrfTest.php @@ -13,6 +13,11 @@ /** * Tests the CSRF route processor. + * + * @see Drupal + * @see Routing + * + * @see \Drupal\Core\Access\RouteProcessorCsrf */ class RouteProcessorCsrfTest extends UnitTestCase { diff --git a/core/tests/Drupal/Tests/Core/RouteProcessor/RouteProcessorManagerTest.php b/core/tests/Drupal/Tests/Core/RouteProcessor/RouteProcessorManagerTest.php index 498faec..6d23ca6 100644 --- a/core/tests/Drupal/Tests/Core/RouteProcessor/RouteProcessorManagerTest.php +++ b/core/tests/Drupal/Tests/Core/RouteProcessor/RouteProcessorManagerTest.php @@ -13,6 +13,11 @@ /** * Tests the RouteProcessorManager class. + * + * @group Drupal + * @group Routing + * + * @see \Drupal\Core\RouteProcessor\RouteProcessorManager */ class RouteProcessorManagerTest extends UnitTestCase { diff --git a/core/tests/Drupal/Tests/Core/Routing/UrlGeneratorTest.php b/core/tests/Drupal/Tests/Core/Routing/UrlGeneratorTest.php index 0997c2c..d1c59c9 100644 --- a/core/tests/Drupal/Tests/Core/Routing/UrlGeneratorTest.php +++ b/core/tests/Drupal/Tests/Core/Routing/UrlGeneratorTest.php @@ -10,7 +10,6 @@ use Drupal\Component\Utility\Settings; use Drupal\Core\PathProcessor\PathProcessorAlias; use Drupal\Core\PathProcessor\PathProcessorManager; -use Drupal\Core\RouteProcessor\RouteProcessorManager; use Drupal\Core\Routing\UrlGenerator; use Drupal\Tests\UnitTestCase; use Symfony\Component\HttpFoundation\Request; @@ -39,8 +38,20 @@ class UrlGeneratorTest extends UnitTestCase { */ protected $generatorMixedMode; + /** + * The alias manager. + * + * @var \Drupal\Core\Path\AliasManager|\PHPUnit_Framework_MockObject_MockObject + */ protected $aliasManager; + /** + * The mock route processor manager. + * + * @var \Drupal\Core\RouteProcessor\RouteProcessorManager|\PHPUnit_Framework_MockObject_MockObject + */ + protected $routeProcessorManager; + public static function getInfo() { return array( 'name' => 'UrlGenerator', @@ -116,16 +127,18 @@ function setUp() { $processor_manager = new PathProcessorManager(); $processor_manager->addOutbound($processor, 1000); - $route_processor_manager = new RouteProcessorManager(); + $this->routeProcessorManager = $this->getMockBuilder('Drupal\Core\RouteProcessor\RouteProcessorManager') + ->disableOriginalConstructor() + ->getMock(); $config_factory_stub = $this->getConfigFactoryStub(array('system.filter' => array('protocols' => array('http', 'https')))); - $generator = new UrlGenerator($provider, $processor_manager, $route_processor_manager, $config_factory_stub, new Settings(array())); + $generator = new UrlGenerator($provider, $processor_manager, $this->routeProcessorManager, $config_factory_stub, new Settings(array())); $generator->setContext($context); $this->generator = $generator; // Second generator for mixed-mode sessions. - $generator = new UrlGenerator($provider, $processor_manager, $route_processor_manager, $config_factory_stub, new Settings(array('mixed_mode_sessions' => TRUE))); + $generator = new UrlGenerator($provider, $processor_manager, $this->routeProcessorManager, $config_factory_stub, new Settings(array('mixed_mode_sessions' => TRUE))); $generator->setContext($context); $this->generatorMixedMode = $generator; } @@ -160,6 +173,11 @@ public function testAliasGeneration() { $url = $this->generator->generate('test_1'); $this->assertEquals('/hello/world', $url); + $this->routeProcessorManager->expects($this->once()) + ->method('processOutbound') + ->with($this->anything()); + + // Check that the two generate methods return the same result. $url_from_route = $this->generator->generateFromRoute('test_1'); $this->assertEquals($url_from_route, $url); @@ -174,6 +192,9 @@ public function testAliasGeneration() { public function testGetPathFromRouteWithSubdirectory() { $this->generator->setBasePath('/test-base-path'); + $this->routeProcessorManager->expects($this->never()) + ->method('processOutbound'); + $path = $this->generator->getPathFromRoute('test_1'); $this->assertEquals('test/one', $path); } @@ -185,6 +206,10 @@ public function testAliasGenerationWithParameters() { $url = $this->generator->generate('test_2', array('narf' => '5')); $this->assertEquals('/goodbye/cruel/world', $url); + $this->routeProcessorManager->expects($this->exactly(3)) + ->method('processOutbound') + ->with($this->anything()); + $options = array('fragment' => 'top'); // Extra parameters should appear in the query string. $url = $this->generator->generateFromRoute('test_1', array('zoo' => '5'), $options); @@ -206,6 +231,9 @@ public function testAliasGenerationWithParameters() { * Tests URL generation from route with trailing start and end slashes. */ public function testGetPathFromRouteTrailing() { + $this->routeProcessorManager->expects($this->never()) + ->method('processOutbound'); + $path = $this->generator->getPathFromRoute('test_3'); $this->assertEquals($path, 'test/two'); } @@ -217,6 +245,10 @@ public function testAbsoluteURLGeneration() { $url = $this->generator->generate('test_1', array(), TRUE); $this->assertEquals('http://localhost/hello/world', $url); + $this->routeProcessorManager->expects($this->once()) + ->method('processOutbound') + ->with($this->anything()); + $options = array('absolute' => TRUE, 'fragment' => 'top'); // Extra parameters should appear in the query string. $url = $this->generator->generateFromRoute('test_1', array('zoo' => '5'), $options); @@ -230,6 +262,10 @@ public function testUrlGenerationWithHttpsRequirement() { $url = $this->generator->generate('test_4', array(), TRUE); $this->assertEquals('https://localhost/test/four', $url); + $this->routeProcessorManager->expects($this->exactly(2)) + ->method('processOutbound') + ->with($this->anything()); + $options = array('absolute' => TRUE, 'https' => TRUE); // Mixed-mode sessions are not enabled, so the https option is ignored. $url = $this->generator->generateFromRoute('test_1', array(), $options);