Commit cd74c624 authored by webchick's avatar webchick

Issue #2091691 by tim.plunkett: Convert test non-form page callbacks to routes and controllers.

parent 2867e5ba
...@@ -1942,10 +1942,10 @@ function menu_navigation_links($menu_name, $level = 0) { ...@@ -1942,10 +1942,10 @@ function menu_navigation_links($menu_name, $level = 0) {
/** /**
* Collects the local tasks (tabs), action links, and the root path. * Collects the local tasks (tabs), action links, and the root path.
* *
* @param $level * @param int $level
* The level of tasks you ask for. Primary tasks are 0, secondary are 1. * The level of tasks you ask for. Primary tasks are 0, secondary are 1.
* *
* @return * @return array
* An array containing * An array containing
* - tabs: Local tasks for the requested level. * - tabs: Local tasks for the requested level.
* - actions: Action links for the requested level. * - actions: Action links for the requested level.
...@@ -1965,11 +1965,6 @@ function menu_local_tasks($level = 0) { ...@@ -1965,11 +1965,6 @@ function menu_local_tasks($level = 0) {
); );
if (!isset($data)) { if (!isset($data)) {
$data = array();
// Set defaults in case there are no actions or tabs.
$actions = $empty['actions'];
$tabs = array();
// Look for route-based tabs. // Look for route-based tabs.
$data['tabs'] = array(); $data['tabs'] = array();
$data['actions'] = array(); $data['actions'] = array();
...@@ -1983,202 +1978,30 @@ function menu_local_tasks($level = 0) { ...@@ -1983,202 +1978,30 @@ function menu_local_tasks($level = 0) {
} }
} }
// @todo Remove the code below once the old menu router system got removed. // @todo Remove when all local tasks/actions are converted to plugins.
$router_item = menu_get_item(); $router_item = menu_get_item();
// If this router item points to its parent, start from the parents to // If this router item points to its parent, start from the parents to
// compute tabs and actions. // compute tabs and actions.
if ($router_item && ($router_item['type'] & MENU_LINKS_TO_PARENT)) { if ($router_item && ($router_item['type'] & MENU_LINKS_TO_PARENT)) {
$router_item = menu_get_item($router_item['tab_parent_href']); $router_item = menu_get_item($router_item['tab_parent_href']);
} }
// If we failed to fetch a router item or the current user doesn't have // If we failed to fetch a router item or the current user doesn't have
// access to it, don't bother computing the tabs. // access to it, don't bother computing the tabs.
if (!$router_item || !$router_item['access']) { if ((!$route_name && !$router_item) || ($router_item && !$router_item['access'])) {
return $empty; return $empty;
} }
// @todo remove all code using {menu_router} and anything using MENU_* if ($router_item) {
// constants when all local actions and local tasks are converted to _menu_get_legacy_tasks($router_item, $data, $root_path);
// plugins. The remaining code should just invoke those managers plus do the
// invocations of hook_menu_local_tasks() and hook_menu_local_tasks_alter().
// Get all tabs (also known as local tasks) and the root page.
$result = db_select('menu_router', NULL, array('fetch' => PDO::FETCH_ASSOC))
->fields('menu_router')
->condition('tab_root', $router_item['tab_root'])
->condition('context', MENU_CONTEXT_INLINE, '<>')
->orderBy('weight')
->orderBy('title')
->execute();
$map = $router_item['original_map'];
$children = array();
$tasks = array();
$root_path = $router_item['path'];
foreach ($result as $item) {
_menu_translate($item, $map, TRUE);
if ($item['tab_parent']) {
// All tabs, but not the root page.
$children[$item['tab_parent']][$item['path']] = $item;
}
// Store the translated item for later use.
$tasks[$item['path']] = $item;
}
// Find all tabs below the current path.
$path = $router_item['path'];
// Tab parenting may skip levels, so the number of parts in the path may not
// equal the depth. Thus we use the $depth counter (offset by 1000 for ksort).
$depth = 1001;
$actions = array();
while (isset($children[$path])) {
$tabs_current = array();
$actions_current = array();
$next_path = '';
$tab_count = 0;
$action_count = 0;
foreach ($children[$path] as $item) {
// Local tasks can be normal items too, so bitmask with
// MENU_IS_LOCAL_TASK before checking.
if (!($item['type'] & MENU_IS_LOCAL_TASK)) {
// This item is not a tab, skip it.
continue;
}
if ($item['access']) {
$link = $item;
// The default task is always active. As tabs can be normal items
// too, so bitmask with MENU_LINKS_TO_PARENT before checking.
if (($item['type'] & MENU_LINKS_TO_PARENT) == MENU_LINKS_TO_PARENT) {
// Find the first parent which is not a default local task or action.
for ($p = $item['tab_parent']; ($tasks[$p]['type'] & MENU_LINKS_TO_PARENT) == MENU_LINKS_TO_PARENT; $p = $tasks[$p]['tab_parent']);
// Use the path of the parent instead.
$link['href'] = $tasks[$p]['href'];
// Mark the link as active, if the current path happens to be the
// path of the default local task itself (i.e., instead of its
// tab_parent_href or tab_root_href). Normally, links for default
// local tasks link to their parent, but the path of default local
// tasks can still be accessed directly, in which case this link
// would not be marked as active, since l() only compares the href
// with current_path().
if ($link['href'] != current_path()) {
$link['localized_options']['attributes']['class'][] = 'active';
}
$tabs_current[$link['href']] = array(
'#theme' => 'menu_local_task',
'#link' => $link,
'#active' => TRUE,
'#weight' => isset($link['weight']) ? $link['weight'] : NULL,
);
$next_path = $item['path'];
$tab_count++;
}
else {
// Actions can be normal items too, so bitmask with
// MENU_IS_LOCAL_ACTION before checking.
if (($item['type'] & MENU_IS_LOCAL_ACTION) == MENU_IS_LOCAL_ACTION) {
// The item is an action, display it as such.
$actions_current[$link['href']] = array(
'#theme' => 'menu_local_action',
'#link' => $link,
'#weight' => isset($link['weight']) ? $link['weight'] : NULL,
);
$action_count++;
}
else {
// Otherwise, it's a normal tab.
$tabs_current[$link['href']] = array(
'#theme' => 'menu_local_task',
'#link' => $link,
'#weight' => isset($link['weight']) ? $link['weight'] : NULL,
);
$tab_count++;
}
}
}
}
$path = $next_path;
$tabs[$depth] = $tabs_current;
$actions = array_merge($actions, $actions_current);
$depth++;
}
$data['actions'] = $actions;
// Find all tabs at the same level or above the current one.
$parent = $router_item['tab_parent'];
$path = $router_item['path'];
$current = $router_item;
$depth = 1000;
while (isset($children[$parent])) {
$tabs_current = array();
$next_path = '';
$next_parent = '';
$count = 0;
foreach ($children[$parent] as $item) {
// Skip local actions.
if ($item['type'] & MENU_IS_LOCAL_ACTION) {
continue;
}
if ($item['access']) {
$count++;
$link = $item;
// Local tasks can be normal items too, so bitmask with
// MENU_LINKS_TO_PARENT before checking.
if (($item['type'] & MENU_LINKS_TO_PARENT) == MENU_LINKS_TO_PARENT) {
// Find the first parent which is not a default local task.
for ($p = $item['tab_parent']; ($tasks[$p]['type'] & MENU_LINKS_TO_PARENT) == MENU_LINKS_TO_PARENT; $p = $tasks[$p]['tab_parent']);
// Use the path of the parent instead.
$link['href'] = $tasks[$p]['href'];
if ($item['path'] == $router_item['path']) {
$root_path = $tasks[$p]['path'];
}
}
// We check for the active tab.
if ($item['path'] == $path) {
// Mark the link as active, if the current path is a (second-level)
// local task of a default local task. Since this default local task
// links to its parent, l() will not mark it as active, as it only
// compares the link's href to current_path().
if ($link['href'] != current_path()) {
$link['localized_options']['attributes']['class'][] = 'active';
}
$tabs_current[$link['href']] = array(
'#theme' => 'menu_local_task',
'#link' => $link,
'#active' => TRUE,
'#weight' => isset($link['weight']) ? $link['weight'] : NULL,
);
$next_path = $item['tab_parent'];
if (isset($tasks[$next_path])) {
$next_parent = $tasks[$next_path]['tab_parent'];
}
}
else {
$tabs_current[$link['href']] = array(
'#theme' => 'menu_local_task',
'#link' => $link,
'#weight' => isset($link['weight']) ? $link['weight'] : NULL,
);
}
}
}
$path = $next_path;
$parent = $next_parent;
$tabs[$depth] = $tabs_current;
$depth--;
} }
// Sort by depth.
ksort($tabs);
// Remove the depth, we are interested only in their relative placement.
$tabs = array_values($tabs);
$data['tabs'] += $tabs;
// Allow modules to dynamically add further tasks. // Allow modules to dynamically add further tasks.
$module_handler = \Drupal::moduleHandler(); $module_handler = \Drupal::moduleHandler();
foreach ($module_handler->getImplementations('menu_local_tasks') as $module) { foreach ($module_handler->getImplementations('menu_local_tasks') as $module) {
$function = $module . '_menu_local_tasks'; $function = $module . '_menu_local_tasks';
$function($data, $router_item, $root_path); $function($data, $route_name);
} }
// Allow modules to alter local tasks. // Allow modules to alter local tasks.
$module_handler->alter('menu_local_tasks', $data, $router_item, $root_path); $module_handler->alter('menu_local_tasks', $data, $route_name);
} }
if (isset($data['tabs'][$level])) { if (isset($data['tabs'][$level])) {
...@@ -2194,6 +2017,189 @@ function menu_local_tasks($level = 0) { ...@@ -2194,6 +2017,189 @@ function menu_local_tasks($level = 0) {
return $empty; return $empty;
} }
/**
* Finds legacy local tasks/actions.
*
* @param array $router_item
* The current router item.
* @param array $data
* An associative array of local tasks/actions.
* @param string $root_path
*
* @deprecated Remove once all local tasks/actions are converted to plugins.
*/
function _menu_get_legacy_tasks($router_item, &$data, &$root_path) {
// Get all tabs (also known as local tasks) and the root page.
$result = db_select('menu_router', NULL, array('fetch' => PDO::FETCH_ASSOC))
->fields('menu_router')
->condition('tab_root', $router_item['tab_root'])
->condition('context', MENU_CONTEXT_INLINE, '<>')
->orderBy('weight')
->orderBy('title')
->execute();
$map = $router_item['original_map'];
$children = array();
$tasks = array();
$root_path = $router_item['path'];
foreach ($result as $item) {
_menu_translate($item, $map, TRUE);
if ($item['tab_parent']) {
// All tabs, but not the root page.
$children[$item['tab_parent']][$item['path']] = $item;
}
// Store the translated item for later use.
$tasks[$item['path']] = $item;
}
// Find all tabs below the current path.
$path = $router_item['path'];
// Tab parenting may skip levels, so the number of parts in the path may not
// equal the depth. Thus we use the $depth counter (offset by 1000 for ksort).
$depth = 1001;
$tabs = array();
$actions = array();
while (isset($children[$path])) {
$tabs_current = array();
$actions_current = array();
$next_path = '';
$tab_count = 0;
$action_count = 0;
foreach ($children[$path] as $item) {
// Local tasks can be normal items too, so bitmask with
// MENU_IS_LOCAL_TASK before checking.
if (!($item['type'] & MENU_IS_LOCAL_TASK)) {
// This item is not a tab, skip it.
continue;
}
if ($item['access']) {
$link = $item;
// The default task is always active. As tabs can be normal items
// too, so bitmask with MENU_LINKS_TO_PARENT before checking.
if (($item['type'] & MENU_LINKS_TO_PARENT) == MENU_LINKS_TO_PARENT) {
// Find the first parent which is not a default local task or action.
for ($p = $item['tab_parent']; ($tasks[$p]['type'] & MENU_LINKS_TO_PARENT) == MENU_LINKS_TO_PARENT; $p = $tasks[$p]['tab_parent']);
// Use the path of the parent instead.
$link['href'] = $tasks[$p]['href'];
// Mark the link as active, if the current path happens to be the
// path of the default local task itself (i.e., instead of its
// tab_parent_href or tab_root_href). Normally, links for default
// local tasks link to their parent, but the path of default local
// tasks can still be accessed directly, in which case this link
// would not be marked as active, since l() only compares the href
// with current_path().
if ($link['href'] != current_path()) {
$link['localized_options']['attributes']['class'][] = 'active';
}
$tabs_current[$link['href']] = array(
'#theme' => 'menu_local_task',
'#link' => $link,
'#active' => TRUE,
'#weight' => isset($link['weight']) ? $link['weight'] : NULL,
);
$next_path = $item['path'];
$tab_count++;
}
else {
// Actions can be normal items too, so bitmask with
// MENU_IS_LOCAL_ACTION before checking.
if (($item['type'] & MENU_IS_LOCAL_ACTION) == MENU_IS_LOCAL_ACTION) {
// The item is an action, display it as such.
$actions_current[$link['href']] = array(
'#theme' => 'menu_local_action',
'#link' => $link,
'#weight' => isset($link['weight']) ? $link['weight'] : NULL,
);
$action_count++;
}
else {
// Otherwise, it's a normal tab.
$tabs_current[$link['href']] = array(
'#theme' => 'menu_local_task',
'#link' => $link,
'#weight' => isset($link['weight']) ? $link['weight'] : NULL,
);
$tab_count++;
}
}
}
}
$path = $next_path;
$tabs[$depth] = $tabs_current;
$actions = array_merge($actions, $actions_current);
$depth++;
}
$data['actions'] = $actions;
// Find all tabs at the same level or above the current one.
$parent = $router_item['tab_parent'];
$path = $router_item['path'];
$current = $router_item;
$depth = 1000;
while (isset($children[$parent])) {
$tabs_current = array();
$next_path = '';
$next_parent = '';
$count = 0;
foreach ($children[$parent] as $item) {
// Skip local actions.
if ($item['type'] & MENU_IS_LOCAL_ACTION) {
continue;
}
if ($item['access']) {
$count++;
$link = $item;
// Local tasks can be normal items too, so bitmask with
// MENU_LINKS_TO_PARENT before checking.
if (($item['type'] & MENU_LINKS_TO_PARENT) == MENU_LINKS_TO_PARENT) {
// Find the first parent which is not a default local task.
for ($p = $item['tab_parent']; ($tasks[$p]['type'] & MENU_LINKS_TO_PARENT) == MENU_LINKS_TO_PARENT; $p = $tasks[$p]['tab_parent']);
// Use the path of the parent instead.
$link['href'] = $tasks[$p]['href'];
if ($item['path'] == $router_item['path']) {
$root_path = $tasks[$p]['path'];
}
}
// We check for the active tab.
if ($item['path'] == $path) {
// Mark the link as active, if the current path is a (second-level)
// local task of a default local task. Since this default local task
// links to its parent, l() will not mark it as active, as it only
// compares the link's href to current_path().
if ($link['href'] != current_path()) {
$link['localized_options']['attributes']['class'][] = 'active';
}
$tabs_current[$link['href']] = array(
'#theme' => 'menu_local_task',
'#link' => $link,
'#active' => TRUE,
'#weight' => isset($link['weight']) ? $link['weight'] : NULL,
);
$next_path = $item['tab_parent'];
if (isset($tasks[$next_path])) {
$next_parent = $tasks[$next_path]['tab_parent'];
}
}
else {
$tabs_current[$link['href']] = array(
'#theme' => 'menu_local_task',
'#link' => $link,
'#weight' => isset($link['weight']) ? $link['weight'] : NULL,
);
}
}
}
$path = $next_path;
$parent = $next_parent;
$tabs[$depth] = $tabs_current;
$depth--;
}
// Sort by depth.
ksort($tabs);
// Remove the depth, we are interested only in their relative placement.
$tabs = array_values($tabs);
$data['tabs'] += $tabs;
}
/** /**
* Retrieves contextual links for a path based on registered local tasks. * Retrieves contextual links for a path based on registered local tasks.
* *
......
...@@ -84,7 +84,9 @@ public function content(Request $request, $_content) { ...@@ -84,7 +84,9 @@ public function content(Request $request, $_content) {
} }
if (!is_array($page_content)) { if (!is_array($page_content)) {
$page_content = array( $page_content = array(
'#markup' => $page_content, 'main' => array(
'#markup' => $page_content,
),
); );
} }
if (!isset($page_content['#title'])) { if (!isset($page_content['#title'])) {
......
...@@ -30,8 +30,8 @@ function custom_block_help($path, $arg) { ...@@ -30,8 +30,8 @@ function custom_block_help($path, $arg) {
/** /**
* Implements hook_menu_local_tasks(). * Implements hook_menu_local_tasks().
*/ */
function custom_block_menu_local_tasks(&$data, $router_item, $root_path) { function custom_block_menu_local_tasks(&$data, $route_name) {
if ($router_item['route_name'] == 'custom_block.list') { if ($route_name == 'custom_block.list') {
// @todo Move to a LocalAction plugin when https://drupal.org/node/2045267 // @todo Move to a LocalAction plugin when https://drupal.org/node/2045267
// allows local actions to work with query strings. // allows local actions to work with query strings.
$item = menu_get_item('block/add'); $item = menu_get_item('block/add');
...@@ -48,13 +48,13 @@ function custom_block_menu_local_tasks(&$data, $router_item, $root_path) { ...@@ -48,13 +48,13 @@ function custom_block_menu_local_tasks(&$data, $router_item, $root_path) {
$routes = array_map(function ($theme) { $routes = array_map(function ($theme) {
return "block.admin_display_$theme"; return "block.admin_display_$theme";
}, array_keys(list_themes())); }, array_keys(list_themes()));
if (in_array($router_item['route_name'], $routes)) { if (in_array($route_name, $routes)) {
// @todo Move to a LocalAction plugin when https://drupal.org/node/2045267 // @todo Move to a LocalAction plugin when https://drupal.org/node/2045267
// allows local actions to work with query strings. // allows local actions to work with query strings.
$item = menu_get_item('block/add'); $item = menu_get_item('block/add');
if ($item['access']) { if ($item['access']) {
// Add a destination parameter. // Add a destination parameter.
$item['localized_options']['query']['theme'] = end($router_item['map']); $item['localized_options']['query']['theme'] = \Drupal::request()->attributes->get('theme');
$data['actions']['block/add'] = array( $data['actions']['block/add'] = array(
'#theme' => 'menu_local_action', '#theme' => 'menu_local_action',
'#link' => $item, '#link' => $item,
......
...@@ -92,10 +92,7 @@ function custom_block_test_menu() { ...@@ -92,10 +92,7 @@ function custom_block_test_menu() {
$items['custom-block/%custom_block'] = array( $items['custom-block/%custom_block'] = array(
'title callback' => 'entity_page_label', 'title callback' => 'entity_page_label',
'title arguments' => array(1), 'title arguments' => array(1),
'page callback' => 'entity_view', 'route_name' => 'custom_block_test.custom_block_view',
'page arguments' => array(1, 'default'),
'access callback' => 'entity_page_access',
'access arguments' => array(1, 'view'),
); );
return $items; return $items;
} }
custom_block_test.custom_block_view:
path: '/custom-block/{custom_block}'
defaults:
_entity_view: 'custom_block'
requirements:
_entity_access: 'custom_block.view'
...@@ -372,7 +372,7 @@ function testCommentFunctionality() { ...@@ -372,7 +372,7 @@ function testCommentFunctionality() {
$data = array('bundle' => 'entity_test_render', 'name' => $random_label); $data = array('bundle' => 'entity_test_render', 'name' => $random_label);
$new_entity = entity_create('entity_test_render', $data); $new_entity = entity_create('entity_test_render', $data);
$new_entity->save(); $new_entity->save();
$this->drupalGet('entity_test_render/manage/' . $new_entity->id() . '/edit'); $this->drupalGet('entity_test_render/manage/' . $new_entity->id());
$this->assertNoFieldChecked('edit-field-foobar-0-status-1'); $this->assertNoFieldChecked('edit-field-foobar-0-status-1');
$this->assertFieldChecked('edit-field-foobar-0-status-2'); $this->assertFieldChecked('edit-field-foobar-0-status-2');
$this->assertNoField('edit-field-foobar-0-status-0'); $this->assertNoField('edit-field-foobar-0-status-0');
......
content_translation.local_tasks:
derivative: 'Drupal\content_translation\Plugin\Derivative\ContentTranslationLocalTasks'
class: 'Drupal\content_translation\Plugin\ContentTranslationLocalTasks'
weight: 100
<?php
/**
* @file
* Contains \Drupal\content_translation\Plugin\ContentTranslationLocalTasks.
*/
namespace Drupal\content_translation\Plugin;
use Drupal\Core\Menu\LocalTaskDefault;
use Symfony\Component\HttpFoundation\Request;
/**
* Provides route parameter manipulation for content translation local tasks.
*/
class ContentTranslationLocalTasks extends LocalTaskDefault {
/**
* {@inheritdoc}
*/
public function getRouteParameters(Request $request) {
$parameters = parent::getRouteParameters($request);
$entity_type = $this->pluginDefinition['entity_type'];