- 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_all_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
* 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) {
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'],
))
->execute();
menu_cache_clear_all();
// Since custom menus are keyed by name and their machine-name cannot be
// 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'])
->execute();
menu_cache_clear_all();
module_invoke_all('menu_delete', $menu);
}
@ -710,16 +735,14 @@ function menu_form_node_type_form_alter(&$form, $form_state) {
* titles as the values.
*/
function menu_get_menus($all = TRUE) {
$system_menus = array_keys(menu_list_system_menus());
$query = db_select('menu_custom');
$query->addTag('translatable');
$query->addField('menu_custom', 'menu_name', 'menu_name');
$query->addField('menu_custom', 'title', 'title');
if (!$all) {
$query->condition('menu_name', $system_menus, 'NOT IN');
if ($custom_menus = menu_load_all()) {
if (!$all) {
$custom_menus = array_diff_key($custom_menus, menu_list_system_menus());
}
foreach ($custom_menus as $menu_name => $menu) {
$custom_menus[$menu_name] = t($menu['title']);
}
asort($custom_menus);
}
$query->orderBy('title');
return $query->execute()->fetchAllKeyed();
return $custom_menus;
}

View File

@ -1347,16 +1347,32 @@ function user_register_access() {
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) {
return $account && $account->uid &&
(
// Always let users view their own profile.
($GLOBALS['user']->uid == $account->uid) ||
// Administrators can view all accounts.
user_access('administer users') ||
// The user is not blocked and logged in at least once.
($account->access && $account->status && user_access('access user profiles'))
);
$uid = is_object($account) ? $account->uid : (int) $account;
// Never allow access to view the anonymous user account.
if ($uid) {
// Admins can view all, users can view own profiles at all times.
if ($GLOBALS['user']->uid == $uid || user_access('administer users')) {
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,
);
$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 callback' => 'user_page_title',
'title arguments' => array(1),
'page callback' => 'user_view',
'page callback' => 'user_view_page',
'page arguments' => array(1),
'access callback' => 'user_view_access',
'access arguments' => array(1),
'weight' => -10,
'menu_name' => 'user-menu',
'file' => 'user.pages.inc',
);
$items['user/%user/view'] = array(
@ -1616,6 +1633,7 @@ function user_init() {
* cannot be loaded.
*
* @see user_load()
* @todo rethink the naming of this in Drupal 8.
*/
function user_uid_optional_load($uid = NULL) {
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) {
// 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;
}
/**
* 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.
*/
function user_page_title($account) {
return format_username($account);
function user_page_title($uid) {
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();
}
/**
* 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.
*