- Patch #638070 by carlos8f, Gábor Hojtsy, ksenzee, pwolanin, chx, catch: router loaders causing a lot of database hits for access checks.

merge-requests/26/head
Dries Buytaert 2010-01-14 13:45:33 +00:00
parent fafabc7e2a
commit a417a986ea
3 changed files with 96 additions and 27 deletions

View File

@ -2225,6 +2225,7 @@ function menu_reset_static_cache() {
drupal_static_reset('menu_tree'); drupal_static_reset('menu_tree');
drupal_static_reset('menu_tree_all_data'); drupal_static_reset('menu_tree_all_data');
drupal_static_reset('menu_tree_page_data'); drupal_static_reset('menu_tree_page_data');
drupal_static_reset('menu_load_all');
} }
/** /**

View File

@ -213,9 +213,32 @@ function menu_overview_title($menu) {
* *
* @param $menu_name * @param $menu_name
* The unique name of a custom menu to load. * The unique name of a custom menu to load.
* @return
* Array defining the custom menu, or FALSE if the menu doesn't exist.
*/ */
function menu_load($menu_name) { function menu_load($menu_name) {
return db_query("SELECT * FROM {menu_custom} WHERE menu_name = :menu", array(':menu' => $menu_name))->fetchAssoc(); $all_menus = menu_load_all();
return isset($all_menus[$menu_name]) ? $all_menus[$menu_name] : FALSE;
}
/**
* Load all custom menu data.
*
* @return
* Array of custom menu data.
*/
function menu_load_all() {
$custom_menus = &drupal_static(__FUNCTION__);
if (!isset($custom_menus)) {
if ($cached = cache_get('menu_custom', 'cache_menu')) {
$custom_menus = $cached->data;
}
else {
$custom_menus = db_query('SELECT * FROM {menu_custom}')->fetchAllAssoc('menu_name', PDO::FETCH_ASSOC);
cache_set('menu_custom', $custom_menus, 'cache_menu');
}
}
return $custom_menus;
} }
/** /**
@ -242,6 +265,7 @@ function menu_save($menu) {
'description' => $menu['description'], 'description' => $menu['description'],
)) ))
->execute(); ->execute();
menu_cache_clear_all();
// Since custom menus are keyed by name and their machine-name cannot be // Since custom menus are keyed by name and their machine-name cannot be
// changed, there is no real differentiation between inserting and updating a // changed, there is no real differentiation between inserting and updating a
@ -290,6 +314,7 @@ function menu_delete($menu) {
->condition('menu_name', $menu['menu_name']) ->condition('menu_name', $menu['menu_name'])
->execute(); ->execute();
menu_cache_clear_all();
module_invoke_all('menu_delete', $menu); module_invoke_all('menu_delete', $menu);
} }
@ -710,16 +735,14 @@ function menu_form_node_type_form_alter(&$form, $form_state) {
* titles as the values. * titles as the values.
*/ */
function menu_get_menus($all = TRUE) { function menu_get_menus($all = TRUE) {
$system_menus = array_keys(menu_list_system_menus()); if ($custom_menus = menu_load_all()) {
$query = db_select('menu_custom'); if (!$all) {
$query->addTag('translatable'); $custom_menus = array_diff_key($custom_menus, menu_list_system_menus());
$query->addField('menu_custom', 'menu_name', 'menu_name'); }
$query->addField('menu_custom', 'title', 'title'); foreach ($custom_menus as $menu_name => $menu) {
if (!$all) { $custom_menus[$menu_name] = t($menu['title']);
$query->condition('menu_name', $system_menus, 'NOT IN'); }
asort($custom_menus);
} }
$query->orderBy('title'); return $custom_menus;
return $query->execute()->fetchAllKeyed();
} }

View File

@ -1347,16 +1347,32 @@ function user_register_access() {
return user_is_anonymous() && variable_get('user_register', 1); return user_is_anonymous() && variable_get('user_register', 1);
} }
/**
* User view access callback.
*
* @param $account
* Can either be a full user object or a $uid.
*/
function user_view_access($account) { function user_view_access($account) {
return $account && $account->uid &&
( $uid = is_object($account) ? $account->uid : (int) $account;
// Always let users view their own profile.
($GLOBALS['user']->uid == $account->uid) || // Never allow access to view the anonymous user account.
// Administrators can view all accounts. if ($uid) {
user_access('administer users') || // Admins can view all, users can view own profiles at all times.
// The user is not blocked and logged in at least once. if ($GLOBALS['user']->uid == $uid || user_access('administer users')) {
($account->access && $account->status && user_access('access user profiles')) return TRUE;
); }
elseif (user_access('access user profiles')) {
// At this point, load the complete account object.
if (!is_object($account)) {
$account = user_load($uid);
}
return (is_object($account) && $account->access && $account->status);
}
}
return FALSE;
} }
/** /**
@ -1520,17 +1536,18 @@ function user_menu() {
'weight' => -8, 'weight' => -8,
); );
$items['user/%user_uid_optional'] = array( // Use %user_uid_only_optional here to avoid loading the full user for
// basic access checks.
$items['user/%user_uid_only_optional'] = array(
'title' => 'My account', 'title' => 'My account',
'title callback' => 'user_page_title', 'title callback' => 'user_page_title',
'title arguments' => array(1), 'title arguments' => array(1),
'page callback' => 'user_view', 'page callback' => 'user_view_page',
'page arguments' => array(1), 'page arguments' => array(1),
'access callback' => 'user_view_access', 'access callback' => 'user_view_access',
'access arguments' => array(1), 'access arguments' => array(1),
'weight' => -10, 'weight' => -10,
'menu_name' => 'user-menu', 'menu_name' => 'user-menu',
'file' => 'user.pages.inc',
); );
$items['user/%user/view'] = array( $items['user/%user/view'] = array(
@ -1616,6 +1633,7 @@ function user_init() {
* cannot be loaded. * cannot be loaded.
* *
* @see user_load() * @see user_load()
* @todo rethink the naming of this in Drupal 8.
*/ */
function user_uid_optional_load($uid = NULL) { function user_uid_optional_load($uid = NULL) {
if (!isset($uid)) { if (!isset($uid)) {
@ -1663,7 +1681,9 @@ function user_category_load($uid, &$map, $index) {
} }
/** /**
* Returns the user id of the currently logged in user. * Returns $arg or the user ID of the current user if $arg is '%' or empty.
*
* @todo rethink the naming of this in Drupal 8.
*/ */
function user_uid_optional_to_arg($arg) { function user_uid_optional_to_arg($arg) {
// Give back the current user uid when called from eg. tracker, aka. // Give back the current user uid when called from eg. tracker, aka.
@ -1672,11 +1692,26 @@ function user_uid_optional_to_arg($arg) {
return empty($arg) || $arg == '%' ? $GLOBALS['user']->uid : $arg; return empty($arg) || $arg == '%' ? $GLOBALS['user']->uid : $arg;
} }
/**
* Returns $arg or the user ID of the current user if $arg is '%' or empty.
*
* @todo rethink the naming of this in Drupal 8.
*/
function user_uid_only_optional_to_arg($arg) {
return user_uid_optional_to_arg($arg);
}
/** /**
* Menu item title callback - use the user name. * Menu item title callback - use the user name.
*/ */
function user_page_title($account) { function user_page_title($uid) {
return format_username($account); if ($GLOBALS['user']->uid == $uid) {
$account = $GLOBALS['user'];
}
else {
$account = user_load($uid);
}
return is_object($account) ? format_username($account) : '';
} }
/** /**
@ -2107,6 +2142,16 @@ function _user_cancel($edit, $account, $method) {
cache_clear_all(); cache_clear_all();
} }
/**
* Page callback wrapper for user_view().
*/
function user_view_page($uid) {
// An administrator may try to view a non-existent account,
// so we give them a 404 (versus a 403 for non-admins).
$account = user_load($uid);
return is_object($account) ? user_view($account) : MENU_NOT_FOUND;
}
/** /**
* Generate an array for rendering the given user. * Generate an array for rendering the given user.
* *