Commit | Line | Data |
---|---|---|
7f254ad8 AE |
1 | <?php |
2 | ||
3 | /** | |
4 | * @file | |
5 | * Install, update and uninstall functions for the user module. | |
6 | */ | |
7 | ||
8 | /** | |
9 | * Implements hook_schema(). | |
10 | */ | |
11 | function user_schema() { | |
12 | $schema['authmap'] = array( | |
13 | 'description' => 'Stores distributed authentication mapping.', | |
14 | 'fields' => array( | |
15 | 'aid' => array( | |
16 | 'description' => 'Primary Key: Unique authmap ID.', | |
17 | 'type' => 'serial', | |
18 | 'unsigned' => TRUE, | |
19 | 'not null' => TRUE, | |
20 | ), | |
21 | 'uid' => array( | |
22 | 'type' => 'int', | |
23 | 'not null' => TRUE, | |
24 | 'default' => 0, | |
25 | 'description' => "User's {users}.uid.", | |
26 | ), | |
27 | 'authname' => array( | |
28 | 'type' => 'varchar', | |
29 | 'length' => 128, | |
30 | 'not null' => TRUE, | |
31 | 'default' => '', | |
32 | 'description' => 'Unique authentication name.', | |
33 | ), | |
34 | 'module' => array( | |
35 | 'type' => 'varchar', | |
36 | 'length' => 128, | |
37 | 'not null' => TRUE, | |
38 | 'default' => '', | |
39 | 'description' => 'Module which is controlling the authentication.', | |
40 | ), | |
41 | ), | |
42 | 'unique keys' => array( | |
43 | 'authname' => array('authname'), | |
44 | ), | |
45 | 'primary key' => array('aid'), | |
46 | 'foreign keys' => array( | |
47 | 'user' => array( | |
48 | 'table' => 'users', | |
49 | 'columns' => array('uid' => 'uid'), | |
50 | ), | |
51 | ), | |
52 | 'indexes' => array( | |
53 | 'uid_module' => array('uid', 'module'), | |
54 | ), | |
55 | ); | |
56 | ||
57 | $schema['role_permission'] = array( | |
58 | 'description' => 'Stores the permissions assigned to user roles.', | |
59 | 'fields' => array( | |
60 | 'rid' => array( | |
61 | 'type' => 'int', | |
62 | 'unsigned' => TRUE, | |
63 | 'not null' => TRUE, | |
64 | 'description' => 'Foreign Key: {role}.rid.', | |
65 | ), | |
66 | 'permission' => array( | |
67 | 'type' => 'varchar', | |
68 | 'length' => 128, | |
69 | 'not null' => TRUE, | |
70 | 'default' => '', | |
71 | 'description' => 'A single permission granted to the role identified by rid.', | |
72 | ), | |
73 | 'module' => array( | |
74 | 'type' => 'varchar', | |
75 | 'length' => 255, | |
76 | 'not null' => TRUE, | |
77 | 'default' => '', | |
78 | 'description' => "The module declaring the permission.", | |
79 | ), | |
80 | ), | |
81 | 'primary key' => array('rid', 'permission'), | |
82 | 'indexes' => array( | |
83 | 'permission' => array('permission'), | |
84 | ), | |
85 | 'foreign keys' => array( | |
86 | 'role' => array( | |
87 | 'table' => 'role', | |
88 | 'columns' => array('rid' => 'rid'), | |
89 | ), | |
90 | ), | |
91 | ); | |
92 | ||
93 | $schema['role'] = array( | |
94 | 'description' => 'Stores user roles.', | |
95 | 'fields' => array( | |
96 | 'rid' => array( | |
97 | 'type' => 'serial', | |
98 | 'unsigned' => TRUE, | |
99 | 'not null' => TRUE, | |
100 | 'description' => 'Primary Key: Unique role ID.', | |
101 | ), | |
102 | 'name' => array( | |
103 | 'type' => 'varchar', | |
104 | 'length' => 64, | |
105 | 'not null' => TRUE, | |
106 | 'default' => '', | |
107 | 'description' => 'Unique role name.', | |
108 | 'translatable' => TRUE, | |
109 | ), | |
110 | 'weight' => array( | |
111 | 'type' => 'int', | |
112 | 'not null' => TRUE, | |
113 | 'default' => 0, | |
114 | 'description' => 'The weight of this role in listings and the user interface.', | |
115 | ), | |
116 | ), | |
117 | 'unique keys' => array( | |
118 | 'name' => array('name'), | |
119 | ), | |
120 | 'primary key' => array('rid'), | |
121 | 'indexes' => array( | |
122 | 'name_weight' => array('name', 'weight'), | |
123 | ), | |
124 | ); | |
125 | ||
126 | // The table name here is plural, despite Drupal table naming standards, | |
127 | // because "user" is a reserved word in many databases. | |
128 | $schema['users'] = array( | |
129 | 'description' => 'Stores user data.', | |
130 | 'fields' => array( | |
131 | 'uid' => array( | |
132 | 'type' => 'int', | |
133 | 'unsigned' => TRUE, | |
134 | 'not null' => TRUE, | |
135 | 'description' => 'Primary Key: Unique user ID.', | |
136 | 'default' => 0, | |
137 | ), | |
138 | 'name' => array( | |
139 | 'type' => 'varchar', | |
140 | 'length' => 60, | |
141 | 'not null' => TRUE, | |
142 | 'default' => '', | |
143 | 'description' => 'Unique user name.', | |
144 | ), | |
145 | 'pass' => array( | |
146 | 'type' => 'varchar', | |
147 | 'length' => 128, | |
148 | 'not null' => TRUE, | |
149 | 'default' => '', | |
150 | 'description' => "User's password (hashed).", | |
151 | ), | |
152 | 'mail' => array( | |
153 | 'type' => 'varchar', | |
154 | 'length' => 254, | |
155 | 'not null' => FALSE, | |
156 | 'default' => '', | |
157 | 'description' => "User's e-mail address.", | |
158 | ), | |
159 | 'theme' => array( | |
160 | 'type' => 'varchar', | |
161 | 'length' => 255, | |
162 | 'not null' => TRUE, | |
163 | 'default' => '', | |
164 | 'description' => "User's default theme.", | |
165 | ), | |
166 | 'signature' => array( | |
167 | 'type' => 'varchar', | |
168 | 'length' => 255, | |
169 | 'not null' => TRUE, | |
170 | 'default' => '', | |
171 | 'description' => "User's signature.", | |
172 | ), | |
173 | 'signature_format' => array( | |
174 | 'type' => 'varchar', | |
175 | 'length' => 255, | |
176 | 'not null' => FALSE, | |
177 | 'description' => 'The {filter_format}.format of the signature.', | |
178 | ), | |
179 | 'created' => array( | |
180 | 'type' => 'int', | |
181 | 'not null' => TRUE, | |
182 | 'default' => 0, | |
183 | 'description' => 'Timestamp for when user was created.', | |
184 | ), | |
185 | 'access' => array( | |
186 | 'type' => 'int', | |
187 | 'not null' => TRUE, | |
188 | 'default' => 0, | |
189 | 'description' => 'Timestamp for previous time user accessed the site.', | |
190 | ), | |
191 | 'login' => array( | |
192 | 'type' => 'int', | |
193 | 'not null' => TRUE, | |
194 | 'default' => 0, | |
195 | 'description' => "Timestamp for user's last login.", | |
196 | ), | |
197 | 'status' => array( | |
198 | 'type' => 'int', | |
199 | 'not null' => TRUE, | |
200 | 'default' => 0, | |
201 | 'size' => 'tiny', | |
202 | 'description' => 'Whether the user is active(1) or blocked(0).', | |
203 | ), | |
204 | 'timezone' => array( | |
205 | 'type' => 'varchar', | |
206 | 'length' => 32, | |
207 | 'not null' => FALSE, | |
208 | 'description' => "User's time zone.", | |
209 | ), | |
210 | 'language' => array( | |
211 | 'type' => 'varchar', | |
212 | 'length' => 12, | |
213 | 'not null' => TRUE, | |
214 | 'default' => '', | |
215 | 'description' => "User's default language.", | |
216 | ), | |
217 | 'picture' => array( | |
218 | 'type' => 'int', | |
219 | 'not null' => TRUE, | |
220 | 'default' => 0, | |
221 | 'description' => "Foreign key: {file_managed}.fid of user's picture.", | |
222 | ), | |
223 | 'init' => array( | |
224 | 'type' => 'varchar', | |
225 | 'length' => 254, | |
226 | 'not null' => FALSE, | |
227 | 'default' => '', | |
228 | 'description' => 'E-mail address used for initial account creation.', | |
229 | ), | |
230 | 'data' => array( | |
231 | 'type' => 'blob', | |
232 | 'not null' => FALSE, | |
233 | 'size' => 'big', | |
234 | 'serialize' => TRUE, | |
235 | 'description' => 'A serialized array of name value pairs that are related to the user. Any form values posted during user edit are stored and are loaded into the $user object during user_load(). Use of this field is discouraged and it will likely disappear in a future version of Drupal.', | |
236 | ), | |
237 | ), | |
238 | 'indexes' => array( | |
239 | 'access' => array('access'), | |
240 | 'created' => array('created'), | |
241 | 'mail' => array('mail'), | |
242 | 'picture' => array('picture'), | |
243 | ), | |
244 | 'unique keys' => array( | |
245 | 'name' => array('name'), | |
246 | ), | |
247 | 'primary key' => array('uid'), | |
248 | 'foreign keys' => array( | |
249 | 'signature_format' => array( | |
250 | 'table' => 'filter_format', | |
251 | 'columns' => array('signature_format' => 'format'), | |
252 | ), | |
253 | ), | |
254 | ); | |
255 | ||
256 | $schema['users_roles'] = array( | |
257 | 'description' => 'Maps users to roles.', | |
258 | 'fields' => array( | |
259 | 'uid' => array( | |
260 | 'type' => 'int', | |
261 | 'unsigned' => TRUE, | |
262 | 'not null' => TRUE, | |
263 | 'default' => 0, | |
264 | 'description' => 'Primary Key: {users}.uid for user.', | |
265 | ), | |
266 | 'rid' => array( | |
267 | 'type' => 'int', | |
268 | 'unsigned' => TRUE, | |
269 | 'not null' => TRUE, | |
270 | 'default' => 0, | |
271 | 'description' => 'Primary Key: {role}.rid for role.', | |
272 | ), | |
273 | ), | |
274 | 'primary key' => array('uid', 'rid'), | |
275 | 'indexes' => array( | |
276 | 'rid' => array('rid'), | |
277 | ), | |
278 | 'foreign keys' => array( | |
279 | 'user' => array( | |
280 | 'table' => 'users', | |
281 | 'columns' => array('uid' => 'uid'), | |
282 | ), | |
283 | 'role' => array( | |
284 | 'table' => 'role', | |
285 | 'columns' => array('rid' => 'rid'), | |
286 | ), | |
287 | ), | |
288 | ); | |
289 | ||
290 | return $schema; | |
291 | } | |
292 | ||
293 | /** | |
294 | * Implements hook_install(). | |
295 | */ | |
296 | function user_install() { | |
297 | // Insert a row for the anonymous user. | |
298 | db_insert('users') | |
299 | ->fields(array( | |
300 | 'uid' => 0, | |
301 | 'name' => '', | |
302 | 'mail' => '', | |
303 | )) | |
304 | ->execute(); | |
305 | ||
306 | // We need some placeholders here as name and mail are uniques and data is | |
307 | // presumed to be a serialized array. This will be changed by the settings | |
308 | // form in the installer. | |
309 | db_insert('users') | |
310 | ->fields(array( | |
311 | 'uid' => 1, | |
312 | 'name' => 'placeholder-for-uid-1', | |
313 | 'mail' => 'placeholder-for-uid-1', | |
314 | 'created' => REQUEST_TIME, | |
315 | 'status' => 1, | |
316 | 'data' => NULL, | |
317 | )) | |
318 | ->execute(); | |
319 | ||
320 | // Built-in roles. | |
321 | $rid_anonymous = db_insert('role') | |
322 | ->fields(array('name' => 'anonymous user', 'weight' => 0)) | |
323 | ->execute(); | |
324 | $rid_authenticated = db_insert('role') | |
325 | ->fields(array('name' => 'authenticated user', 'weight' => 1)) | |
326 | ->execute(); | |
327 | ||
328 | // Sanity check to ensure the anonymous and authenticated role IDs are the | |
329 | // same as the drupal defined constants. In certain situations, this will | |
330 | // not be true. | |
331 | if ($rid_anonymous != DRUPAL_ANONYMOUS_RID) { | |
332 | db_update('role') | |
333 | ->fields(array('rid' => DRUPAL_ANONYMOUS_RID)) | |
334 | ->condition('rid', $rid_anonymous) | |
335 | ->execute(); | |
336 | } | |
337 | if ($rid_authenticated != DRUPAL_AUTHENTICATED_RID) { | |
338 | db_update('role') | |
339 | ->fields(array('rid' => DRUPAL_AUTHENTICATED_RID)) | |
340 | ->condition('rid', $rid_authenticated) | |
341 | ->execute(); | |
342 | } | |
343 | } | |
344 | ||
345 | /** | |
346 | * Implements hook_update_dependencies(). | |
347 | */ | |
348 | function user_update_dependencies() { | |
349 | // user_update_7006() updates data in the {role_permission} table, so it must | |
350 | // run after system_update_7007(), which populates that table. | |
351 | $dependencies['user'][7006] = array( | |
352 | 'system' => 7007, | |
353 | ); | |
354 | ||
355 | // user_update_7010() needs to query the {filter_format} table to get a list | |
356 | // of existing text formats, so it must run after filter_update_7000(), which | |
357 | // creates that table. | |
358 | $dependencies['user'][7010] = array( | |
359 | 'filter' => 7000, | |
360 | ); | |
361 | ||
362 | // user_update_7012() uses the file API and inserts records into the | |
363 | // {file_managed} table, so it therefore must run after system_update_7061(), | |
364 | // which inserts files with specific IDs into the table and therefore relies | |
365 | // on the table being empty (otherwise it would accidentally overwrite | |
366 | // existing records). | |
367 | $dependencies['user'][7012] = array( | |
368 | 'system' => 7061, | |
369 | ); | |
370 | ||
371 | // user_update_7013() uses the file usage API, which relies on the | |
372 | // {file_usage} table, so it must run after system_update_7059(), which | |
373 | // creates that table. | |
374 | $dependencies['user'][7013] = array( | |
375 | 'system' => 7059, | |
376 | ); | |
377 | ||
378 | return $dependencies; | |
379 | } | |
380 | ||
381 | /** | |
382 | * Utility function: grant a set of permissions to a role during update. | |
383 | * | |
384 | * This function is valid for a database schema version 7000. | |
385 | * | |
386 | * @param $rid | |
387 | * The role ID. | |
388 | * @param $permissions | |
389 | * An array of permissions names. | |
390 | * @param $module | |
391 | * The name of the module defining the permissions. | |
392 | * @ingroup update_api | |
393 | */ | |
394 | function _update_7000_user_role_grant_permissions($rid, array $permissions, $module) { | |
395 | // Grant new permissions for the role. | |
396 | foreach ($permissions as $name) { | |
397 | db_merge('role_permission') | |
398 | ->key(array( | |
399 | 'rid' => $rid, | |
400 | 'permission' => $name, | |
401 | )) | |
402 | ->fields(array( | |
403 | 'module' => $module, | |
404 | )) | |
405 | ->execute(); | |
406 | } | |
407 | } | |
408 | ||
409 | /** | |
410 | * @addtogroup updates-6.x-to-7.x | |
411 | * @{ | |
412 | */ | |
413 | ||
414 | /** | |
415 | * Increase the length of the password field to accommodate better hashes. | |
416 | * | |
417 | * Also re-hashes all current passwords to improve security. This may be a | |
418 | * lengthy process, and is performed batch-wise. | |
419 | */ | |
420 | function user_update_7000(&$sandbox) { | |
421 | $sandbox['#finished'] = 0; | |
422 | // Lower than DRUPAL_HASH_COUNT to make the update run at a reasonable speed. | |
423 | $hash_count_log2 = 11; | |
424 | // Multi-part update. | |
425 | if (!isset($sandbox['user_from'])) { | |
426 | db_change_field('users', 'pass', 'pass', array('type' => 'varchar', 'length' => 128, 'not null' => TRUE, 'default' => '')); | |
427 | $sandbox['user_from'] = 0; | |
428 | $sandbox['user_count'] = db_query("SELECT COUNT(uid) FROM {users}")->fetchField(); | |
429 | } | |
430 | else { | |
431 | require_once DRUPAL_ROOT . '/' . variable_get('password_inc', 'includes/password.inc'); | |
432 | // Hash again all current hashed passwords. | |
433 | $has_rows = FALSE; | |
434 | // Update this many per page load. | |
435 | $count = 1000; | |
436 | $result = db_query_range("SELECT uid, pass FROM {users} WHERE uid > 0 ORDER BY uid", $sandbox['user_from'], $count); | |
437 | foreach ($result as $account) { | |
438 | $has_rows = TRUE; | |
439 | ||
440 | // If the $account->pass value is not a MD5 hash (a 32 character | |
441 | // hexadecimal string) then skip it. | |
442 | if (!preg_match('/^[0-9a-f]{32}$/', $account->pass)) { | |
443 | continue; | |
444 | } | |
445 | ||
446 | $new_hash = user_hash_password($account->pass, $hash_count_log2); | |
447 | if ($new_hash) { | |
448 | // Indicate an updated password. | |
449 | $new_hash = 'U' . $new_hash; | |
450 | db_update('users') | |
451 | ->fields(array('pass' => $new_hash)) | |
452 | ->condition('uid', $account->uid) | |
453 | ->execute(); | |
454 | } | |
455 | } | |
456 | $sandbox['#finished'] = $sandbox['user_from']/$sandbox['user_count']; | |
457 | $sandbox['user_from'] += $count; | |
458 | if (!$has_rows) { | |
459 | $sandbox['#finished'] = 1; | |
460 | return t('User passwords rehashed to improve security'); | |
461 | } | |
462 | } | |
463 | } | |
464 | ||
465 | /** | |
466 | * Remove the 'threshold', 'mode' and 'sort' columns from the {users} table. | |
467 | * | |
468 | * These fields were previously used to store per-user comment settings. | |
469 | */ | |
470 | ||
471 | function user_update_7001() { | |
472 | db_drop_field('users', 'threshold'); | |
473 | db_drop_field('users', 'mode'); | |
474 | db_drop_field('users', 'sort'); | |
475 | } | |
476 | ||
477 | /** | |
478 | * Convert user time zones from time zone offsets to time zone names. | |
479 | */ | |
480 | function user_update_7002(&$sandbox) { | |
481 | $sandbox['#finished'] = 0; | |
482 | ||
483 | // Multi-part update. | |
484 | if (!isset($sandbox['user_from'])) { | |
485 | db_change_field('users', 'timezone', 'timezone', array('type' => 'varchar', 'length' => 32, 'not null' => FALSE)); | |
486 | $sandbox['user_from'] = 0; | |
487 | $sandbox['user_count'] = db_query("SELECT COUNT(uid) FROM {users}")->fetchField(); | |
488 | $sandbox['user_not_migrated'] = 0; | |
489 | } | |
490 | else { | |
491 | $timezones = system_time_zones(); | |
492 | // Update this many per page load. | |
493 | $count = 10000; | |
494 | $contributed_date_module = db_field_exists('users', 'timezone_name'); | |
495 | $contributed_event_module = db_field_exists('users', 'timezone_id'); | |
496 | ||
497 | $results = db_query_range("SELECT uid FROM {users} ORDER BY uid", $sandbox['user_from'], $count); | |
498 | foreach ($results as $account) { | |
499 | $timezone = NULL; | |
500 | // If the contributed Date module has created a users.timezone_name | |
501 | // column, use this data to set each user's time zone. | |
502 | if ($contributed_date_module) { | |
503 | $date_timezone = db_query("SELECT timezone_name FROM {users} WHERE uid = :uid", array(':uid' => $account->uid))->fetchField(); | |
504 | if (isset($timezones[$date_timezone])) { | |
505 | $timezone = $date_timezone; | |
506 | } | |
507 | } | |
508 | // If the contributed Event module has stored user time zone information | |
509 | // use that information to update the user accounts. | |
510 | if (!$timezone && $contributed_event_module) { | |
511 | try { | |
512 | $event_timezone = db_query("SELECT t.name FROM {users} u LEFT JOIN {event_timezones} t ON u.timezone_id = t.timezone WHERE u.uid = :uid", array(':uid' => $account->uid))->fetchField(); | |
513 | $event_timezone = str_replace(' ', '_', $event_timezone); | |
514 | if (isset($timezones[$event_timezone])) { | |
515 | $timezone = $event_timezone; | |
516 | } | |
517 | } | |
518 | catch (PDOException $e) { | |
519 | // Ignore error if event_timezones table does not exist or unexpected | |
520 | // schema found. | |
521 | } | |
522 | } | |
523 | if ($timezone) { | |
524 | db_update('users') | |
525 | ->fields(array('timezone' => $timezone)) | |
526 | ->condition('uid', $account->uid) | |
527 | ->execute(); | |
528 | } | |
529 | else { | |
530 | $sandbox['user_not_migrated']++; | |
531 | db_update('users') | |
532 | ->fields(array('timezone' => NULL)) | |
533 | ->condition('uid', $account->uid) | |
534 | ->execute(); | |
535 | } | |
536 | $sandbox['user_from']++; | |
537 | } | |
538 | ||
539 | $sandbox['#finished'] = $sandbox['user_from'] / $sandbox['user_count']; | |
540 | if ($sandbox['user_from'] == $sandbox['user_count']) { | |
541 | if ($sandbox['user_not_migrated'] > 0) { | |
542 | variable_set('empty_timezone_message', 1); | |
543 | drupal_set_message(format_string('Some user time zones have been emptied and need to be set to the correct values. Use the new <a href="@config-url">time zone options</a> to choose whether to remind users at login to set the correct time zone.', array('@config-url' => url('admin/config/regional/settings'))), 'warning'); | |
544 | } | |
545 | return t('Migrated user time zones'); | |
546 | } | |
547 | } | |
548 | } | |
549 | ||
550 | /** | |
551 | * Update user settings for cancelling user accounts. | |
552 | * | |
553 | * Prior to 7.x, users were not able to cancel their accounts. When | |
554 | * administrators deleted an account, all contents were assigned to uid 0, | |
555 | * which is the same as the 'user_cancel_reassign' method now. | |
556 | */ | |
557 | function user_update_7003() { | |
558 | // Set the default account cancellation method. | |
559 | variable_set('user_cancel_method', 'user_cancel_reassign'); | |
560 | // Re-assign notification setting. | |
561 | if ($setting = variable_get('user_mail_status_deleted_notify', FALSE)) { | |
562 | variable_set('user_mail_status_canceled_notify', $setting); | |
563 | variable_del('user_mail_status_deleted_notify'); | |
564 | } | |
565 | // Re-assign "Account deleted" mail strings to "Account canceled" mail. | |
566 | if ($setting = variable_get('user_mail_status_deleted_subject', FALSE)) { | |
567 | variable_set('user_mail_status_canceled_subject', $setting); | |
568 | variable_del('user_mail_status_deleted_subject'); | |
569 | } | |
570 | if ($setting = variable_get('user_mail_status_deleted_body', FALSE)) { | |
571 | variable_set('user_mail_status_canceled_body', $setting); | |
572 | variable_del('user_mail_status_deleted_body'); | |
573 | } | |
574 | } | |
575 | ||
576 | /** | |
577 | * Changes the users table to allow longer e-mail addresses. | |
578 | */ | |
579 | function user_update_7005(&$sandbox) { | |
580 | $mail_field = array( | |
581 | 'type' => 'varchar', | |
582 | 'length' => 254, | |
583 | 'not null' => FALSE, | |
584 | 'default' => '', | |
585 | 'description' => "User's e-mail address.", | |
586 | ); | |
587 | $init_field = array( | |
588 | 'type' => 'varchar', | |
589 | 'length' => 254, | |
590 | 'not null' => FALSE, | |
591 | 'default' => '', | |
592 | 'description' => 'E-mail address used for initial account creation.', | |
593 | ); | |
594 | db_drop_index('users', 'mail'); | |
595 | db_change_field('users', 'mail', 'mail', $mail_field, array('indexes' => array('mail' => array('mail')))); | |
596 | db_change_field('users', 'init', 'init', $init_field); | |
597 | } | |
598 | ||
599 | /** | |
600 | * Add module data to {role_permission}. | |
601 | */ | |
602 | function user_update_7006(&$sandbox) { | |
603 | $module_field = array( | |
604 | 'type' => 'varchar', | |
605 | 'length' => 255, | |
606 | 'not null' => TRUE, | |
607 | 'default' => '', | |
608 | 'description' => "The module declaring the permission.", | |
609 | ); | |
610 | // Check that the field hasn't been updated in an aborted run of this | |
611 | // update. | |
612 | if (!db_field_exists('role_permission', 'module')) { | |
613 | // Add a new field for the fid. | |
614 | db_add_field('role_permission', 'module', $module_field); | |
615 | } | |
616 | } | |
617 | ||
618 | /** | |
619 | * Add a weight column to user roles. | |
620 | */ | |
621 | function user_update_7007() { | |
622 | db_add_field('role', 'weight', array('type' => 'int', 'not null' => TRUE, 'default' => 0)); | |
623 | db_add_index('role', 'name_weight', array('name', 'weight')); | |
624 | } | |
625 | ||
626 | /** | |
627 | * If 'user_register' variable was unset in Drupal 6, set it to be the same as | |
628 | * the Drupal 6 default setting. | |
629 | */ | |
630 | function user_update_7008() { | |
631 | if (!isset($GLOBALS['conf']['user_register'])) { | |
632 | // Set to the Drupal 6 default, "visitors can create accounts". | |
633 | variable_set('user_register', USER_REGISTER_VISITORS); | |
634 | } | |
635 | } | |
636 | ||
637 | /** | |
638 | * Converts fields that store serialized variables from text to blob. | |
639 | */ | |
640 | function user_update_7009() { | |
641 | $spec = array( | |
642 | 'type' => 'blob', | |
643 | 'not null' => FALSE, | |
644 | 'size' => 'big', | |
645 | 'serialize' => TRUE, | |
646 | 'description' => 'A serialized array of name value pairs that are related to the user. Any form values posted during user edit are stored and are loaded into the $user object during user_load(). Use of this field is discouraged and it will likely disappear in a future version of Drupal.', | |
647 | ); | |
648 | db_change_field('users', 'data', 'data', $spec); | |
649 | } | |
650 | ||
651 | /** | |
652 | * Update the {user}.signature_format column. | |
653 | */ | |
654 | function user_update_7010() { | |
655 | // Update the database column to allow NULL values. | |
656 | db_change_field('users', 'signature_format', 'signature_format', array( | |
657 | 'type' => 'int', | |
658 | 'unsigned' => TRUE, | |
659 | 'not null' => FALSE, | |
660 | 'description' => 'The {filter_format}.format of the signature.', | |
661 | )); | |
662 | ||
663 | // Replace the signature format with NULL if the signature is empty and does | |
664 | // not already have a stored text format. | |
665 | // | |
666 | // In Drupal 6, "0" (the former FILTER_FORMAT_DEFAULT constant) could be used | |
667 | // to indicate this situation, but in Drupal 7, only NULL is supported. This | |
668 | // update therefore preserves the ability of user accounts which were never | |
669 | // given a signature (for example, if the site did not have user signatures | |
670 | // enabled, or if the user never edited their account information) to not | |
671 | // have a particular text format assumed for them the first time the | |
672 | // signature is edited. | |
673 | db_update('users') | |
674 | ->fields(array('signature_format' => NULL)) | |
675 | ->condition('signature', '') | |
676 | ->condition('signature_format', 0) | |
677 | ->execute(); | |
678 | ||
679 | // There are a number of situations in which a Drupal 6 site could store | |
680 | // content with a nonexistent text format. This includes text formats that | |
681 | // had later been deleted, or non-empty content stored with a value of "0" | |
682 | // (the former FILTER_FORMAT_DEFAULT constant). Drupal 6 would filter this | |
683 | // content using whatever the site-wide default text format was at the moment | |
684 | // the text was being displayed. | |
685 | // | |
686 | // In Drupal 7, this behavior is no longer supported, and all content must be | |
687 | // stored with an explicit text format (or it will not be displayed when it | |
688 | // is filtered). Therefore, to preserve the behavior of the site after the | |
689 | // upgrade, we must replace all instances described above with the current | |
690 | // value of the (old) site-wide default format at the moment of the upgrade. | |
691 | $existing_formats = db_query("SELECT format FROM {filter_format}")->fetchCol(); | |
692 | $default_format = variable_get('filter_default_format', 1); | |
693 | db_update('users') | |
694 | ->fields(array('signature_format' => $default_format)) | |
695 | ->isNotNull('signature_format') | |
696 | ->condition('signature_format', $existing_formats, 'NOT IN') | |
697 | ->execute(); | |
698 | } | |
699 | ||
700 | /** | |
701 | * Placeholder function. | |
702 | * | |
703 | * As a fix for user_update_7011() not updating email templates to use the new | |
704 | * tokens, user_update_7017() now targets email templates of Drupal 6 sites and | |
705 | * already upgraded sites. | |
706 | */ | |
707 | function user_update_7011() { | |
708 | } | |
709 | ||
710 | /** | |
711 | * Add the user's pictures to the {file_managed} table and make them managed | |
712 | * files. | |
713 | */ | |
714 | function user_update_7012(&$sandbox) { | |
715 | ||
716 | $picture_field = array( | |
717 | 'type' => 'int', | |
718 | 'not null' => TRUE, | |
719 | 'default' => 0, | |
720 | 'description' => "Foreign key: {file_managed}.fid of user's picture.", | |
721 | ); | |
722 | ||
723 | if (!isset($sandbox['progress'])) { | |
724 | // Check that the field hasn't been updated in an aborted run of this | |
725 | // update. | |
726 | if (!db_field_exists('users', 'picture_fid')) { | |
727 | // Add a new field for the fid. | |
728 | db_add_field('users', 'picture_fid', $picture_field); | |
729 | } | |
730 | ||
731 | // Initialize batch update information. | |
732 | $sandbox['progress'] = 0; | |
733 | $sandbox['last_user_processed'] = -1; | |
734 | $sandbox['max'] = db_query("SELECT COUNT(*) FROM {users} WHERE picture <> ''")->fetchField(); | |
735 | } | |
736 | ||
737 | // As a batch operation move the photos into the {file_managed} table and | |
738 | // update the {users} records. | |
739 | $limit = 500; | |
740 | $result = db_query_range("SELECT uid, picture FROM {users} WHERE picture <> '' AND uid > :uid ORDER BY uid", 0, $limit, array(':uid' => $sandbox['last_user_processed'])); | |
741 | foreach ($result as $user) { | |
742 | // Don't bother adding files that don't exist. | |
743 | if (file_exists($user->picture)) { | |
744 | ||
745 | // Check if the file already exists. | |
746 | $files = file_load_multiple(array(), array('uri' => $user->picture)); | |
747 | if (count($files)) { | |
748 | $file = reset($files); | |
749 | } | |
750 | else { | |
751 | // Create a file object. | |
752 | $file = new stdClass(); | |
753 | $file->uri = $user->picture; | |
754 | $file->filename = drupal_basename($file->uri); | |
755 | $file->filemime = file_get_mimetype($file->uri); | |
756 | $file->uid = $user->uid; | |
757 | $file->status = FILE_STATUS_PERMANENT; | |
758 | $file = file_save($file); | |
759 | } | |
760 | ||
761 | db_update('users') | |
762 | ->fields(array('picture_fid' => $file->fid)) | |
763 | ->condition('uid', $user->uid) | |
764 | ->execute(); | |
765 | } | |
766 | ||
767 | // Update our progress information for the batch update. | |
768 | $sandbox['progress']++; | |
769 | $sandbox['last_user_processed'] = $user->uid; | |
770 | } | |
771 | ||
772 | // Indicate our current progress to the batch update system. If there's no | |
773 | // max value then there's nothing to update and we're finished. | |
774 | $sandbox['#finished'] = empty($sandbox['max']) ? 1 : ($sandbox['progress'] / $sandbox['max']); | |
775 | ||
776 | // When we're finished, drop the old picture field and rename the new one to | |
777 | // replace it. | |
778 | if (isset($sandbox['#finished']) && $sandbox['#finished'] == 1) { | |
779 | db_drop_field('users', 'picture'); | |
780 | db_change_field('users', 'picture_fid', 'picture', $picture_field); | |
781 | } | |
782 | } | |
783 | ||
784 | /** | |
785 | * Add user module file usage entries. | |
786 | */ | |
787 | function user_update_7013(&$sandbox) { | |
788 | if (!isset($sandbox['progress'])) { | |
789 | // Initialize batch update information. | |
790 | $sandbox['progress'] = 0; | |
791 | $sandbox['last_uid_processed'] = -1; | |
792 | $sandbox['max'] = db_query("SELECT COUNT(*) FROM {users} u WHERE u.picture <> 0")->fetchField(); | |
793 | } | |
794 | ||
795 | // Add usage entries for the user picture files. | |
796 | $limit = 500; | |
797 | $result = db_query_range('SELECT f.*, u.uid as user_uid FROM {users} u INNER JOIN {file_managed} f ON u.picture = f.fid WHERE u.picture <> 0 AND u.uid > :uid ORDER BY u.uid', 0, $limit, array(':uid' => $sandbox['last_uid_processed']))->fetchAllAssoc('fid', PDO::FETCH_ASSOC); | |
798 | foreach ($result as $row) { | |
799 | $uid = $row['user_uid']; | |
800 | $file = (object) $row; | |
801 | file_usage_add($file, 'user', 'user', $uid); | |
802 | ||
803 | // Update our progress information for the batch update. | |
804 | $sandbox['progress']++; | |
805 | $sandbox['last_uid_processed'] = $uid; | |
806 | } | |
807 | ||
808 | // Indicate our current progress to the batch update system. | |
809 | $sandbox['#finished'] = empty($sandbox['max']) || ($sandbox['progress'] / $sandbox['max']); | |
810 | } | |
811 | ||
812 | /** | |
813 | * Rename the 'post comments without approval' permission. | |
814 | * | |
815 | * In Drupal 7, this permission has been renamed to 'skip comment approval'. | |
816 | */ | |
817 | function user_update_7014() { | |
818 | db_update('role_permission') | |
819 | ->fields(array('permission' => 'skip comment approval')) | |
820 | ->condition('permission', 'post comments without approval') | |
821 | ->execute(); | |
822 | ||
823 | return t("Renamed the 'post comments without approval' permission to 'skip comment approval'."); | |
824 | } | |
825 | ||
826 | /** | |
827 | * Change {users}.signature_format into varchar. | |
828 | */ | |
829 | function user_update_7015() { | |
830 | db_change_field('users', 'signature_format', 'signature_format', array( | |
831 | 'type' => 'varchar', | |
832 | 'length' => 255, | |
833 | 'not null' => FALSE, | |
834 | 'description' => 'The {filter_format}.format of the signature.', | |
835 | )); | |
836 | } | |
837 | ||
838 | /** | |
839 | * @} End of "addtogroup updates-6.x-to-7.x". | |
840 | */ | |
841 | ||
842 | /** | |
843 | * @addtogroup updates-7.x-extra | |
844 | * @{ | |
845 | */ | |
846 | ||
847 | /** | |
848 | * Update the database to match the schema. | |
849 | */ | |
850 | function user_update_7016() { | |
851 | // Add field default. | |
852 | db_change_field('users', 'uid', 'uid', array( | |
853 | 'type' => 'int', | |
854 | 'unsigned' => TRUE, | |
855 | 'not null' => TRUE, | |
856 | 'default' => 0, | |
857 | )); | |
858 | } | |
859 | ||
860 | /** | |
861 | * Update email templates to use new tokens. | |
862 | * | |
863 | * This function upgrades customized email templates from the old !token format | |
864 | * to the new core tokens format. Additionally, in Drupal 7 we no longer e-mail | |
865 | * plain text passwords to users, and there is no token for a plain text | |
866 | * password in the new token system. Therefore, it also modifies any saved | |
867 | * templates using the old '!password' token such that the token is removed, and | |
868 | * displays a warning to users that they may need to go and modify the wording | |
869 | * of their templates. | |
870 | */ | |
871 | function user_update_7017() { | |
872 | $message = ''; | |
873 | ||
874 | $tokens = array( | |
875 | '!site' => '[site:name]', | |
876 | '!username' => '[user:name]', | |
877 | '!mailto' => '[user:mail]', | |
878 | '!login_uri' => '[site:login-url]', | |
879 | '!uri_brief' => '[site:url-brief]', | |
880 | '!edit_uri' => '[user:edit-url]', | |
881 | '!login_url' => '[user:one-time-login-url]', | |
882 | '!uri' => '[site:url]', | |
883 | '!date' => '[date:medium]', | |
884 | '!password' => '', | |
885 | ); | |
886 | ||
887 | $result = db_select('variable', 'v') | |
888 | ->fields('v', array('name')) | |
889 | ->condition('name', db_like('user_mail_') . '%', 'LIKE') | |
890 | ->execute(); | |
891 | ||
892 | foreach ($result as $row) { | |
893 | // Use variable_get() to get the unserialized value for free. | |
894 | if ($value = variable_get($row->name, FALSE)) { | |
895 | ||
896 | if (empty($message) && (strpos($value, '!password') !== FALSE)) { | |
897 | $message = t('The ability to send users their passwords in plain text has been removed in Drupal 7. Your existing email templates have been modified to remove it. You should <a href="@template-url">review these templates</a> to make sure they read properly.', array('@template-url' => url('admin/config/people/accounts'))); | |
898 | } | |
899 | ||
900 | variable_set($row->name, str_replace(array_keys($tokens), $tokens, $value)); | |
901 | } | |
902 | } | |
903 | ||
904 | return $message; | |
905 | } | |
906 | ||
907 | /** | |
908 | * Ensure there is an index on {users}.picture. | |
909 | */ | |
910 | function user_update_7018() { | |
911 | if (!db_index_exists('users', 'picture')) { | |
912 | db_add_index('users', 'picture', array('picture')); | |
913 | } | |
914 | } | |
915 | ||
916 | /** | |
917 | * Ensure there is a combined index on {authmap}.uid and {authmap}.module. | |
918 | */ | |
919 | function user_update_7019() { | |
920 | // Check first in case it was already added manually. | |
921 | if (!db_index_exists('authmap', 'uid_module')) { | |
922 | db_add_index('authmap', 'uid_module', array('uid', 'module')); | |
923 | } | |
924 | } | |
925 | /** | |
926 | * @} End of "addtogroup updates-7.x-extra". | |
927 | */ |