diff --git a/core/includes/menu.inc b/core/includes/menu.inc index 66afab8..f68e1f6 100644 --- a/core/includes/menu.inc +++ b/core/includes/menu.inc @@ -2803,11 +2803,11 @@ function menu_router_build($save = FALSE) { * The translated path pattern from the route. */ function _menu_router_translate_route($route_name) { - $route = Drupal::service('router.route_provider')->getRouteByName($route_name); - $path = trim($route->getPattern(), '/'); - - // Translate placeholders, e.g. {foo} -> %. - return preg_replace('/{' . DRUPAL_PHP_FUNCTION_PATTERN . '}/', '%', $path); + $outline = Drupal::service('router.route_provider') + ->getRouteByName($route_name) + ->compile() + ->getPatternOutline(); + return trim($outline, '/'); } /** diff --git a/core/modules/system/lib/Drupal/system/Tests/Menu/MenuRouterTest.php b/core/modules/system/lib/Drupal/system/Tests/Menu/MenuRouterTest.php index 6829939..ac5e151 100644 --- a/core/modules/system/lib/Drupal/system/Tests/Menu/MenuRouterTest.php +++ b/core/modules/system/lib/Drupal/system/Tests/Menu/MenuRouterTest.php @@ -614,4 +614,18 @@ function testMenuLoadArgumentsInheritance() { $this->assertIdentical(unserialize($router_item['load_functions']), $load_functions, format_string('Expected load functions for router %router_path' , array('%router_path' => $router_path))); } } + + /** + * Test menu links that have optional placeholders. + */ + public function testMenuOptionalPlaceholders() { + $this->drupalGet('menu-test/optional'); + $this->assertResponse(200); + $this->assertText('Sometimes there is no placeholder.'); + + $this->drupalGet('menu-test/optional/foobar'); + $this->assertResponse(200); + $this->assertText("Sometimes there is a placeholder: 'foobar'."); + } + } diff --git a/core/modules/system/tests/modules/menu_test/lib/Drupal/menu_test/TestControllers.php b/core/modules/system/tests/modules/menu_test/lib/Drupal/menu_test/TestControllers.php index 48c2da3..c36a0ae 100644 --- a/core/modules/system/tests/modules/menu_test/lib/Drupal/menu_test/TestControllers.php +++ b/core/modules/system/tests/modules/menu_test/lib/Drupal/menu_test/TestControllers.php @@ -7,6 +7,7 @@ namespace Drupal\menu_test; +use Drupal\Component\Utility\String; use Drupal\Core\Entity\EntityInterface; /** @@ -35,4 +36,22 @@ public function test2() { return 'test2'; } + /** + * Prints out test data. + * + * @param string|null $placeholder + * A placeholder for the return string. + * + * @return string + * The string for this route. + */ + public function testDefaults($placeholder = NULL) { + if ($placeholder) { + return String::format("Sometimes there is a placeholder: '@placeholder'.", array('@placeholder' => $placeholder)); + } + else { + return String::format('Sometimes there is no placeholder.'); + } + } + } 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 eb43fdf..8f71bd3 100644 --- a/core/modules/system/tests/modules/menu_test/menu_test.module +++ b/core/modules/system/tests/modules/menu_test/menu_test.module @@ -438,6 +438,11 @@ function menu_test_menu() { 'title' => 'Local tasks', 'route_name' => 'menu_local_task_test_tasks', ); + $items['menu-test/optional'] = array( + 'title' => 'Test optional placeholder', + 'route_name' => 'menu_test_optional_placeholder', + 'type' => MENU_LOCAL_TASK, + ); return $items; } 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 4eee7ed..9cf8f11 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 @@ -99,3 +99,11 @@ menu_local_task_test_tasks_settings_sub2: _content: '\Drupal\menu_test\TestControllers::test1' requirements: _access: 'TRUE' + +menu_test_optional_placeholder: + pattern: '/menu-test/optional/{placeholder}' + defaults: + _content: '\Drupal\menu_test\TestControllers::testDefaults' + placeholder: ~ + requirements: + _access: 'TRUE'