Index: modules/user/user.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/user/user.module,v
retrieving revision 1.999
diff -u -p -r1.999 user.module
--- modules/user/user.module	4 Jun 2009 11:25:03 -0000	1.999
+++ modules/user/user.module	6 Jun 2009 01:20:52 -0000
@@ -171,9 +171,6 @@ function user_external_login($account, $
  * @param $conditions
  *   An array of conditions to match against the {users} table. These
  *   should be supplied in the form array('field_name' => 'field_value').
- * @param $reset
- *   A boolean indicating that the internal cache should be reset. Use this if
- *   loading a user object which has been altered during the page request.
  * @return
  *   An array of user objects, indexed by uid.
  *
@@ -181,11 +178,8 @@ function user_external_login($account, $
  * @see user_load_by_mail()
  * @see user_load_by_name()
  */
-function user_load_multiple($uids = array(), $conditions = array(), $reset = FALSE) {
-  static $user_cache = array();
-  if ($reset) {
-    $user_cache = array();
-  }
+function user_load_multiple($uids = array(), $conditions = array()) {
+  $user_cache = &drupal_static(__FUNCTION__, array());
 
   $users = array();
 
@@ -303,20 +297,25 @@ function user_load_multiple($uids = arra
  *
  * @param $uid
  *   Integer specifying the user id.
- * @param $reset
- *   A boolean indicating that the internal cache should be reset.
  * @return
  *   A fully-loaded $user object upon successful user load or FALSE if user
  *   cannot be loaded.
  *
  * @see user_load_multiple()
  */
-function user_load($uid, $reset = FALSE) {
-  $users = user_load_multiple(array($uid), array(), $reset);
+function user_load($uid) {
+  $users = user_load_multiple(array($uid), array());
   return reset($users);
 }
 
 /**
+ * Reset static variables used by user_load().
+ */
+function user_load_reset() {
+  drupal_static_reset('user_load_multiple');
+}
+
+/**
  * Fetch a user object by email address.
  *
  * @param $mail
@@ -499,7 +498,8 @@ function user_save($account, $edit = arr
     field_attach_update('user', $object);
 
     // Refresh user object.
-    $user = user_load($account->uid, TRUE);
+    user_load_reset();
+    $user = user_load($account->uid);
 
     // Send emails after we have the new user object.
     if (isset($edit['status']) && $edit['status'] != $account->status) {
@@ -530,7 +530,8 @@ function user_save($account, $edit = arr
     }
 
     // Build the initial user object.
-    $user = user_load($edit['uid'], TRUE);
+    user_load_reset();
+    $user = user_load($edit['uid']);
 
     $object = (object) $edit;
     field_attach_insert('user', $object);
@@ -571,7 +572,8 @@ function user_save($account, $edit = arr
     }
 
     // Build the finished user object.
-    $user = user_load($edit['uid'], TRUE);
+    user_load_reset();
+    $user = user_load($edit['uid']);
   }
 
   return $user;
@@ -673,20 +675,13 @@ function user_password($length = 10) {
  *
  * @param $roles
  *   An array whose keys are the role IDs of interest, such as $user->roles.
- * @param $reset
- *   Optional parameter - if TRUE data in the static variable is rebuilt.
  *
  * @return
  *   An array indexed by role ID. Each value is an array whose keys are the
  *   permission strings for the given role ID.
  */
-function user_role_permissions($roles = array(), $reset = FALSE) {
-  static $stored_permissions = array();
-
-  if ($reset) {
-    // Clear the data cached in the static variable.
-    $stored_permissions = array();
-  }
+function user_role_permissions($roles = array()) {
+  $stored_permissions = &drupal_static(__FUNCTION__, array());
 
   $role_permissions = $fetch = array();
 
@@ -728,10 +723,6 @@ function user_role_permissions($roles = 
  *   The permission, such as "administer nodes", being checked for.
  * @param $account
  *   (optional) The account to check, if not given use currently logged in user.
- * @param $reset
- *   (optional) Resets the user's permissions cache, which will result in a
- *   recalculation of the user's permissions. This is necessary to support
- *   dynamically added user roles.
  *
  * @return
  *   Boolean TRUE if the current user has the requested permission.
@@ -740,13 +731,9 @@ function user_role_permissions($roles = 
  * way, we guarantee consistent behavior, and ensure that the superuser
  * can perform all actions.
  */
-function user_access($string, $account = NULL, $reset = FALSE) {
+function user_access($string, $account = NULL) {
   global $user;
-  static $perm = array();
-
-  if ($reset) {
-    $perm = array();
-  }
+  $perm = &drupal_static(__FUNCTION__, array());
 
   if (is_null($account)) {
     $account = $user;
@@ -760,7 +747,7 @@ function user_access($string, $account =
   // To reduce the number of SQL queries, we cache the user's permissions
   // in a static variable.
   if (!isset($perm[$account->uid])) {
-    $role_permissions = user_role_permissions($account->roles, $reset);
+    $role_permissions = user_role_permissions($account->roles);
 
     $perms = array();
     foreach ($role_permissions as $one_role) {
@@ -773,6 +760,14 @@ function user_access($string, $account =
 }
 
 /**
+ * Reset static variables used by user_access().
+ */
+function user_access_reset() {
+  drupal_static_reset('user_access');
+  drupal_static_reset('user_role_permissions');
+}
+
+/**
  * Checks for usernames blocked by user administration.
  *
  * @return boolean TRUE for blocked users, FALSE for active.
@@ -1475,7 +1470,8 @@ function user_uid_optional_load($arg) {
  * Return a user object after checking if any profile category in the path exists.
  */
 function user_category_load($uid, &$map, $index) {
-  static $user_categories, $accounts;
+  $user_categories = &drupal_static(__FUNCTION__);
+  $accounts = &drupal_static(__FUNCTION__ . ':accounts');
 
   // Cache $account - this load function will get called for each profile tab.
   if (!isset($accounts[$uid])) {
@@ -2644,7 +2640,7 @@ function _user_mail_notify($op, $account
  * strings that need to be passed to the javascript code.
  */
 function _user_password_dynamic_validation() {
-  static $complete = FALSE;
+  $complete = &drupal_static(__FUNCTION__, FALSE);
   global $user;
   // Only need to do once per page.
   if (!$complete) {
Index: modules/user/user.test
===================================================================
RCS file: /cvs/drupal/drupal/modules/user/user.test,v
retrieving revision 1.40
diff -u -p -r1.40 user.test
--- modules/user/user.test	5 Jun 2009 09:26:06 -0000	1.40
+++ modules/user/user.test	6 Jun 2009 01:20:52 -0000
@@ -82,7 +82,8 @@ class UserRegistrationTestCase extends D
     // Make sure password changes are present in database.
     require_once DRUPAL_ROOT . '/' . variable_get('password_inc', 'includes/password.inc');
 
-    $user = user_load($user->uid, TRUE);
+    user_load_reset()
+    $user = user_load($user->uid);
     $this->assertTrue(user_check_password($new_pass, $user), t('Correct password in database.'));
 
     // Logout of user account.
@@ -178,7 +179,8 @@ class UserCancelTestCase extends DrupalW
     $account = $this->drupalCreateUser(array());
     $this->drupalLogin($account);
     // Load real user object.
-    $account = user_load($account->uid, TRUE);
+    user_load_reset();
+    $account = user_load($account->uid);
 
     // Create a node.
     $node = $this->drupalCreateNode(array('uid' => $account->uid));
@@ -209,7 +211,8 @@ class UserCancelTestCase extends DrupalW
     $account = $this->drupalCreateUser(array('cancel account'));
     $this->drupalLogin($account);
     // Load real user object.
-    $account = user_load($account->uid, TRUE);
+    user_load_reset();
+    $account = user_load($account->uid);
 
     // Create a node.
     $node = $this->drupalCreateNode(array('uid' => $account->uid));
@@ -251,7 +254,8 @@ class UserCancelTestCase extends DrupalW
     $this->drupalLogin($web_user);
 
     // Load real user object.
-    $account = user_load($web_user->uid, TRUE);
+    user_load_reset();
+    $account = user_load($web_user->uid);
 
     // Attempt to cancel account.
     $this->drupalGet('user/' . $account->uid . '/edit');
@@ -268,7 +272,8 @@ class UserCancelTestCase extends DrupalW
 
     // Confirm account cancellation request.
     $this->drupalGet("user/$account->uid/cancel/confirm/$timestamp/" . user_pass_rehash($account->pass, $timestamp, $account->login));
-    $account = user_load($account->uid, TRUE);
+    user_load_reset();
+    $account = user_load($account->uid);
     $this->assertTrue($account->status == 0, t('User has been blocked.'));
 
     // Confirm user is logged out.
@@ -285,7 +290,8 @@ class UserCancelTestCase extends DrupalW
     $account = $this->drupalCreateUser(array('cancel account'));
     $this->drupalLogin($account);
     // Load real user object.
-    $account = user_load($account->uid, TRUE);
+    user_load_reset();
+    $account = user_load($account->uid);
 
     // Create a node with two revisions.
     $node = $this->drupalCreateNode(array('uid' => $account->uid));
@@ -306,7 +312,8 @@ class UserCancelTestCase extends DrupalW
 
     // Confirm account cancellation request.
     $this->drupalGet("user/$account->uid/cancel/confirm/$timestamp/" . user_pass_rehash($account->pass, $timestamp, $account->login));
-    $account = user_load($account->uid, TRUE);
+    user_load_reset();
+    $account = user_load($account->uid);
     $this->assertTrue($account->status == 0, t('User has been blocked.'));
 
     // Confirm user's content has been unpublished.
@@ -329,7 +336,8 @@ class UserCancelTestCase extends DrupalW
     $account = $this->drupalCreateUser(array('cancel account'));
     $this->drupalLogin($account);
     // Load real user object.
-    $account = user_load($account->uid, TRUE);
+    user_load_reset();
+    $account = user_load($account->uid);
 
     // Create a simple node.
     $node = $this->drupalCreateNode(array('uid' => $account->uid));
@@ -356,7 +364,8 @@ class UserCancelTestCase extends DrupalW
 
     // Confirm account cancellation request.
     $this->drupalGet("user/$account->uid/cancel/confirm/$timestamp/" . user_pass_rehash($account->pass, $timestamp, $account->login));
-    $this->assertFalse(user_load($account->uid, TRUE), t('User is not found in the database.'));
+    user_load_reset();
+    $this->assertFalse(user_load($account->uid), t('User is not found in the database.'));
 
     // Confirm that user's content has been attributed to anonymous user.
     $test_node = node_load($node->nid, NULL, TRUE);
@@ -380,7 +389,8 @@ class UserCancelTestCase extends DrupalW
     $account = $this->drupalCreateUser(array('cancel account'));
     $this->drupalLogin($account);
     // Load real user object.
-    $account = user_load($account->uid, TRUE);
+    user_load_reset();
+    $account = user_load($account->uid);
 
     // Create a simple node.
     $node = $this->drupalCreateNode(array('uid' => $account->uid));
@@ -412,7 +422,8 @@ class UserCancelTestCase extends DrupalW
 
     // Confirm account cancellation request.
     $this->drupalGet("user/$account->uid/cancel/confirm/$timestamp/" . user_pass_rehash($account->pass, $timestamp, $account->login));
-    $this->assertFalse(user_load($account->uid, TRUE), t('User is not found in the database.'));
+    user_load_reset();
+    $this->assertFalse(user_load($account->uid), t('User is not found in the database.'));
 
     // Confirm that user's content has been deleted.
     $this->assertFalse(node_load($node->nid, NULL, TRUE), t('Node of the user has been deleted.'));
@@ -486,7 +497,8 @@ class UserCancelTestCase extends DrupalW
     $status = TRUE;
     foreach ($users as $account) {
       $status = $status && (strpos($this->content, t('%name has been deleted.', array('%name' => $account->name))) !== FALSE);
-      $status = $status && !user_load($account->uid, TRUE);
+      user_load_reset();
+      $status = $status && !user_load($account->uid);
     }
     $this->assertTrue($status, t('Users deleted and not found in the database.'));
 
@@ -749,20 +761,24 @@ class UserPermissionsTestCase extends Dr
     $account = $this->admin_user;
 
     // Add a permission.
-    $this->assertFalse(user_access('administer nodes', $account, TRUE), t('User does not have "administer nodes" permission.'));
+    user_access_reset();
+    $this->assertFalse(user_access('administer nodes', $account), t('User does not have "administer nodes" permission.'));
     $edit = array();
     $edit[$rid . '[administer nodes]'] = TRUE;
     $this->drupalPost('admin/user/permissions', $edit, t('Save permissions'));
     $this->assertText(t('The changes have been saved.'), t('Successful save message displayed.'));
-    $this->assertTrue(user_access('administer nodes', $account, TRUE), t('User now has "administer nodes" permission.'));
+    user_access_reset();
+    $this->assertTrue(user_access('administer nodes', $account), t('User now has "administer nodes" permission.'));
 
     // Remove a permission.
-    $this->assertTrue(user_access('access user profiles', $account, TRUE), t('User has "access user profiles" permission.'));
+    user_access_reset();
+    $this->assertTrue(user_access('access user profiles', $account), t('User has "access user profiles" permission.'));
     $edit = array();
     $edit[$rid . '[access user profiles]'] = FALSE;
     $this->drupalPost('admin/user/permissions', $edit, t('Save permissions'));
     $this->assertText(t('The changes have been saved.'), t('Successful save message displayed.'));
-    $this->assertFalse(user_access('access user profiles', $account, TRUE), t('User no longer has "access user profiles" permission.'));
+    user_access_reset();
+    $this->assertFalse(user_access('access user profiles', $account), t('User no longer has "access user profiles" permission.'));
   }
 
   /**
@@ -783,7 +799,8 @@ class UserPermissionsTestCase extends Dr
     $edit['modules[Core][aggregator][enable]'] = TRUE;
     $this->drupalPost('admin/build/modules', $edit, t('Save configuration'));
 
-    $this->assertTrue(user_access('administer news feeds', $this->admin_user, TRUE), t('The permission was automatically assigned to the administrator role'));
+    user_access_reset();
+    $this->assertTrue(user_access('administer news feeds', $this->admin_user), t('The permission was automatically assigned to the administrator role'));
   }
 }
 
@@ -832,7 +849,8 @@ class UserAdminTestCase extends DrupalWe
     $edit['operation'] = 'block';
     $edit['accounts[' . $account->uid . ']'] = TRUE;
     $this->drupalPost('admin/user/user', $edit, t('Update'));
-    $account = user_load($user_b->uid, TRUE);
+    user_load_reset();
+    $account = user_load($user_b->uid);
     $this->assertEqual($account->status, 0, 'User B blocked');
   }
 }
