Commit 0223bf1d authored by webchick's avatar webchick
Browse files

#699858 by David_Rothstein, catch, yoroy, sun, ronald_istos, et al: Fix...

#699858 by David_Rothstein, catch, yoroy, sun, ronald_istos, et al: Fix admin/by-task is confusing because it looks too similar to admin/config. Makes admin/by-task a very minimal view, and makes admin/by-module a more fully fledged index.
parent 337dbc4f
......@@ -220,7 +220,7 @@ function comment_menu() {
'description' => 'List and edit site comments and the comment approval queue.',
'page callback' => 'comment_admin',
'access arguments' => array('administer comments'),
'type' => MENU_LOCAL_TASK,
'type' => MENU_LOCAL_TASK | MENU_NORMAL_ITEM,
'file' => 'comment.admin.inc',
);
// Tabs begin here.
......
......@@ -33,26 +33,26 @@ function dashboard_help($path, $arg) {
function dashboard_menu() {
$items['admin/structure/dashboard'] = array(
'title' => 'Dashboard',
'description' => "Configure which blocks can be shown on the dashboard.",
'description' => 'Configure which blocks can be shown on the dashboard.',
'page callback' => 'dashboard_admin_blocks',
'access arguments' => array('administer blocks'),
);
$items['admin/dashboard'] = array(
'title' => 'Dashboard',
'description' => 'View and customize your dashboard',
'description' => 'View and customize your dashboard.',
'page callback' => 'dashboard_admin',
'access arguments' => array('access dashboard'),
'type' => MENU_LOCAL_TASK | MENU_NORMAL_ITEM,
// Make this appear first, so for example, in admin menus, it shows up on
// the top corner of the window as a convinient "home link".
// the top corner of the window as a convenient "home link".
'weight' => -15,
);
$items['admin/dashboard/customize'] = array(
'title' => 'Dashboard',
'description' => 'View and customize your dashboard',
'title' => 'Customize dashboard',
'description' => 'Customize your dashboard.',
'page callback' => 'dashboard_admin',
'page arguments' => array(TRUE),
'access arguments' => array('access dashboard'),
'type' => MENU_VISIBLE_IN_BREADCRUMB,
);
$items['admin/dashboard/drawer'] = array(
'page callback' => 'dashboard_show_disabled',
......@@ -235,14 +235,6 @@ function dashboard_forms() {
* Whether to launch in customization mode right away. TRUE or FALSE.
*/
function dashboard_admin($launch_customize = FALSE) {
// Only continue if provided arguments are expected. This function serves
// as the callback for the top-level admin/ page, so any unexpected arguments
// are likely the result of someone typing in the URL of an administrative
// page that doesn't actually exist; for example, admin/some/random/page.
if (!is_bool($launch_customize)) {
return MENU_NOT_FOUND;
}
$js_settings = array(
'dashboard' => array(
'drawer' => url('admin/dashboard/drawer'),
......
......@@ -22,12 +22,12 @@ function help_main() {
function help_page($name) {
$output = '';
if (module_hook($name, 'help')) {
$module = drupal_parse_info_file(drupal_get_path('module', $name) . '/' . $name . '.info');
drupal_set_title($module['name']);
$info = system_get_info('module');
drupal_set_title($info[$name]['name']);
$temp = module_invoke($name, 'help', "admin/help#$name", drupal_help_arg());
if (empty($temp)) {
$output .= t("No help is available for module %module.", array('%module' => $module['name']));
$output .= t("No help is available for module %module.", array('%module' => $info[$name]['name']));
}
else {
$output .= $temp;
......@@ -35,12 +35,14 @@ function help_page($name) {
// Only print list of administration pages if the module in question has
// any such pages associated to it.
$admin_tasks = system_get_module_admin_tasks($name);
$admin_tasks = system_get_module_admin_tasks($name, $info[$name]);
if (!empty($admin_tasks)) {
ksort($admin_tasks);
$output .= theme('item_list', array('items' => $admin_tasks, 'title' => t('@module administration pages', array('@module' => $module['name']))));
$links = array();
foreach ($admin_tasks as $task) {
$links[] = l($task['title'], $task['link_path'], $task['localized_options']);
}
$output .= theme('item_list', array('items' => $links, 'title' => t('@module administration pages', array('@module' => $info[$name]['name']))));
}
}
return $output;
}
......
......@@ -25,6 +25,7 @@ function help_menu() {
'page callback' => 'help_page',
'page arguments' => array(2),
'access arguments' => array('access administration pages'),
'type' => MENU_VISIBLE_IN_BREADCRUMB,
'file' => 'help.admin.inc',
);
}
......
......@@ -136,6 +136,7 @@ function locale_menu() {
'page arguments' => array('locale_language_providers_url_form'),
'access arguments' => array('administer languages'),
'file' => 'locale.admin.inc',
'type' => MENU_VISIBLE_IN_BREADCRUMB,
);
$items['admin/config/regional/language/configure/session'] = array(
'title' => 'Session language detection configuration',
......@@ -143,6 +144,7 @@ function locale_menu() {
'page arguments' => array('locale_language_providers_session_form'),
'access arguments' => array('administer languages'),
'file' => 'locale.admin.inc',
'type' => MENU_VISIBLE_IN_BREADCRUMB,
);
$items['admin/config/regional/language/edit/%'] = array(
'title' => 'Edit language',
......
......@@ -98,6 +98,7 @@ function profile_menu() {
'page callback' => 'drupal_get_form',
'page arguments' => array('profile_field_form'),
'access arguments' => array('administer users'),
'type' => MENU_VISIBLE_IN_BREADCRUMB,
'file' => 'profile.admin.inc',
);
$items['admin/config/people/profile/autocomplete'] = array(
......@@ -112,6 +113,7 @@ function profile_menu() {
'page callback' => 'drupal_get_form',
'page arguments' => array('profile_field_form'),
'access arguments' => array('administer users'),
'type' => MENU_VISIBLE_IN_BREADCRUMB,
'file' => 'profile.admin.inc',
);
$items['admin/config/people/profile/delete'] = array(
......@@ -119,6 +121,7 @@ function profile_menu() {
'page callback' => 'drupal_get_form',
'page arguments' => array('profile_field_delete'),
'access arguments' => array('administer users'),
'type' => MENU_VISIBLE_IN_BREADCRUMB,
'file' => 'profile.admin.inc',
);
$items['profile/autocomplete'] = array(
......
......@@ -173,7 +173,6 @@ function search_menu() {
'page callback' => 'drupal_get_form',
'page arguments' => array('search_admin_settings'),
'access arguments' => array('administer search'),
'type' => MENU_NORMAL_ITEM,
'weight' => -10,
'file' => 'search.admin.inc',
);
......@@ -182,6 +181,7 @@ function search_menu() {
'page callback' => 'drupal_get_form',
'page arguments' => array('search_reindex_confirm'),
'access arguments' => array('administer search'),
'type' => MENU_VISIBLE_IN_BREADCRUMB,
'file' => 'search.admin.inc',
);
......
......@@ -551,7 +551,7 @@ class MenuBreadcrumbTestCase extends DrupalWebTestCase {
function testBreadCrumbs() {
// Prepare common base breadcrumb elements.
$home = array('<front>' => 'Home');
$admin = $home + array('admin' => t('Administer'));
$admin = $home + array('admin' => t('Administration'));
$config = $admin + array('admin/config' => t('Configuration'));
$type = 'article';
$langcode = LANGUAGE_NONE;
......
......@@ -219,7 +219,6 @@ function menu_test_menu() {
'description' => 'File inheritance test description',
'page callback' => 'menu_test_callback',
'access arguments' => array('access content'),
'type' => MENU_LOCAL_TASK,
);
$items['menu_login_callback'] = array(
......
......@@ -6,70 +6,6 @@
* Admin page callbacks for the system module.
*/
/**
* Menu callback; Provide the administration overview page.
*/
function system_main_admin_page($arg = NULL) {
// Only continue if provided arguments are expected. This function serves
// as the callback for the top-level admin/ page, so any unexpected arguments
// are likely the result of someone typing in the URL of an administrative
// page that doesn't actually exist; for example, admin/some/random/page.
if (isset($arg) && substr($arg, 0, 3) != 'by-') {
return MENU_NOT_FOUND;
}
// Check for status report errors.
if (system_status(TRUE) && user_access('administer site configuration')) {
drupal_set_message(t('One or more problems were detected with your Drupal installation. Check the <a href="@status">status report</a> for more information.', array('@status' => url('admin/reports/status'))), 'error');
}
$blocks = array();
if ($admin = db_query("SELECT menu_name, mlid FROM {menu_links} WHERE link_path = 'admin' AND module = 'system'")->fetchAssoc()) {
$result = db_query("
SELECT m.*, ml.*
FROM {menu_links} ml
INNER JOIN {menu_router} m ON ml.router_path = m.path
WHERE ml.link_path != 'admin/help' AND menu_name = :menu_name AND ml.plid = :mlid AND hidden = 0", $admin, array('fetch' => PDO::FETCH_ASSOC));
foreach ($result as $item) {
_menu_link_translate($item);
if (!$item['access']) {
continue;
}
// The link 'description' either derived from the hook_menu 'description'
// or entered by the user via menu module is saved as the title attribute.
if (!empty($item['localized_options']['attributes']['title'])) {
$item['description'] = $item['localized_options']['attributes']['title'];
}
$block = $item;
$block['content'] = '';
$block['show'] = FALSE;
if ($item['block_callback'] && function_exists($item['block_callback'])) {
$function = $item['block_callback'];
$block['content'] .= $function();
}
$content = system_admin_menu_block($item);
if ((isset($item['page_callback']) && !in_array($item['page_callback'], array('system_admin_menu_block_page', 'system_admin_config_page', 'system_settings_overview'))) || count($content)) {
// Only show blocks for items which are not containers, or those which
// are containers and do have items we can show.
$block['show'] = TRUE;
$block['title'] = l($item['title'], $item['href'], $item['localized_options']);
if (!empty($content)) {
$block['content'] .= theme('admin_block_content', array('content' => $content));
}
}
// Prepare for sorting as in function _menu_tree_check_access().
// The weight is offset so it is always positive, with a uniform 5-digits.
$blocks[(50000 + $item['weight']) . ' ' . $item['title'] . ' ' . $item['mlid']] = $block;
}
}
if ($blocks) {
ksort($blocks);
return theme('admin_page', array('blocks' => $blocks));
}
else {
return t('You do not have any administrative items.');
}
}
/**
* Menu callback; Provide the administration overview page.
*/
......@@ -90,10 +26,11 @@ function system_admin_config_page() {
if (!$item['access']) {
continue;
}
// The link 'description' either derived from the hook_menu 'description'
// or entered by the user via menu module is saved as the title attribute.
// The link description, either derived from 'description' in hook_menu()
// or customized via menu module is used as title attribute.
if (!empty($item['localized_options']['attributes']['title'])) {
$item['description'] = $item['localized_options']['attributes']['title'];
unset($item['localized_options']['attributes']['title']);
}
$block = $item;
$block['content'] = '';
......@@ -142,9 +79,9 @@ function system_admin_menu_block_page() {
}
/**
* Menu callback; prints a listing of admin tasks for each installed module.
* Menu callback; prints a listing of admin tasks, organized by module.
*/
function system_admin_by_module() {
function system_admin_index() {
$module_info = system_get_info('module');
foreach ($module_info as $module => $info) {
$module_info[$module] = new stdClass();
......@@ -152,30 +89,24 @@ function system_admin_by_module() {
}
uasort($module_info, 'system_sort_modules_by_info_name');
$menu_items = array();
$help_arg = module_exists('help') ? drupal_help_arg() : FALSE;
foreach ($module_info as $module => $info) {
if ($module == 'help') {
continue;
}
$admin_tasks = system_get_module_admin_tasks($module);
// Only display a section if there are any available tasks.
if (count($admin_tasks)) {
// Check for help links.
if ($help_arg && module_invoke($module, 'help', "admin/help#$module", $help_arg)) {
$admin_tasks[100] = l(t('Get help'), "admin/help/$module");
if ($admin_tasks = system_get_module_admin_tasks($module, $info->info)) {
// Sort links by title.
uasort($admin_tasks, 'system_sort_by_title');
// Move 'Configure permissions' links to the bottom of each section.
$permission_key = "admin/people/permissions#module-$module";
if (isset($admin_tasks[$permission_key])) {
$permission_task = $admin_tasks[$permission_key];
unset($admin_tasks[$permission_key]);
$admin_tasks[$permission_key] = $permission_task;
}
// Sort.
ksort($admin_tasks);
$menu_items[$info->info['name']] = array($info->info['description'], $admin_tasks);
}
}
return theme('system_admin_by_module', array('menu_items' => $menu_items));
return theme('system_admin_index', array('menu_items' => $menu_items));
}
/**
......@@ -977,6 +908,19 @@ function system_modules($form, $form_state = array()) {
return $form;
}
/**
* Array sorting callback; sorts elements by 'title' key.
*/
function system_sort_by_title($a, $b) {
if (!isset($b['title'])) {
return -1;
}
if (!isset($a['title'])) {
return 1;
}
return strcasecmp($a['title'], $b['title']);
}
/**
* Array sorting callback; sorts modules or themes by their name.
*/
......@@ -2387,43 +2331,36 @@ function system_batch_page() {
*
* @param $variables
* An associative array containing:
* - block: An array containing information about the block. It should include
* a 'title', a 'description' and a formatted 'content'.
* - block: An array containing information about the block:
* - show: A Boolean whether to output the block. Defaults to FALSE.
* - title: The block's title.
* - content: (optional) Formatted content for the block.
* - description: (optional) Description of the block. Only output if
* 'content' is not set.
*
* @ingroup themeable
*/
function theme_admin_block($variables) {
$block = $variables['block'];
$output = '';
// Don't display the block if it has no content to display.
if (empty($block['show'])) {
return '';
return $output;
}
if (empty($block['content'])) {
$output = <<< EOT
<div class="admin-panel">
<h3>
$block[title]
</h3>
<div class="description">
$block[description]
</div>
</div>
EOT;
$output .= '<div class="admin-panel">';
if (!empty($block['title'])) {
$output .= '<h3>' . $block['title'] . '</h3>';
}
if (!empty($block['content'])) {
$output .= '<div class="body">' . $block['content'] . '</div>';
}
else {
$output = <<< EOT
<div class="admin-panel">
<h3>
$block[title]
</h3>
<div class="body">
$block[content]
</div>
</div>
EOT;
$output .= '<div class="description">' . $block['description'] . '</div>';
}
$output .= '</div>';
return $output;
}
......@@ -2432,30 +2369,28 @@ function theme_admin_block($variables) {
*
* @param $variables
* An associative array containing:
* - content: An array containing information about the block. It should
* include a 'title', a 'description' and a formatted 'content'.
* - content: An array containing information about the block. Each element
* of the array represents an administrative menu item, and must at least
* contain the keys 'title', 'href', and 'localized_options', which are
* passed to l(). A 'description' key may also be provided.
*
* @ingroup themeable
*/
function theme_admin_block_content($variables) {
$content = $variables['content'];
$output = '';
if (!$content) {
return '';
}
if (system_admin_compact_mode()) {
$output = '<ul class="menu">';
foreach ($content as $item) {
$output .= '<li class="leaf">' . l($item['title'], $item['href'], $item['localized_options']) . '</li>';
if (!empty($content)) {
$class = 'admin-list';
if ($compact = system_admin_compact_mode()) {
$class .= ' compact';
}
$output .= '</ul>';
}
else {
$output = '<dl class="admin-list">';
$output .= '<dl class="' . $class . '">';
foreach ($content as $item) {
$output .= '<dt>' . l($item['title'], $item['href'], $item['localized_options']) . '</dt>';
$output .= '<dd>' . filter_xss_admin($item['description']) . '</dd>';
if (!$compact && isset($item['description'])) {
$output .= '<dd>' . filter_xss_admin($item['description']) . '</dd>';
}
}
$output .= '</dl>';
}
......@@ -2514,11 +2449,10 @@ function theme_admin_page($variables) {
*
* @ingroup themeable
*/
function theme_system_admin_by_module($variables) {
function theme_system_admin_index($variables) {
$menu_items = $variables['menu_items'];
$stripe = 0;
$output = '';
$container = array('left' => '', 'right' => '');
$flip = array('left' => 'right', 'right' => 'left');
$position = 'left';
......@@ -2531,7 +2465,7 @@ function theme_system_admin_by_module($variables) {
if (count($items)) {
$block = array();
$block['title'] = $module;
$block['content'] = theme('item_list', array('items' => $items));
$block['content'] = theme('admin_block_content', array('content' => $items));
$block['description'] = t($description);
$block['show'] = TRUE;
......@@ -2547,6 +2481,7 @@ function theme_system_admin_by_module($variables) {
}
$output = '<div class="admin clearfix">';
$output .= theme('system_compact_link');
foreach ($container as $id => $data) {
$output .= '<div class="' . $id . ' clearfix">';
$output .= $data;
......
......@@ -87,7 +87,7 @@ function system_help($path, $arg) {
$output .= '<dd>' . t('Actions are individual tasks that the system can do, such as unpublishing a piece of content or banning a user. Modules, such as the <a href="@trigger-help">Trigger module</a>, can fire these actions when certain system events happen; for example, when a new post is added or when a user logs in. Modules may also provide additional actions. Visit the <a href="@actions">Actions page</a> to configure actions.', array('@trigger-help' => url('admin/help/trigger'), '@actions' => url('admin/config/system/actions'))) . '</dd>';
$output .= '</dl>';
return $output;
case 'admin/by-module':
case 'admin/index':
return '<p>' . t('This page shows you all available administration tasks for each module.') . '</p>';
case 'admin/appearance':
$output = '<p>' . t('Set and configure the default theme for your website. Alternative <a href="@themes">themes</a> are available.', array('@themes' => 'http://drupal.org/project/themes')) . '</p>';
......@@ -184,7 +184,7 @@ function system_theme() {
'variables' => array('content' => NULL),
'file' => 'system.admin.inc',
),
'system_admin_by_module' => array(
'system_admin_index' => array(
'variables' => array('menu_items' => NULL),
'file' => 'system.admin.inc',
),
......@@ -526,9 +526,9 @@ function system_menu() {
'file' => 'system.admin.inc',
);
$items['admin'] = array(
'title' => 'Administer',
'title' => 'Administration',
'access arguments' => array('access administration pages'),
'page callback' => 'system_main_admin_page',
'page callback' => 'system_admin_menu_block_page',
'weight' => 9,
'menu_name' => 'management',
'theme callback' => 'variable_get',
......@@ -542,17 +542,14 @@ function system_menu() {
'type' => MENU_CALLBACK,
'file' => 'system.admin.inc',
);
$items['admin/by-task'] = array(
'title' => 'By task',
'page callback' => 'system_main_admin_page',
'access arguments' => array('access administration pages'),
$items['admin/tasks'] = array(
'title' => 'Tasks',
'type' => MENU_DEFAULT_LOCAL_TASK,
'file' => 'system.admin.inc',
'weight' => -20,
);
$items['admin/by-module'] = array(
'title' => 'By module',
'page callback' => 'system_admin_by_module',
$items['admin/index'] = array(
'title' => 'Index',
'page callback' => 'system_admin_index',
'access arguments' => array('access administration pages'),
'type' => MENU_LOCAL_TASK,
'weight' => -18,
......@@ -652,6 +649,7 @@ function system_menu() {
$items['admin/modules/list/confirm'] = array(
'title' => 'List',
'access arguments' => array('administer modules'),
'type' => MENU_VISIBLE_IN_BREADCRUMB,
);
$items['admin/modules/uninstall'] = array(
'title' => 'Uninstall',
......@@ -664,6 +662,7 @@ function system_menu() {
$items['admin/modules/uninstall/confirm'] = array(
'title' => 'Uninstall',
'access arguments' => array('administer modules'),
'type' => MENU_VISIBLE_IN_BREADCRUMB,
'file' => 'system.admin.inc',
);
......@@ -874,6 +873,7 @@ function system_menu() {
'title' => 'Date and time lookup',
'page callback' => 'system_date_time_lookup',
'access arguments' => array('administer site configuration'),
'type' => MENU_CALLBACK,
'file' => 'system.admin.inc',
);
......@@ -935,6 +935,7 @@ function system_menu() {
'page callback' => 'drupal_get_form',
'page arguments' => array('system_actions_configure'),
'access arguments' => array('administer actions'),
'type' => MENU_VISIBLE_IN_BREADCRUMB,
'file' => 'system.admin.inc',
);
$items['admin/config/system/actions/delete/%actions'] = array(
......@@ -2024,6 +2025,14 @@ function system_preprocess_block(&$variables) {
*/
function system_admin_menu_block($item) {
$cache = &drupal_static(__FUNCTION__, array());
// If we are calling this function for a menu item that corresponds to a
// local task (for example, admin/tasks), then we want to retrieve the
// parent item's child links, not this item's (since this item won't have
// any).
if ($item['tab_root'] != $item['path']) {
$item = menu_get_item($item['tab_root_href']);
}
if (!isset($item['mlid'])) {
$item += db_query("SELECT mlid, menu_name FROM {menu_links} ml WHERE ml.router_path = :path AND module = 'system'", array(':path' => $item['path']))->fetchAssoc();
}
......@@ -2033,53 +2042,31 @@ function system_admin_menu_block($item) {
}
$content = array();
$default_task = NULL;
$has_subitems = FALSE;
$result = db_query("
SELECT m.load_functions, m.to_arg_functions, m.access_callback, m.access_arguments, m.page_callback, m.page_arguments, m.delivery_callback, m.title, m.title_callback, m.title_arguments, m.theme_callback, m.theme_arguments, m.type, m.description, m.path, m.weight as router_weight, ml.*
FROM {menu_router} m
LEFT JOIN {menu_links} ml ON m.path = ml.router_path
WHERE (ml.plid = :plid AND ml.menu_name = :name AND hidden = 0) OR (m.tab_parent = :path AND m.type IN (:local_task, :default_task))", array(':plid' => $item['mlid'], ':name' => $item['menu_name'], ':path' => $item['path'], ':local_task' => MENU_LOCAL_TASK, ':default_task' => MENU_DEFAULT_LOCAL_TASK), array('fetch' => PDO::FETCH_ASSOC));
foreach ($result as $link) {
if (!isset($link['link_path'])) {
// If this was not an actual link, fake the tab as a menu link, so we
// don't need to special case it beyond this point.
$link['link_title'] = $link['title'];
$link['link_path'] = $link['path'];
$link['options'] = 'a:0:{}';
$link['weight'] = $link['router_weight'];
}
else {
// We found a non-tab subitem, remember that.
$has_subitems = TRUE;
}
$query = db_select('menu_links', 'ml', array('fetch' => PDO::FETCH_ASSOC));
$query->join('menu_router', 'm', 'm.path = ml.router_path');
$query
->fields('ml')
// Weight should be taken from {menu_links}, not {menu_router}.
->fields('m', array_diff(drupal_schema_fields_sql('menu_router'), array('weight')))
->condition('ml.plid', $item['mlid'])
->condition('ml.menu_name', $item['menu_name'])
->condition('ml.hidden', 0);
foreach ($query->execute() as $link) {
_menu_link_translate($link);
if (!$link['access']) {
continue;
}
// The link 'description' — either derived from the hook_menu 'description' or
// entered by the user via menu module — is saved as the title attribute.
// The title attribute is then unset to reduce redundancy in admin pages
// for screen readers.
if (!empty($link['localized_options']['attributes']['title'])) {
$link['description'] = $link['localized_options']['attributes']['title'];
unset($link['localized_options']['attributes']['title']);