Index: includes/menu.inc
=========================================================
--- includes/menu.inc	(revision 1.406)
+++ includes/menu.inc	Mon Aug 23 13:37:00 CEST 2010
@@ -2141,7 +2141,7 @@
       // The title of a local task is used for the tab, never the page title.
       // Thus, replace it with the item corresponding to the root path to get
       // the relevant href and title. For example, the menu item corresponding
-      // to 'admin' is used when on the 'By module' tab at 'admin/by-module'.
+      // to 'admin' is used when on the 'Index' tab at 'admin/index'.
       $parts = explode('/', $item['tab_root']);
       $args = arg();
       // Replace wildcards in the root path using the current path.
Index: modules/dashboard/dashboard.module
=========================================================
--- modules/dashboard/dashboard.module	(revision 1.33)
+++ modules/dashboard/dashboard.module	Mon Aug 23 13:37:00 CEST 2010
@@ -30,9 +30,8 @@
     '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(
@@ -202,14 +201,6 @@
  *   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'),
Index: modules/help/help.admin.inc
=========================================================
--- modules/help/help.admin.inc	(revision 1.12)
+++ modules/help/help.admin.inc	Mon Aug 23 13:37:00 CEST 2010
@@ -22,12 +22,12 @@
 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,10 +35,14 @@
 
     // 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]);
+    $links = array();
+    foreach ($admin_tasks as $task) {
+      $links[] = l($task['title'], $task['link_path'], $task['localized_options']);
+    }
+
     if (!empty($admin_tasks)) {
-      ksort($admin_tasks);
-      $output .= theme('item_list', array('items' => $admin_tasks, 'title' => t('@module administration pages', array('@module' => $module['name']))));
+      $output .= theme('item_list', array('items' => $links, 'title' => t('@module administration pages', array('@module' => $info[$name]['name']))));
     }
 
   }
Index: modules/simpletest/tests/menu_test.module
=========================================================
--- modules/simpletest/tests/menu_test.module	(revision 1.15)
+++ modules/simpletest/tests/menu_test.module	Mon Aug 23 13:37:00 CEST 2010
@@ -186,7 +186,6 @@
     'description' => 'File inheritance test description',
     'page callback' => 'menu_test_callback',
     'access arguments' => array('access content'),
-    'type' => MENU_LOCAL_TASK,
   );
 
   $items['menu_login_callback'] = array(
Index: modules/system/system.admin.inc
=========================================================
--- modules/system/system.admin.inc	(revision 1.298)
+++ modules/system/system.admin.inc	Mon Aug 23 13:37:00 CEST 2010
@@ -9,70 +9,6 @@
 /**
  * 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.
- */
 function system_admin_config_page() {
   // Check for status report errors.
   if (system_status(TRUE) && user_access('administer site configuration')) {
@@ -152,25 +88,24 @@
   }
   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);
+    $admin_tasks = system_get_module_admin_tasks($module, $info->info);
 
     // 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");
+      // Move 'Configure permissions' links to the bottom of each section.
+      if (isset($admin_tasks[-1]) && $item = $admin_tasks[-1]) {
+        unset($admin_tasks[-1]);
+        $admin_tasks[] = $item;
       }
-
       // Sort.
       ksort($admin_tasks);
+      // Move 'Configure permissions' links to the bottom of each section.
+      if (isset($admin_tasks[-1]) && $item = $admin_tasks[-1]) {
+        unset($admin_tasks[-1]);
+        $admin_tasks[] = $item;
+      }
 
       $menu_items[$info->info['name']] = array($info->info['description'], $admin_tasks);
     }
@@ -2506,7 +2441,6 @@
   $menu_items = $variables['menu_items'];
 
   $stripe = 0;
-  $output = '';
   $container = array('left' => '', 'right' => '');
   $flip = array('left' => 'right', 'right' => 'left');
   $position = 'left';
@@ -2519,7 +2453,7 @@
     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;
 
@@ -2535,6 +2469,7 @@
   }
 
   $output = '<div class="admin clearfix">';
+  $output .= theme('system_compact_link');
   foreach ($container as $id => $data) {
     $output .= '<div class="' . $id . ' clearfix">';
     $output .= $data;
Index: modules/system/system.module
=========================================================
--- modules/system/system.module	(revision 1.957)
+++ modules/system/system.module	Mon Aug 23 14:48:41 CEST 2010
@@ -87,7 +87,10 @@
       $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':
+    case 'admin/by-task':
+      return '';
+    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>';
@@ -521,9 +524,9 @@
     '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',
@@ -538,15 +541,12 @@
     'file' => 'system.admin.inc',
   );
   $items['admin/by-task'] = array(
-    'title' => 'By task',
-    'page callback' => 'system_main_admin_page',
-    'access arguments' => array('access administration pages'),
+    'title' => 'Administration',
     'type' => MENU_DEFAULT_LOCAL_TASK,
-    'file' => 'system.admin.inc',
     'weight' => -20,
   );
-  $items['admin/by-module'] = array(
-    'title' => 'By module',
+  $items['admin/index'] = array(
+    'title' => 'Index',
     'page callback' => 'system_admin_by_module',
     'access arguments' => array('access administration pages'),
     'type' => MENU_LOCAL_TASK,
@@ -2008,6 +2008,15 @@
  */
 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/by-task), then we want to retrieve the
+  // parent item's child links, not this item's (since this item won't have
+  // any).
+  // @todo Not sure if this is completely correct.
+  if ($item['tab_root'] != $item['path']) {
+    $item = menu_get_item($item['tab_root']);
+  }
+
   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();
   }
@@ -2017,26 +2026,12 @@
   }
 
   $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.*
+    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, 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));
+    WHERE ml.plid = :plid AND ml.menu_name = :name AND hidden = 0", array(':plid' => $item['mlid'], ':name' => $item['menu_name']), 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;
-    }
     _menu_link_translate($link);
     if (!$link['access']) {
       continue;
@@ -2055,14 +2050,6 @@
     // The weight is offset so it is always positive, with a uniform 5-digits.
     $key = (50000 + $link['weight']) . ' ' . drupal_strtolower($link['title']) . ' ' . $link['mlid'];
     $content[$key] = $link;
-    if ($link['type'] == MENU_DEFAULT_LOCAL_TASK) {
-      $default_task = $key;
-    }
-  }
-  if ($has_subitems) {
-    // If we've had at least one non-tab subitem, remove the link for the
-    // default task, since that is already broken down to subitems.
-    unset($content[$default_task]);
   }
   ksort($content);
   $cache[$item['mlid']] = $content;
@@ -2761,16 +2748,19 @@
  *
  * @param $module
  *   Module name.
+ * @param $info
+ *   Module's info array from {system} table (as built by system_get_info).
+ *
  * @return
  *   An array of task links.
  */
-function system_get_module_admin_tasks($module) {
+function system_get_module_admin_tasks($module, $info) {
   $items = &drupal_static(__FUNCTION__, array());
 
   if (empty($items)) {
     $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, ml.*
-       FROM {menu_links} ml INNER JOIN {menu_router} m ON ml.router_path = m.path WHERE ml.link_path LIKE 'admin/%' AND hidden >= 0 AND module = 'system' AND m.number_parts > 2", array(), array('fetch' => PDO::FETCH_ASSOC));
+       FROM {menu_links} ml INNER JOIN {menu_router} m ON ml.router_path = m.path WHERE ml.link_path LIKE 'admin/%' AND hidden >= 0 AND module = 'system' AND m.number_parts > 1 AND page_callback <> 'system_admin_menu_block_page'", array(), array('fetch' => PDO::FETCH_ASSOC));
     foreach ($result as $item) {
       _menu_link_translate($item);
       if ($item['access']) {
@@ -2783,15 +2773,28 @@
   $admin_tasks = array();
   $admin_task_count = 0;
   // Check for permissions.
+  $permissions_menu_item = menu_get_item('admin/people/permissions');
+  $permissions_menu_item['description'] = NULL;
+  $permissions_menu_item['title'] = t('Configure @module permissions', array('@module' => $info['name']));
   if (in_array($module, module_implements('permission')) && $admin_access) {
-    $admin_tasks[-1] = l(t('Configure permissions'), 'admin/people/permissions', array('fragment' => 'module-' . $module));
+    $permissions_menu_item['link_path'] = 'admin/people/permissions';
+    $permissions_menu_item['localized_options']['fragment'] = 'module-' . $module;
+    $admin_tasks[-1] = $permissions_menu_item;
   }
 
   // Check for menu items that are admin links.
   if (in_array($module, module_implements('menu')) && $menu = module_invoke($module, 'menu')) {
     foreach (array_keys($menu) as $path) {
       if (isset($items[$path])) {
-        $admin_tasks[$items[$path]['title'] . $admin_task_count ++] = l($items[$path]['title'], $path);
+        // 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($items[$path]['localized_options']['attributes']['title'])) {
+          $items[$path]['description'] = $items[$path]['localized_options']['attributes']['title'];
+          unset($items[$path]['localized_options']['attributes']['title']);
+        }
+        $admin_tasks[$items[$path]['title'] . $admin_task_count ++] = $items[$path];
       }
     }
   }
