Error message

You are browsing documentation for drupal 7.x, which is not supported anymore. Read the updated version of this page for drupal 11.x (the latest version).

function user_save

Save changes to a user account or add a new user.

Parameters

$account: (optional) The user object to modify or add. If you want to modify an existing user account, you will need to ensure that (a) $account is an object, and (b) you have set $account->uid to the numeric user ID of the user account you wish to modify. If you want to create a new user account, you can set $account->is_new to TRUE or omit the $account->uid field.

$edit: An array of fields and values to save. For example array('name' => 'My name'). Key / value pairs added to the $edit['data'] will be serialized and saved in the {users.data} column.

$category: (optional) The category for storing profile information in.

Return value

A fully-loaded $user object upon successful save or FALSE if the save failed.

30 calls to user_save()
BlockCacheTestCase::setUp in modules/block/block.test
Sets up a Drupal site for running functional and integration tests.
ContactPersonalTestCase::testPersonalContactAccess in modules/contact/contact.test
Tests access to the personal contact form.
DrupalRenderTestCase::testDrupalRenderCache in modules/simpletest/tests/common.test
Tests caching of render items.
DrupalWebTestCase::drupalCreateUser in modules/simpletest/drupal_web_test_case.php
Create a user with a given set of permissions.
EntityCrudHookTestCase::testUserHooks in modules/simpletest/tests/entity_crud_hook_test.test
Tests hook invocations for CRUD operations on users.

... See full list

File

modules/user/user.module, line 422

Code

function user_save ($account, $edit = array(), $category = 'account') {
 $transaction = db_transaction ();
 try {
 if (isset($edit['pass']) && strlen (trim ($edit['pass'])) > 0) {
 // Allow alternate password hashing schemes.
 require_once DRUPAL_ROOT  . '/' . variable_get ('password_inc', 'includes/password.inc');
 $edit['pass'] = user_hash_password (trim ($edit['pass']));
 // Abort if the hashing failed and returned FALSE.
 if (!$edit['pass']) {
 return FALSE;
 }
 }
 else {
 // Avoid overwriting an existing password with a blank password.
 unset($edit['pass']);
 }
 if (isset($edit['mail'])) {
 $edit['mail'] = trim ($edit['mail']);
 }
 // Load the stored entity, if any.
 if (!empty($account->uid) && !isset($account->original)) {
 $account->original = entity_load_unchanged ('user', $account->uid);
 }
 if (empty($account)) {
 $account = new stdClass();
 }
 if (!isset($account->is_new )) {
 $account->is_new  = empty($account->uid);
 }
 // Prepopulate $edit['data'] with the current value of $account->data.
 // Modules can add to or remove from this array in hook_user_presave().
 if (!empty($account->data )) {
 $edit['data'] = !empty($edit['data']) ? array_merge ($account->data , $edit['data']) : $account->data ;
 }
 // Invoke hook_user_presave() for all modules.
 user_module_invoke ('presave', $edit, $account, $category);
 // Invoke presave operations of Field Attach API and Entity API. Those APIs
 // require a fully-fledged and updated entity object. Therefore, we need to
 // copy any new property values of $edit into it.
 foreach ($edit as $key => $value) {
 $account->{$key} = $value;
 }
 field_attach_presave ('user', $account);
 module_invoke_all ('entity_presave', $account, 'user');
 if (is_object ($account) && !$account->is_new ) {
 // Process picture uploads.
 if (!empty($account->picture->fid) && (!isset($account->original->picture->fid) || $account->picture->fid != $account->original->picture->fid)) {
 $picture = $account->picture;
 // If the picture is a temporary file move it to its final location and
 // make it permanent.
 if (!$picture->status) {
 $info = image_get_info ($picture->uri );
 $picture_directory = file_default_scheme () . '://' . variable_get ('user_picture_path', 'pictures');
 // Prepare the pictures directory.
 file_prepare_directory ($picture_directory, FILE_CREATE_DIRECTORY );
 $destination = file_stream_wrapper_uri_normalize ($picture_directory . '/picture-' . $account->uid . '-' . REQUEST_TIME  . '.' . $info['extension']);
 // Move the temporary file into the final location.
 if ($picture = file_move ($picture, $destination, FILE_EXISTS_RENAME )) {
 $picture->status = FILE_STATUS_PERMANENT ;
 $account->picture = file_save ($picture);
 file_usage_add ($picture, 'user', 'user', $account->uid);
 }
 }
 // Delete the previous picture if it was deleted or replaced.
 if (!empty($account->original->picture->fid)) {
 file_usage_delete ($account->original->picture, 'user', 'user', $account->uid);
 file_delete ($account->original->picture);
 }
 }
 elseif (isset($edit['picture_delete']) && $edit['picture_delete']) {
 file_usage_delete ($account->original->picture, 'user', 'user', $account->uid);
 file_delete ($account->original->picture);
 }
 // Save the picture object, if it is set. drupal_write_record() expects
 // $account->picture to be a FID.
 $picture = empty($account->picture) ? NULL : $account->picture;
 $account->picture = empty($account->picture->fid) ? 0 : $account->picture->fid;
 // Do not allow 'uid' to be changed.
 $account->uid = $account->original->uid;
 // Save current time as last changed time.
 $account->changed  = REQUEST_TIME ;
 // Save changes to the user table.
 $success = drupal_write_record ('users', $account, 'uid');
 // Restore the picture object.
 $account->picture = $picture;
 if ($success === FALSE) {
 // The query failed - better to abort the save than risk further
 // data loss.
 return FALSE;
 }
 // Reload user roles if provided.
 if ($account->roles != $account->original->roles) {
 db_delete ('users_roles')->condition ('uid', $account->uid)
 ->execute ();
 $query = db_insert ('users_roles')->fields (array(
 'uid',
 'rid',
 ));
 foreach (array_keys ($account->roles) as $rid) {
 if (!in_array ($rid, array(
 DRUPAL_ANONYMOUS_RID ,
 DRUPAL_AUTHENTICATED_RID ,
 ))) {
 $query->values (array(
 'uid' => $account->uid,
 'rid' => $rid,
 ));
 }
 }
 $query->execute ();
 }
 // Delete a blocked user's sessions to kick them if they are online.
 if ($account->original->status != $account->status && $account->status == 0) {
 drupal_session_destroy_uid ($account->uid);
 }
 // If the password changed, delete all open sessions and recreate
 // the current one.
 if ($account->pass  != $account->original->pass ) {
 drupal_session_destroy_uid ($account->uid);
 if ($account->uid == $GLOBALS['user']->uid) {
 drupal_session_regenerate ();
 }
 }
 // Save Field data.
 field_attach_update ('user', $account);
 // Send emails after we have the new user object.
 if ($account->status != $account->original->status) {
 // The user's status is changing; conditionally send notification email.
 $op = $account->status == 1 ? 'status_activated' : 'status_blocked';
 _user_mail_notify ($op, $account);
 }
 // Update $edit with any interim changes to $account.
 foreach ($account as $key => $value) {
 if (!property_exists ($account->original, $key) || $value !== $account->original->{$key}) {
 $edit[$key] = $value;
 }
 }
 user_module_invoke ('update', $edit, $account, $category);
 module_invoke_all ('entity_update', $account, 'user');
 }
 else {
 // Allow 'uid' to be set by the caller. There is no danger of writing an
 // existing user as drupal_write_record will do an INSERT.
 if (empty($account->uid)) {
 $account->uid = db_next_id (db_query ('SELECT MAX(uid) FROM {users}')->fetchField ());
 }
 // Allow 'created' to be set by the caller.
 if (!isset($account->created)) {
 $account->created = REQUEST_TIME ;
 }
 // Save current time as last changed time.
 $account->changed  = REQUEST_TIME ;
 $success = drupal_write_record ('users', $account);
 if ($success === FALSE) {
 // On a failed INSERT some other existing user's uid may be returned.
 // We must abort to avoid overwriting their account.
 return FALSE;
 }
 // Make sure $account is properly initialized.
 $account->roles[DRUPAL_AUTHENTICATED_RID ] = 'authenticated user';
 field_attach_insert ('user', $account);
 $edit = (array) $account;
 user_module_invoke ('insert', $edit, $account, $category);
 module_invoke_all ('entity_insert', $account, 'user');
 // Save user roles. Skip built-in roles, and ones that were already saved
 // to the database during hook calls.
 $rids_to_skip = array_merge (array(
 DRUPAL_ANONYMOUS_RID ,
 DRUPAL_AUTHENTICATED_RID ,
 ), db_query ('SELECT rid FROM {users_roles} WHERE uid = :uid', array(
 ':uid' => $account->uid,
 ))
 ->fetchCol ());
 if ($rids_to_save = array_diff (array_keys ($account->roles), $rids_to_skip)) {
 $query = db_insert ('users_roles')->fields (array(
 'uid',
 'rid',
 ));
 foreach ($rids_to_save as $rid) {
 $query->values (array(
 'uid' => $account->uid,
 'rid' => $rid,
 ));
 }
 $query->execute ();
 }
 }
 // Clear internal properties.
 unset($account->is_new );
 unset($account->original);
 // Clear the static loading cache.
 entity_get_controller ('user')->resetCache (array(
 $account->uid,
 ));
 return $account;
 } catch (Exception $e) {
 $transaction->rollback ();
 watchdog_exception ('user', $e);
 throw $e;
 }
}

Buggy or inaccurate documentation? Please file an issue. Need support? Need help programming? Connect with the Drupal community.