diff --git a/core/includes/install.inc b/core/includes/install.inc index f5d7399..3126c80 100644 --- a/core/includes/install.inc +++ b/core/includes/install.inc @@ -411,7 +411,9 @@ function drupal_install_system() { require_once DRUPAL_ROOT . '/' . $system_path . '/system.install'; $system_versions = drupal_get_schema_versions('system'); $system_version = $system_versions ? max($system_versions) : SCHEMA_INSTALLED; - drupal_container() + // Now that we have a {key_value} database table, we need a fresh container, + // so we can actually store schema data and configuration. + drupal_container(NULL, TRUE) ->get('keyvalue') ->get('system.schema') ->set('system', $system_version); @@ -426,6 +428,7 @@ function drupal_install_system() { // Clear out module list and hook implementation statics. system_list_reset(); + module_list_reset(); module_implements_reset(); config_install_default_config('module', 'system'); diff --git a/core/includes/menu.inc b/core/includes/menu.inc index f54eb73..d28316b 100644 --- a/core/includes/menu.inc +++ b/core/includes/menu.inc @@ -1623,9 +1623,6 @@ function theme_menu_link(array $variables) { */ function theme_menu_local_task($variables) { $link = $variables['element']['#link']; - $link += array( - 'localized_options' => array(), - ); $link_text = $link['title']; if (!empty($variables['element']['#active'])) { @@ -1872,8 +1869,8 @@ function menu_local_tasks($level = 0) { $data = &drupal_static(__FUNCTION__); $root_path = &drupal_static(__FUNCTION__ . ':root_path', ''); $empty = array( - 'tabs' => array(), - 'actions' => array(), + 'tabs' => array('count' => 0, 'output' => array()), + 'actions' => array('count' => 0, 'output' => array()), 'root_path' => &$root_path, ); @@ -1925,7 +1922,8 @@ function menu_local_tasks($level = 0) { // 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(); + $actions['count'] = 0; + $actions['output'] = array(); while (isset($children[$path])) { $tabs_current = array(); $actions_current = array(); @@ -1962,7 +1960,6 @@ function menu_local_tasks($level = 0) { '#theme' => 'menu_local_task', '#link' => $link, '#active' => TRUE, - '#weight' => isset($link['weight']) ? $link['weight'] : NULL, ); $next_path = $item['path']; $tab_count++; @@ -1975,7 +1972,6 @@ function menu_local_tasks($level = 0) { $actions_current[] = array( '#theme' => 'menu_local_action', '#link' => $link, - '#weight' => isset($link['weight']) ? $link['weight'] : NULL, ); $action_count++; } @@ -1984,7 +1980,6 @@ function menu_local_tasks($level = 0) { $tabs_current[] = array( '#theme' => 'menu_local_task', '#link' => $link, - '#weight' => isset($link['weight']) ? $link['weight'] : NULL, ); $tab_count++; } @@ -1992,8 +1987,10 @@ function menu_local_tasks($level = 0) { } } $path = $next_path; - $tabs[$depth] = $tabs_current; - $actions = array_merge($actions, $actions_current); + $tabs[$depth]['count'] = $tab_count; + $tabs[$depth]['output'] = $tabs_current; + $actions['count'] += $action_count; + $actions['output'] = array_merge($actions['output'], $actions_current); $depth++; } $data['actions'] = $actions; @@ -2039,7 +2036,6 @@ function menu_local_tasks($level = 0) { '#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])) { @@ -2050,14 +2046,14 @@ function menu_local_tasks($level = 0) { $tabs_current[] = array( '#theme' => 'menu_local_task', '#link' => $link, - '#weight' => isset($link['weight']) ? $link['weight'] : NULL, ); } } } $path = $next_path; $parent = $next_parent; - $tabs[$depth] = $tabs_current; + $tabs[$depth]['count'] = $count; + $tabs[$depth]['output'] = $tabs_current; $depth--; } // Sort by depth. @@ -2079,7 +2075,7 @@ function menu_local_tasks($level = 0) { } // @todo If there are no tabs, then there still can be actions; for example, // when added via hook_menu_local_tasks_alter(). - elseif (!empty($data['actions'])) { + elseif (!empty($data['actions']['output'])) { return array('actions' => $data['actions']) + $empty; } return $empty; @@ -2192,7 +2188,7 @@ function menu_contextual_links($module, $parent_path, $args) { function menu_primary_local_tasks() { $links = menu_local_tasks(0); // Do not display single tabs. - return count($links['tabs']) > 1 ? $links['tabs'] : ''; + return ($links['tabs']['count'] > 1 ? $links['tabs']['output'] : ''); } /** @@ -2201,7 +2197,7 @@ function menu_primary_local_tasks() { function menu_secondary_local_tasks() { $links = menu_local_tasks(1); // Do not display single tabs. - return count($links['tabs']) > 1 ? $links['tabs'] : ''; + return ($links['tabs']['count'] > 1 ? $links['tabs']['output'] : ''); } /** @@ -2209,7 +2205,7 @@ function menu_secondary_local_tasks() { */ function menu_local_actions() { $links = menu_local_tasks(); - return $links['actions']; + return $links['actions']['output']; } /** @@ -3553,6 +3549,7 @@ function _menu_router_build($callbacks) { $item['to_arg_functions'] = empty($to_arg_functions) ? '' : serialize($to_arg_functions); $item += array( 'title' => '', + 'weight' => 0, 'type' => MENU_NORMAL_ITEM, 'module' => '', '_number_parts' => $number_parts, @@ -3560,9 +3557,6 @@ function _menu_router_build($callbacks) { '_fit' => $fit, ); $item += array( - // Default MENU_DEFAULT_LOCAL_TASKs to a weight of -10, so they appear as - // first tab by default. - 'weight' => ($item['type'] & MENU_DEFAULT_LOCAL_TASK) == MENU_DEFAULT_LOCAL_TASK ? -10 : 0, '_visible' => (bool) ($item['type'] & MENU_VISIBLE_IN_BREADCRUMB), '_tab' => (bool) ($item['type'] & MENU_IS_LOCAL_TASK), ); diff --git a/core/includes/theme.maintenance.inc b/core/includes/theme.maintenance.inc index 6718e87..7513cb8 100644 --- a/core/includes/theme.maintenance.inc +++ b/core/includes/theme.maintenance.inc @@ -17,6 +17,7 @@ function _drupal_maintenance_theme() { global $theme, $theme_key, $conf; + require_once DRUPAL_ROOT . '/core/includes/database.inc'; require_once DRUPAL_ROOT . '/' . variable_get('path_inc', 'core/includes/path.inc'); require_once DRUPAL_ROOT . '/core/includes/theme.inc'; require_once DRUPAL_ROOT . '/core/includes/common.inc'; @@ -30,13 +31,6 @@ function _drupal_maintenance_theme() { $custom_theme = (isset($conf['maintenance_theme']) ? $conf['maintenance_theme'] : 'seven'); } else { - // The bootstrap was not complete. So we are operating in a crippled - // environment, we need to bootstrap just enough to allow hook invocations - // to work. See _drupal_log_error(). - if (!class_exists('Drupal\Core\Database\Database', FALSE)) { - require_once DRUPAL_ROOT . '/core/includes/database.inc'; - } - // We use the default theme as the maintenance theme. If a default theme // isn't specified in the database or in settings.php, we use Bartik. // @todo Should use the actual default theme configured, but that depends on @@ -56,6 +50,9 @@ function _drupal_maintenance_theme() { } $themes = list_themes(); + if (empty($themes) || !isset($themes[$custom_theme])) { + $themes = _system_rebuild_theme_data(); + } // list_themes() triggers a drupal_alter() in maintenance mode, but we can't // let themes alter the .info data until we know a theme's base themes. So diff --git a/core/modules/block/block.module b/core/modules/block/block.module index ced66f4..5118087 100644 --- a/core/modules/block/block.module +++ b/core/modules/block/block.module @@ -194,48 +194,50 @@ function block_menu() { * Implements hook_menu_local_tasks_alter(). */ function block_menu_local_tasks_alter(&$data, $router_item, $root_path) { - if ($root_path == 'admin/structure/block' || strpos($root_path, 'admin/structure/block/list') === 0) { - // Replace the tab title of the default local task with the name of the - // default theme. - $themes = list_themes(); - $default_theme = variable_get('theme_default', 'stark'); - foreach ($data['tabs'][0] as $i => &$tab) { - if (isset($tab['#link']['path'])) { - if ($tab['#link']['path'] == 'admin/structure/block/list/default') { - $tab['#link']['title'] = $themes[$default_theme]->info['name']; - } - elseif ($tab['#link']['path'] == 'admin/structure/block/list/%') { - $selected_theme_index = $i; - } + if ($root_path === 'admin/structure/block' || $root_path === 'admin/structure/block/list/%') { + $tabs = &$data['tabs'][0]['output']; + // Determine the currently selected tab, if any. + $selected_index = -1; + $selected_id = ''; + foreach ($tabs as $index => &$tab) { + if (isset($tab['#link']['path']) && $tab['#link']['path'] == 'admin/structure/block/list/%') { + $selected_index = $index; + $selected_id = $router_item['original_map'][4]; + break; } } - // Expand the dynamic %theme argument into a tab for each theme. - $selected_theme = isset($router_item['original_map'][4]) ? $router_item['original_map'][4] : NULL; + $themes = list_themes(); + $default_theme = variable_get('theme_default', 'stark'); foreach ($themes as $theme) { // The default theme is always exposed as default local task already. if ($theme->name === $default_theme) { + $tabs[0]['#link']['title'] = $theme->info['name']; continue; } - // If the current page shows the interface for a selected theme, then the - // menu router item with the %theme argument will expose the selected - // theme already; do not duplicate that tab, but ensure it appears in a - // consistent order when switching between tabs. - if ($theme->name === $selected_theme) { - $data['tabs'][0][] = $data['tabs'][0][$selected_theme_index]; - unset($data['tabs'][0][$selected_theme_index]); + // If the current page is the active tab registered in hook_menu(), then + // the menu router item with the dynamic argument will be exposed already. + // We must not duplicate that tab, but in order to ensure that all of our + // tabs appear in a consistent order when switching between tabs, we need + // to re-inject it. + if ($theme->name === $selected_id) { + $tabs[$selected_index]['#link']['title'] = $theme->info['name']; + $tabs[] = $tabs[$selected_index]; + unset($tabs[$selected_index]); continue; } - $data['tabs'][0][] = array( + $tabs[] = array( '#theme' => 'menu_local_task', '#link' => array( 'title' => $theme->info['name'], 'href' => 'admin/structure/block/list/' . $theme->name, + 'localized_options' => array('html' => FALSE), ), - '#active' => $theme->name === $selected_theme, - '#weight' => $theme->name === $default_theme ? -10 : 0, ); } + if (count($themes) > 1) { + $data['tabs'][0]['count']++; + } } } diff --git a/core/modules/forum/forum.module b/core/modules/forum/forum.module index 1bcb29c..459cbeb 100644 --- a/core/modules/forum/forum.module +++ b/core/modules/forum/forum.module @@ -209,7 +209,7 @@ function forum_menu_local_tasks_alter(&$data, $router_item, $root_path) { ); } } - $data['actions'] = array_merge($data['actions'], $links); + $data['actions']['output'] = array_merge($data['actions']['output'], $links); } } } diff --git a/core/modules/node/node.module b/core/modules/node/node.module index bbb23e6..5c11424 100644 --- a/core/modules/node/node.module +++ b/core/modules/node/node.module @@ -1827,7 +1827,7 @@ function node_menu_local_tasks_alter(&$data, $router_item, $root_path) { if ($root_path == 'admin/content') { $item = menu_get_item('node/add'); if ($item['access']) { - $data['actions'][] = array( + $data['actions']['output'][] = array( '#theme' => 'menu_local_action', '#link' => $item, ); diff --git a/core/modules/system/system.api.php b/core/modules/system/system.api.php index 2f3cdb1..2d09534 100644 --- a/core/modules/system/system.api.php +++ b/core/modules/system/system.api.php @@ -1084,10 +1084,17 @@ function hook_menu_link_delete($link) { * * @param $data * An associative array containing: - * - actions: A list of of actions, each one being an associative array - * as described above. - * - tabs: A list of (up to 2) tab levels that contain a list of of tabs, each - * one being an associative array as described above. + * - actions: An associative array containing: + * - count: The amount of actions determined by the menu system, which can + * be ignored. + * - output: A list of of actions, each one being an associative array + * as described above. + * - tabs: An indexed array (list) of tab levels (up to 2 levels), each + * containing an associative array: + * - count: The amount of tabs determined by the menu system. This value + * does not need to be altered if there is more than one tab. + * - output: A list of of tabs, each one being an associative array as + * described above. * @param $router_item * The menu system router item of the page. * @param $root_path @@ -1095,7 +1102,7 @@ function hook_menu_link_delete($link) { */ function hook_menu_local_tasks_alter(&$data, $router_item, $root_path) { // Add an action linking to node/add to all pages. - $data['actions'][] = array( + $data['actions']['output'][] = array( '#theme' => 'menu_local_task', '#link' => array( 'title' => t('Add new content'), @@ -1109,7 +1116,7 @@ function hook_menu_local_tasks_alter(&$data, $router_item, $root_path) { ); // Add a tab linking to node/add to all pages. - $data['tabs'][0][] = array( + $data['tabs'][0]['output'][] = array( '#theme' => 'menu_local_task', '#link' => array( 'title' => t('Example tab'), diff --git a/core/modules/system/system.module b/core/modules/system/system.module index 358b9cf..68ccf7e 100644 --- a/core/modules/system/system.module +++ b/core/modules/system/system.module @@ -690,6 +690,7 @@ function system_menu() { 'file' => 'system.admin.inc', 'weight' => 20, ); + // Theme configuration subtabs. $items['admin/appearance/settings/global'] = array( 'title' => 'Global settings', 'type' => MENU_DEFAULT_LOCAL_TASK, @@ -1081,33 +1082,43 @@ function system_menu() { */ function system_menu_local_tasks_alter(&$data, $router_item, $root_path) { if ($root_path === 'admin/appearance/settings' || $root_path === 'admin/appearance/settings/%') { - // Expand the dynamic %theme argument into a tab for each theme. - foreach ($data['tabs'][1] as $i => $tab) { + $tabs = &$data['tabs'][1]['output']; + // Determine the currently selected tab, if any. + $selected_index = -1; + $selected_id = ''; + foreach ($tabs as $index => &$tab) { if (isset($tab['#link']['path']) && $tab['#link']['path'] == 'admin/appearance/settings/%') { - $selected_theme_index = $i; + $selected_index = $index; + $selected_id = $router_item['original_map'][3]; break; } } + // Expand the dynamic %theme argument into a tab for each theme. $themes = list_themes(); - $selected_theme = isset($router_item['original_map'][3]) ? $router_item['original_map'][3] : NULL; foreach ($themes as $theme) { - // If the current page shows the interface for a selected theme, then the - // menu router item with the %theme argument will expose the selected - // theme already; do not duplicate that tab, but ensure it appears in a - // consistent order when switching between tabs. - if ($theme->name === $selected_theme) { - $data['tabs'][1][] = $data['tabs'][1][$selected_theme_index]; - unset($data['tabs'][1][$selected_theme_index]); + // If the current page is the active tab registered in hook_menu(), then + // the menu router item with the dynamic argument will be exposed already. + // We must not duplicate that tab, but in order to ensure that all of our + // tabs appear in a consistent order when switching between tabs, we need + // to re-inject it. + if ($theme->name === $selected_id) { + $tabs[$selected_index]['#link']['title'] = $theme->info['name']; + $tabs[] = $tabs[$selected_index]; + unset($tabs[$selected_index]); continue; } - $data['tabs'][1][] = array( + $tabs[] = array( '#theme' => 'menu_local_task', '#link' => array( 'title' => $theme->info['name'], 'href' => 'admin/appearance/settings/' . $theme->name, + 'localized_options' => array('html' => FALSE), ), ); } + if (count($themes) > 1) { + $data['tabs'][1]['count']++; + } } }