diff --git a/core/includes/install.core.inc b/core/includes/install.core.inc
index cfbdffb..b010385 100644
--- a/core/includes/install.core.inc
+++ b/core/includes/install.core.inc
@@ -1915,8 +1915,13 @@ function install_configure_form_submit($form, &$form_state) {
// We precreated user 1 with placeholder values. Let's save the real values.
$account = user_load(1);
- $merge_data = array('init' => $form_state['values']['account']['mail'], 'roles' => !empty($account->roles) ? $account->roles : array(), 'status' => 1, 'timezone' => $form_state['values']['date_default_timezone']);
- user_save($account, array_merge($form_state['values']['account'], $merge_data));
+ $account->init = $account->mail = $form_state['values']['account']['mail'];
+ $account->roles = !empty($account->roles) ? $account->roles : array();
+ $account->status = 1;
+ $account->timezone = $form_state['values']['date_default_timezone'];
+ $account->pass = $form_state['values']['account']['pass'];
+ $account->name = $form_state['values']['account']['name'];
+ $account->save();
// Load global $user and perform final login tasks.
$user = user_load(1);
user_login_finalize();
diff --git a/core/modules/block/block.module b/core/modules/block/block.module
index 25bd3b1..a541409 100644
--- a/core/modules/block/block.module
+++ b/core/modules/block/block.module
@@ -628,9 +628,9 @@ function block_form_user_profile_form_alter(&$form, &$form_state) {
/**
* Implements hook_user_presave().
*/
-function block_user_presave(&$edit, $account) {
- if (isset($edit['block'])) {
- $edit['data']['block'] = $edit['block'];
+function block_user_presave($account) {
+ if (isset($account->block)) {
+ $account->data['block'] = $account->block;
}
}
diff --git a/core/modules/block/block.test b/core/modules/block/block.test
index 4af6240..4642da2 100644
--- a/core/modules/block/block.test
+++ b/core/modules/block/block.test
@@ -542,8 +542,8 @@ class BlockCacheTestCase extends DrupalWebTestCase {
$this->normal_user_alt = $this->drupalCreateUser();
// Sync the roles, since drupalCreateUser() creates separate roles for
// the same permission sets.
- user_save($this->normal_user_alt, array('roles' => $this->normal_user->roles));
$this->normal_user_alt->roles = $this->normal_user->roles;
+ $this->normal_user_alt->save();
// Enable our test block.
$edit['blocks[block_test_test_cache][region]'] = 'sidebar_first';
diff --git a/core/modules/comment/comment.entity.inc b/core/modules/comment/comment.entity.inc
index bce8b56..cb4d6d6 100644
--- a/core/modules/comment/comment.entity.inc
+++ b/core/modules/comment/comment.entity.inc
@@ -73,6 +73,19 @@ class Comment extends Entity {
*/
public $homepage;
+ /**
+ * Implements EntityInterface::id().
+ */
+ public function id() {
+ return $this->cid;
+ }
+
+ /**
+ * Implements EntityInterface::bundle().
+ */
+ public function bundle() {
+ return $this->node_type;
+ }
}
/**
diff --git a/core/modules/contact/contact.module b/core/modules/contact/contact.module
index 89ce0bc..c695c7e 100644
--- a/core/modules/contact/contact.module
+++ b/core/modules/contact/contact.module
@@ -233,8 +233,8 @@ function contact_form_user_profile_form_alter(&$form, &$form_state) {
/**
* Implements hook_user_presave().
*/
-function contact_user_presave(&$edit, $account) {
- $edit['data']['contact'] = isset($edit['contact']) ? $edit['contact'] : variable_get('contact_default_status', 1);
+function contact_user_presave($account) {
+ $account->data['contact'] = isset($account->contact) ? $account->contact : variable_get('contact_default_status', 1);
}
/**
diff --git a/core/modules/contact/contact.test b/core/modules/contact/contact.test
index d7f26ac..490d8f8 100644
--- a/core/modules/contact/contact.test
+++ b/core/modules/contact/contact.test
@@ -374,7 +374,8 @@ class ContactPersonalTestCase extends DrupalWebTestCase {
// Re-create our contacted user as a blocked user.
$this->contact_user = $this->drupalCreateUser();
- user_save($this->contact_user, array('status' => 0));
+ $this->contact_user->status = 0;
+ $this->contact_user->save();
// Test that blocked users can still be contacted by admin.
$this->drupalGet('user/' . $this->contact_user->uid . '/contact');
diff --git a/core/modules/entity/entity.class.inc b/core/modules/entity/entity.class.inc
index 7ffd496..2311af5 100644
--- a/core/modules/entity/entity.class.inc
+++ b/core/modules/entity/entity.class.inc
@@ -146,27 +146,6 @@ class Entity implements EntityInterface {
protected $entityType;
/**
- * Information about the entity's type.
- *
- * @var array
- */
- protected $entityInfo;
-
- /**
- * The entity ID key.
- *
- * @var string
- */
- protected $idKey;
-
- /**
- * The entity bundle key.
- *
- * @var string
- */
- protected $bundleKey;
-
- /**
* Boolean indicating whether the entity should be forced to be new.
*
* @var bool
@@ -178,7 +157,6 @@ class Entity implements EntityInterface {
*/
public function __construct(array $values = array(), $entity_type) {
$this->entityType = $entity_type;
- $this->setUp();
// Set initial values.
foreach ($values as $key => $value) {
$this->$key = $value;
@@ -186,26 +164,17 @@ class Entity implements EntityInterface {
}
/**
- * Sets up the object instance on construction or unserialization.
- */
- protected function setUp() {
- $this->entityInfo = entity_get_info($this->entityType);
- $this->idKey = $this->entityInfo['entity keys']['id'];
- $this->bundleKey = isset($this->entityInfo['entity keys']['bundle']) ? $this->entityInfo['entity keys']['bundle'] : NULL;
- }
-
- /**
* Implements EntityInterface::id().
*/
public function id() {
- return isset($this->{$this->idKey}) ? $this->{$this->idKey} : NULL;
+ return isset($this->id) ? $this->id : NULL;
}
/**
* Implements EntityInterface::isNew().
*/
public function isNew() {
- return !empty($this->enforceIsNew) || empty($this->{$this->idKey});
+ return !empty($this->enforceIsNew) || !$this->id();
}
/**
@@ -226,7 +195,7 @@ class Entity implements EntityInterface {
* Implements EntityInterface::bundle().
*/
public function bundle() {
- return isset($this->bundleKey) ? $this->{$this->bundleKey} : $this->entityType;
+ return $this->entityType;
}
/**
@@ -236,11 +205,12 @@ class Entity implements EntityInterface {
*/
public function label() {
$label = FALSE;
- if (isset($this->entityInfo['label callback']) && function_exists($this->entityInfo['label callback'])) {
- $label = $this->entityInfo['label callback']($this->entityType, $this);
+ $entity_info = $this->entityInfo();
+ if (isset($entity_info['label callback']) && function_exists($entity_info['label callback'])) {
+ $label = $entity_info['label callback']($this->entityType, $this);
}
- elseif (!empty($this->entityInfo['entity keys']['label']) && isset($this->{$this->entityInfo['entity keys']['label']})) {
- $label = $this->{$this->entityInfo['entity keys']['label']};
+ elseif (!empty($entity_info['entity keys']['label']) && isset($this->{$entity_info['entity keys']['label']})) {
+ $label = $this->{$entity_info['entity keys']['label']};
}
return $label;
}
@@ -254,11 +224,12 @@ class Entity implements EntityInterface {
$bundle = $this->bundle();
// A bundle-specific callback takes precedence over the generic one for the
// entity type.
- if (isset($this->entityInfo['bundles'][$bundle]['uri callback'])) {
- $uri_callback = $this->entityInfo['bundles'][$bundle]['uri callback'];
+ $entity_info = $this->entityInfo();
+ if (isset($entity_info['bundles'][$bundle]['uri callback'])) {
+ $uri_callback = $entity_info['bundles'][$bundle]['uri callback'];
}
- elseif (isset($this->entityInfo['uri callback'])) {
- $uri_callback = $this->entityInfo['uri callback'];
+ elseif (isset($entity_info['uri callback'])) {
+ $uri_callback = $entity_info['uri callback'];
}
else {
return NULL;
@@ -304,28 +275,6 @@ class Entity implements EntityInterface {
* Implements EntityInterface::entityInfo().
*/
public function entityInfo() {
- return $this->entityInfo;
- }
-
- /**
- * Serializes only what is necessary.
- *
- * See @link http://www.php.net/manual/language.oop5.magic.php#language.oop5.magic.sleep PHP Magic Methods @endlink.
- */
- public function __sleep() {
- $vars = get_object_vars($this);
- unset($vars['entityInfo'], $vars['idKey'], $vars['bundleKey']);
- // Also key the returned array with the variable names so the method may
- // be easily overridden and customized.
- return drupal_map_assoc(array_keys($vars));
- }
-
- /**
- * Invokes setUp() on unserialization.
- *
- * See @link http://www.php.net/manual/language.oop5.magic.php#language.oop5.magic.sleep PHP Magic Methods @endlink
- */
- public function __wakeup() {
- $this->setUp();
+ return entity_get_info($this->entityType);
}
}
diff --git a/core/modules/entity/tests/entity_crud_hook_test.test b/core/modules/entity/tests/entity_crud_hook_test.test
index be59e99..f582c74 100644
--- a/core/modules/entity/tests/entity_crud_hook_test.test
+++ b/core/modules/entity/tests/entity_crud_hook_test.test
@@ -356,16 +356,15 @@ class EntityCrudHookTestCase extends DrupalWebTestCase {
* Tests hook invocations for CRUD operations on users.
*/
public function testUserHooks() {
- $edit = array(
+ $account = entity_create('user', array(
'name' => 'Test user',
'mail' => 'test@example.com',
'created' => REQUEST_TIME,
'status' => 1,
'language' => 'en',
- );
- $account = (object) $edit;
+ ));
$_SESSION['entity_crud_hook_test'] = array();
- $account = user_save($account, $edit);
+ $account->save();
$this->assertHookMessageOrder(array(
'entity_crud_hook_test_user_presave called',
@@ -375,7 +374,7 @@ class EntityCrudHookTestCase extends DrupalWebTestCase {
));
$_SESSION['entity_crud_hook_test'] = array();
- $account = user_load($account->uid);
+ user_load($account->uid);
$this->assertHookMessageOrder(array(
'entity_crud_hook_test_entity_load called for type user',
@@ -383,8 +382,8 @@ class EntityCrudHookTestCase extends DrupalWebTestCase {
));
$_SESSION['entity_crud_hook_test'] = array();
- $edit['name'] = 'New name';
- $account = user_save($account, $edit);
+ $account->name = 'New name';
+ $account->save();
$this->assertHookMessageOrder(array(
'entity_crud_hook_test_user_presave called',
diff --git a/core/modules/file/tests/file.test b/core/modules/file/tests/file.test
index 05083fc..92b7ef3 100644
--- a/core/modules/file/tests/file.test
+++ b/core/modules/file/tests/file.test
@@ -709,9 +709,8 @@ class FileFieldRevisionTestCase extends FileFieldTestCase {
// Attach the second file to a user.
$user = $this->drupalCreateUser();
- $edit = (array) $user;
- $edit[$field_name][LANGUAGE_NOT_SPECIFIED][0] = (array) $node_file_r3;
- user_save($user, $edit);
+ $user->{$field_name}[LANGUAGE_NOT_SPECIFIED][0] = (array) $node_file_r3;
+ $user->save();
$this->drupalGet('user/' . $user->uid . '/edit');
// Delete the third revision and check that the file is not deleted yet.
diff --git a/core/modules/openid/openid.module b/core/modules/openid/openid.module
index a3df38f..ddde6db 100644
--- a/core/modules/openid/openid.module
+++ b/core/modules/openid/openid.module
@@ -83,15 +83,15 @@ function openid_help($path, $arg) {
/**
* Implements hook_user_insert().
*/
-function openid_user_insert(&$edit, $account) {
- if (!empty($edit['openid_claimed_id'])) {
+function openid_user_insert($account) {
+ if (!empty($account->openid_claimed_id)) {
// The user has registered after trying to log in via OpenID.
if (variable_get('user_email_verification', TRUE)) {
drupal_set_message(t('Once you have verified your e-mail address, you may log in via OpenID.'));
}
- user_set_authmaps($account, array('authname_openid' => $edit['openid_claimed_id']));
+ user_set_authmaps($account, array('authname_openid' => $account->openid_claimed_id));
unset($_SESSION['openid']);
- unset($edit['openid_claimed_id']);
+ unset($account->openid_claimed_id);
}
}
@@ -100,7 +100,7 @@ function openid_user_insert(&$edit, $account) {
*
* Save openid_identifier to visitor cookie.
*/
-function openid_user_login(&$edit, $account) {
+function openid_user_login($account) {
if (isset($_SESSION['openid'])) {
// The user has logged in via OpenID.
user_cookie_save(array_intersect_key($_SESSION['openid']['user_login_values'], array_flip(array('openid_identifier'))));
diff --git a/core/modules/openid/openid.test b/core/modules/openid/openid.test
index 7a4c9cf..e6a4f46 100644
--- a/core/modules/openid/openid.test
+++ b/core/modules/openid/openid.test
@@ -189,9 +189,9 @@ class OpenIDFunctionalTestCase extends OpenIDWebTestCase {
$identity = url('openid-test/yadis/xrds', array('absolute' => TRUE));
$this->addIdentity($identity);
$response = variable_get('openid_test_hook_openid_response_response');
- $account = variable_get('openid_test_hook_openid_response_account');
+ $account_uid = variable_get('openid_test_hook_openid_response_account');
$this->assertEqual($response['openid.claimed_id'], $identity, t('hook_openid_response() was invoked.'));
- $this->assertEqual($account->uid, $this->web_user->uid, t('Proper user object passed to hook_openid_response().'));
+ $this->assertEqual($account_uid, $this->web_user->uid, 'Proper user object passed to hook_openid_response().');
$this->drupalLogout();
@@ -201,9 +201,9 @@ class OpenIDFunctionalTestCase extends OpenIDWebTestCase {
$this->submitLoginForm($identity);
$this->assertLink(t('Log out'), 0, t('User was logged in.'));
$response = variable_get('openid_test_hook_openid_response_response');
- $account = variable_get('openid_test_hook_openid_response_account');
+ $account_uid = variable_get('openid_test_hook_openid_response_account');
$this->assertEqual($response['openid.claimed_id'], $identity, t('hook_openid_response() was invoked.'));
- $this->assertEqual($account->uid, $this->web_user->uid, t('Proper user object passed to hook_openid_response().'));
+ $this->assertEqual($account_uid, $this->web_user->uid, 'Proper user object passed to hook_openid_response().');
$this->drupalLogout();
@@ -571,7 +571,7 @@ class OpenIDRegistrationTestCase extends OpenIDWebTestCase {
$user = user_load_by_name('john');
$this->assertTrue($user, t('User was registered with right username.'));
- $this->assertFalse($user->preferred_langcode, t('No user language was saved.'));
+ $this->assertEqual($user->preferred_langcode, LANGUAGE_NOT_SPECIFIED, 'No user language was saved.');
$this->assertFalse($user->data, t('No additional user info was saved.'));
// Follow the one-time login that was sent in the welcome e-mail.
@@ -611,7 +611,7 @@ class OpenIDRegistrationTestCase extends OpenIDWebTestCase {
$user = user_load_by_name('john');
$this->assertTrue($user, t('User was registered with right username.'));
- $this->assertFalse($user->preferred_langcode, t('No user language was saved.'));
+ $this->assertEqual($user->preferred_langcode, LANGUAGE_NOT_SPECIFIED, 'No user language was saved.');
$this->assertFalse($user->data, t('No additional user info was saved.'));
// Follow the one-time login that was sent in the welcome e-mail.
diff --git a/core/modules/openid/tests/openid_test.module b/core/modules/openid/tests/openid_test.module
index 5bd2f4d..0db8a05 100644
--- a/core/modules/openid/tests/openid_test.module
+++ b/core/modules/openid/tests/openid_test.module
@@ -378,5 +378,5 @@ function openid_test_openid_request_alter(&$request, $service) {
*/
function openid_test_openid_response($response, $account) {
variable_set('openid_test_hook_openid_response_response', $response);
- variable_set('openid_test_hook_openid_response_account', $account ? $account : FALSE);
+ variable_set('openid_test_hook_openid_response_account', $account ? $account->uid : FALSE);
}
diff --git a/core/modules/overlay/overlay.module b/core/modules/overlay/overlay.module
index 58dcbab..f62cf57 100644
--- a/core/modules/overlay/overlay.module
+++ b/core/modules/overlay/overlay.module
@@ -102,9 +102,9 @@ function overlay_form_user_profile_form_alter(&$form, &$form_state) {
/**
* Implements hook_user_presave().
*/
-function overlay_user_presave(&$edit, $account) {
- if (isset($edit['overlay'])) {
- $edit['data']['overlay'] = $edit['overlay'];
+function overlay_user_presave($account) {
+ if (isset($account->overlay)) {
+ $account->data['overlay'] = $account->overlay;
}
}
@@ -311,7 +311,9 @@ function overlay_user_dismiss_message() {
return MENU_ACCESS_DENIED;
}
else {
- user_save(user_load($user->uid), array('data' => array('overlay_message_dismissed' => 1)));
+ $account = user_load($user->uid);
+ $account->data['overlay_message_dismissed'] = 1;
+ $account->save();
drupal_set_message(t('The message has been dismissed. You can change your overlay settings at any time by visiting your profile page.'));
// Destination is normally given. Go to the user profile as a fallback.
drupal_goto('user/' . $user->uid . '/edit');
diff --git a/core/modules/simpletest/drupal_web_test_case.php b/core/modules/simpletest/drupal_web_test_case.php
index 7163739..c6f0c92 100644
--- a/core/modules/simpletest/drupal_web_test_case.php
+++ b/core/modules/simpletest/drupal_web_test_case.php
@@ -1126,7 +1126,8 @@ class DrupalWebTestCase extends DrupalTestCase {
$edit['roles'] = array($rid => $rid);
}
- $account = user_save(drupal_anonymous_user(), $edit);
+ $account = entity_create('user', $edit);
+ $account->save();
$this->assertTrue(!empty($account->uid), t('User created with name %name and pass %pass', array('%name' => $edit['name'], '%pass' => $edit['pass'])), t('User login'));
if (empty($account->uid)) {
@@ -1230,7 +1231,7 @@ class DrupalWebTestCase extends DrupalTestCase {
*
* @see drupalCreateUser()
*/
- protected function drupalLogin(stdClass $user) {
+ protected function drupalLogin($user) {
if ($this->loggedInUser) {
$this->drupalLogout();
}
diff --git a/core/modules/simpletest/tests/session.test b/core/modules/simpletest/tests/session.test
index 6303ca5..bc17bae 100644
--- a/core/modules/simpletest/tests/session.test
+++ b/core/modules/simpletest/tests/session.test
@@ -41,8 +41,8 @@ class SessionTestCase extends DrupalWebTestCase {
// Verify that the session is regenerated if a module calls exit
// in hook_user_login().
- user_save($user, array('name' => 'session_test_user'));
$user->name = 'session_test_user';
+ $user->save();
$this->drupalGet('session-test/id');
$matches = array();
preg_match('/\s*session_id:(.*)\n/', $this->drupalGetContent(), $matches);
diff --git a/core/modules/system/system.module b/core/modules/system/system.module
index 82013ce..ceab02e 100644
--- a/core/modules/system/system.module
+++ b/core/modules/system/system.module
@@ -2009,9 +2009,9 @@ function system_form_user_register_form_alter(&$form, &$form_state) {
}
/**
- * Implements hook_user_insert().
+ * Implements hook_user_presave().
*/
-function system_user_presave(&$edit, $account) {
+function system_user_presave($account) {
if (variable_get('configurable_timezones', 1) && empty($account->timezone) && !variable_get('user_default_timezone', DRUPAL_USER_TIMEZONE_DEFAULT)) {
$account->timezone = variable_get('date_default_timezone', '');
}
@@ -2021,7 +2021,7 @@ function system_user_presave(&$edit, $account) {
/**
* Implements hook_user_login().
*/
-function system_user_login(&$edit, $account) {
+function system_user_login($account) {
// If the user has a NULL time zone, notify them to set a time zone.
if (!$account->timezone && variable_get('configurable_timezones', 1) && variable_get('empty_timezone_message', 0)) {
drupal_set_message(t('Configure your account time zone setting.', array('@user-edit' => url("user/$account->uid/edit", array('query' => drupal_get_destination(), 'fragment' => 'edit-timezone')))));
diff --git a/core/modules/taxonomy/taxonomy.entity.inc b/core/modules/taxonomy/taxonomy.entity.inc
index 00182d8..3562580 100644
--- a/core/modules/taxonomy/taxonomy.entity.inc
+++ b/core/modules/taxonomy/taxonomy.entity.inc
@@ -75,6 +75,20 @@ class TaxonomyTerm extends Entity {
* @var string
*/
public $vocabulary_machine_name;
+
+ /**
+ * Implements EntityInterface::id().
+ */
+ public function id() {
+ return $this->tid;
+ }
+
+ /**
+ * Implements EntityInterface::bundle().
+ */
+ public function bundle() {
+ return $this->vocabulary_machine_name;
+ }
}
/**
@@ -263,6 +277,13 @@ class TaxonomyVocabulary extends Entity {
* @var integer
*/
public $weight = 0;
+
+ /**
+ * Implements EntityInterface::id().
+ */
+ public function id() {
+ return $this->vid;
+ }
}
/**
diff --git a/core/modules/taxonomy/taxonomy.module b/core/modules/taxonomy/taxonomy.module
index 0bd31ef..719817b 100644
--- a/core/modules/taxonomy/taxonomy.module
+++ b/core/modules/taxonomy/taxonomy.module
@@ -1531,8 +1531,8 @@ function taxonomy_rdf_mapping() {
function taxonomy_field_presave($entity_type, $entity, $field, $instance, $langcode, &$items) {
foreach ($items as $delta => $item) {
if ($item['tid'] == 'autocreate') {
+ unset($item['tid']);
$term = entity_create('taxonomy_term', $item);
- unset($term->tid);
$term->langcode = $langcode;
taxonomy_term_save($term);
$items[$delta]['tid'] = $term->tid;
diff --git a/core/modules/taxonomy/taxonomy.test b/core/modules/taxonomy/taxonomy.test
index 00c29dd..65d6805 100644
--- a/core/modules/taxonomy/taxonomy.test
+++ b/core/modules/taxonomy/taxonomy.test
@@ -400,7 +400,7 @@ class TaxonomyVocabularyUnitTest extends TaxonomyWebTestCase {
// connected to this vocabulary name should have been removed when the
// module was uninstalled. Creating a new field with the same name and
// an instance of this field on the same bundle name should be successful.
- unset($this->vocabulary->vid);
+ $this->vocabulary->enforceIsNew();
taxonomy_vocabulary_save($this->vocabulary);
unset($this->field['id']);
field_create_field($this->field);
diff --git a/core/modules/user/lib/Drupal/user/User.php b/core/modules/user/lib/Drupal/user/User.php
new file mode 100644
index 0000000..46a8362
--- /dev/null
+++ b/core/modules/user/lib/Drupal/user/User.php
@@ -0,0 +1,145 @@
+uid;
+ }
+}
diff --git a/core/modules/user/lib/Drupal/user/UserStorageController.php b/core/modules/user/lib/Drupal/user/UserStorageController.php
new file mode 100644
index 0000000..3f73832
--- /dev/null
+++ b/core/modules/user/lib/Drupal/user/UserStorageController.php
@@ -0,0 +1,227 @@
+ $record) {
+ if ($record->picture) {
+ $picture_fids[] = $record->picture;
+ }
+ $queried_users[$key]->data = unserialize($record->data);
+ $queried_users[$key]->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';
+ }
+ }
+
+ // 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;
+ }
+
+ // 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 $entity) {
+ if (!empty($entity->picture) && isset($pictures[$entity->picture])) {
+ $entity->picture = $pictures[$entity->picture];
+ }
+ }
+ }
+ // Call the default attachLoad() method. This will add fields and call
+ // hook_user_load().
+ parent::attachLoad($queried_users, $revision_id);
+ }
+
+ /**
+ * Overrides EntityDatabaseStorageController::create().
+ */
+ public function create(array $values) {
+ if (!isset($values['created'])) {
+ $values['created'] = REQUEST_TIME;
+ }
+ // Users always have the authenticated user role.
+ $values['roles'][DRUPAL_AUTHENTICATED_RID] = 'authenticated user';
+
+ return parent::create($values);
+ }
+
+ /**
+ * Overrides EntityDatabaseStorageController::save().
+ */
+ public function save(EntityInterface $entity) {
+ if (empty($entity->uid)) {
+ $entity->uid = db_next_id(db_query('SELECT MAX(uid) FROM {users}')->fetchField());
+ $entity->enforceIsNew();
+ }
+ parent::save($entity);
+ }
+
+ /**
+ * Overrides EntityDatabaseStorageController::preSave().
+ */
+ protected function preSave(EntityInterface $entity) {
+ // Update the user password if it has changed.
+ if ($entity->isNew() || (!empty($entity->pass) && $entity->pass != $entity->original->pass)) {
+ // Allow alternate password hashing schemes.
+ require_once DRUPAL_ROOT . '/' . variable_get('password_inc', 'core/includes/password.inc');
+ $entity->pass = user_hash_password(trim($entity->pass));
+ // Abort if the hashing failed and returned FALSE.
+ if (!$entity->pass) {
+ throw new EntityMalformedException("The entity doesn't have a password.");
+ }
+ }
+
+ if (!empty($entity->picture_upload)) {
+ $entity->picture = $entity->picture_upload;
+ }
+ // Delete the picture if the submission indicates that it should be deleted
+ // and no replacement was submitted.
+ elseif (!empty($entity->picture_delete)) {
+ $entity->picture = 0;
+ file_usage_delete($entity->original->picture, 'user', 'user', $entity->uid);
+ file_delete($entity->original->picture);
+ }
+
+ if (!$entity->isNew()) {
+ // Process picture uploads.
+ if (!empty($entity->picture->fid) && (!isset($entity->original->picture->fid) || $entity->picture->fid != $entity->original->picture->fid)) {
+ $picture = $entity->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-' . $entity->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;
+ $entity->picture = file_save($picture);
+ file_usage_add($picture, 'user', 'user', $entity->uid);
+ }
+ }
+ // Delete the previous picture if it was deleted or replaced.
+ if (!empty($entity->original->picture->fid)) {
+ file_usage_delete($entity->original->picture, 'user', 'user', $entity->uid);
+ file_delete($entity->original->picture);
+ }
+ }
+ $entity->picture = empty($entity->picture->fid) ? 0 : $entity->picture->fid;
+
+ // If the password is empty, that means it was not changed, so use the
+ // original password.
+ if (empty($entity->pass)) {
+ $entity->pass = $entity->original->pass;
+ }
+ }
+
+ // Prepare user roles.
+ if (isset($entity->roles)) {
+ $entity->roles = array_filter($entity->roles);
+ }
+
+ // Move account cancellation information into $entity->data.
+ foreach (array('user_cancel_method', 'user_cancel_notify') as $key) {
+ if (isset($entity->{$key})) {
+ $entity->data[$key] = $entity->{$key};
+ }
+ }
+ }
+
+ /**
+ * Overrides EntityDatabaseStorageController::postSave().
+ */
+ protected function postSave(EntityInterface $entity, $update) {
+
+ if ($update) {
+ // If the password has been changed, delete all open sessions for the
+ // user and recreate the current one.
+ if ($entity->pass != $entity->original->pass) {
+ drupal_session_destroy_uid($entity->uid);
+ if ($entity->uid == $GLOBALS['user']->uid) {
+ drupal_session_regenerate();
+ }
+ }
+
+ // Remove roles that are no longer enabled for the user.
+ $entity->roles = array_filter($entity->roles);
+
+ // Reload user roles if provided.
+ if ($entity->roles != $entity->original->roles) {
+ db_delete('users_roles')
+ ->condition('uid', $entity->uid)
+ ->execute();
+
+ $query = db_insert('users_roles')->fields(array('uid', 'rid'));
+ foreach (array_keys($entity->roles) as $rid) {
+ if (!in_array($rid, array(DRUPAL_ANONYMOUS_RID, DRUPAL_AUTHENTICATED_RID))) {
+ $query->values(array(
+ 'uid' => $entity->uid,
+ 'rid' => $rid,
+ ));
+ }
+ }
+ $query->execute();
+ }
+
+ // If the user was blocked, delete the user's sessions to force a logout.
+ if ($entity->original->status != $entity->status && $entity->status == 0) {
+ drupal_session_destroy_uid($entity->uid);
+ }
+
+ // Send emails after we have the new user object.
+ if ($entity->status != $entity->original->status) {
+ // The user's status is changing; conditionally send notification email.
+ $op = $entity->status == 1 ? 'status_activated' : 'status_blocked';
+ _user_mail_notify($op, $entity);
+ }
+ }
+ else {
+ // Save user roles.
+ if (count($entity->roles) > 1) {
+ $query = db_insert('users_roles')->fields(array('uid', 'rid'));
+ foreach (array_keys($entity->roles) as $rid) {
+ if (!in_array($rid, array(DRUPAL_ANONYMOUS_RID, DRUPAL_AUTHENTICATED_RID))) {
+ $query->values(array(
+ 'uid' => $entity->uid,
+ 'rid' => $rid,
+ ));
+ }
+ }
+ $query->execute();
+ }
+ }
+ }
+}
diff --git a/core/modules/user/user.api.php b/core/modules/user/user.api.php
index dc16906..574ce32 100644
--- a/core/modules/user/user.api.php
+++ b/core/modules/user/user.api.php
@@ -227,67 +227,57 @@ function hook_user_operations() {
}
/**
- * A user account is about to be created or updated.
+ * Act on a user account being inserted or updated.
*
- * This hook is primarily intended for modules that want to store properties in
- * the serialized {users}.data column, which is automatically loaded whenever a
- * user account object is loaded, modules may add to $edit['data'] in order
- * to have their data serialized on save.
+ * This hook is invoked before the user account is saved to the database.
+ *
+ * Modules that want to store properties in the serialized {users}.data column,
+ * which is automatically loaded whenever a user account object is loaded, may
+ * add their properties to $account->data in order to have their data serialized
+ * on save.
*
- * @param $edit
- * The array of form values submitted by the user.
* @param $account
- * The user object on which the operation is performed.
+ * The user account object.
*
* @see hook_user_insert()
* @see hook_user_update()
*/
-function hook_user_presave(&$edit, $account) {
+function hook_user_presave($account) {
// Make sure that our form value 'mymodule_foo' is stored as
// 'mymodule_bar' in the 'data' (serialized) column.
- if (isset($edit['mymodule_foo'])) {
- $edit['data']['mymodule_bar'] = $edit['mymodule_foo'];
+ if (isset($account->mymodule_foo)) {
+ $account->data['mymodule_bar'] = $account->mymodule_foo;
}
}
/**
- * A user account was created.
- *
- * The module should save its custom additions to the user object into the
- * database.
+ * Respond to creation of a new user account.
*
- * @param $edit
- * The array of form values submitted by the user.
* @param $account
- * The user object on which the operation is being performed.
+ * The user account object.
*
* @see hook_user_presave()
* @see hook_user_update()
*/
-function hook_user_insert(&$edit, $account) {
- db_insert('mytable')
+function hook_user_insert($account) {
+ db_insert('user_changes')
->fields(array(
- 'myfield' => $edit['myfield'],
'uid' => $account->uid,
+ 'created' => time(),
))
->execute();
}
/**
- * A user account was updated.
- *
- * Modules may use this hook to update their user data in a custom storage
- * after a user account has been updated.
+ * Respond to updates to a user account.
*
- * @param $edit
- * The array of form values submitted by the user.
* @param $account
- * The user object on which the operation is performed.
+ * The user account object.
*
* @see hook_user_presave()
* @see hook_user_insert()
*/
-function hook_user_update(&$edit, $account) {
+function hook_user_update($account) {
db_insert('user_changes')
->fields(array(
'uid' => $account->uid,
@@ -297,14 +287,12 @@ function hook_user_update(&$edit, $account) {
}
/**
- * The user just logged in.
+ * Respond to a user logging in.
*
- * @param $edit
- * The array of form values submitted by the user.
* @param $account
- * The user object on which the operation was just performed.
+ * The user account object.
*/
-function hook_user_login(&$edit, $account) {
+function hook_user_login($account) {
// If the user has a NULL time zone, notify them to set a time zone.
if (!$account->timezone && variable_get('configurable_timezones', 1) && variable_get('empty_timezone_message', 0)) {
drupal_set_message(t('Configure your account time zone setting.', array('@user-edit' => url("user/$account->uid/edit", array('query' => drupal_get_destination(), 'fragment' => 'edit-timezone')))));
diff --git a/core/modules/user/user.entity.inc b/core/modules/user/user.entity.inc
deleted file mode 100644
index 5549c77..0000000
--- a/core/modules/user/user.entity.inc
+++ /dev/null
@@ -1,52 +0,0 @@
- $record) {
- $picture_fids[] = $record->picture;
- $queried_users[$key]->data = unserialize($record->data);
- $queried_users[$key]->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';
- }
- }
-
- // 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;
- }
-
- // 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;
- }
- }
- }
- // Call the default attachLoad() method. This will add fields and call
- // hook_user_load().
- parent::attachLoad($queried_users, $revision_id);
- }
-}
diff --git a/core/modules/user/user.info b/core/modules/user/user.info
index d887352..8dad5a3 100644
--- a/core/modules/user/user.info
+++ b/core/modules/user/user.info
@@ -3,7 +3,6 @@ description = Manages the user registration and login system.
package = Core
version = VERSION
core = 8.x
-files[] = user.entity.inc
files[] = user.test
required = TRUE
configure = admin/config/people
diff --git a/core/modules/user/user.module b/core/modules/user/user.module
index 865f17b..f320dfb 100644
--- a/core/modules/user/user.module
+++ b/core/modules/user/user.module
@@ -77,33 +77,6 @@ function user_help($path, $arg) {
}
/**
- * Invokes a user hook in every module.
- *
- * We cannot use module_invoke() for this, because the arguments need to
- * be passed by reference.
- *
- * @param $type
- * A text string that controls which user hook to invoke. Valid choices are:
- * - cancel: Invokes hook_user_cancel().
- * - insert: Invokes hook_user_insert().
- * - login: Invokes hook_user_login().
- * - presave: Invokes hook_user_presave().
- * - update: Invokes hook_user_update().
- * @param $edit
- * An associative array variable containing form values to be passed
- * as the first parameter of the hook function.
- * @param $account
- * The user account object to be passed as the second parameter of the hook
- * function.
- */
-function user_module_invoke($type, &$edit, $account) {
- foreach (module_implements('user_' . $type) as $module) {
- $function = $module . '_user_' . $type;
- $function($edit, $account);
- }
-}
-
-/**
* Implements hook_theme().
*/
function user_theme() {
@@ -145,14 +118,15 @@ function user_theme() {
* Implements hook_entity_info().
*/
function user_entity_info() {
- $return = array(
+ return array(
'user' => array(
'label' => t('User'),
- 'controller class' => 'UserController',
+ 'controller class' => 'Drupal\user\UserStorageController',
'base table' => 'users',
'uri callback' => 'user_uri',
'label callback' => 'user_label',
'fieldable' => TRUE,
+ 'entity class' => 'Drupal\user\User',
'entity keys' => array(
'id' => 'uid',
),
@@ -173,7 +147,6 @@ function user_entity_info() {
),
),
);
- return $return;
}
/**
@@ -360,224 +333,6 @@ function user_load_by_name($name) {
}
/**
- * Save changes to a user account or add a new user.
- *
- * @param $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.
- * @param $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.
- *
- * @return
- * A fully-loaded $user object upon successful save or FALSE if the save failed.
- *
- * @todo D8: Drop $edit and fix user_save() to be consistent with others.
- */
-function user_save($account, $edit = array()) {
- $transaction = db_transaction();
- try {
- if (!empty($edit['pass'])) {
- // Allow alternate password hashing schemes.
- require_once DRUPAL_ROOT . '/' . variable_get('password_inc', 'core/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']);
- }
-
- // 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);
-
- // 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;
- }
- // Default the user entity language to the user's preferred language.
- if (!isset($account->langcode) && isset($account->preferred_langcode)) {
- $account->langcode = $account->preferred_langcode;
- }
- 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);
- }
- $account->picture = empty($account->picture->fid) ? 0 : $account->picture->fid;
-
- // Do not allow 'uid' to be changed.
- $account->uid = $account->original->uid;
- // Save changes to the user table.
- $success = drupal_write_record('users', $account, 'uid');
- 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);
- 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;
- }
- $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);
- module_invoke_all('entity_insert', $account, 'user');
-
- // Save user roles.
- if (count($account->roles) > 1) {
- $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();
- }
- }
- // 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;
- }
-}
-
-/**
* Verify the syntax of the given name.
*/
function user_validate_name($name) {
@@ -1126,14 +881,28 @@ function user_account_form_validate($form, &$form_state) {
if ($error = user_validate_name($form_state['values']['name'])) {
form_set_error('name', $error);
}
- elseif ((bool) db_select('users')->fields('users', array('uid'))->condition('uid', $account->uid, '<>')->condition('name', db_like($form_state['values']['name']), 'LIKE')->range(0, 1)->execute()->fetchField()) {
+ // Cast the user ID as an integer. It might have been set to NULL, which
+ // could lead to unexpected results.
+ elseif ((bool) db_select('users')
+ ->fields('users', array('uid'))
+ ->condition('uid', (int) $account->uid, '<>')
+ ->condition('name', db_like($form_state['values']['name']), 'LIKE')
+ ->range(0, 1)
+ ->execute()
+ ->fetchField()) {
form_set_error('name', t('The name %name is already taken.', array('%name' => $form_state['values']['name'])));
}
}
$mail = $form_state['values']['mail'];
- if ((bool) db_select('users')->fields('users', array('uid'))->condition('uid', $account->uid, '<>')->condition('mail', db_like($mail), 'LIKE')->range(0, 1)->execute()->fetchField()) {
+ if ((bool) db_select('users')
+ ->fields('users', array('uid'))
+ ->condition('uid', (int) $account->uid, '<>')
+ ->condition('mail', db_like($mail), 'LIKE')
+ ->range(0, 1)
+ ->execute()
+ ->fetchField()) {
// Format error message dependent on whether the user is logged in or not.
if ($GLOBALS['user']->uid) {
form_set_error('mail', t('The e-mail address %email is already taken.', array('%email' => $mail)));
@@ -1158,30 +927,6 @@ function user_account_form_validate($form, &$form_state) {
}
}
-/**
- * Implements hook_user_presave().
- */
-function user_user_presave(&$edit, $account) {
- if (!empty($edit['picture_upload'])) {
- $edit['picture'] = $edit['picture_upload'];
- }
- // Delete picture if requested, and if no replacement picture was given.
- elseif (!empty($edit['picture_delete'])) {
- $edit['picture'] = NULL;
- }
- // Prepare user roles.
- if (isset($edit['roles'])) {
- $edit['roles'] = array_filter($edit['roles']);
- }
-
- // Move account cancellation information into $user->data.
- foreach (array('user_cancel_method', 'user_cancel_notify') as $key) {
- if (isset($edit[$key])) {
- $edit['data'][$key] = $edit[$key];
- }
- }
-}
-
function user_login_block($form) {
$form['#action'] = url($_GET['q'], array('query' => drupal_get_destination()));
$form['#id'] = 'user-login-form';
@@ -2181,7 +1926,8 @@ function user_authenticate($name, $password) {
// Update user to new password scheme if needed.
if (user_needs_new_hash($account)) {
- user_save($account, array('pass' => $password));
+ $account->pass = $password;
+ $account->save();
}
}
}
@@ -2211,7 +1957,7 @@ function user_login_finalize(&$edit = array()) {
// or incorrectly does a redirect which would leave the old session in place.
drupal_session_regenerate();
- user_module_invoke('login', $edit, $user);
+ module_invoke_all('user_login', $user);
}
/**
@@ -2236,16 +1982,16 @@ function user_external_login_register($name, $module) {
$account = user_external_load($name);
if (!$account) {
// Register this new user.
- $userinfo = array(
+ $account = entity_create('user', array(
'name' => $name,
'pass' => user_password(),
'init' => $name,
'status' => 1,
'access' => REQUEST_TIME
- );
- $account = user_save(drupal_anonymous_user(), $userinfo);
- // Terminate if an error occurred during user_save().
- if (!$account) {
+ ));
+ $status = $account->save();
+ // Terminate if an error occurred while saving the account.
+ if ($status != SAVED_NEW) {
drupal_set_message(t("Error saving user account."), 'error');
return;
}
@@ -2393,7 +2139,8 @@ function _user_cancel($edit, $account, $method) {
if (!empty($edit['user_cancel_notify'])) {
_user_mail_notify('status_blocked', $account);
}
- user_save($account, array('status' => 0));
+ $account->status = 0;
+ $account->save();
drupal_set_message(t('%name has been disabled.', array('%name' => $account->name)));
watchdog('user', 'Blocked user: %name %email.', array('%name' => $account->name, '%email' => '<' . $account->mail . '>'), WATCHDOG_NOTICE);
break;
@@ -3147,7 +2894,8 @@ function user_user_operations_unblock($accounts) {
foreach ($accounts as $account) {
// Skip unblocking user if they are already unblocked.
if ($account !== FALSE && $account->status == 0) {
- user_save($account, array('status' => 1));
+ $account->status = 1;
+ $account->save();
}
}
}
@@ -3163,7 +2911,8 @@ function user_user_operations_block($accounts) {
// For efficiency manually save the original account before applying any
// changes.
$account->original = clone $account;
- user_save($account, array('status' => 0));
+ $account->status = 0;
+ $account->save();
}
}
}
@@ -3172,8 +2921,6 @@ function user_user_operations_block($accounts) {
* Callback function for admin mass adding/deleting a user role.
*/
function user_multiple_role_edit($accounts, $operation, $rid) {
- // The role name is not necessary as user_save() will reload the user
- // object, but some modules' hook_user() may look at this first.
$role_name = db_query('SELECT name FROM {role} WHERE rid = :rid', array(':rid' => $rid))->fetchField();
switch ($operation) {
@@ -3186,7 +2933,8 @@ function user_multiple_role_edit($accounts, $operation, $rid) {
// For efficiency manually save the original account before applying
// any changes.
$account->original = clone $account;
- user_save($account, array('roles' => $roles));
+ $account->roles = $roles;
+ $account->save();
}
}
break;
@@ -3199,7 +2947,8 @@ function user_multiple_role_edit($accounts, $operation, $rid) {
// For efficiency manually save the original account before applying
// any changes.
$account->original = clone $account;
- user_save($account, array('roles' => $roles));
+ $account->roles = $roles;
+ $account->save();
}
}
break;
@@ -3289,7 +3038,7 @@ function user_multiple_cancel_confirm_submit($form, &$form_state) {
if ($uid == $user->uid) {
$admin_form_state = $form_state;
unset($admin_form_state['values']['user_cancel_confirm']);
- $admin_form_state['values']['_account'] = $user;
+ $admin_form_state['values']['_account'] = user_load($user->uid);
user_cancel_confirm_form_submit(array(), $admin_form_state);
}
else {
@@ -3363,7 +3112,7 @@ function user_build_filter_query(SelectInterface $query) {
// the authenticated role. If so, then all users would be listed, and we can
// skip adding it to the filter query.
if ($key == 'permission') {
- $account = new stdClass();
+ $account = entity_create('user', array());
$account->uid = 'user_filter';
$account->roles = array(DRUPAL_AUTHENTICATED_RID => 1);
if (user_access($value, $account)) {
@@ -3609,7 +3358,8 @@ function user_block_user_action(&$entity, $context = array()) {
$uid = $GLOBALS['user']->uid;
}
$account = user_load($uid);
- $account = user_save($account, array('status' => 0));
+ $account->status = 0;
+ $account->save();
watchdog('action', 'Blocked user %name.', array('%name' => $account->name));
}
@@ -3688,7 +3438,7 @@ function user_register_form($form, &$form_state) {
drupal_goto('user/' . $user->uid);
}
- $form['#user'] = drupal_anonymous_user();
+ $form['#user'] = entity_create('user', array());
$form['#attached']['library'][] = array('system', 'jquery.cookie');
$form['#attributes']['class'][] = 'user-info-from-cookie';
@@ -3759,14 +3509,10 @@ function user_register_submit($form, &$form_state) {
$account = $form['#user'];
entity_form_submit_build_entity('user', $account, $form, $form_state);
+ $status = $account->save();
- // Populate $edit with the properties of $account, which have been edited on
- // this form by taking over all values, which appear in the form values too.
- $edit = array_intersect_key((array) $account, $form_state['values']);
- $account = user_save($account, $edit);
-
- // Terminate if an error occurred during user_save().
- if (!$account) {
+ // Terminate if an error occurred while saving the account.
+ if ($status =! SAVED_NEW) {
drupal_set_message(t("Error saving user account."), 'error');
$form_state['redirect'] = '';
return;
diff --git a/core/modules/user/user.pages.inc b/core/modules/user/user.pages.inc
index f24849c..438fedb 100644
--- a/core/modules/user/user.pages.inc
+++ b/core/modules/user/user.pages.inc
@@ -264,19 +264,8 @@ function user_profile_form_submit($form, &$form_state) {
// Remove unneeded values.
form_state_values_clean($form_state);
- // Before updating the account entity, keep an unchanged copy for use with
- // user_save() later. This is necessary for modules implementing the user
- // hooks to be able to react on changes by comparing the values of $account
- // and $edit.
- $account_unchanged = clone $account;
-
entity_form_submit_build_entity('user', $account, $form, $form_state);
-
- // Populate $edit with the properties of $account, which have been edited on
- // this form by taking over all values, which appear in the form values too.
- $edit = array_intersect_key((array) $account, $form_state['values']);
-
- user_save($account_unchanged, $edit);
+ $account->save();
$form_state['values']['uid'] = $account->uid;
if (!empty($edit['pass'])) {
@@ -400,11 +389,9 @@ function user_cancel_confirm_form_submit($form, &$form_state) {
else {
// Store cancelling method and whether to notify the user in $account for
// user_cancel_confirm().
- $edit = array(
- 'user_cancel_method' => $form_state['values']['user_cancel_method'],
- 'user_cancel_notify' => $form_state['values']['user_cancel_notify'],
- );
- $account = user_save($account, $edit);
+ $account->user_cancel_method = $form_state['values']['user_cancel_method'];
+ $account->user_cancel_notify = $form_state['values']['user_cancel_notify'];
+ $account->save();
_user_mail_notify('cancel_confirm', $account);
drupal_set_message(t('A confirmation request to cancel your account has been sent to your e-mail address.'));
watchdog('user', 'Sent account cancellation request to %name %email.', array('%name' => $account->name, '%email' => '<' . $account->mail . '>'), WATCHDOG_NOTICE);
diff --git a/core/modules/user/user.test b/core/modules/user/user.test
index 06fbc95..d758e3a 100644
--- a/core/modules/user/user.test
+++ b/core/modules/user/user.test
@@ -166,9 +166,9 @@ class UserRegistrationTestCase extends DrupalWebTestCase {
$this->assertTrue(($new_user->created > REQUEST_TIME - 20 ), t('Correct creation time.'));
$this->assertEqual($new_user->status, variable_get('user_register', USER_REGISTER_VISITORS_ADMINISTRATIVE_APPROVAL) == USER_REGISTER_VISITORS ? 1 : 0, t('Correct status field.'));
$this->assertEqual($new_user->timezone, variable_get('date_default_timezone'), t('Correct time zone field.'));
- $this->assertEqual($new_user->langcode, '', t('Correct language field.'));
- $this->assertEqual($new_user->preferred_langcode, '', t('Correct preferred language field.'));
- $this->assertEqual($new_user->picture, '', t('Correct picture field.'));
+ $this->assertEqual($new_user->langcode, LANGUAGE_NOT_SPECIFIED, 'Correct language field.');
+ $this->assertEqual($new_user->preferred_langcode, LANGUAGE_NOT_SPECIFIED, 'Correct preferred language field.');
+ $this->assertEqual($new_user->picture, 0, t('Correct picture field.'));
$this->assertEqual($new_user->init, $mail, t('Correct init field.'));
}
@@ -553,7 +553,8 @@ class UserCancelTestCase extends DrupalWebTestCase {
'name' => 'user1',
'pass' => user_hash_password(trim($password)),
);
- // We cannot use user_save() here or the password would be hashed again.
+ // We cannot use $account->save() here, because this would result in the
+ // password being hashed again.
db_update('users')
->fields($account)
->condition('uid', 1)
@@ -1146,7 +1147,7 @@ class UserPictureTestCase extends DrupalWebTestCase {
// Load actual user data from database.
$account = user_load($this->user->uid, TRUE);
- $pic_path = isset($account->picture) ? $account->picture->uri : NULL;
+ $pic_path = !empty($account->picture) ? $account->picture->uri : NULL;
// Check if image is displayed in user's profile page.
$this->drupalGet('user');
@@ -1160,7 +1161,7 @@ class UserPictureTestCase extends DrupalWebTestCase {
// Load actual user data from database.
$account1 = user_load($this->user->uid, TRUE);
- $this->assertNull($account1->picture, 'User object has no picture');
+ $this->assertFalse($account1->picture, 'User object has no picture');
$file = file_load($account->picture->fid);
$this->assertFalse($file, 'File is removed from database');
@@ -1176,7 +1177,7 @@ class UserPictureTestCase extends DrupalWebTestCase {
// Load actual user data from database.
$account = user_load($this->user->uid, TRUE);
- return isset($account->picture) ? $account->picture->uri : NULL;
+ return !empty($account->picture) ? $account->picture->uri : NULL;
}
}
@@ -1624,14 +1625,14 @@ class UserBlocksUnitTests extends DrupalWebTestCase {
}
/**
- * Test case to test user_save() behaviour.
+ * Tests saving a user account.
*/
class UserSaveTestCase extends DrupalWebTestCase {
public static function getInfo() {
return array(
'name' => 'User save test',
- 'description' => 'Test user_save() for arbitrary new uid.',
+ 'description' => 'Test account saving for arbitrary new uid.',
'group' => 'User',
);
}
@@ -1646,16 +1647,15 @@ class UserSaveTestCase extends DrupalWebTestCase {
$test_name = $this->randomName();
// Create the base user, based on drupalCreateUser().
- $user = array(
+ $user = entity_create('user', array(
'name' => $test_name,
'uid' => $test_uid,
'mail' => $test_name . '@example.com',
- 'is_new' => TRUE,
'pass' => user_password(),
'status' => 1,
- );
- $user_by_return = user_save(drupal_anonymous_user(), $user);
- $this->assertTrue($user_by_return, t('Loading user by return of user_save().'));
+ ));
+ $user->enforceIsNew();
+ $user->save();
// Test if created user exists.
$user_by_uid = user_load($test_uid);
@@ -1713,7 +1713,7 @@ class UserCreateTestCase extends DrupalWebTestCase {
}
/**
- * Test case to test user_save() behaviour.
+ * Tests editing a user account.
*/
class UserEditTestCase extends DrupalWebTestCase {