summaryrefslogtreecommitdiff
path: root/modules/user/user.module
diff options
context:
space:
mode:
Diffstat (limited to 'modules/user/user.module')
-rw-r--r--modules/user/user.module241
1 files changed, 177 insertions, 64 deletions
diff --git a/modules/user/user.module b/modules/user/user.module
index 76fd2834d..d63f27cbd 100644
--- a/modules/user/user.module
+++ b/modules/user/user.module
@@ -160,77 +160,191 @@ function user_external_login($account, $edit = array()) {
}
/**
- * Fetch a user object.
+ * Load multiple users based on certain conditions.
*
- * @param $array
- * An associative array of attributes to search for in selecting the
- * user, such as user name or e-mail address.
+ * This function should be used whenever you need to load more than one user
+ * from the database. Users are loaded into memory and will not require
+ * database access if loaded again during the same page request.
*
+ * @param $uids
+ * An array of user IDs.
+ * @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
- * A fully-loaded $user object upon successful user load or FALSE if user
- * cannot be loaded.
+ * An array of user objects, indexed by uid.
+ *
+ * @see user_load()
+ * @see user_load_by_mail()
+ * @see user_load_by_name()
*/
-function user_load($array = array()) {
- // Dynamically compose a SQL query:
- $query = array();
- $params = array();
-
- if (is_numeric($array)) {
- $array = array('uid' => $array);
- }
- elseif (!is_array($array)) {
- return FALSE;
+function user_load_multiple($uids = array(), $conditions = array(), $reset = FALSE) {
+ static $user_cache = array();
+ if ($reset) {
+ $user_cache = array();
}
- foreach ($array as $key => $value) {
- if ($key == 'uid' || $key == 'status') {
- $query[] = "$key = %d";
- $params[] = $value;
- }
- elseif ($key == 'pass') {
- $query[] = "pass = '%s'";
- $params[] = $value;
- }
- else {
- $query[]= "LOWER($key) = LOWER('%s')";
- $params[] = $value;
+ $users = array();
+
+ // Create a new variable which is either a prepared version of the $uids
+ // array for later comparison with the user cache, or FALSE if no $uids were
+ // passed. The $uids array is reduced as items are loaded from cache, and we
+ // need to know if it's empty for this reason to avoid querying the database
+ // when all requested users are loaded from cache.
+ $passed_uids = !empty($uids) ? array_flip($uids) : FALSE;
+
+ // Load any available users from the internal cache.
+ if ($user_cache) {
+ if ($uids && !$conditions) {
+ $users += array_intersect_key($user_cache, $passed_uids);
+ // If any users were loaded, remove them from the $uids still to load.
+ $uids = array_keys(array_diff_key($passed_uids, $users));
}
}
- $result = db_query('SELECT * FROM {users} u WHERE ' . implode(' AND ', $query), $params);
- if ($user = db_fetch_object($result)) {
- $user = drupal_unpack($user);
+ // Load any remaining users from the database, this is necessary if we have
+ // $uids still to load, or if $conditions was passed without $uids.
+ if ($uids || ($conditions && !$passed_uids)) {
+ $query = db_select('users', 'u')->fields('u');
- $user->roles = array();
- if ($user->uid) {
- $user->roles[DRUPAL_AUTHENTICATED_RID] = 'authenticated user';
+ // If the $uids array is populated, add those to the query.
+ if ($uids) {
+ $query->condition('u.uid', $uids, 'IN');
}
- else {
- $user->roles[DRUPAL_ANONYMOUS_RID] = 'anonymous user';
+ // If the conditions array is populated, add those to the query.
+ if ($conditions) {
+ // TODO D7: Using LIKE() to get a case insensitive comparison because Crell
+ // and chx promise that dbtng will map it to ILIKE in postgres.
+ if (isset($conditions['name'])) {
+ $query->condition('u.name', $conditions['name'], 'LIKE');
+ unset($conditions['name']);
+ }
+ if (isset($conditions['mail'])) {
+ $query->condition('u.mail', $conditions['mail'], 'LIKE');
+ unset($conditions['mail']);
+ }
+ foreach ($conditions as $field => $value) {
+ $query->condition('u.' . $field, $value);
+ }
}
- $result = db_query('SELECT r.rid, r.name FROM {role} r INNER JOIN {users_roles} ur ON ur.rid = r.rid WHERE ur.uid = %d', $user->uid);
- while ($role = db_fetch_object($result)) {
- $user->roles[$role->rid] = $role->name;
+ $result = $query->execute();
+
+ $queried_users = array();
+ // Build an array of user picture IDs so that these can be fetched later.
+ $picture_fids = array();
+ foreach ($result as $record) {
+ $picture_fids[] = $record->picture;
+ $queried_users[$record->uid] = drupal_unpack($record);
+ $queried_users[$record->uid]->roles = array();
+ if ($record->uid) {
+ $queried_users[$record->uid]->roles[DRUPAL_AUTHENTICATED_RID] = 'authenticated user';
+ }
+ else {
+ $queried_users[$record->uid]->roles[DRUPAL_ANONYMOUS_RID] = 'anonymous user';
+ }
}
- // Attach fields.
- // TODO D7 : not sure the 3rd param ($types) is needed.
- field_attach_load('user', array($user->uid => $user));
+ if (!empty($queried_users)) {
+ // Add any additional roles from the database.
+ $result = db_query('SELECT r.rid, r.name, ur.uid FROM {role} r INNER JOIN {users_roles} ur ON ur.rid = r.rid WHERE ur.uid IN (:uids)', array(':uids' => array_keys($queried_users)));
+ foreach ($result as $record) {
+ $queried_users[$record->uid]->roles[$record->rid] = $record->name;
+ }
- if (!empty($user->picture) && ($file = file_load($user->picture))) {
- $user->picture = $file;
- }
- else {
- $user->picture = NULL;
- }
+ // Add the full file objects for user pictures if enabled.
+ if (!empty($picture_fids) && variable_get('user_pictures', 1) == 1) {
+ $pictures = file_load_multiple($picture_fids);
+ foreach ($queried_users as $account) {
+ if (!empty($account->picture) && isset($pictures[$account->picture])) {
+ $account->picture = $pictures[$account->picture];
+ }
+ else {
+ $account->picture = NULL;
+ }
+ }
+ }
+
+ // Invoke hook_user_load() on the users loaded from the database
+ // and add them to the static cache.
+ foreach (module_implements('user_load') as $module) {
+ $function = $module . '_user_load';
+ $function($queried_users);
+ }
- user_module_invoke('load', $array, $user);
+ // TODO D7 : not sure the 3rd param ($types) is needed.
+ field_attach_load('user', $queried_users);
+
+ $users = $users + $queried_users;
+ $user_cache = $user_cache + $queried_users;
+ }
}
- else {
- $user = FALSE;
+
+ // Ensure that the returned array is ordered the same as the original $uids
+ // array if this was passed in and remove any invalid uids.
+ if ($passed_uids) {
+ // Remove any invalid uids from the array.
+ $passed_uids = array_intersect_key($passed_uids, $users);
+ foreach ($users as $user) {
+ $passed_uids[$user->uid] = $user;
+ }
+ $users = $passed_uids;
}
- return $user;
+ return $users;
+}
+
+
+/**
+ * Fetch a user object.
+ *
+ * @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);
+ return reset($users);
+}
+
+/**
+ * Fetch a user object by email address.
+ *
+ * @param $mail
+ * String with the account's e-mail address.
+ * @return
+ * A fully-loaded $user object upon successful user load or FALSE if user
+ * cannot be loaded.
+ *
+ * @see user_load_multiple()
+ */
+function user_load_by_mail($mail) {
+ $users = user_load_multiple(array(), array('mail' => $mail));
+ return reset($users);
+}
+
+/**
+ * Fetch a user object by account name.
+ *
+ * @param $name
+ * String with the account's user name.
+ * @return
+ * A fully-loaded $user object upon successful user load or FALSE if user
+ * cannot be loaded.
+ *
+ * @see user_load_multiple()
+ */
+function user_load_by_name($name) {
+ $users = user_load_multiple(array(), array('name' => $name));
+ return reset($users);
}
/**
@@ -374,7 +488,7 @@ function user_save($account, $edit = array(), $category = 'account') {
field_attach_update('user', $obj);
// Refresh user object.
- $user = user_load(array('uid' => $account->uid));
+ $user = user_load($account->uid, TRUE);
// Send emails after we have the new user object.
if (isset($edit['status']) && $edit['status'] != $account->status) {
@@ -404,7 +518,7 @@ function user_save($account, $edit = array(), $category = 'account') {
}
// Build the initial user object.
- $user = user_load(array('uid' => $edit['uid']));
+ $user = user_load($edit['uid'], TRUE);
$obj = (object) $edit;
field_attach_insert('user', $obj);
@@ -438,7 +552,7 @@ function user_save($account, $edit = array(), $category = 'account') {
}
// Build the finished user object.
- $user = user_load(array('uid' => $edit['uid']));
+ $user = user_load($edit['uid'], TRUE);
}
return $user;
@@ -1291,7 +1405,6 @@ function user_menu() {
'access callback' => 'user_edit_access',
'access arguments' => array(1),
'type' => MENU_LOCAL_TASK,
- 'load arguments' => array('%map', '%index'),
);
$items['user/%user_category/edit/account'] = array(
@@ -1554,8 +1667,8 @@ function user_authenticate($form_values = array()) {
db_query("UPDATE {users} SET pass = '%s' WHERE uid = %d", $new_hash, $account->uid);
}
}
- $account = user_load(array('uid' => $account->uid, 'status' => 1));
- $user = $account;
+ $users = user_load_multiple(array($account->uid), array('status' => '1'));
+ $user = reset($users);
user_authenticate_finalize($form_values);
return $user;
}
@@ -1608,7 +1721,7 @@ function user_login_submit($form, &$form_state) {
function user_external_login_register($name, $module) {
global $user;
- $existing_user = user_load(array('name' => $name));
+ $existing_user = user_load_by_name($name);
if (isset($existing_user->uid)) {
$user = $existing_user;
}
@@ -1799,7 +1912,7 @@ function user_edit_form(&$form_state, $uid, $edit, $register = FALSE) {
function user_cancel($edit, $uid, $method) {
global $user;
- $account = user_load(array('uid' => $uid));
+ $account = user_load($uid);
if (!$account) {
drupal_set_message(t('The user account %id does not exist.', array('%id' => $uid)), 'error');
@@ -2110,7 +2223,7 @@ function user_user_operations($form_state = array()) {
*/
function user_user_operations_unblock($accounts) {
foreach ($accounts as $uid) {
- $account = user_load(array('uid' => (int)$uid));
+ $account = user_load($uid);
// Skip unblocking user if they are already unblocked.
if ($account !== FALSE && $account->status == 0) {
user_save($account, array('status' => 1));
@@ -2123,7 +2236,7 @@ function user_user_operations_unblock($accounts) {
*/
function user_user_operations_block($accounts) {
foreach ($accounts as $uid) {
- $account = user_load(array('uid' => (int)$uid));
+ $account = user_load($uid);
// Skip blocking user if they are already blocked.
if ($account !== FALSE && $account->status == 1) {
user_save($account, array('status' => 0));
@@ -2142,7 +2255,7 @@ function user_multiple_role_edit($accounts, $operation, $rid) {
switch ($operation) {
case 'add_role':
foreach ($accounts as $uid) {
- $account = user_load(array('uid' => (int)$uid));
+ $account = user_load($uid);
// Skip adding the role to the user if they already have it.
if ($account !== FALSE && !isset($account->roles[$rid])) {
$roles = $account->roles + array($rid => $role_name);
@@ -2152,7 +2265,7 @@ function user_multiple_role_edit($accounts, $operation, $rid) {
break;
case 'remove_role':
foreach ($accounts as $uid) {
- $account = user_load(array('uid' => (int)$uid));
+ $account = user_load($uid);
// Skip removing the role from the user if they already don't have it.
if ($account !== FALSE && isset($account->roles[$rid])) {
$roles = array_diff($account->roles, array($rid => $role_name));