summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDries Buytaert <dries@buytaert.net>2010-01-14 13:45:33 +0000
committerDries Buytaert <dries@buytaert.net>2010-01-14 13:45:33 +0000
commita417a986ea78521dddf72e06e14d2516bba48d09 (patch)
tree6dd4d0e4b9e75736848fcc5048e336b1aa5cebc6
parentfafabc7e2a692296bd2a4c607991c24e10674b60 (diff)
downloadbrdo-a417a986ea78521dddf72e06e14d2516bba48d09.tar.gz
brdo-a417a986ea78521dddf72e06e14d2516bba48d09.tar.bz2
- Patch #638070 by carlos8f, Gábor Hojtsy, ksenzee, pwolanin, chx, catch: router loaders causing a lot of database hits for access checks.
-rw-r--r--includes/menu.inc1
-rw-r--r--modules/menu/menu.module47
-rw-r--r--modules/user/user.module75
3 files changed, 96 insertions, 27 deletions
diff --git a/includes/menu.inc b/includes/menu.inc
index cc7fe485c..4708a7c18 100644
--- a/includes/menu.inc
+++ b/includes/menu.inc
@@ -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');
}
/**
diff --git a/modules/menu/menu.module b/modules/menu/menu.module
index 5f203a7f6..01477fafe 100644
--- a/modules/menu/menu.module
+++ b/modules/menu/menu.module
@@ -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;
}
-
diff --git a/modules/user/user.module b/modules/user/user.module
index e91e40f9b..ee9e5287f 100644
--- a/modules/user/user.module
+++ b/modules/user/user.module
@@ -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.
@@ -1673,10 +1693,25 @@ function user_uid_optional_to_arg($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) : '';
}
/**
@@ -2108,6 +2143,16 @@ function _user_cancel($edit, $account, $method) {
}
/**
+ * 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.
*
* When viewing a user profile, the $page array contains: