Issue #1479454 by Hugo Wetterberg, galooph, dawehner, andypost, marcingy, heyrocker...
[project/drupal.git] / core / modules / user / lib / Drupal / user / UserStorageController.php
1 <?php
2
3 /**
4 * @file
5 * Definition of Drupal\user\UserStorageController.
6 */
7
8 namespace Drupal\user;
9
10 use Drupal\Core\Entity\EntityInterface;
11 use Drupal\Core\Entity\EntityMalformedException;
12 use Drupal\Core\Entity\DatabaseStorageController;
13
14 /**
15 * Controller class for users.
16 *
17 * This extends the Drupal\Core\Entity\DatabaseStorageController class, adding
18 * required special handling for user objects.
19 */
20 class UserStorageController extends DatabaseStorageController {
21
22 /**
23 * Overrides Drupal\Core\Entity\DatabaseStorageController::attachLoad().
24 */
25 function attachLoad(&$queried_users, $load_revision = FALSE) {
26 foreach ($queried_users as $key => $record) {
27 $queried_users[$key]->roles = array();
28 if ($record->uid) {
29 $queried_users[$record->uid]->roles[DRUPAL_AUTHENTICATED_RID] = DRUPAL_AUTHENTICATED_RID;
30 }
31 else {
32 $queried_users[$record->uid]->roles[DRUPAL_ANONYMOUS_RID] = DRUPAL_ANONYMOUS_RID;
33 }
34 }
35
36 // Add any additional roles from the database.
37 $result = db_query('SELECT rid, uid FROM {users_roles} WHERE uid IN (:uids)', array(':uids' => array_keys($queried_users)));
38 foreach ($result as $record) {
39 $queried_users[$record->uid]->roles[$record->rid] = $record->rid;
40 }
41
42 // Call the default attachLoad() method. This will add fields and call
43 // hook_user_load().
44 parent::attachLoad($queried_users, $load_revision);
45 }
46
47 /**
48 * Overrides Drupal\Core\Entity\DatabaseStorageController::create().
49 */
50 public function create(array $values) {
51 if (!isset($values['created'])) {
52 $values['created'] = REQUEST_TIME;
53 }
54 // Users always have the authenticated user role.
55 $values['roles'][DRUPAL_AUTHENTICATED_RID] = DRUPAL_AUTHENTICATED_RID;
56
57 return parent::create($values);
58 }
59
60 /**
61 * Overrides Drupal\Core\Entity\DatabaseStorageController::save().
62 */
63 public function save(EntityInterface $entity) {
64 if (empty($entity->uid)) {
65 $entity->uid = db_next_id(db_query('SELECT MAX(uid) FROM {users}')->fetchField());
66 $entity->enforceIsNew();
67 }
68 parent::save($entity);
69 }
70
71 /**
72 * Overrides Drupal\Core\Entity\DatabaseStorageController::preSave().
73 */
74 protected function preSave(EntityInterface $entity) {
75 // Update the user password if it has changed.
76 if ($entity->isNew() || (!empty($entity->pass) && $entity->pass != $entity->original->pass)) {
77 // Allow alternate password hashing schemes.
78 $entity->pass = drupal_container()->get('password')->hash(trim($entity->pass));
79 // Abort if the hashing failed and returned FALSE.
80 if (!$entity->pass) {
81 throw new EntityMalformedException('The entity does not have a password.');
82 }
83 }
84
85 if (!$entity->isNew()) {
86 // If the password is empty, that means it was not changed, so use the
87 // original password.
88 if (empty($entity->pass)) {
89 $entity->pass = $entity->original->pass;
90 }
91 }
92
93 // Prepare user roles.
94 if (isset($entity->roles)) {
95 $entity->roles = array_filter($entity->roles);
96 }
97
98 // Store account cancellation information.
99 foreach (array('user_cancel_method', 'user_cancel_notify') as $key) {
100 if (isset($entity->{$key})) {
101 drupal_container()->get('user.data')->set('user', $entity->id(), substr($key, 5), $entity->{$key});
102 }
103 }
104 }
105
106 /**
107 * Overrides Drupal\Core\Entity\DatabaseStorageController::postSave().
108 */
109 protected function postSave(EntityInterface $entity, $update) {
110
111 if ($update) {
112 // If the password has been changed, delete all open sessions for the
113 // user and recreate the current one.
114 if ($entity->pass != $entity->original->pass) {
115 drupal_session_destroy_uid($entity->uid);
116 if ($entity->uid == $GLOBALS['user']->uid) {
117 drupal_session_regenerate();
118 }
119 }
120
121 // Remove roles that are no longer enabled for the user.
122 $entity->roles = array_filter($entity->roles);
123
124 // Reload user roles if provided.
125 if ($entity->roles != $entity->original->roles) {
126 db_delete('users_roles')
127 ->condition('uid', $entity->uid)
128 ->execute();
129
130 $query = db_insert('users_roles')->fields(array('uid', 'rid'));
131 foreach (array_keys($entity->roles) as $rid) {
132 if (!in_array($rid, array(DRUPAL_ANONYMOUS_RID, DRUPAL_AUTHENTICATED_RID))) {
133 $query->values(array(
134 'uid' => $entity->uid,
135 'rid' => $rid,
136 ));
137 }
138 }
139 $query->execute();
140 }
141
142 // If the user was blocked, delete the user's sessions to force a logout.
143 if ($entity->original->status != $entity->status && $entity->status == 0) {
144 drupal_session_destroy_uid($entity->uid);
145 }
146
147 // Send emails after we have the new user object.
148 if ($entity->status != $entity->original->status) {
149 // The user's status is changing; conditionally send notification email.
150 $op = $entity->status == 1 ? 'status_activated' : 'status_blocked';
151 _user_mail_notify($op, $entity);
152 }
153 }
154 else {
155 // Save user roles.
156 if (count($entity->roles) > 1) {
157 $query = db_insert('users_roles')->fields(array('uid', 'rid'));
158 foreach (array_keys($entity->roles) as $rid) {
159 if (!in_array($rid, array(DRUPAL_ANONYMOUS_RID, DRUPAL_AUTHENTICATED_RID))) {
160 $query->values(array(
161 'uid' => $entity->uid,
162 'rid' => $rid,
163 ));
164 }
165 }
166 $query->execute();
167 }
168 }
169 }
170
171 /**
172 * Overrides Drupal\Core\Entity\DatabaseStorageController::postDelete().
173 */
174 protected function postDelete($entities) {
175 db_delete('users_roles')
176 ->condition('uid', array_keys($entities), 'IN')
177 ->execute();
178 drupal_container()->get('user.data')->delete(NULL, array_keys($entities));
179 }
180 }