diff --git a/core/includes/menu.inc b/core/includes/menu.inc index bbf5c43..96f810e 100644 --- a/core/includes/menu.inc +++ b/core/includes/menu.inc @@ -9,13 +9,13 @@ use Drupal\Component\Utility\String; use Drupal\Core\Cache\Cache; use Drupal\Core\Language\Language; +use Drupal\Core\ParamConverter\ParamNotConvertedException; use Drupal\Core\Routing\RequestHelper; use Drupal\Core\Template\Attribute; use Drupal\menu_link\Entity\MenuLink; use Drupal\menu_link\MenuLinkStorageController; use Symfony\Cmf\Component\Routing\RouteObjectInterface; use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; use Symfony\Component\Routing\Route; /** @@ -934,7 +934,7 @@ function menu_item_route_access(Route $route, $href, &$map, Request $request = N try { $request->attributes->add(\Drupal::service('router')->matchRequest($request)); } - catch (NotFoundHttpException $e) { + catch (ParamNotConvertedException $e) { return FALSE; } diff --git a/core/modules/config_translation/lib/Drupal/config_translation/Controller/ConfigTranslationController.php b/core/modules/config_translation/lib/Drupal/config_translation/Controller/ConfigTranslationController.php index 03c2a20..9c65218 100644 --- a/core/modules/config_translation/lib/Drupal/config_translation/Controller/ConfigTranslationController.php +++ b/core/modules/config_translation/lib/Drupal/config_translation/Controller/ConfigTranslationController.php @@ -13,12 +13,12 @@ use Drupal\Core\DependencyInjection\ContainerInjectionInterface; use Drupal\Core\Language\Language; use Drupal\Core\Language\LanguageManagerInterface; +use Drupal\Core\ParamConverter\ParamNotConvertedException; use Drupal\Core\PathProcessor\InboundPathProcessorInterface; use Drupal\Core\Session\AccountInterface; use Symfony\Cmf\Component\Routing\RouteObjectInterface; use Symfony\Component\DependencyInjection\ContainerInterface; use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; use Symfony\Component\Routing\Exception\ResourceNotFoundException; use Symfony\Component\Routing\Matcher\RequestMatcherInterface; @@ -252,7 +252,7 @@ protected function getRequestForPath(Request $request, $path) { $route_request->attributes->add($this->router->matchRequest($route_request)); return $route_request; } - catch (NotFoundHttpException $e) { + catch (ParamNotConvertedException $e) { return NULL; } catch (ResourceNotFoundException $e) { diff --git a/core/modules/edit/lib/Drupal/edit/Access/EditEntityAccessCheck.php b/core/modules/edit/lib/Drupal/edit/Access/EditEntityAccessCheck.php index 827c06f..3c6dbcd 100644 --- a/core/modules/edit/lib/Drupal/edit/Access/EditEntityAccessCheck.php +++ b/core/modules/edit/lib/Drupal/edit/Access/EditEntityAccessCheck.php @@ -44,7 +44,9 @@ public function access(Route $route, Request $request, AccountInterface $account // @todo Request argument validation and object loading should happen // elsewhere in the request processing pipeline: // http://drupal.org/node/1798214. - $this->validateAndUpcastRequestAttributes($request); + if (!$this->validateAndUpcastRequestAttributes($request)) { + return static::KILL; + } return $this->accessEditEntity($request->attributes->get('entity'), $account) ? static::ALLOW : static::DENY; } @@ -65,14 +67,16 @@ protected function validateAndUpcastRequestAttributes(Request $request) { $entity_id = $entity; $entity_type = $request->attributes->get('entity_type'); if (!$entity_type || !$this->entityManager->getDefinition($entity_type)) { - throw new NotFoundHttpException(); + return FALSE; } $entity = $this->entityManager->getStorageController($entity_type)->load($entity_id); if (!$entity) { - throw new NotFoundHttpException(); + return FALSE; } $request->attributes->set('entity', $entity); } + + return TRUE; } } diff --git a/core/modules/edit/lib/Drupal/edit/Access/EditEntityFieldAccessCheck.php b/core/modules/edit/lib/Drupal/edit/Access/EditEntityFieldAccessCheck.php index 9de7347..50aaf64 100644 --- a/core/modules/edit/lib/Drupal/edit/Access/EditEntityFieldAccessCheck.php +++ b/core/modules/edit/lib/Drupal/edit/Access/EditEntityFieldAccessCheck.php @@ -12,7 +12,6 @@ use Drupal\Core\Session\AccountInterface; use Symfony\Component\Routing\Route; use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; use Drupal\Core\Entity\EntityInterface; /** @@ -44,7 +43,9 @@ public function access(Route $route, Request $request, AccountInterface $account // @todo Request argument validation and object loading should happen // elsewhere in the request processing pipeline: // http://drupal.org/node/1798214. - $this->validateAndUpcastRequestAttributes($request); + if (!$this->validateAndUpcastRequestAttributes($request)) { + return static::KILL; + } return $this->accessEditEntityField($request->attributes->get('entity'), $request->attributes->get('field_name')) ? static::ALLOW : static::DENY; } @@ -65,11 +66,11 @@ protected function validateAndUpcastRequestAttributes(Request $request) { $entity_id = $entity; $entity_type = $request->attributes->get('entity_type'); if (!$entity_type || !$this->entityManager->getDefinition($entity_type)) { - throw new NotFoundHttpException(); + return FALSE; } $entity = $this->entityManager->getStorageController($entity_type)->load($entity_id); if (!$entity) { - throw new NotFoundHttpException(); + return FALSE; } $request->attributes->set('entity', $entity); } @@ -77,12 +78,14 @@ protected function validateAndUpcastRequestAttributes(Request $request) { // Validate the field name and language. $field_name = $request->attributes->get('field_name'); if (!$field_name || !$entity->hasField($field_name)) { - throw new NotFoundHttpException(); + return FALSE; } $langcode = $request->attributes->get('langcode'); if (!$langcode || !$entity->hasTranslation($langcode)) { - throw new NotFoundHttpException(); + return FALSE; } + + return TRUE; } } diff --git a/core/modules/edit/tests/Drupal/edit/Tests/Access/EditEntityAccessCheckTest.php b/core/modules/edit/tests/Drupal/edit/Tests/Access/EditEntityAccessCheckTest.php index 0d5ca57..9e8d050 100644 --- a/core/modules/edit/tests/Drupal/edit/Tests/Access/EditEntityAccessCheckTest.php +++ b/core/modules/edit/tests/Drupal/edit/Tests/Access/EditEntityAccessCheckTest.php @@ -117,8 +117,6 @@ public function testAccess(EntityInterface $entity, $expected_result) { /** * Tests the access method with an undefined entity type. - * - * @expectedException \Symfony\Component\HttpKernel\Exception\NotFoundHttpException */ public function testAccessWithUndefinedEntityType() { $route = new Route('/edit/form/test_entity/1/body/und/full', array(), array('_access_edit_entity' => 'TRUE')); @@ -131,13 +129,11 @@ public function testAccessWithUndefinedEntityType() { ->will($this->returnValue(NULL)); $account = $this->getMock('Drupal\Core\Session\AccountInterface'); - $this->editAccessCheck->access($route, $request, $account); + $this->assertSame(AccessCheckInterface::KILL, $this->editAccessCheck->access($route, $request, $account)); } /** * Tests the access method with a non existing entity. - * - * @expectedException \Symfony\Component\HttpKernel\Exception\NotFoundHttpException */ public function testAccessWithNotExistingEntity() { $route = new Route('/edit/form/test_entity/1/body/und/full', array(), array('_access_edit_entity_field' => 'TRUE')); @@ -156,7 +152,7 @@ public function testAccessWithNotExistingEntity() { ->will($this->returnValue(NULL)); $account = $this->getMock('Drupal\Core\Session\AccountInterface'); - $this->editAccessCheck->access($route, $request, $account); + $this->assertSame(AccessCheckInterface::KILL, $this->editAccessCheck->access($route, $request, $account)); } } diff --git a/core/modules/edit/tests/Drupal/edit/Tests/Access/EditEntityFieldAccessCheckTest.php b/core/modules/edit/tests/Drupal/edit/Tests/Access/EditEntityFieldAccessCheckTest.php index b9c847d..0791249 100644 --- a/core/modules/edit/tests/Drupal/edit/Tests/Access/EditEntityFieldAccessCheckTest.php +++ b/core/modules/edit/tests/Drupal/edit/Tests/Access/EditEntityFieldAccessCheckTest.php @@ -144,8 +144,6 @@ public function testAccess(EntityInterface $entity, FieldInterface $field = NULL /** * Tests the access method with an undefined entity type. - * - * @expectedException \Symfony\Component\HttpKernel\Exception\NotFoundHttpException */ public function testAccessWithUndefinedEntityType() { $route = new Route('/edit/form/test_entity/1/body/und/full', array(), array('_access_edit_entity_field' => 'TRUE')); @@ -158,13 +156,11 @@ public function testAccessWithUndefinedEntityType() { ->will($this->returnValue(NULL)); $account = $this->getMock('Drupal\Core\Session\AccountInterface'); - $this->editAccessCheck->access($route, $request, $account); + $this->assertSame(AccessCheckInterface::KILL, $this->editAccessCheck->access($route, $request, $account)); } /** * Tests the access method with a non existing entity. - * - * @expectedException \Symfony\Component\HttpKernel\Exception\NotFoundHttpException */ public function testAccessWithNotExistingEntity() { $route = new Route('/edit/form/test_entity/1/body/und/full', array(), array('_access_edit_entity_field' => 'TRUE')); @@ -183,13 +179,11 @@ public function testAccessWithNotExistingEntity() { ->will($this->returnValue(NULL)); $account = $this->getMock('Drupal\Core\Session\AccountInterface'); - $this->editAccessCheck->access($route, $request, $account); + $this->assertSame(AccessCheckInterface::KILL, $this->editAccessCheck->access($route, $request, $account)); } /** * Tests the access method with a forgotten passed field_name. - * - * @expectedException \Symfony\Component\HttpKernel\Exception\NotFoundHttpException */ public function testAccessWithNotPassedFieldName() { $route = new Route('/edit/form/test_entity/1/body/und/full', array(), array('_access_edit_entity_field' => 'TRUE')); @@ -198,13 +192,11 @@ public function testAccessWithNotPassedFieldName() { $request->attributes->set('entity', $this->createMockEntity()); $account = $this->getMock('Drupal\Core\Session\AccountInterface'); - $this->editAccessCheck->access($route, $request, $account); + $this->assertSame(AccessCheckInterface::KILL, $this->editAccessCheck->access($route, $request, $account)); } /** * Tests the access method with a non existing field. - * - * @expectedException \Symfony\Component\HttpKernel\Exception\NotFoundHttpException */ public function testAccessWithNonExistingField() { $route = new Route('/edit/form/test_entity/1/body/und/full', array(), array('_access_edit_entity_field' => 'TRUE')); @@ -214,13 +206,11 @@ public function testAccessWithNonExistingField() { $request->attributes->set('field_name', 'not_valid'); $account = $this->getMock('Drupal\Core\Session\AccountInterface'); - $this->editAccessCheck->access($route, $request, $account); + $this->assertSame(AccessCheckInterface::KILL, $this->editAccessCheck->access($route, $request, $account)); } /** * Tests the access method with a forgotten passed language. - * - * @expectedException \Symfony\Component\HttpKernel\Exception\NotFoundHttpException */ public function testAccessWithNotPassedLanguage() { $route = new Route('/edit/form/test_entity/1/body/und/full', array(), array('_access_edit_entity_field' => 'TRUE')); @@ -230,13 +220,11 @@ public function testAccessWithNotPassedLanguage() { $request->attributes->set('field_name', 'valid'); $account = $this->getMock('Drupal\Core\Session\AccountInterface'); - $this->editAccessCheck->access($route, $request, $account); + $this->assertSame(AccessCheckInterface::KILL, $this->editAccessCheck->access($route, $request, $account)); } /** * Tests the access method with an invalid language. - * - * @expectedException \Symfony\Component\HttpKernel\Exception\NotFoundHttpException */ public function testAccessWithInvalidLanguage() { $entity = $this->createMockEntity(); @@ -253,7 +241,7 @@ public function testAccessWithInvalidLanguage() { $request->attributes->set('langcode', 'xx-lolspeak'); $account = $this->getMock('Drupal\Core\Session\AccountInterface'); - $this->editAccessCheck->access($route, $request, $account); + $this->assertSame(AccessCheckInterface::KILL, $this->editAccessCheck->access($route, $request, $account)); } /** diff --git a/core/modules/system/lib/Drupal/system/PathBasedBreadcrumbBuilder.php b/core/modules/system/lib/Drupal/system/PathBasedBreadcrumbBuilder.php index 4ab853c..f39a1a5 100644 --- a/core/modules/system/lib/Drupal/system/PathBasedBreadcrumbBuilder.php +++ b/core/modules/system/lib/Drupal/system/PathBasedBreadcrumbBuilder.php @@ -12,10 +12,10 @@ use Drupal\Core\Controller\TitleResolverInterface; use Drupal\Core\Access\AccessManager; use Drupal\Core\Entity\EntityManagerInterface; +use Drupal\Core\ParamConverter\ParamNotConvertedException; use Drupal\Core\PathProcessor\InboundPathProcessorInterface; use Drupal\Component\Utility\Unicode; use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; use Symfony\Cmf\Component\Routing\RouteObjectInterface; use Symfony\Component\Routing\Matcher\RequestMatcherInterface; use Symfony\Component\Routing\Exception\ResourceNotFoundException; @@ -192,7 +192,7 @@ protected function getRequestForPath($path, array $exclude) { $request->attributes->add($this->router->matchRequest($request)); return $request; } - catch (NotFoundHttpException $e) { + catch (ParamNotConvertedException $e) { return NULL; } catch (ResourceNotFoundException $e) { diff --git a/core/modules/system/lib/Drupal/system/Tests/Routing/RouterTest.php b/core/modules/system/lib/Drupal/system/Tests/Routing/RouterTest.php index 25d3de0..2ce0f87 100644 --- a/core/modules/system/lib/Drupal/system/Tests/Routing/RouterTest.php +++ b/core/modules/system/lib/Drupal/system/Tests/Routing/RouterTest.php @@ -149,6 +149,20 @@ public function testUrlGeneratorFront() { } /** + * Tests that a page trying to match a path will succeed. + */ + public function testRouterMatching() { + $this->drupalGet('router_test/test14/1'); + $this->assertResponse(200); + $this->assertText('User route "user.view" was matched.'); + + // Try to match a route for a non-existent user. + $this->drupalGet('router_test/test14/2'); + $this->assertResponse(200); + $this->assertText('Route not matched.'); + } + + /** * Tests the user account on the DIC. */ public function testUserAccount() { diff --git a/core/modules/system/tests/modules/router_test_directory/lib/Drupal/router_test/TestControllers.php b/core/modules/system/tests/modules/router_test_directory/lib/Drupal/router_test/TestControllers.php index 86342d5..0db6826 100644 --- a/core/modules/system/tests/modules/router_test_directory/lib/Drupal/router_test/TestControllers.php +++ b/core/modules/system/tests/modules/router_test_directory/lib/Drupal/router_test/TestControllers.php @@ -7,6 +7,9 @@ namespace Drupal\router_test; +use Drupal\Core\ParamConverter\ParamNotConvertedException; +use Drupal\user\UserInterface; +use Symfony\Cmf\Component\Routing\RouteObjectInterface; use Symfony\Component\HttpFoundation\Response; /** @@ -50,4 +53,17 @@ public function test8() { return new Response('test8'); } + public function test9($uid) { + $text = 'Route not matched.'; + try { + $match = \Drupal::service('router')->match('/user/' . $uid); + if (isset($match['user']) && $match['user'] instanceof UserInterface) { + $text = sprintf('User route "%s" was matched.', $match[RouteObjectInterface::ROUTE_NAME]); + } + } + catch (ParamNotConvertedException $e) { + } + return new Response($text); + } + } diff --git a/core/modules/system/tests/modules/router_test_directory/router_test.routing.yml b/core/modules/system/tests/modules/router_test_directory/router_test.routing.yml index 7ad0607..d0460a1 100644 --- a/core/modules/system/tests/modules/router_test_directory/router_test.routing.yml +++ b/core/modules/system/tests/modules/router_test_directory/router_test.routing.yml @@ -86,3 +86,10 @@ router_test.13: defaults: _content: '\Drupal\router_test\TestContent::testAccount' +router_test.14: + path: '/router_test/test14/{uid}' + requirements: + _access: 'TRUE' + defaults: + _controller: '\Drupal\router_test\TestControllers::test9' +