Commit 03752e35 authored by Dries's avatar Dries

- Patch #34755 by chx et al: faster menu system. HEAD is temporary broken and...

- Patch #34755 by chx et al: faster menu system.  HEAD is temporary broken and there is no upgrade path yet.
parent d407de4c
......@@ -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();
......
......@@ -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;
}
......@@ -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';
......
This diff is collapsed.
......@@ -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);
}
}
......
......@@ -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];
}
}
......
......@@ -533,6 +533,7 @@ function install_complete($profile) {
// Bootstrap newly installed Drupal, while preserving existing messages.
$messages = $_SESSION['messages'];
drupal_bootstrap(DRUPAL_BOOTSTRAP_FULL);
menu_rebuild();
$_SESSION['messages'] = $messages;
// Build final page.
......
This diff is collapsed.
......@@ -58,48 +58,43 @@ function block_perm() {
/**
* Implementation of hook_menu().
*/
function block_menu($may_cache) {
$items = array();
if ($may_cache) {
$items[] = array(
'path' => 'admin/build/block',
'title' => t('Blocks'),
'access' => user_access('administer blocks'),
'description' => t('Configure what block content appears in your site\'s sidebars and other regions.'),
'callback' => 'drupal_get_form',
'callback arguments' => array('block_admin_display'));
$items[] = array('path' => 'admin/build/block/list', 'title' => t('List'),
'type' => MENU_DEFAULT_LOCAL_TASK, 'weight' => -10);
$items[] = array('path' => 'admin/build/block/configure', 'title' => t('Configure block'),
'access' => user_access('administer blocks'),
'callback' => 'drupal_get_form',
'callback arguments' => array('block_admin_configure'),
'type' => MENU_CALLBACK);
$items[] = array('path' => 'admin/build/block/delete', 'title' => t('Delete block'),
'access' => user_access('administer blocks'),
'callback' => 'drupal_get_form',
'callback arguments' => array('block_box_delete'),
'type' => MENU_CALLBACK);
$items[] = array('path' => 'admin/build/block/add', 'title' => t('Add block'),
'access' => user_access('administer blocks'),
'callback' => 'drupal_get_form',
'callback arguments' => array('block_add_block_form'),
'type' => MENU_LOCAL_TASK);
$default = variable_get('theme_default', 'garland');
foreach (list_themes() as $key => $theme) {
$items[] = array(
'path' => 'admin/build/block/list/'. $key,
'title' => t('!key settings', array('!key' => $key)),
'callback' => 'drupal_get_form',
'callback arguments' => array('block_admin_display', $key),
'access' => user_access('administer blocks'),
'type' => $key == $default ? MENU_DEFAULT_LOCAL_TASK : MENU_LOCAL_TASK,
'weight' => $key == $default ? -10 : 0,
);
}
function block_menu() {
$items['admin/build/block'] = array(
'title' => t('Blocks'),
'description' => t('Configure what block content appears in your site\'s sidebars and other regions.'),
'page callback' => 'drupal_get_form',
'page arguments' => array('block_admin_display'),
'access arguments' => array('administer blocks'),
);
$items['admin/build/block/list'] = array(
'title' => t('List'),
'type' => MENU_DEFAULT_LOCAL_TASK,
'weight' => -10,
);
$items['admin/build/block/configure'] = array(
'title' => t('Configure block'),
'page arguments' => array('block_admin_configure'),
'type' => MENU_CALLBACK,
);
$items['admin/build/block/delete'] = array(
'title' => t('Delete block'),
'page arguments' => array('block_box_delete'),
'type' => MENU_CALLBACK,
);
$items['admin/build/block/add'] = array(
'title' => t('Add block'),
'page arguments' => array('block_add_block_form'),
'type' => MENU_LOCAL_TASK,
);
$default = variable_get('theme_default', 'garland');
foreach (list_themes() as $key => $theme) {
$items['admin/build/block/list/'. $key] = array(
'title' => t('!key settings', array('!key' => $key)),
'page arguments' => array('block_admin_display', $key),
'type' => $key== $default ? MENU_DEFAULT_LOCAL_TASK : MENU_LOCAL_TASK,
'weight' => $key == $default ? -10 : 0,
);
}
return $items;
}
......
......@@ -249,19 +249,18 @@ function blog_link($type, $node = NULL, $teaser = FALSE) {
/**
* Implementation of hook_menu().
*/
function blog_menu($may_cache) {
global $user;
$items = array();
if ($may_cache) {
$items[] = array('path' => 'blog', 'title' => t('Blogs'),
'callback' => 'blog_page',
'access' => user_access('access content'),
'type' => MENU_SUGGESTED_ITEM);
$items[] = array('path' => 'blog/'. $user->uid, 'title' => t('My blog'),
'access' => user_access('edit own blog'),
'type' => MENU_DYNAMIC_ITEM);
}
function blog_menu() {
$items['blog'] = array(
'title' => t('Blogs'),
'page callback' => 'blog_page',
'access arguments' => array('access content'),
'type' => MENU_SUGGESTED_ITEM,
);
$items['blog/%'] = array(
'title' => t('My blog'),
'page arguments' => array(1),
'access arguments' => array('edit own blog'),
);
return $items;
}
......
......@@ -551,46 +551,32 @@ function blogapi_admin_settings() {
return system_settings_form($form);
}
function blogapi_menu($may_cache) {
$items = array();
function blogapi_menu() {
$items['blogapi/rsd'] = array(
'title' => t('RSD'),
'page callback' => 'blogapi_rsd',
'access arguments' => array('access content'),
'type' => MENU_CALLBACK,
);
$items['admin/settings/blogapi'] = array(
'title' => t('Blog APIs'),
'description' => t('Configure which content types and engines external blog clients can use.'),
'page callback' => 'drupal_get_form',
'page arguments' => array('blogapi_admin_settings'),
'access arguments' => array('administer site configuration'),
'type' => MENU_NORMAL_ITEM,
);
return $items;
}
function blogapi_init() {
if (drupal_is_front_page()) {
drupal_add_link(array('rel' => 'EditURI',
'type' => 'application/rsd+xml',
'title' => t('RSD'),
'href' => url('blogapi/rsd', NULL, NULL, TRUE)));
}
if ($may_cache) {
$items[] = array(
'path' => 'blogapi',
'title' => t('RSD'),
'callback' => 'blogapi_blogapi',
'access' => user_access('access content'),
'type' => MENU_CALLBACK);
$items[] = array(
'path' => 'admin/settings/blogapi',
'title' => t('Blog APIs'),
'description' => t('Configure which content types and engines external blog clients can use.'),
'callback' => 'drupal_get_form',
'callback arguments' => array('blogapi_admin_settings'),
'access' => user_access('administer site configuration'),
'type' => MENU_NORMAL_ITEM
);
}
return $items;
}
function blogapi_blogapi() {
switch (arg(1)) {
case 'rsd':
blogapi_rsd();
break;
default:
drupal_not_found();
break;
}
}
function blogapi_rsd() {
......
......@@ -85,65 +85,58 @@ function book_link($type, $node = NULL, $teaser = FALSE) {
/**
* Implementation of hook_menu().
*/
function book_menu($may_cache) {
$items = array();
if ($may_cache) {
$items[] = array(
'path' => 'admin/content/book',
'title' => t('Books'),
'description' => t("Manage site's books and orphaned book pages."),
'callback' => 'book_admin',
'access' => user_access('administer nodes'));
$items[] = array(
'path' => 'admin/content/book/list',
'title' => t('List'),
'type' => MENU_DEFAULT_LOCAL_TASK);
$items[] = array(
'path' => 'admin/content/book/orphan',
'title' => t('Orphan pages'),
'callback' => 'drupal_get_form',
'callback arguments' => array('book_admin_orphan'),
'type' => MENU_LOCAL_TASK,
'weight' => 8);
$items[] = array(
'path' => 'book',
'title' => t('Books'),
'callback' => 'book_render',
'access' => user_access('access content'),
'type' => MENU_SUGGESTED_ITEM);
$items[] = array(
'path' => 'book/export',
'callback' => 'book_export',
'access' => user_access('access content'),
'type' => MENU_CALLBACK);
}
else {
// Add the CSS for this module
// We put this in !$may_cache so it's only added once per request
drupal_add_css(drupal_get_path('module', 'book') .'/book.css');
// To avoid SQL overhead, check whether we are on a node page and whether the
// user is allowed to outline posts in books.
if (arg(0) == 'node' && is_numeric(arg(1)) && user_access('outline posts in books')) {
// Only add the outline-tab for non-book pages:
$result = db_query(db_rewrite_sql("SELECT n.nid FROM {node} n WHERE n.nid = %d AND n.type != 'book'"), arg(1));
if (db_num_rows($result) > 0) {
$items[] = array(
'path' => 'node/'. arg(1) .'/outline',
'title' => t('Outline'),
'callback' => 'drupal_get_form',
'callback arguments' => array('book_outline', arg(1)),
'access' => user_access('outline posts in books'),
'type' => MENU_LOCAL_TASK,
'weight' => 2);
}
}
}
function book_menu() {
$items['admin/content/book'] = array(
'title' => t('Books'),
'description' => t("Manage site's books and orphaned book pages."),
'page callback' => 'book_admin',
'access arguments' => array('administer nodes'),
);
$items['admin/content/book/list'] = array(
'title' => t('List'),
'type' => MENU_DEFAULT_LOCAL_TASK,
);
$items['admin/content/book/orphan'] = array(
'title' => t('Orphan pages'),
'page callback' => 'drupal_get_form',
'page arguments' => array('book_admin_orphan'),
'type' => MENU_LOCAL_TASK,
'weight' => 8,
);
$items['book'] = array(
'title' => t('Books'),
'page callback' => 'book_render',
'access arguments' => array('access content'),
'type' => MENU_SUGGESTED_ITEM,
);
$items['book/export/%/%'] = array(
'page callback' => 'book_export',
'page arguments' => array(2, 3),
'type' => MENU_CALLBACK,
);
$items['node/%/outline'] = array(
'title' => t('Outline'),
'page callback' => 'drupal_get_form',
'page arguments' => array('book_outline', 1),
'access callback' => '_book_outline_access',
'access arguments' => array(1),
'map arguments' => array('node_load', 1),
'type' => MENU_LOCAL_TASK,
'weight' => 2,
);
return $items;
}
function _book_outline_access($node) {
// Only add the outline-tab for non-book pages:
return user_access('outline posts in books') && $node && ($node->type != 'book');
}
function book_init() {
drupal_add_css(drupal_get_path('module', 'book') .'/book.css');
}
/**
* Implementation of hook_block().
*
......@@ -256,9 +249,7 @@ function book_form(&$node) {
* Implementation of function book_outline()
* Handles all book outline operations.
*/
function book_outline($nid) {
$node = node_load($nid);
function book_outline($node) {
$form['parent'] = array('#type' => 'select',
'#title' => t('Parent'),
'#default_value' => $node->parent,
......@@ -637,7 +628,7 @@ function book_render() {
* - an integer representing the node id (nid) of the node to export
*
*/
function book_export($type = 'html', $nid = 0) {
function book_export($type, $nid) {
$type = drupal_strtolower($type);
$node_result = db_query(db_rewrite_sql('SELECT n.nid, n.title, b.parent FROM {node} n INNER JOIN {book} b ON n.vid = b.vid WHERE n.nid = %d'), $nid);
if (db_num_rows($node_result) > 0) {
......
......@@ -140,70 +140,77 @@ function comment_help($section) {
}
}
function _comment_view_access($node, $cid) {
return $node && $cid;
}
/**
* Implementation of hook_menu().
*/
function comment_menu($may_cache) {
$items = array();
function comment_menu() {
$items['admin/content/comment'] = array(
'title' => t('Comments'),
'description' => t('List and edit site comments and the comment moderation queue.'),
'page callback' => 'comment_admin',
'access arguments' => array('administer comments'),
);
if ($may_cache) {
$access = user_access('administer comments');
$items[] = array(
'path' => 'admin/content/comment',
'title' => t('Comments'),
'description' => t('List and edit site comments and the comment moderation queue.'),
'callback' => 'comment_admin',
'access' => $access
);
// Tabs:
$items['admin/content/comment/list'] = array(
'title' => t('List'),
'type' => MENU_DEFAULT_LOCAL_TASK,
'weight' => -10,
);
// Tabs:
$items[] = array('path' => 'admin/content/comment/list', 'title' => t('List'),
'type' => MENU_DEFAULT_LOCAL_TASK, 'weight' => -10);
// Subtabs:
$items[] = array('path' => 'admin/content/comment/list/new', 'title' => t('Published comments'),
'type' => MENU_DEFAULT_LOCAL_TASK, 'weight' => -10);
$items[] = array('path' => 'admin/content/comment/list/approval', 'title' => t('Approval queue'),
'callback' => 'comment_admin',
'callback arguments' => array('approval'),
'access' => $access,
'type' => MENU_LOCAL_TASK);
$items[] = array(
'path' => 'admin/content/comment/settings',
'title' => t('Settings'),
'callback' => 'drupal_get_form',
'callback arguments' => array('comment_admin_settings'),
'access' => $access,
'weight' => 10,
'type' => MENU_LOCAL_TASK);
$items[] = array('path' => 'comment/delete', 'title' => t('Delete comment'),
'callback' => 'comment_delete', 'access' => $access, 'type' => MENU_CALLBACK);
$access = user_access('post comments');
$items[] = array('path' => 'comment/edit', 'title' => t('Edit comment'),
'callback' => 'comment_edit',
'access' => $access, 'type' => MENU_CALLBACK);
}
else {
if (arg(0) == 'comment' && arg(1) == 'reply' && is_numeric(arg(2))) {
$node = node_load(arg(2));
if ($node->nid) {
$items[] = array('path' => 'comment/reply', 'title' => t('Reply to comment'),
'callback' => 'comment_reply', 'access' => node_access('view', $node), 'type' => MENU_CALLBACK);
}
}
if ((arg(0) == 'node') && is_numeric(arg(1)) && is_numeric(arg(2))) {
$items[] = array(
'path' => ('node/'. arg(1) .'/'. arg(2)),
'title' => t('View'),
'callback' => 'node_page_view',
'callback arguments' => array(node_load(arg(1)), arg(2)),
'type' => MENU_CALLBACK,
);
}
}
// Subtabs:
$items['admin/content/comment/list/new'] = array(
'title' => t('Published comments'),
'type' => MENU_DEFAULT_LOCAL_TASK,
'weight' => -10,
);
$items['admin/content/comment/list/approval'] = array(
'title' => t('Approval queue'),
'page arguments' => array('approval'),
'type' => MENU_LOCAL_TASK,
);
$items['admin/content/comment/settings'] = array(
'title' => t('Settings'),
'page callback' => 'drupal_get_form',
'page arguments' => array('comment_admin_settings'),
'weight' => 10,
'type' => MENU_LOCAL_TASK,
);
$items['comment/delete'] = array(
'title' => t('Delete comment'),
'page callback' => 'comment_delete',
'access arguments' => array('administer comments'),
'type' => MENU_CALLBACK,
);
$items['comment/edit'] = array(
'title' => t('Edit comment'),
'page callback' => 'comment_edit',
'access arguments' => array('post comments'),
'type' => MENU_CALLBACK,
);
$items['comment/reply'] = array(
'title' => t('Reply to comment'),
'page callback' => 'comment_reply',
'access callback' => 'node_access',
'access arguments' => array('view', 2),
'map arguments' => array('node_load', 2),
'type' => MENU_CALLBACK,
);
$items['node/%/%'] = array(
'title' => t('View'),
'page callback' => 'node_page_view',
'page arguments' => array(1, 2),
'access callback' => '_comment_view_access',
'access arguments' => array(1, 2),
'type' => MENU_CALLBACK,
);
return $items;
}
......@@ -1980,25 +1987,6 @@ function comment_invoke_comment(&$comment, $op) {
return $return;
}
/**
* 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;
}
/**
* Decode vancode back to an integer.
*/
......
......@@ -40,77 +40,68 @@ function contact_perm() {
/**
* Implementation of hook_menu().
*/
function contact_menu($may_cache) {
$items = array();
if ($may_cache) {
$items[] = array('path' => 'admin/build/contact',
'title' => t('Contact form'),
'description' => t('Create a system contact form and set up categories for the form to use.'),
'callback' => 'contact_admin_categories',
'access' => user_access('administer site configuration'),
);
$items[] = array('path' => 'admin/build/contact/list',
'title' => t('List'),
'callback' => 'contact_admin_categories',
'access' => user_access('administer site configuration'),
'type' => MENU_DEFAULT_LOCAL_TASK,
);
$items[] = array('path' => 'admin/build/contact/add',
'title' => t('Add category'),
'callback' => 'drupal_get_form',
'callback arguments' => array('contact_admin_edit'),
'access' => user_access('administer site configuration'),
'type' => MENU_LOCAL_TASK,
'weight' => 1,
);
$items[] = array('path' => 'admin/build/contact/edit',
'title' => t('Edit contact category'),
'callback' => 'drupal_get_form',
'callback arguments' => array('contact_admin_edit'),
'access' => user_access('administer site configuration'),
'type' => MENU_CALLBACK,
);
$items[] = array('path' => 'admin/build/contact/delete',
'title' => t('Delete contact'),
'callback' => 'drupal_get_form',
'callback arguments' => array('contact_admin_delete'),
'access' => user_access('administer site configuration'),
'type' => MENU_CALLBACK,
);
$items[] = array('path' => 'admin/build/contact/settings',
'title' => t('Settings'),
'callback' => 'drupal_get_form',
'callback arguments' => array('contact_admin_settings'),
'access' => user_access('administer site configuration'),
'type' => MENU_LOCAL_TASK,
'weight' => 2,
);
$items[] = array('path' => 'contact',
'title' => t('Contact'),
'callback' => 'contact_site_page',
'access' => user_access('access site-wide contact form'),
'type' => MENU_SUGGESTED_ITEM,
);
}
else {
if (arg(0) == 'user' && is_numeric(arg(1))) {
global $user;
$account = user_load(array('uid' => arg(1)));
if (($user->uid != $account->uid && $account->contact) || user_access('administer users')) {
$items[] = array('path' => 'user/'. arg(1) .'/contact',
'title' => t('Contact'),
'callback' => 'contact_user_page',
'type' => MENU_LOCAL_TASK,
'access' => $user->uid,
'weight' => 2,
);
}
}
}
function contact_menu() {
$items['admin/build/contact'] = array(
'title' => t('Contact form'),
'description' => t('Create a system contact form and set up categories for the form to use.'),
'page callback' => 'contact_admin_categories',
'access arguments' => array('administer site configuration'),
);
$items['admin/build/contact/list'] = array(
'title' => t('List'),
'page callback' => 'contact_admin_categories',
'type' => MENU_DEFAULT_LOCAL_TASK,
);
$items['admin/build/contact/add'] = array(
'title' => t('Add category'),
'page callback' => 'drupal_get_form',
'page arguments' => array('contact_admin_edit'),
'type' => MENU_LOCAL_TASK,
'weight' => 1,
);
$items['admin/build/contact/edit'] = array(
'title' => t('Edit contact category'),
'page callback' => 'drupal_get_form',
'page arguments' => array('contact_admin_edit'),
'type' => MENU_CALLBACK,
);
$items['admin/build/contact/delete'] = array(
'title' => t('Delete contact'),
'page callback' => 'drupal_get_form',
'page arguments' => array('contact_admin_delete'),
'type' => MENU_CALLBACK,
);
$items['admin/build/contact/settings'] = array(
'title' => t('Settings'),
'page callback' => 'drupal_get_form',
'page arguments' => array('contact_admin_settings'),
'type' => MENU_LOCAL_TASK,
'weight' => 2,
);
$items['contact'] = array(
'title' => t('Contact'),
'page callback' => 'contact_site_page',
'access arguments' => array('access site-wide contact form'),
'type' => MENU_SUGGESTED_ITEM,
);
$items['user/%/contact'] = array(
'title' => t('Contact'),
'page callback' => 'contact_user_page',
'page arguments' => array(1),
'type' => MENU_LOCAL_TASK,
'access callback' => '_contact_user_tab_access',
'access arguments' => array(1),