? node_load_static_cache.patch
? sites
Index: modules/user/user.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/user/user.module,v
retrieving revision 1.911
diff -u -p -r1.911 user.module
--- modules/user/user.module	27 Jun 2008 07:25:11 -0000	1.911
+++ modules/user/user.module	11 Jul 2008 21:29:39 -0000
@@ -137,27 +137,85 @@ function user_external_login($account, $
 /**
  * Fetch a user object.
  *
- * @param $array
+ * @param $conditions
  *   An associative array of attributes to search for in selecting the
  *   user, such as user name or e-mail address.
- *
+ * @param $reset
+ *   Resets the internal cache for the first user object that is saved
+ *   in the cache that matches the $conditions, or when $conditions is
+ *   an empty array it resets the whole internal cache
  * @return
  *   A fully-loaded $user object upon successful user load or FALSE if user
  *   cannot be loaded.
  */
-function user_load($array = array()) {
-  // Dynamically compose a SQL query:
-  $query = array();
-  $params = array();
+function user_load($conditions = array(), $reset = NULL) {
+  static $cache;
 
-  if (is_numeric($array)) {
-    $array = array('uid' => $array);
+  //Instantiate cache or reset cache when conditions are zero
+  if (!$cache OR (count($conditions)==0 AND $reset) ) {
+    $cache = array();
+    $cache['users'] = $cache['conditions'] = array();
   }
-  elseif (!is_array($array)) {
+
+  //Make sure $conditions is an array at all times - or jack out
+  if (is_numeric($conditions)) {
+    $conditions = array('uid' => $conditions);
+  }
+  elseif (!is_array($conditions)) {
     return FALSE;
   }
 
-  foreach ($array as $key => $value) {
+  //Return user from cache if only uid was given
+  if (isset($conditions['uid']) && (count($conditions)==1) && !$reset) {
+    $uid = $conditions['uid'];
+    if (isset($cache['users'][$uid])) {
+      return $cache['users'][$uid];
+    }
+  }
+
+  //Try to match the exact condition set and return from cache based on that
+  $uid_matches = array();
+  foreach ($conditions AS $key => $value) {
+    if ($key == 'uid') continue;
+
+    if (isset($cache['conditions'][$key])) {
+      if (isset($cache['conditions'][$key][$value])) {
+
+        //Collect the matching uid's
+        foreach ($cache['conditions'][$key][$value] as $uid) {
+          $uid_matches[] = (int)$uid;
+        }
+      }
+      else {
+        break;
+      }
+    }
+    else {
+      break;
+    }
+  }
+  if ($match_count = count($uid_matches)) {
+
+    //Are all uid's in the array equal?
+    if ( (array_sum($uid_matches)/$match_count) == $uid_matches[0]) {
+      $uid = $uid_matches[0];
+
+      if (isset($cache['users'][$uid])) {
+        if ($reset) {
+          unset($cache['users'][$uid]);
+        }
+        else {
+          return $cache['users'][$uid];
+        }
+      }
+    }
+  }
+
+  // Dynamically compose a SQL query:
+  $query  = array();
+  $params = array();
+
+  foreach ($conditions as $key => $value) {
     if ($key == 'uid' || $key == 'status') {
       $query[] = "$key = %d";
       $params[] = $value;
@@ -171,10 +229,10 @@ function user_load($array = array()) {
       $params[] = $value;
     }
   }
-  $result = db_query('SELECT * FROM {users} u WHERE ' . implode(' AND ', $query), $params);
+  $result = db_fetch_object(db_query('SELECT * FROM {users} u WHERE ' . implode(' AND ', $query), $params));
 
-  if ($user = db_fetch_object($result)) {
-    $user = drupal_unpack($user);
+  if (isset($result->uid)) {
+    $user = drupal_unpack($result);
 
     $user->roles = array();
     if ($user->uid) {
@@ -188,8 +246,29 @@ function user_load($array = array()) {
       $user->roles[$role->rid] = $role->name;
     }
     user_module_invoke('load', $array, $user);
+
+    //Save the uid of the object in the conditions cache,
+    //we group the database keys, then their values so we
+    //have a unique match at all times
+    foreach ($conditions as $key => $value) {
+      if (!isset($cache['conditions'][$key][$value])) {
+        $cache['conditions'][$key][$value] = array();
+      }
+      if (!in_array($user->uid, $cache['conditions'][$key][$value])) {
+        $cache['conditions'][$key][$value][] = $user->uid;
+      }
+    }
+
+    //Save user object in cache
+    $cache['users'][$user->uid] = $user;
   }
   else {
+    if (isset($conditions['uid'])) {
+      $uid = $conditions['uid'];
+      if (isset($cache['users'][$uid])) {
+        unset($cache['users'][$uid]);
+      }
+    }
     $user = FALSE;
   }
 
@@ -288,7 +367,7 @@ function user_save($account, $array = ar
     }
 
     // Refresh user object.
-    $user = user_load(array('uid' => $account->uid));
+    $user = user_load(array('uid' => $account->uid), true);
 
     // Send emails after we have the new user object.
     if (isset($array['status']) && $array['status'] != $account->status) {
@@ -318,7 +397,7 @@ function user_save($account, $array = ar
     }
 
     // Build the initial user object.
-    $user = user_load(array('uid' => $array['uid']));
+    $user = user_load(array('uid' => $array['uid']), true);
 
     user_module_invoke('insert', $array, $user, $category);
 
@@ -346,7 +425,7 @@ function user_save($account, $array = ar
     }
 
     // Build the finished user object.
-    $user = user_load(array('uid' => $array['uid']));
+    $user = user_load(array('uid' => $array['uid']), true);
   }
 
   return $user;
@@ -1555,6 +1634,7 @@ function user_delete($edit, $uid) {
   db_query('DELETE FROM {users} WHERE uid = %d', $uid);
   db_query('DELETE FROM {users_roles} WHERE uid = %d', $uid);
   db_query('DELETE FROM {authmap} WHERE uid = %d', $uid);
+  user_load($uid, true);//Update user_load() cache
   $variables = array('%name' => $account->name, '%email' => '<' . $account->mail . '>');
   watchdog('user', 'Deleted user: %name %email.', $variables, WATCHDOG_NOTICE);
   module_invoke_all('user', 'delete', $edit, $account);
Index: modules/user/user.test
===================================================================
RCS file: /cvs/drupal/drupal/modules/user/user.test,v
retrieving revision 1.10
diff -u -p -r1.10 user.test
--- modules/user/user.test	27 Jun 2008 07:25:11 -0000	1.10
+++ modules/user/user.test	11 Jul 2008 21:29:39 -0000
@@ -77,7 +77,7 @@ class UserRegistrationTestCase extends D
     // Make sure password changes are present in database.
     require_once variable_get('password_inc', './includes/password.inc');
 
-    $user = user_load(array('uid' => $user->uid));
+    $user = user_load(array('uid' => $user->uid), true);
     $this->assertTrue(user_check_password($new_pass, $user), t('Correct password in database.'));
 
     // Logout of user account.
@@ -198,7 +198,7 @@ class UserDeleteTestCase extends DrupalW
     // Confirm deletion.
     $this->drupalPost(NULL, NULL, t('Delete'));
     $this->assertRaw(t('%name has been deleted.', array('%name' => $user->name)), t('User deleted'));
-    $this->assertFalse(user_load($edit), t('User is not found in the database'));
+    $this->assertFalse(user_load($edit, true), t('User is not found in the database'));
   }
 }
 
