summaryrefslogtreecommitdiff
path: root/includes
diff options
context:
space:
mode:
Diffstat (limited to 'includes')
-rw-r--r--includes/bootstrap.inc4
-rw-r--r--includes/common.inc19
-rw-r--r--includes/locale.inc1
-rw-r--r--includes/menu.inc1390
-rw-r--r--includes/module.inc2
-rw-r--r--includes/path.inc20
6 files changed, 324 insertions, 1112 deletions
diff --git a/includes/bootstrap.inc b/includes/bootstrap.inc
index 995b2f05f..308dafc47 100644
--- a/includes/bootstrap.inc
+++ b/includes/bootstrap.inc
@@ -550,7 +550,7 @@ function drupal_page_cache_header($cache) {
* Define the critical hooks that force modules to always be loaded.
*/
function bootstrap_hooks() {
- return array('init', 'exit');
+ return array('boot', 'exit');
}
/**
@@ -856,7 +856,7 @@ function _drupal_cache_init($phase) {
}
elseif (variable_get('cache', CACHE_DISABLED) == CACHE_NORMAL) {
require_once './includes/module.inc';
- bootstrap_invoke_all('init');
+ bootstrap_invoke_all('boot');
drupal_page_cache_header($cache);
bootstrap_invoke_all('exit');
exit();
diff --git a/includes/common.inc b/includes/common.inc
index 8827a732b..8811a36d8 100644
--- a/includes/common.inc
+++ b/includes/common.inc
@@ -2209,3 +2209,22 @@ function element_child($key) {
function element_children($element) {
return array_filter(array_keys((array) $element), 'element_child');
}
+
+/**
+ * Generate vancode.
+ *
+ * Consists of a leading character indicating length, followed by N digits
+ * with a numerical value in base 36. Vancodes can be sorted as strings
+ * without messing up numerical order.
+ *
+ * It goes:
+ * 00, 01, 02, ..., 0y, 0z,
+ * 110, 111, ... , 1zy, 1zz,
+ * 2100, 2101, ..., 2zzy, 2zzz,
+ * 31000, 31001, ...
+ */
+function int2vancode($i = 0) {
+ $num = base_convert((int)$i, 10, 36);
+ $length = strlen($num);
+ return chr($length + ord('0') - 1) . $num;
+}
diff --git a/includes/locale.inc b/includes/locale.inc
index 376dee5f1..02a4eed68 100644
--- a/includes/locale.inc
+++ b/includes/locale.inc
@@ -119,7 +119,6 @@ function _locale_admin_manage_screen_submit($form_id, $form_values) {
drupal_set_message(t('Configuration saved.'));
// Changing the locale settings impacts the interface:
- cache_clear_all('*', 'cache_menu', TRUE);
cache_clear_all('*', 'cache_page', TRUE);
return 'admin/settings/locale/language/overview';
diff --git a/includes/menu.inc b/includes/menu.inc
index 3ff61171e..8a5ac6d8c 100644
--- a/includes/menu.inc
+++ b/includes/menu.inc
@@ -172,327 +172,220 @@ define('MENU_SITE_OFFLINE', 4);
*/
/**
- * Return the menu data structure.
- *
- * The returned structure contains much information that is useful only
- * internally in the menu system. External modules are likely to need only
- * the ['visible'] element of the returned array. All menu items that are
- * accessible to the current user and not hidden will be present here, so
- * modules and themes can use this structure to build their own representations
- * of the menu.
- *
- * $menu['visible'] will contain an associative array, the keys of which
- * are menu IDs. The values of this array are themselves associative arrays,
- * with the following key-value pairs defined:
- * - 'title' - The displayed title of the menu or menu item. It will already
- * have been translated by the locale system.
- * - 'description' - The description (link title attribute) of the menu item.
- * It will already have been translated by the locale system.
- * - 'path' - The Drupal path to the menu item. A link to a particular item
- * can thus be constructed with
- * l($item['title'], $item['path'], array('title' => $item['description'])).
- * - 'children' - A linear list of the menu ID's of this item's children.
- *
- * Menu ID 0 is the "root" of the menu. The children of this item are the
- * menus themselves (they will have no associated path). Menu ID 1 will
- * always be one of these children; it is the default "Navigation" menu.
- */
-function menu_get_menu() {
- global $_menu;
- global $user;
- global $locale;
-
- if (!isset($_menu['items'])) {
- // _menu_build() may indirectly call this function, so prevent infinite loops.
- $_menu['items'] = array();
-
- $cid = "$user->uid:$locale";
- if ($cached = cache_get($cid, 'cache_menu')) {
- $_menu = unserialize($cached->data);
+ * Returns the ancestors (and relevant placeholders) for any given path.
+ *
+ * For example, the ancestors of node/12345/edit are:
+ *
+ * node/12345/edit
+ * node/12345/%
+ * node/%/edit
+ * node/%/%
+ * node/12345
+ * node/%
+ * node
+ *
+ * To generate these, we will use binary numbers. Each bit represents a
+ * part of the path. If the bit is 1, then it represents the original
+ * value while 0 means wildcard. If the path is node/12/edit/foo
+ * then the 1011 bitstring represents node/%/edit/foo where % means that
+ * any argument matches that part.
+ *
+ * @param $parts
+ * An array of path parts, for the above example
+ * array('node', '12345', 'edit').
+ * @return
+ * An array which contains the ancestors and placeholders. Placeholders
+ * simply contain as many %s as the ancestors.
+ */
+function menu_get_ancestors($parts) {
+ $n1 = count($parts);
+ $placeholders = array();
+ $ancestors = array();
+ $end = (1 << $n1) - 1;
+ $length = $n1 - 1;
+ for ($i = $end; $i > 0; $i--) {
+ $current = '';
+ $count = 0;
+ for ($j = $length; $j >= 0; $j--) {
+ if ($i & (1 << $j)) {
+ $count++;
+ $current .= $parts[$length - $j];
+ }
+ else {
+ $current .= '%';
+ }
+ if ($j) {
+ $current .= '/';
+ }
}
- else {
- _menu_build();
- // Cache the menu structure for this user, to expire after one day.
- cache_set($cid, 'cache_menu', serialize($_menu), time() + (60 * 60 * 24));
+ // If the number was like 10...0 then the next number will be 11...11,
+ // one bit less wide.
+ if ($count == 1) {
+ $length--;
}
-
- // Make sure items that cannot be cached are added.
- _menu_append_contextual_items();
-
- // Reset the cached $menu in menu_get_item().
- menu_get_item(NULL, NULL, TRUE);
+ $placeholders[] = "'%s'";
+ $ancestors[] = $current;
}
-
- return $_menu;
+ return array($ancestors, $placeholders);
}
/**
- * Return the local task tree.
+ * The menu system uses serialized arrays stored in the database for
+ * arguments. However, often these need to change according to the
+ * current path. This function unserializes such an array and does the
+ * necessary change.
*
- * Unlike the rest of the menu structure, the local task tree cannot be cached
- * nor determined too early in the page request, because the user's current
- * location may be changed by a menu_set_location() call, and the tasks shown
- * (just as the breadcrumb trail) need to reflect the changed location.
- */
-function menu_get_local_tasks() {
- global $_menu;
-
- // Don't cache the local task tree, as it varies by location and tasks are
- // allowed to be dynamically determined.
- if (!isset($_menu['local tasks'])) {
- // _menu_build_local_tasks() may indirectly call this function, so prevent
- // infinite loops.
- $_menu['local tasks'] = array();
- $pid = menu_get_active_nontask_item();
- if (!_menu_build_local_tasks($pid)) {
- // If the build returned FALSE, the tasks need not be displayed.
- $_menu['local tasks'][$pid]['children'] = array();
- }
- }
-
- return $_menu['local tasks'];
-}
-
-/**
- * Retrieves the menu item specified by $mid, or by $path if $mid is not given.
- *
- * @param $mid
- * The menu ID of the menu item to retrieve.
- * @param $path
- * The internal path of the menu item to retrieve. Defaults to NULL. Only
- * used if $mid is not set.
- * @param $reset
- * Optional flag that resets the static variable cache of the menu tree, if
- * set to TRUE. Default is FALSE.
+ * Integer values are mapped according to the $map parameter. For
+ * example, if unserialize($data) is array('node_load', 1) and $map is
+ * array('node', '12345') then 'node_load' will not be changed
+ * because it is not an integer, but 1 will as it is an integer. As
+ * $map[1] is '12345', 1 will be replaced with '12345'. So the result
+ * will be array('node_load', '12345').
*
+ * @param @data
+ * A serialized array.
+ * @param @map
+ * An array of potential replacements.
* @return
- * The menu item found in the site menu, or an empty array if none could be
- * found.
+ * The $data array unserialized and mapped.
*/
-function menu_get_item($mid, $path = NULL, $reset = FALSE) {
- static $menu;
-
- if (!isset($menu) || $reset) {
- $menu = menu_get_menu();
- }
-
- if (isset($mid)) {
- return $menu['items'][$mid];
+function menu_unserialize($data, $map) {
+ if ($data = unserialize($data)) {
+ foreach ($data as $k => $v) {
+ if (is_int($v)) {
+ $data[$k] = isset($map[$v]) ? $map[$v] : '';
+ }
+ }
+ return $data;
}
-
- if (isset($path)) {
- return $menu['items'][$menu['path index'][$path]];
+ else {
+ return array();
}
-
- return array();
}
/**
- * Retrieves the menu ID and title of all root menus.
+ * Replaces the statically cached item for a given path.
*
- * @return
- * Array containing all menus (but not menu items), in the form mid => title.
+ * @param $path
+ * The path
+ * @param $item
+ * The menu item. This is a menu entry, an associative array,
+ * with keys like title, access callback, access arguments etc.
*/
-function menu_get_root_menus() {
- $menu = menu_get_menu();
- $root_menus = array();
-
- foreach ($menu['items'][0]['children'] as $mid) {
- $root_menus[$mid] = $menu['items'][$mid]['title'];
- }
-
- return $root_menus;
+function menu_set_item($path, $item) {
+ menu_get_item($path, TRUE, $item);
}
-/**
- * Change the current menu location of the user.
- *
- * Frequently, modules may want to make a page or node act as if it were
- * in the menu tree somewhere, even though it was not registered in a
- * hook_menu() implementation. If the administrator has rearranged the menu,
- * the newly set location should respect this in the breadcrumb trail and
- * expanded/collapsed status of menu items in the tree. This function
- * allows this behavior.
- *
- * @param $location
- * An array specifying a complete or partial breadcrumb trail for the
- * new location, in the same format as the return value of hook_menu().
- * The last element of this array should be the new location itself.
- *
- * This function will set the new breadcrumb trail to the passed-in value,
- * but if any elements of this trail are visible in the site tree, the
- * trail will be "spliced in" to the existing site navigation at that point.
- */
-function menu_set_location($location) {
- global $_menu;
- $temp_id = min(array_keys($_menu['items'])) - 1;
- $prev_id = 0;
-
- // Don't allow this function to change the actual current path, just the
- // position in the menu tree.
- $location[count($location) - 1]['path'] = $_GET['q'];
-
- foreach (array_reverse($location) as $item) {
- if (isset($_menu['path index'][$item['path']])) {
- $mid = $_menu['path index'][$item['path']];
- if (isset($_menu['visible'][$mid])) {
- // Splice in the breadcrumb at this location.
- if ($prev_id) {
- $_menu['items'][$prev_id]['pid'] = $mid;
- }
- $prev_id = 0;
- break;
- }
- else {
- // A hidden item; show it, but only temporarily.
- $_menu['items'][$mid]['type'] |= MENU_VISIBLE_IN_BREADCRUMB;
- if ($prev_id) {
- $_menu['items'][$prev_id]['pid'] = $mid;
- }
- $prev_id = $mid;
+function menu_get_item($path = NULL, $execute = TRUE, $item = NULL) {
+ static $items;
+ if (!isset($path)) {
+ $path = $_GET['q'];
+ }
+ if (isset($item)) {
+ $items[$path] = $item;
+ }
+ if (!isset($items[$path])) {
+ $map = arg(NULL, $path);
+ $parts = array_slice($map, 0, 6);
+ list($ancestors, $placeholders) = menu_get_ancestors($parts);
+ if ($item = db_fetch_object(db_query_range('SELECT * FROM {menu} WHERE path IN ('. implode (',', $placeholders) .') ORDER BY fit DESC', $ancestors, 0, 1))) {
+ $item->access = _menu_access($item, $map);
+ if ($map === FALSE) {
+ $items[$path] = FALSE;
+ return FALSE;
}
- }
- else {
- $item['type'] |= MENU_VISIBLE_IN_BREADCRUMB;
- if ($prev_id) {
- $_menu['items'][$prev_id]['pid'] = $temp_id;
+ if ($execute) {
+ $item->page_arguments = array_merge(menu_unserialize($item->page_arguments, $map), array_slice($parts, $item->number_parts));
}
- $_menu['items'][$temp_id] = $item;
- $_menu['path index'][$item['path']] = $temp_id;
-
- $prev_id = $temp_id;
- $temp_id--;
}
+ $items[$path] = $item;
}
-
- if ($prev_id) {
- // Didn't find a home, so attach this to the main navigation menu.
- $_menu['items'][$prev_id]['pid'] = 1;
- }
-
- $final_item = array_pop($location);
- menu_set_active_item($final_item['path']);
+ return $items[$path];
}
/**
* Execute the handler associated with the active menu item.
- *
- * This is called early in the page request. The active menu item is at
- * this point determined exclusively by the URL. The handler that is called
- * here may, as a side effect, change the active menu item so that later
- * menu functions (that display the menus and breadcrumbs, for example)
- * act as if the user were in a different location on the site.
*/
function menu_execute_active_handler() {
- if (_menu_site_is_offline()) {
- return MENU_SITE_OFFLINE;
- }
-
- $menu = menu_get_menu();
-
- // Determine the menu item containing the callback.
- $path = $_GET['q'];
- while ($path && !isset($menu['callbacks'][$path])) {
- $path = substr($path, 0, strrpos($path, '/'));
- }
-
- if (!isset($menu['callbacks'][$path])) {
- return MENU_NOT_FOUND;
+ if ($item = menu_get_item()) {
+ return $item->access ? call_user_func_array($item->page_callback, $item->page_arguments) : MENU_ACCESS_DENIED;
}
+ return MENU_NOT_FOUND;
+}
- if (!function_exists($menu['callbacks'][$path]['callback'])) {
- return MENU_NOT_FOUND;
+function _menu_access($item, &$map) {
+ if ($item->map_callback) {
+ $map = call_user_func_array($item->map_callback, array_merge(array($map), unserialize($item->map_arguments)));
+ if ($map === FALSE) {
+ return FALSE;
+ }
}
-
- if (!_menu_item_is_accessible(menu_get_active_item())) {
- return MENU_ACCESS_DENIED;
+ $callback = $item->access_callback;
+ if (is_numeric($callback)) {
+ return $callback;
}
-
- // We found one, and are allowed to execute it.
- $arguments = isset($menu['callbacks'][$path]['callback arguments']) ? $menu['callbacks'][$path]['callback arguments'] : array();
- $arg = substr($_GET['q'], strlen($path) + 1);
- if (strlen($arg)) {
- $arguments = array_merge($arguments, explode('/', $arg));
+ $arguments = menu_unserialize($item->access_arguments, $map);
+ // As call_user_func_array is quite slow and user_access is a very common
+ // callback, it is worth making a special case for it.
+ if ($callback == 'user_access') {
+ return (count($arguments) == 1) ? user_access($arguments[0]) : user_access($arguments[0], $arguments[1]);
}
-
- return call_user_func_array($menu['callbacks'][$path]['callback'], $arguments);
+ return call_user_func_array($callback, $arguments);
}
/**
- * Returns the ID of the active menu item.
+ * Returns a rendered menu tree.
*/
-function menu_get_active_item() {
- return menu_set_active_item();
+function menu_tree() {
+ $item = menu_get_item();
+ list(, $menu) = _menu_tree(db_query('SELECT * FROM {menu} WHERE pid IN ('. $item->parents .') AND visible = 1 ORDER BY vancode'));
+ return $menu;
}
-/**
- * Sets the path of the active menu item.
- */
-function menu_set_active_item($path = NULL) {
- static $stored_mid;
-
- if (!isset($stored_mid) || isset($path)) {
- if (!isset($path)) {
- $path = $_GET['q'];
+function _menu_tree($result = NULL, $depth = 0, $link = array('link' => '', 'has_children' => FALSE)) {
+ static $original_map;
+ $remnant = array('link' => '', 'has_children' => FALSE);
+ $tree = '';
+ while ($item = db_fetch_object($result)) {
+ $map = arg(NULL, $item->path);
+ if (!_menu_access($item, $map)) {
+ continue;
}
- else {
- $_GET['q'] = $path;
+ $menu_link = array('link' => $item->menu_link, 'has_children' => $item->has_children);
+ if ($item->depth > $depth) {
+ list($remnant, $menu) = _menu_tree($result, $item->depth, $menu_link);
+ $tree .= theme('menu_tree', $link, $menu);
+ $link = $remnant;
+ $remnant = '';
}
- $menu = menu_get_menu();
-
- while ($path && !isset($menu['path index'][$path])) {
- $path = substr($path, 0, strrpos($path, '/'));
+ elseif ($item->depth == $depth) {
+ $tree .= theme('menu_link', $link);
+ $link = $menu_link;
}
- $stored_mid = isset($menu['path index'][$path]) ? $menu['path index'][$path] : 0;
-
- // Search for default local tasks to activate instead of this item.
- $continue = TRUE;
- while ($continue) {
- $continue = FALSE;
- if (isset($menu['items'][$stored_mid]['children'])) {
- foreach ($menu['items'][$stored_mid]['children'] as $cid) {
- if ($menu['items'][$cid]['type'] & MENU_LINKS_TO_PARENT) {
- $stored_mid = $cid;
- $continue = TRUE;
- }
- }
- }
+ else {
+ $remnant = $menu_link;
+ break;
}
-
- // Reset the cached $menu in menu_get_item().
- menu_get_item(NULL, NULL, TRUE);
}
-
- return $stored_mid;
+ if ($link['link']) {
+ $tree .= theme('menu_link', $link);
+ }
+ return array($remnant, $tree);
}
/**
- * Returns the ID of the current menu item or, if the current item is a
- * local task, the menu item to which this task is attached.
+ * Generate the HTML for a menu tree.
*/
-function menu_get_active_nontask_item() {
- $mid = menu_get_active_item();
-
- // Find the first non-task item:
- while ($mid) {
- $item = menu_get_item($mid);
-
- if (!($item['type'] & MENU_IS_LOCAL_TASK)) {
- return $mid;
- }
-
- $mid = $item['pid'];
- }
+function theme_menu_tree($link, $tree) {
+ $tree = '<ul class="menu">'. $tree .'</ul>';
+ return $link['link'] ? theme('menu_link', $link, $tree) : $tree;
}
/**
- * Returns the title of the active menu item.
+ * Generate the HTML for a menu link.
*/
-function menu_get_active_title() {
- if ($mid = menu_get_active_nontask_item()) {
- $item = menu_get_item($mid);
- return $item['title'];
- }
+function theme_menu_link($link, $menu = '') {
+ return '<li class="'. ($menu ? 'expanded' : ($link['has_children'] ? 'collapsed' : 'leaf')) .'">'. $link['link'] . $menu .'</li>' . "\n";
}
/**
@@ -501,8 +394,9 @@ function menu_get_active_title() {
function menu_get_active_help() {
$path = $_GET['q'];
$output = '';
+ $item = menu_get_item();
- if (!_menu_item_is_accessible(menu_get_active_item())) {
+ if (!$item->access) {
// Don't return help text for areas the user cannot access.
return;
}
@@ -510,7 +404,7 @@ function menu_get_active_help() {
foreach (module_list() as $name) {
if (module_hook($name, 'help')) {
if ($temp = module_invoke($name, 'help', $path)) {
- $output .= $temp . "\n";
+ $output .= $temp ."\n";
}
if (module_hook('help', 'page')) {
if (arg(0) == "admin") {
@@ -525,868 +419,166 @@ function menu_get_active_help() {
}
/**
- * Returns an array of rendered menu items in the active breadcrumb trail.
- */
-function menu_get_active_breadcrumb() {
-
- // No breadcrumb for the front page.
- if (drupal_is_front_page()) {
- return array();
- }
-
- // We do *not* want to use "variable_get('site_frontpage', 'node)" here
- // as that will create the link '/node'. This is unsightly and creates
- // a second URL for the homepage ('/' *and* '/node').
- $links[] = l(t('Home'), '');
-
- $trail = _menu_get_active_trail();
- foreach ($trail as $mid) {
- $item = menu_get_item($mid);
- if ($item['type'] & MENU_VISIBLE_IN_BREADCRUMB) {
- $links[] = menu_item_link($mid);
- }
- }
-
- // The last item in the trail is the page title; don't display it here.
- array_pop($links);
-
- return $links;
-}
-
-/**
- * Returns TRUE when the menu item is in the active trail.
- */
-function menu_in_active_trail($mid) {
- $trail = _menu_get_active_trail();
-
- return in_array($mid, $trail);
-}
-
-/**
- * Returns TRUE when the menu item is in the active trail within a
- * specific subsection of the menu tree.
- *
- * @param $mid
- * The menu item being considered.
- * @param $pid
- * The root of the subsection of the menu tree in which to look.
- */
-function menu_in_active_trail_in_submenu($mid, $pid) {
- $trail = _menu_get_active_trail_in_submenu($pid);
-
- if (!$trail) {
- return FALSE;
- }
-
- return in_array($mid, $trail);
-}
-
-/**
* Populate the database representation of the menu.
- *
- * This need only be called at the start of pages that modify the menu.
*/
function menu_rebuild() {
- // Clear the page cache, so that changed menus are reflected for anonymous users.
- cache_clear_all('*', 'cache_page', TRUE);
- // Also clear the menu cache.
- cache_clear_all('*', 'cache_menu', TRUE);
-
- _menu_build();
-
- if (module_exists('menu')) {
- $menu = menu_get_menu();
-
- // Fill a queue of new menu items which are modifiable.
- $new_items = array();
- foreach ($menu['items'] as $mid => $item) {
- if ($mid < 0 && ($item['type'] & MENU_MODIFIABLE_BY_ADMIN)) {
- $new_items[$mid] = $item;
- }
+ $next = array();
+ db_query('DELETE FROM {menu}');
+ $menu = module_invoke_all('menu');
+ foreach (module_implements('menu_alter') as $module) {
+ $function = $module .'_menu_alter';
+ $function($menu);
+ }
+ $mid = 1;
+ // First pass.
+ foreach ($menu as $path => $item) {
+ $item = &$menu[$path];
+ $parts = explode('/', $path, 6);
+ $number_parts = count($parts);
+ // We store the highest index of parts here to save some work in the weight
+ // calculation loop.
+ $slashes = $number_parts - 1;
+ // If there is no %, it fits maximally.
+ if (strpos($path, '%') === FALSE) {
+ $fit = (1 << $number_parts) - 1;
}
-
- $old_count = -1;
- // Save the new items updating the pids in each iteration
- while (($c = count($new_items)) && ($c != $old_count)) {
- $old_count = count($new_items);
- foreach ($new_items as $mid => $item) {
- // If the item has a valid parent, save it
- if ($item['pid'] >= 0) {
- // The new menu ID gets passed back by reference as $item['mid']
- menu_save_item($item);
- // Fix parent IDs for the children of the menu item just saved
- if ($item['children']) {
- foreach ($item['children'] as $child) {
- if (isset($new_items[$child])) {
- $new_items[$child]['pid'] = $item['mid'];
- }
- }
+ else {
+ // We need to calculate the fitness.
+ $fit = 0;
+ foreach ($parts as $k => $part) {
+ // ($part != '%') is the bit we want and we shift it to its place
+ // by shifting to left by ($slashes - $k) bits.
+ $fit |= ($part != '%') << ($slashes - $k);
+ }
+ }
+ if (!isset($item['_visible'])) {
+ $item['_visible'] = (!isset($item['type']) || ($item['type'] & MENU_VISIBLE_IN_TREE)) ? 1 : 0;
+ }
+ $depth = 1;
+ if (!isset($item['_mid'])) {
+ $item['_mid'] = $mid++;
+ }
+ $parents = array($item['_mid']);
+ for ($i = $slashes; $i; $i--) {
+ $parent_path = implode('/', array_slice($parts, 0, $i));
+ // We need to calculate depth to be able to sort. depth needs visibility.
+ if (isset($menu[$parent_path])) {
+ $parent = &$menu[$parent_path];
+ // It's possible that the parent was not processed yet.
+ if (!isset($parent['_mid'])) {
+ $parent['_mid'] = $mid++;
+ }
+ if (!isset($parent['_visible'])) {
+ $parent['_visible'] = (!isset($parent['type']) || ($parent['type'] & MENU_VISIBLE_IN_TREE)) ? 1 : 0;
+ }
+ if ($item['_visible'] && $parent['_visible']) {
+ $parent['_has_children'] = 1;
+ $depth++;
+ $parents[] = $parent['_mid'];
+ if (!isset($item['_pid'])) {
+ $item['_pid'] = $parent['_mid'];
+ $item['_visible_parent_path'] = $parent_path;
}
- // remove the item
- unset($new_items[$mid]);
}
- }
- }
- // Rebuild the menu to account for the changes.
- _menu_build();
- }
-
- // Reset the cached $menu in menu_get_item().
- menu_get_item(NULL, NULL, TRUE);
-
-}
-
-/**
- * Generate the HTML for a menu tree.
- *
- * @param $pid
- * The parent id of the menu.
- *
- * @ingroup themeable
- */
-function theme_menu_tree($pid = 1) {
- if ($tree = menu_tree($pid)) {
- return "\n<ul class=\"menu\">\n". $tree ."\n</ul>\n";
- }
-}
-
-/**
- * Returns a rendered menu tree.
- *
- * @param $pid
- * The parent id of the menu.
- */
-function menu_tree($pid = 1) {
- $menu = menu_get_menu();
- $output = '';
-
- if (isset($menu['visible'][$pid]) && $menu['visible'][$pid]['children']) {
- foreach ($menu['visible'][$pid]['children'] as $mid) {
- $type = isset($menu['visible'][$mid]['type']) ? $menu['visible'][$mid]['type'] : NULL;
- $children = isset($menu['visible'][$mid]['children']) ? $menu['visible'][$mid]['children'] : NULL;
- $output .= theme('menu_item', $mid, menu_in_active_trail($mid) || ($type & MENU_EXPANDED) ? theme('menu_tree', $mid) : '', count($children) == 0);
- }
- }
-
- return $output;
-}
-
-/**
- * Generate the HTML output for a single menu item.
- *
- * @param $mid
- * The menu id of the item.
- * @param $children
- * A string containing any rendered child items of this menu.
- * @param $leaf
- * A boolean indicating whether this menu item is a leaf.
- *
- * @ingroup themeable
- */
-function theme_menu_item($mid, $children = '', $leaf = TRUE) {
- return '<li class="'. ($leaf ? 'leaf' : ($children ? 'expanded' : 'collapsed')) .'">'. menu_item_link($mid) . $children ."</li>\n";
-}
-
-/**
- * Generate the HTML representing a given menu item ID.
- *
- * @param $item
- * The menu item to render.
- * @param $link_item
- * The menu item which should be used to find the correct path.
- *
- * @ingroup themeable
- */
-function theme_menu_item_link($item, $link_item) {
- return l($item['title'], $link_item['path'], !empty($item['description']) ? array('title' => $item['description']) : array(), isset($item['query']) ? $item['query'] : NULL);
-}
-
-/**
- * Returns the rendered link to a menu item.
- *
- * @param $mid
- * The menu item id to render.
- * @param $theme
- * Whether to return a themed link or the link as an array
- */
-function menu_item_link($mid, $theme = TRUE) {
- $item = menu_get_item($mid);
- $link_item = $item;
- $link = '';
-
- while ($link_item['type'] & MENU_LINKS_TO_PARENT) {
- $link_item = menu_get_item($link_item['pid']);
- }
-
- if ($theme) {
- $link = theme('menu_item_link', $item, $link_item);
- }
- else {
- $link = array(
- 'title' => $item['title'],
- 'href' => $link_item['path'],
- 'attributes' => !empty($item['description']) ? array('title' => $item['description']) : array()
+ unset($parent);
+ }
+ }
+ $parents[] = 0;
+ $parents = implode(',', array_reverse($parents));
+ // Store variables and set defaults.
+ $item += array(
+ '_fit' => $fit,
+ '_number_parts' => $number_parts,
+ '_parts' => $parts,
+ '_pid' => 0,
+ '_depth' => $depth,
+ '_parents' => $parents,
+ '_has_children' => 0,
+ 'title' => '',
+ 'weight' => 0,
);
- }
-
- return $link;
-}
-
-/**
- * Returns the rendered local tasks. The default implementation renders
- * them as tabs.
- *
- * @ingroup themeable
- */
-function theme_menu_local_tasks() {
- $output = '';
-
- if ($primary = menu_primary_local_tasks()) {
- $output .= "<ul class=\"tabs primary\">\n". $primary ."</ul>\n";
- }
- if ($secondary = menu_secondary_local_tasks()) {
- $output .= "<ul class=\"tabs secondary\">\n". $secondary ."</ul>\n";
- }
-
- return $output;
-}
-
-/**
- * Returns the rendered HTML of the primary local tasks.
- */
-function menu_primary_local_tasks() {
- $local_tasks = menu_get_local_tasks();
- $pid = menu_get_active_nontask_item();
- $output = '';
-
- if (count($local_tasks[$pid]['children'])) {
- foreach ($local_tasks[$pid]['children'] as $mid) {
- $output .= theme('menu_local_task', $mid, menu_in_active_trail($mid), TRUE);
- }
- }
-
- return $output;
-}
-
-/**
- * Returns the rendered HTML of the secondary local tasks.
- */
-function menu_secondary_local_tasks() {
- $local_tasks = menu_get_local_tasks();
- $pid = menu_get_active_nontask_item();
- $output = '';
-
- if (count($local_tasks[$pid]['children'])) {
- foreach ($local_tasks[$pid]['children'] as $mid) {
- if (menu_in_active_trail($mid) && count($local_tasks[$mid]['children']) > 1) {
- foreach ($local_tasks[$mid]['children'] as $cid) {
- $output .= theme('menu_local_task', $cid, menu_in_active_trail($cid), FALSE);
+ $sort[$path] = ($item['_visible'] ? $depth : $number_parts) . sprintf('%05d', $item['weight']) . $item['title'];
+ unset($item);
+ }
+ array_multisort($sort, $menu);
+ // Second pass: calculate ancestors, vancode and store into the database.
+ foreach ($menu as $path => $item) {
+ $item = &$menu[$path];
+ for ($i = $item['_number_parts'] - 1; $i; $i--) {
+ $parent_path = implode('/', array_slice($item['_parts'], 0, $i));
+ if (isset($menu[$parent_path])) {
+ $parent = $menu[$parent_path];
+ // If a callback is not found, we try to find the first parent that
+ // has this callback. When found, its callback argument will also be
+ // copied but only if there is none in the current item.
+ foreach (array('access', 'map', 'page') as $type) {
+ if (!isset($item["$type callback"]) && isset($parent["$type callback"])) {
+ $item["$type callback"] = $parent["$type callback"];
+ if (!isset($item["$type arguments"]) && isset($parent["$type arguments"])) {
+ $item["$type arguments"] = $parent["$type arguments"];
+ }
+ }
}
}
}
- }
-
- return $output;
-}
-
-/**
- * Generate the HTML representing a given menu item ID as a tab.
- *
- * @param $mid
- * The menu ID to render.
- * @param $active
- * Whether this tab or a subtab is the active menu item.
- * @param $primary
- * Whether this tab is a primary tab or a subtab.
- *
- * @ingroup themeable
- */
-function theme_menu_local_task($mid, $active, $primary) {
- if ($active) {
- return '<li class="active">'. menu_item_link($mid) ."</li>\n";
- }
- else {
- return '<li>'. menu_item_link($mid) ."</li>\n";
- }
-}
-
-/**
- * Returns an array containing the primary links.
- * Can optionally descend from the root of the Primary links menu towards the
- * current node for a specified number of levels and return that submenu.
- * Used to generate a primary/secondary menu from different levels of one menu.
- *
- * @param $start_level
- * This optional parameter can be used to retrieve a context-sensitive array
- * of links at $start_level levels deep into the Primary links menu.
- * The default is to return the top-level links.
- * @param $pid
- * The parent menu ID from which to search for children. Defaults to the
- * menu_primary_menu setting.
- * @return A nested array of links and their properties. The keys of
- * the array contain some extra encoded information about the results.
- * The format of the key is {level}-{num}{-active}.
- * level is the depth within the menu tree of this list.
- * num is the number within this array, used only to make the key unique.
- * -active is appended if this element is in the active trail.
- */
-function menu_primary_links($start_level = 1, $pid = 0) {
- if (!module_exists('menu')) {
- return NULL;
- }
- if (!$pid) {
- $pid = variable_get('menu_primary_menu', 0);
- }
- if (!$pid) {
- return NULL;
- }
-
- if ($start_level < 1) {
- $start_level = 1;
- }
-
- if ($start_level > 1) {
- $trail = _menu_get_active_trail_in_submenu($pid);
- if (!$trail) {
- return NULL;
+ if (!isset($item['access callback'])) {
+ $menu[$path]['access callback'] = isset($item['access arguments']) ? 'user_access' : 0;
}
- else {
- $pid = $trail[$start_level - 1];
+ if (!isset($item['map callback']) && isset($item['map arguments'])) {
+ $item['map callback'] = 'menu_map';
}
- }
-
- $menu = menu_get_menu();
- $links = array();
- if ($pid && is_array($menu['visible'][$pid]) && isset($menu['visible'][$pid]['children'])) {
- $count = 1;
- foreach ($menu['visible'][$pid]['children'] as $cid) {
- $index = "menu-$start_level-$count-$pid";
- if (menu_in_active_trail_in_submenu($cid, $pid)) {
- $index .= "-active";
+ foreach (array('access', 'map', 'page') as $type) {
+ if (isset($item["$type callback"]) && !isset($item["$type arguments"])) {
+ $item["$type arguments"] = array();
}
- $links[$index] = menu_item_link($cid, FALSE);
- $count++;
}
- }
-
- // Special case - provide link to admin/build/menu if primary links is empty.
- if (empty($links) && $start_level == 1 && $pid == variable_get('menu_primary_menu', 0) && user_access('administer menu')) {
- $links['1-1'] = array(
- 'title' => t('Edit primary links'),
- 'href' => 'admin/build/menu'
- );
- }
-
- return $links;
-}
-
-/**
- * Returns an array containing the secondary links.
- * Secondary links can be either a second level of the Primary links
- * menu or generated from their own menu.
- */
-function menu_secondary_links() {
- $msm = variable_get('menu_secondary_menu', 0);
- if ($msm == 0) {
- return NULL;
- }
-
- if ($msm == variable_get('menu_primary_menu', 0)) {
- return menu_primary_links(2, $msm);
- }
-
- return menu_primary_links(1, $msm);
-}
-
-/**
- * Returns the themed HTML for primary and secondary links.
- * Note that this function is overridden by most core themes because
- * those themes display links in "link | link" format, not from a list.
- * Also note that by default links rendered with this function are
- * displayed with the same CSS as is used for the local tasks.
- * If a theme wishes to render links from a ul it is expected that
- * the theme will provide suitable CSS.
- *
- * @param $links
- * An array containing links to render.
- * @return
- * A string containing the themed links.
- *
- * @ingroup themeable
- */
-function theme_menu_links($links) {
- if (!count($links)) {
- return '';
- }
- $level_tmp = explode('-', key($links));
- $level = $level_tmp[0];
- $output = "<ul class=\"links-$level\">\n";
- foreach ($links as $index => $link) {
- $output .= '<li';
- if (stristr($index, 'active')) {
- $output .= ' class="active"';
- }
- $output .= ">". l($link['title'], $link['href'], $link['attributes'], $link['query'], $link['fragment']) ."</li>\n";
- }
- $output .= '</ul>';
-
- return $output;
-}
-
-/**
- * @} End of "defgroup menu".
- */
-
-/**
- * Returns an array with the menu items that lead to the current menu item.
- */
-function _menu_get_active_trail() {
- static $trail;
-
- if (!isset($trail)) {
- $trail = array();
-
- $mid = menu_get_active_item();
-
- // Follow the parents up the chain to get the trail.
- while ($mid && ($item = menu_get_item($mid))) {
- array_unshift($trail, $mid);
- $mid = $item['pid'];
+ if (is_bool($item['access callback'])) {
+ $item['access callback'] = intval($item['access callback']);
}
- }
- return $trail;
-}
-
-/**
- * Find the active trail through a specific subsection of the menu tree.
- *
- * @param $pid
- * The root item from which the active trail must descend.
- */
-function _menu_get_active_trail_in_submenu($pid) {
- static $trails;
-
- if (!isset($trails)) {
- // Find all menu items which point to the current node and for each
- // follow the parents up the chain to build an active trail.
- $trails = array();
- $menu = menu_get_menu();
- $path = $_GET['q'];
- $count = 0;
- while ($path && !$count) {
- foreach ($menu['items'] as $key => $item) {
- if (isset($item['path']) && $item['path'] == $path) {
- $trails[$count] = array();
- $mid = $key;
- while ($mid && $menu['items'][$mid]) {
- array_unshift($trails[$count], $mid);
- $mid = $menu['items'][$mid]['pid'];
- }
- $count ++;
- }
+ if ($item['_visible']) {
+ $prefix = isset($item['_visible_parent_path']) ? $menu[$item['_visible_parent_path']]['_prefix'] : '';
+ if (!isset($next[$prefix])) {
+ $next[$prefix] = 0;
}
- $path = substr($path, 0, strrpos($path, '/'));
+ $vancode = $prefix . int2vancode($next[$prefix]++);
+ $menu[$path]['_prefix'] = $vancode .'.';
+ $link = l($item['title'], $path, isset($item['attributes']) ? $item['attributes'] : array(), isset($item['query']) ? $item['query'] : NULL, isset($item['fragment']) ? $item['fragment'] : NULL);
}
- }
-
- if ($trails) {
- foreach ($trails as $trail) {
- $count_trail = count($trail);
- for ($i = 0; $i < $count_trail; $i++) {
- if ($trail[$i] == $pid) {
- // Return a trail from $pid down to the current page inclusive.
- for ( ; $i < $count_trail; $i++) {
- $subtrail[] = $trail[$i];
- }
- return $subtrail;
- }
- }
+ else {
+ $vancode = '';
+ $link = '';
}
+ db_query("INSERT INTO {menu} (mid, pid, path, access_callback, access_arguments, page_callback, page_arguments, map_callback, map_arguments, fit, number_parts, vancode, menu_link, visible, parents, depth, has_children) VALUES (%d, %d, '%s', '%s', '%s', '%s', '%s', '%s', '%s', %d, %d, '%s', '%s', %d, '%s', %d, %d)", $item['_mid'], $item['_pid'], $path, $item['access callback'], serialize($item['access arguments']), $item['page callback'], serialize($item['page arguments']), $item['map callback'], serialize($item['map arguments']), $item['_fit'], $item['_number_parts'], $vancode .'+', $link, $item['_visible'], $item['_parents'], $item['_depth'], $item['_has_children']);
+ // $item needs to be unset because of the reference above.
+ unset($item);
}
-
- return NULL;
}
-/**
- * Comparator routine for use in sorting menu items.
- */
-function _menu_sort($a, $b) {
- $menu = menu_get_menu();
-
- $a = $menu['items'][$a];
- $b = $menu['items'][$b];
-
- if ($a['weight'] < $b['weight']) {
- return -1;
- }
- elseif ($a['weight'] > $b['weight']) {
- return 1;
- }
- elseif (isset($a['title']) && isset($b['title'])) {
- return strnatcasecmp($a['title'], $b['title']);
- }
- else {
- return 1;
- }
+function menu_map($arg, $function, $index, $default = FALSE) {
+ $arg[$index] = is_numeric($arg[$index]) ? $function($arg[$index]) : $default;
+ return $arg[$index] ? $arg : FALSE;
}
-/**
- * Build the menu by querying both modules and the database.
- */
-function _menu_build() {
- global $_menu;
- global $user;
-
- // Start from a clean slate.
- $_menu = array();
-
- $_menu['path index'] = array();
- // Set up items array, including default "Navigation" menu.
- $_menu['items'] = array(
- 0 => array('path' => '', 'title' => '', 'type' => MENU_IS_ROOT),
- 1 => array('pid' => 0, 'path' => '', 'title' => t('Navigation'), 'weight' => -50, 'access' => TRUE, 'type' => MENU_IS_ROOT | MENU_VISIBLE_IN_TREE)
- );
- $_menu['callbacks'] = array();
-
- // Build a sequential list of all menu items.
- $menu_item_list = module_invoke_all('menu', TRUE);
-
- // Menu items not in the DB get temporary negative IDs.
- $temp_mid = -1;
-
- foreach ($menu_item_list as $item) {
- if (!isset($item['path'])) {
- $item['path'] = '';
- }
- if (!isset($item['type'])) {
- $item['type'] = MENU_NORMAL_ITEM;
- }
- if (!isset($item['weight'])) {
- $item['weight'] = 0;
- }
- $mid = $temp_mid;
- if (isset($_menu['path index'][$item['path']])) {
- // Newer menu items overwrite older ones.
- unset($_menu['items'][$_menu['path index'][$item['path']]]);
- }
- if (isset($item['callback'])) {
- $_menu['callbacks'][$item['path']] = array('callback' => $item['callback']);
- if (isset($item['callback arguments'])) {
- $_menu['callbacks'][$item['path']]['callback arguments'] = $item['callback arguments'];
- unset($item['callback arguments']);
- }
- unset($item['callback']);
- }
- $_menu['items'][$mid] = $item;
- $_menu['path index'][$item['path']] = $mid;
-
- $temp_mid--;
- }
-
- // Now fetch items from the DB, reassigning menu IDs as needed.
- if (module_exists('menu')) {
- $result = db_query(db_rewrite_sql('SELECT m.mid, m.* FROM {menu} m ORDER BY m.mid ASC', 'm', 'mid'));
- while ($item = db_fetch_object($result)) {
- // Handle URL aliases if entered in menu administration.
- if (!isset($_menu['path index'][$item->path])) {
- $item->path = drupal_get_normal_path($item->path);
- }
- if (isset($_menu['path index'][$item->path])) {
- // The path is already declared.
- $old_mid = $_menu['path index'][$item->path];
- if ($old_mid < 0) {
- // It had a temporary ID, so use a permanent one.
- $_menu['items'][$item->mid] = $_menu['items'][$old_mid];
- if ($_menu['items'][$item->mid]['type'] & $item->type) {
- // If the item is of the same type, delete the old item.
- unset($_menu['items'][$old_mid]);
- $_menu['path index'][$item->path] = $item->mid;
- }
- // The new menu item gets all the custom type flags from the database
- $_menu['items'][$item->mid]['type'] &= $item->type;
- }
- else {
- // It has a permanent ID. Only replace with non-custom menu items.
- if ($item->type & MENU_CREATED_BY_ADMIN) {
- $_menu['items'][$item->mid] = array('path' => $item->path);
- }
- else {
- // Leave the old item around as a shortcut to this one.
- $_menu['items'][$item->mid] = $_menu['items'][$old_mid];
- $_menu['path index'][$item->path] = $item->mid;
- }
- }
- }
- else {
- // The path was not declared, so this is a custom item or an orphaned one.
- if ($item->type & MENU_CREATED_BY_ADMIN) {
- $_menu['items'][$item->mid] = array('path' => $item->path);
- if (!empty($item->path)) {
- $_menu['path index'][$item->path] = $item->mid;
- }
- }
- }
-
- // If the administrator has changed the item, reflect the change.
- if ($item->type & MENU_MODIFIED_BY_ADMIN) {
- $_menu['items'][$item->mid]['title'] = $item->title;
- $_menu['items'][$item->mid]['description'] = $item->description;
- $_menu['items'][$item->mid]['pid'] = $item->pid;
- $_menu['items'][$item->mid]['weight'] = $item->weight;
- $_menu['items'][$item->mid]['type'] = $item->type;
- }
- }
- }
-
- // Associate parent and child menu items.
- _menu_find_parents($_menu['items']);
-
- // Prepare to display trees to the user as required.
- _menu_build_visible_tree();
+// Placeholders.
+function menu_primary_links() {
}
-/**
- * Determine whether the given menu item is accessible to the current user.
- *
- * Use this instead of just checking the "access" property of a menu item
- * to properly handle items with fall-through semantics.
- */
-function _menu_item_is_accessible($mid) {
- $menu = menu_get_menu();
-
- // Follow the path up to find the first "access" attribute.
- $path = isset($menu['items'][$mid]['path']) ? $menu['items'][$mid]['path'] : NULL;
- while ($path && (!isset($menu['path index'][$path]) || !isset($menu['items'][$menu['path index'][$path]]['access']))) {
- $path = substr($path, 0, strrpos($path, '/'));
- }
- if (empty($path)) {
- // Items without any access attribute up the chain are denied, unless they
- // were created by the admin. They most likely point to non-Drupal directories
- // or to an external URL and should be allowed.
- return $menu['items'][$mid]['type'] & MENU_CREATED_BY_ADMIN;
- }
- return $menu['items'][$menu['path index'][$path]]['access'];
+function menu_secondary_links() {
}
-/**
- * Find all visible items in the menu tree, for ease in displaying to user.
- *
- * Since this is only for display, we only need title, path, and children
- * for each item.
- */
-function _menu_build_visible_tree($pid = 0) {
- global $_menu;
-
- if (isset($_menu['items'][$pid])) {
- $parent = $_menu['items'][$pid];
-
- $children = array();
- if (isset($parent['children'])) {
- usort($parent['children'], '_menu_sort');
- foreach ($parent['children'] as $mid) {
- $children = array_merge($children, _menu_build_visible_tree($mid));
- }
- }
- $visible = ($parent['type'] & MENU_VISIBLE_IN_TREE) ||
- ($parent['type'] & MENU_VISIBLE_IF_HAS_CHILDREN && count($children) > 0);
- $allowed = _menu_item_is_accessible($pid);
-
- if (($parent['type'] & MENU_IS_ROOT) || ($visible && $allowed)) {
- $_menu['visible'][$pid] = array('title' => $parent['title'], 'path' => $parent['path'], 'children' => $children, 'type' => $parent['type']);
- foreach ($children as $mid) {
- $_menu['visible'][$mid]['pid'] = $pid;
- }
- return array($pid);
- }
- else {
- return $children;
- }
- }
-
- return array();
+function menu_primary_local_tasks() {
}
-/**
- * Account for menu items that are only defined at certain paths, so will not
- * be cached.
- *
- * We don't support the full range of menu item options for these menu items. We
- * don't support MENU_VISIBLE_IF_HAS_CHILDREN, and we require parent items to be
- * declared before their children.
- */
-function _menu_append_contextual_items() {
- global $_menu;
-
- // Build a sequential list of all menu items.
- $menu_item_list = module_invoke_all('menu', FALSE);
-
- // Menu items not in the DB get temporary negative IDs.
- $temp_mid = min(array_keys($_menu['items'])) - 1;
- $new_items = array();
-
- foreach ($menu_item_list as $item) {
- if (isset($item['callback'])) {
- $_menu['callbacks'][$item['path']] = array('callback' => $item['callback']);
- if (isset($item['callback arguments'])) {
- $_menu['callbacks'][$item['path']]['callback arguments'] = $item['callback arguments'];
- unset($item['callback arguments']);
- }
- unset($item['callback']);
- }
- if (!isset($_menu['path index'][$item['path']])) {
- if (!isset($item['path'])) {
- $item['path'] = '';
- }
- if (!isset($item['type'])) {
- $item['type'] = MENU_NORMAL_ITEM;
- }
- if (!isset($item['weight'])) {
- $item['weight'] = 0;
- }
- $_menu['items'][$temp_mid] = $item;
- $_menu['path index'][$item['path']] = $temp_mid;
- $new_items[$temp_mid] = $item;
- $temp_mid--;
- }
- else {
- $mid = $_menu['path index'][$item['path']];
- if ($_menu['items'][$mid]['type'] & MENU_CREATED_BY_ADMIN) {
- $_menu['items'][$mid]['access'] = $item['access'];
- if (isset($_menu['items'][$mid]['callback'])) {
- $_menu['items'][$mid]['callback'] = $item['callback'];
- }
- if (isset($_menu['items'][$mid]['callback arguments'])) {
- $_menu['items'][$mid]['callback arguments'] = $item['callback arguments'];
- }
- }
- if ($item['type'] & MENU_LOCAL_TASK && !($_menu['items'][$mid]['type'] & MENU_LOCAL_TASK)) {
- // A local task is in the menu table and the path is already present
- $_menu['items'][$mid]['type'] = MENU_LOCAL_TASK;
- $new_items[$mid] = $item;
- }
- }
- }
-
- // Establish parent-child relationships.
- _menu_find_parents($new_items);
-
- // Add new items to the visible tree if necessary.
- foreach ($new_items as $mid => $item) {
- $item = $_menu['items'][$mid];
- if (($item['type'] & MENU_VISIBLE_IN_TREE) && _menu_item_is_accessible($mid)) {
- $pid = $item['pid'];
- while ($pid && !isset($_menu['visible'][$pid])) {
- $pid = $_menu['items'][$pid]['pid'];
- }
- $_menu['visible'][$mid] = array('title' => $item['title'], 'path' => $item['path'], 'pid' => $pid);
- $_menu['visible'][$pid]['children'][] = $mid;
- usort($_menu['visible'][$pid]['children'], '_menu_sort');
- }
- }
+function menu_secondary_local_tasks() {
}
-/**
- * Establish parent-child relationships.
- */
-function _menu_find_parents(&$items) {
- global $_menu;
-
- foreach ($items as $mid => $item) {
- if (!isset($item['pid'])) {
- // Parent's location has not been customized, so figure it out using the path.
- $parent = $item['path'];
- if ($parent) {
- do {
- $parent = substr($parent, 0, strrpos($parent, '/'));
- }
- while ($parent && !isset($_menu['path index'][$parent]));
- }
-
- $pid = $parent ? $_menu['path index'][$parent] : 1;
- $_menu['items'][$mid]['pid'] = $pid;
- }
- else {
- $pid = $item['pid'];
- }
-
- // Don't make root a child of itself.
- if ($mid) {
- if (isset ($_menu['items'][$pid])) {
- $_menu['items'][$pid]['children'][] = $mid;
- }
- else {
- // If parent is missing, it is a menu item that used to be defined
- // but is no longer. Default to a root-level "Navigation" menu item.
- $_menu['items'][1]['children'][] = $mid;
- }
- }
- }
+function menu_set_active_item() {
}
-/**
- * Find all the items in the current local task tree.
- *
- * Since this is only for display, we only need title, path, and children
- * for each item.
- *
- * At the close of this function, $_menu['local tasks'] is populated with the
- * menu items in the local task tree.
- *
- * @return
- * TRUE if the local task tree is forked. It does not need to be displayed
- * otherwise.
- */
-function _menu_build_local_tasks($pid) {
- global $_menu;
-
- $forked = FALSE;
-
- if (isset($_menu['items'][$pid])) {
- $parent = $_menu['items'][$pid];
-
- $children = array();
- if (isset($parent['children'])) {
- foreach ($parent['children'] as $mid) {
- if (($_menu['items'][$mid]['type'] & MENU_IS_LOCAL_TASK) && _menu_item_is_accessible($mid)) {
- $children[] = $mid;
- // Beware short-circuiting || operator!
- $forked = _menu_build_local_tasks($mid) || $forked;
- }
- }
- }
- usort($children, '_menu_sort');
- $forked = $forked || count($children) > 1;
-
- $_menu['local tasks'][$pid] = array('title' => $parent['title'], 'path' => $parent['path'], 'children' => $children);
- foreach ($children as $mid) {
- $_menu['local tasks'][$mid]['pid'] = $pid;
- }
- }
-
- return $forked;
+function menu_set_location() {
}
-/**
- * Returns TRUE if the site is off-line for maintenance.
- */
-function _menu_site_is_offline() {
- // Check if site is set to off-line mode
- if (variable_get('site_offline', 0)) {
- // Check if the user has administration privileges
- if (!user_access('administer site configuration')) {
- // Check if this is an attempt to login
- if (drupal_get_normal_path($_GET['q']) != 'user') {
- return TRUE;
- }
- }
- else {
- $offline_message = t('Operating in off-line mode.');
- $messages = drupal_set_message();
- // Ensure that the off-line message is displayed only once [allowing for page redirects].
- if (!isset($messages) || !isset($messages['status']) || !in_array($offline_message, $messages['status'])) {
- drupal_set_message($offline_message);
- }
- }
- }
- return FALSE;
+function menu_get_active_breadcrumb() {
+ return array(l(t('Home'), ''));
}
+
diff --git a/includes/module.inc b/includes/module.inc
index 84cb4653e..44aba1874 100644
--- a/includes/module.inc
+++ b/includes/module.inc
@@ -253,7 +253,6 @@ function module_enable($module_list) {
module_list(TRUE, FALSE);
// Force to regenerate the stored list of hook implementations.
module_implements('', FALSE, TRUE);
- cache_clear_all('*', 'cache_menu', TRUE);
}
foreach ($invoke_modules as $module) {
@@ -283,7 +282,6 @@ function module_disable($module_list) {
module_list(TRUE, FALSE);
// Force to regenerate the stored list of hook implementations.
module_implements('', FALSE, TRUE);
- cache_clear_all('*', 'cache_menu', TRUE);
}
}
diff --git a/includes/path.inc b/includes/path.inc
index b911dae60..4801458db 100644
--- a/includes/path.inc
+++ b/includes/path.inc
@@ -145,16 +145,20 @@ function drupal_get_normal_path($path) {
* The component specified by $index, or FALSE if the specified component was
* not found.
*/
-function arg($index) {
- static $arguments, $q;
+function arg($index = NULL, $path = NULL) {
+ static $arguments;
- if (empty($arguments) || $q != $_GET['q']) {
- $arguments = explode('/', $_GET['q']);
- $q = $_GET['q'];
+ if (!isset($path)) {
+ $path = $_GET['q'];
}
-
- if (isset($arguments[$index])) {
- return $arguments[$index];
+ if (!isset($arguments[$path])) {
+ $arguments[$path] = explode('/', $path);
+ }
+ if (!isset($index)) {
+ return $arguments[$path];
+ }
+ if (isset($arguments[$path][$index])) {
+ return $arguments[$path][$index];
}
}