From a417a986ea78521dddf72e06e14d2516bba48d09 Mon Sep 17 00:00:00 2001 From: Dries Buytaert Date: Thu, 14 Jan 2010 13:45:33 +0000 Subject: [PATCH] =?UTF-8?q?-=20Patch=20#638070=20by=20carlos8f,=20G=C3=A1b?= =?UTF-8?q?or=20Hojtsy,=20ksenzee,=20pwolanin,=20chx,=20catch:=20router=20?= =?UTF-8?q?loaders=20causing=20a=20lot=20of=20database=20hits=20for=20acce?= =?UTF-8?q?ss=20checks.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- includes/menu.inc | 1 + modules/menu/menu.module | 47 ++++++++++++++++++------- modules/user/user.module | 75 ++++++++++++++++++++++++++++++++-------- 3 files changed, 96 insertions(+), 27 deletions(-) diff --git a/includes/menu.inc b/includes/menu.inc index cc7fe485c04..4708a7c1887 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 5f203a7f6ac..01477fafe33 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 e91e40f9b19..ee9e5287fed 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. @@ -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. *