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