From 594c849d8d7f404df835e213476085e4ea0eea61 Mon Sep 17 00:00:00 2001 From: webchick <webchick@24967.no-reply.drupal.org> Date: Wed, 1 May 2013 21:09:48 -0700 Subject: [PATCH] Issue #1938960 by tim.plunkett, dawehner: Fixed _menu_translate() doesn't care about new routes. --- core/includes/menu.inc | 16 +++- .../Drupal/Core/Access/DefaultAccessCheck.php | 2 +- .../system/Tests/Menu/MenuTranslateTest.php | 53 +++++++++++++ .../system/Tests/Menu/TreeAccessTest.php | 4 +- core/modules/system/system.install | 18 +++++ .../tests/modules/menu_test/menu_test.module | 5 ++ .../modules/menu_test/menu_test.routing.yml | 8 +- .../Core/Access/DefaultAccessCheckTest.php | 75 +++++++++++++++++++ 8 files changed, 176 insertions(+), 5 deletions(-) create mode 100644 core/modules/system/lib/Drupal/system/Tests/Menu/MenuTranslateTest.php create mode 100644 core/tests/Drupal/Tests/Core/Access/DefaultAccessCheckTest.php diff --git a/core/includes/menu.inc b/core/includes/menu.inc index 6b62bf878de4..7065218a007e 100644 --- a/core/includes/menu.inc +++ b/core/includes/menu.inc @@ -766,7 +766,18 @@ function _menu_translate(&$router_item, $map, $to_arg = FALSE) { $router_item['tab_root_href'] = implode('/', $tab_root_map); $router_item['tab_parent_href'] = implode('/', $tab_parent_map); $router_item['options'] = array(); - _menu_check_access($router_item, $map); + if (!empty($router_item['route_name'])) { + $route_provider = Drupal::getContainer()->get('router.route_provider'); + $route = $route_provider->getRouteByName($router_item['route_name']); + $request = Request::create('/' . $router_item['href']); + $request->attributes->set('system_path', $router_item['href']); + $request->attributes->add(Drupal::service('router')->matchRequest($request)); + $router_item['access'] = Drupal::service('access_manager')->check($route, $request); + } + else { + // @todo: Remove once all routes are converted. + _menu_check_access($router_item, $map); + } // For performance, don't localize an item the user can't access. if ($router_item['access']) { @@ -3166,6 +3177,7 @@ function _menu_router_build($callbacks, $save = FALSE) { 'file' => '', 'file path' => '', 'include file' => '', + 'route_name' => '', ); // Calculate out the file to be included for each callback, if any. @@ -3227,6 +3239,7 @@ function _menu_router_save($menu, $masks) { 'position', 'weight', 'include_file', + 'route_name', )); $num_records = 0; @@ -3258,6 +3271,7 @@ function _menu_router_save($menu, $masks) { 'position' => $item['position'], 'weight' => $item['weight'], 'include_file' => $item['include file'], + 'route_name' => $item['route_name'], )); // Execute in batches to avoid the memory overhead of all of those records diff --git a/core/lib/Drupal/Core/Access/DefaultAccessCheck.php b/core/lib/Drupal/Core/Access/DefaultAccessCheck.php index 31c6da389625..074dfd0baa01 100644 --- a/core/lib/Drupal/Core/Access/DefaultAccessCheck.php +++ b/core/lib/Drupal/Core/Access/DefaultAccessCheck.php @@ -26,6 +26,6 @@ public function applies(Route $route) { * Implements AccessCheckInterface::access(). */ public function access(Route $route, Request $request) { - return (bool) $route->getRequirement('_access'); + return $route->getRequirement('_access') === 'TRUE'; } } diff --git a/core/modules/system/lib/Drupal/system/Tests/Menu/MenuTranslateTest.php b/core/modules/system/lib/Drupal/system/Tests/Menu/MenuTranslateTest.php new file mode 100644 index 000000000000..33aa51ada658 --- /dev/null +++ b/core/modules/system/lib/Drupal/system/Tests/Menu/MenuTranslateTest.php @@ -0,0 +1,53 @@ +<?php + +/** + * @file + * Contains \Drupal\system\Tests\Menu\MenuTranslateTest. + */ + +namespace Drupal\system\Tests\Menu; + +use Drupal\simpletest\WebTestBase; + +/** + * Defines a test class which tests the _menu_translate method. + * + * @see _menu_translate(). + */ +class MenuTranslateTest extends WebTestBase { + + /** + * Modules to enable. + * + * @var array + */ + public static $modules = array('menu_test'); + + public static function getInfo() { + return array( + 'name' => 'menu_translate', + 'description' => 'Tests the _menu_translate() method.', + 'group' => 'Menu', + ); + } + + /** + * Tests _menu_translate(). + */ + public function testMenuTranslate() { + // Check for access to a restricted local task from a default local task. + $this->drupalGet('foo/asdf'); + $this->assertResponse(200); + $this->assertLinkByHref('foo/asdf'); + $this->assertLinkByHref('foo/asdf/b'); + $this->assertNoLinkByHref('foo/asdf/c'); + + // Attempt to access a restricted local task. + $this->drupalGet('foo/asdf/c'); + $this->assertResponse(403); + $this->assertNoLinkByHref('foo/asdf'); + $this->assertNoLinkByHref('foo/asdf/b'); + $this->assertNoLinkByHref('foo/asdf/c'); + } + +} diff --git a/core/modules/system/lib/Drupal/system/Tests/Menu/TreeAccessTest.php b/core/modules/system/lib/Drupal/system/Tests/Menu/TreeAccessTest.php index 91d1a39bb943..4dafee64d21b 100644 --- a/core/modules/system/lib/Drupal/system/Tests/Menu/TreeAccessTest.php +++ b/core/modules/system/lib/Drupal/system/Tests/Menu/TreeAccessTest.php @@ -67,7 +67,7 @@ protected function getTestRouteCollection() { '_controller' => '\Drupal\menu_test\TestController::test' ), array( - '_access' => '1' + '_access' => 'TRUE' ) )); $route_collection->add('menu_test_2', new Route('/menu_test/test_2', @@ -75,7 +75,7 @@ protected function getTestRouteCollection() { '_controller' => '\Drupal\menu_test\TestController::test' ), array( - '_access' => '0' + '_access' => 'FALSE' ) )); $this->routeCollection = $route_collection; diff --git a/core/modules/system/system.install b/core/modules/system/system.install index e23bf8e0d6ed..ccde9147bb1e 100644 --- a/core/modules/system/system.install +++ b/core/modules/system/system.install @@ -858,6 +858,11 @@ function system_schema() { 'type' => 'text', 'size' => 'medium', ), + 'route_name' => array( + 'description' => 'The machine name of a defined Symfony Route this menu item represents.', + 'type' => 'varchar', + 'length' => 255, + ), ), 'indexes' => array( 'fit' => array('fit'), @@ -2082,6 +2087,19 @@ function system_update_8053() { db_drop_table('cache_form'); } +/** + * Adds route_name column to the menu_router table. + */ +function system_update_8054() { + $spec = array( + 'description' => 'The machine name of a defined Symfony Route this menu item represents.', + 'type' => 'varchar', + 'length' => 255, + ); + + db_add_field('menu_router', 'route_name', $spec); +} + /** * @} End of "defgroup updates-7.x-to-8.x". * The next series of updates should start at 9000. diff --git a/core/modules/system/tests/modules/menu_test/menu_test.module b/core/modules/system/tests/modules/menu_test/menu_test.module index 8a1aac48cf6a..695c2160bfba 100644 --- a/core/modules/system/tests/modules/menu_test/menu_test.module +++ b/core/modules/system/tests/modules/menu_test/menu_test.module @@ -407,6 +407,11 @@ function menu_test_menu() { // Controller-based local task. $items['foo/%/b'] = array( 'title' => 'Local task B', + 'route_name' => 'menu_router_test2', + 'type' => MENU_LOCAL_TASK, + ); + $items['foo/%/c'] = array( + 'title' => 'Local task C', 'route_name' => 'menu_router_test3', 'type' => MENU_LOCAL_TASK, ); diff --git a/core/modules/system/tests/modules/menu_test/menu_test.routing.yml b/core/modules/system/tests/modules/menu_test/menu_test.routing.yml index 9ed262c6270f..12c5ad1ec6ca 100644 --- a/core/modules/system/tests/modules/menu_test/menu_test.routing.yml +++ b/core/modules/system/tests/modules/menu_test/menu_test.routing.yml @@ -4,9 +4,15 @@ menu_router_test1: _content: '\Drupal\menu_test\TestControllers::test1' requirements: _access: 'TRUE' -menu_router_test3: +menu_router_test2: pattern: '/foo/{bar}/b' defaults: _content: '\Drupal\menu_test\TestControllers::test2' requirements: _access: 'TRUE' +menu_router_test3: + pattern: '/foo/{bar}/c' + defaults: + _content: '\Drupal\menu_test\TestControllers::test2' + requirements: + _access: 'FALSE' diff --git a/core/tests/Drupal/Tests/Core/Access/DefaultAccessCheckTest.php b/core/tests/Drupal/Tests/Core/Access/DefaultAccessCheckTest.php new file mode 100644 index 000000000000..d96825c004cf --- /dev/null +++ b/core/tests/Drupal/Tests/Core/Access/DefaultAccessCheckTest.php @@ -0,0 +1,75 @@ +<?php + +/** + * @file + * Contains \Drupal\Tests\Core\Access\DefaultAccessCheckTest. + */ + +namespace Drupal\Tests\Core\Access; + +use Drupal\Core\Access\DefaultAccessCheck; +use Drupal\Tests\UnitTestCase; +use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\Routing\Route; + +/** + * Defines a test to check the default access checker. + * + * @see \Drupal\Core\Access\DefaultAccessCheck + */ +class DefaultAccessCheckTest extends UnitTestCase { + + /** + * The access checker to test. + * + * @var \Drupal\Core\Access\DefaultAccessCheck + */ + protected $accessChecker; + + public static function getInfo() { + return array( + 'name' => 'DefaultAccessCheck access checker', + 'description' => 'Tests the DefaultAccessCheck class.', + 'group' => 'Routing', + ); + } + + /** + * {@inheritdoc} + */ + protected function setUp() { + parent::setUp(); + + $this->accessChecker = new DefaultAccessCheck(); + } + + + /** + * Test the applies method. + */ + public function testApplies() { + $route = new Route('/test-route'); + $this->assertFalse($this->accessChecker->applies($route), 'Access checker applied even no _access was defined as requirement.'); + + $route->addRequirements(array('_access' => 'FALSE')); + $this->assertTrue($this->accessChecker->applies($route), 'Access checker applied even a _access was defined as requirement.'); + + $route->addRequirements(array('_access' => 'TRUE')); + $this->assertTrue($this->accessChecker->applies($route), 'Access checker applied even a _access was defined as requirement.'); + } + + /** + * Test the access method. + */ + public function testAccess() { + $route = new Route('/test-route'); + $request = new Request(array()); + + $route->addRequirements(array('_access' => 'FALSE')); + $this->assertFalse($this->accessChecker->access($route, $request)); + + $route->addRequirements(array('_access' => 'TRUE')); + $this->assertTrue($this->accessChecker->access($route, $request)); + } + +} -- GitLab