Skip to content
Snippets Groups Projects
Commit c7bce9ef authored by Dries Buytaert's avatar Dries Buytaert
Browse files

- Patch #35768 by JonBob/Richard: separate callback handling from menu handling.

  Moves callbacks and arguments to a separate data structure from the visible menu tree. As mentioned on drupal-devel, this change has little impact except to slightly improve code legibility and prepare the code base for future separation of these tasks, with an eye toward performance improvements of the menu system.  Also changes array_key_exists() to isset() in several places, which is reported to perform better.
parent 9677ab12
No related branches found
No related tags found
2 merge requests!7452Issue #1797438. HTML5 validation is preventing form submit and not fully...,!789Issue #3210310: Adjust Database API to remove deprecated Drupal 9 code in Drupal 10
...@@ -334,15 +334,10 @@ function menu_execute_active_handler() { ...@@ -334,15 +334,10 @@ function menu_execute_active_handler() {
// Determine the menu item containing the callback. // Determine the menu item containing the callback.
$path = $_GET['q']; $path = $_GET['q'];
while ($path && (!array_key_exists($path, $menu['path index']) || empty($menu['items'][$menu['path index'][$path]]['callback']))) { while ($path && !isset($menu['callbacks'][$path])) {
$path = substr($path, 0, strrpos($path, '/')); $path = substr($path, 0, strrpos($path, '/'));
} }
if (!array_key_exists($path, $menu['path index'])) { if (!isset($menu['callbacks'][$path])) {
return MENU_NOT_FOUND;
}
$mid = $menu['path index'][$path];
if (empty($menu['items'][$mid]['callback'])) {
return MENU_NOT_FOUND; return MENU_NOT_FOUND;
} }
...@@ -351,13 +346,13 @@ function menu_execute_active_handler() { ...@@ -351,13 +346,13 @@ function menu_execute_active_handler() {
} }
// We found one, and are allowed to execute it. // We found one, and are allowed to execute it.
$arguments = array_key_exists('callback arguments', $menu['items'][$mid]) ? $menu['items'][$mid]['callback arguments'] : array(); $arguments = isset($menu['callbacks'][$path]['callback arguments']) ? $menu['callbacks'][$path]['callback arguments'] : array();
$arg = substr($_GET['q'], strlen($menu['items'][$mid]['path']) + 1); $arg = substr($_GET['q'], strlen($path) + 1);
if (strlen($arg)) { if (strlen($arg)) {
$arguments = array_merge($arguments, explode('/', $arg)); $arguments = array_merge($arguments, explode('/', $arg));
} }
return function_exists($menu['items'][$mid]['callback']) ? call_user_func_array($menu['items'][$mid]['callback'], $arguments) : ''; return function_exists($menu['callbacks'][$path]['callback']) ? call_user_func_array($menu['callbacks'][$path]['callback'], $arguments) : '';
} }
/** /**
...@@ -382,16 +377,16 @@ function menu_set_active_item($path = NULL) { ...@@ -382,16 +377,16 @@ function menu_set_active_item($path = NULL) {
$_GET['q'] = $path; $_GET['q'] = $path;
} }
while ($path && !array_key_exists($path, $menu['path index'])) { while ($path && !isset($menu['path index'][$path])) {
$path = substr($path, 0, strrpos($path, '/')); $path = substr($path, 0, strrpos($path, '/'));
} }
$stored_mid = array_key_exists($path, $menu['path index']) ? $menu['path index'][$path] : 0; $stored_mid = isset($menu['path index'][$path]) ? $menu['path index'][$path] : 0;
// Search for default local tasks to activate instead of this item. // Search for default local tasks to activate instead of this item.
$continue = TRUE; $continue = TRUE;
while ($continue) { while ($continue) {
$continue = FALSE; $continue = FALSE;
if (array_key_exists('children', $menu['items'][$stored_mid])) { if (isset($menu['items'][$stored_mid]['children'])) {
foreach ($menu['items'][$stored_mid]['children'] as $cid) { foreach ($menu['items'][$stored_mid]['children'] as $cid) {
if ($menu['items'][$cid]['type'] & MENU_LINKS_TO_PARENT) { if ($menu['items'][$cid]['type'] & MENU_LINKS_TO_PARENT) {
$stored_mid = $cid; $stored_mid = $cid;
...@@ -554,7 +549,7 @@ function menu_rebuild() { ...@@ -554,7 +549,7 @@ function menu_rebuild() {
} }
} }
$new_items[$mid] = array('mid' => $new_mid, 'pid' => $new_pid, 'path' => $item['path'], 'title' => $item['title'], 'description' => array_key_exists('description', $item) ? $item['description'] : '', 'weight' => $item['weight'], 'type' => $item['type']); $new_items[$mid] = array('mid' => $new_mid, 'pid' => $new_pid, 'path' => $item['path'], 'title' => $item['title'], 'description' => isset($item['description']) ? $item['description'] : '', 'weight' => $item['weight'], 'type' => $item['type']);
} }
} }
...@@ -629,7 +624,7 @@ function theme_menu_item($mid, $children = '', $leaf = TRUE) { ...@@ -629,7 +624,7 @@ function theme_menu_item($mid, $children = '', $leaf = TRUE) {
* @ingroup themeable * @ingroup themeable
*/ */
function theme_menu_item_link($item, $link_item) { function theme_menu_item_link($item, $link_item) {
return l($item['title'], $link_item['path'], array_key_exists('description', $item) ? array('title' => $item['description']) : array()); return l($item['title'], $link_item['path'], isset($item['description']) ? array('title' => $item['description']) : array());
} }
/** /**
...@@ -773,7 +768,7 @@ function menu_primary_links($start_level = 1, $pid = 0) { ...@@ -773,7 +768,7 @@ function menu_primary_links($start_level = 1, $pid = 0) {
} }
$menu = menu_get_menu(); $menu = menu_get_menu();
if ($pid && is_array($menu['visible'][$pid]) && array_key_exists('children', $menu['visible'][$pid])) { if ($pid && is_array($menu['visible'][$pid]) && isset($menu['visible'][$pid]['children'])) {
$count = 1; $count = 1;
foreach ($menu['visible'][$pid]['children'] as $cid) { foreach ($menu['visible'][$pid]['children'] as $cid) {
$index = "$start_level-$count"; $index = "$start_level-$count";
...@@ -891,7 +886,7 @@ function _menu_get_active_trail_in_submenu($pid) { ...@@ -891,7 +886,7 @@ function _menu_get_active_trail_in_submenu($pid) {
$count = 0; $count = 0;
while ($path && !$count) { while ($path && !$count) {
foreach ($menu['items'] as $key => $item) { foreach ($menu['items'] as $key => $item) {
if (array_key_exists('path', $item) && $item['path'] == $path) { if (isset($item['path']) && $item['path'] == $path) {
$trails[$count] = array(); $trails[$count] = array();
$mid = $key; $mid = $key;
while ($mid && $menu['items'][$mid]) { while ($mid && $menu['items'][$mid]) {
...@@ -961,6 +956,7 @@ function _menu_build() { ...@@ -961,6 +956,7 @@ function _menu_build() {
0 => array('path' => '', 'title' => '', 'type' => MENU_IS_ROOT), 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) 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. // Build a sequential list of all menu items.
$menu_item_list = module_invoke_all('menu', TRUE); $menu_item_list = module_invoke_all('menu', TRUE);
...@@ -969,20 +965,28 @@ function _menu_build() { ...@@ -969,20 +965,28 @@ function _menu_build() {
$temp_mid = -1; $temp_mid = -1;
foreach ($menu_item_list as $item) { foreach ($menu_item_list as $item) {
if (!array_key_exists('path', $item)) { if (!isset($item['path'])) {
$item['path'] = ''; $item['path'] = '';
} }
if (!array_key_exists('type', $item)) { if (!isset($item['type'])) {
$item['type'] = MENU_NORMAL_ITEM; $item['type'] = MENU_NORMAL_ITEM;
} }
if (!array_key_exists('weight', $item)) { if (!isset($item['weight'])) {
$item['weight'] = 0; $item['weight'] = 0;
} }
$mid = $temp_mid; $mid = $temp_mid;
if (array_key_exists($item['path'], $_menu['path index'])) { if (isset($_menu['path index'][$item['path']])) {
// Newer menu items overwrite older ones. // Newer menu items overwrite older ones.
unset($_menu['items'][$_menu['path index'][$item['path']]]); 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']);
unset($item['callback arguments']);
$_menu['items'][$mid] = $item; $_menu['items'][$mid] = $item;
$_menu['path index'][$item['path']] = $mid; $_menu['path index'][$item['path']] = $mid;
...@@ -995,7 +999,7 @@ function _menu_build() { ...@@ -995,7 +999,7 @@ function _menu_build() {
while ($item = db_fetch_object($result)) { while ($item = db_fetch_object($result)) {
// Handle URL aliases if entered in menu administration. // Handle URL aliases if entered in menu administration.
$item->path = drupal_get_normal_path($item->path); $item->path = drupal_get_normal_path($item->path);
if (array_key_exists($item->path, $_menu['path index'])) { if (isset($_menu['path index'][$item->path])) {
// The path is already declared. // The path is already declared.
$old_mid = $_menu['path index'][$item->path]; $old_mid = $_menu['path index'][$item->path];
if ($old_mid < 0) { if ($old_mid < 0) {
...@@ -1007,7 +1011,7 @@ function _menu_build() { ...@@ -1007,7 +1011,7 @@ function _menu_build() {
else { else {
// It has a permanent ID. Only replace with non-custom menu items. // It has a permanent ID. Only replace with non-custom menu items.
if ($item->type & MENU_CREATED_BY_ADMIN) { if ($item->type & MENU_CREATED_BY_ADMIN) {
$_menu['items'][$item->mid] = array('path' => $item->path, 'access' => TRUE, 'callback' => ''); $_menu['items'][$item->mid] = array('path' => $item->path, 'access' => TRUE);
} }
else { else {
// Leave the old item around as a shortcut to this one. // Leave the old item around as a shortcut to this one.
...@@ -1019,7 +1023,7 @@ function _menu_build() { ...@@ -1019,7 +1023,7 @@ function _menu_build() {
else { else {
// The path was not declared, so this is a custom item or an orphaned one. // The path was not declared, so this is a custom item or an orphaned one.
if ($item->type & MENU_CREATED_BY_ADMIN) { if ($item->type & MENU_CREATED_BY_ADMIN) {
$_menu['items'][$item->mid] = array('path' => $item->path, 'access' => TRUE, 'callback' => ''); $_menu['items'][$item->mid] = array('path' => $item->path, 'access' => TRUE);
if (!empty($item->path)) { if (!empty($item->path)) {
$_menu['path index'][$item->path] = $item->mid; $_menu['path index'][$item->path] = $item->mid;
} }
...@@ -1055,7 +1059,7 @@ function _menu_item_is_accessible($mid) { ...@@ -1055,7 +1059,7 @@ function _menu_item_is_accessible($mid) {
// Follow the path up to find the first "access" attribute. // Follow the path up to find the first "access" attribute.
$path = $menu['items'][$mid]['path']; $path = $menu['items'][$mid]['path'];
while ($path && (!array_key_exists($path, $menu['path index']) || !array_key_exists('access', $menu['items'][$menu['path index'][$path]]))) { while ($path && (!isset($menu['path index'][$path]) || !isset($menu['items'][$menu['path index'][$path]]['access']))) {
$path = substr($path, 0, strrpos($path, '/')); $path = substr($path, 0, strrpos($path, '/'));
} }
if (empty($path)) { if (empty($path)) {
...@@ -1077,7 +1081,7 @@ function _menu_build_visible_tree($pid = 0) { ...@@ -1077,7 +1081,7 @@ function _menu_build_visible_tree($pid = 0) {
$parent = $_menu['items'][$pid]; $parent = $_menu['items'][$pid];
$children = array(); $children = array();
if (array_key_exists('children', $parent)) { if (isset($parent['children'])) {
usort($parent['children'], '_menu_sort'); usort($parent['children'], '_menu_sort');
foreach ($parent['children'] as $mid) { foreach ($parent['children'] as $mid) {
$children = array_merge($children, _menu_build_visible_tree($mid)); $children = array_merge($children, _menu_build_visible_tree($mid));
...@@ -1121,24 +1125,22 @@ function _menu_append_contextual_items() { ...@@ -1121,24 +1125,22 @@ function _menu_append_contextual_items() {
$new_items = array(); $new_items = array();
foreach ($menu_item_list as $item) { foreach ($menu_item_list as $item) {
if (array_key_exists($item['path'], $_menu['path index'])) { if (isset($item['callback'])) {
// The menu item already exists, so just add appropriate callback information. $_menu['callbacks'][$item['path']] = array('callback' => $item['callback']);
$mid = $_menu['path index'][$item['path']];
$_menu['items'][$mid]['access'] = $item['access'];
$_menu['items'][$mid]['callback'] = $item['callback'];
if (isset($item['callback arguments'])) { if (isset($item['callback arguments'])) {
$_menu['items'][$mid]['callback arguments'] = $item['callback arguments']; $_menu['callbacks'][$item['path']]['callback arguments'] = $item['callback arguments'];
} }
} }
else { unset($item['callback']);
if (!array_key_exists('path', $item)) { unset($item['callback arguments']);
if (!isset($_menu['path index'][$item['path']])) {
if (!isset($item['path'])) {
$item['path'] = ''; $item['path'] = '';
} }
if (!array_key_exists('type', $item)) { if (!isset($item['type'])) {
$item['type'] = MENU_NORMAL_ITEM; $item['type'] = MENU_NORMAL_ITEM;
} }
if (!array_key_exists('weight', $item)) { if (!isset($item['weight'])) {
$item['weight'] = 0; $item['weight'] = 0;
} }
$_menu['items'][$temp_mid] = $item; $_menu['items'][$temp_mid] = $item;
...@@ -1156,7 +1158,7 @@ function _menu_append_contextual_items() { ...@@ -1156,7 +1158,7 @@ function _menu_append_contextual_items() {
$item = $_menu['items'][$mid]; $item = $_menu['items'][$mid];
if (($item['type'] & MENU_VISIBLE_IN_TREE) && _menu_item_is_accessible($mid)) { if (($item['type'] & MENU_VISIBLE_IN_TREE) && _menu_item_is_accessible($mid)) {
$pid = $item['pid']; $pid = $item['pid'];
while ($pid && !array_key_exists($pid, $_menu['visible'])) { while ($pid && !isset($_menu['visible'][$pid])) {
$pid = $_menu['items'][$pid]['pid']; $pid = $_menu['items'][$pid]['pid'];
} }
$_menu['visible'][$mid] = array('title' => $item['title'], 'path' => $item['path'], 'pid' => $pid); $_menu['visible'][$mid] = array('title' => $item['title'], 'path' => $item['path'], 'pid' => $pid);
...@@ -1180,7 +1182,7 @@ function _menu_find_parents(&$items) { ...@@ -1180,7 +1182,7 @@ function _menu_find_parents(&$items) {
do { do {
$parent = substr($parent, 0, strrpos($parent, '/')); $parent = substr($parent, 0, strrpos($parent, '/'));
} }
while ($parent && !array_key_exists($parent, $_menu['path index'])); while ($parent && !isset($_menu['path index'][$parent]));
} }
$pid = $parent ? $_menu['path index'][$parent] : 1; $pid = $parent ? $_menu['path index'][$parent] : 1;
...@@ -1226,7 +1228,7 @@ function _menu_build_local_tasks($pid) { ...@@ -1226,7 +1228,7 @@ function _menu_build_local_tasks($pid) {
$parent = $_menu['items'][$pid]; $parent = $_menu['items'][$pid];
$children = array(); $children = array();
if (array_key_exists('children', $parent)) { if (isset($parent['children'])) {
foreach ($parent['children'] as $mid) { foreach ($parent['children'] as $mid) {
if (($_menu['items'][$mid]['type'] & MENU_IS_LOCAL_TASK) && _menu_item_is_accessible($mid)) { if (($_menu['items'][$mid]['type'] & MENU_IS_LOCAL_TASK) && _menu_item_is_accessible($mid)) {
$children[] = $mid; $children[] = $mid;
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment