Issue #1909418 by tim.plunkett, damiankloip, larowlan, dawehner, kim.pepper: Allow...
[project/drupal.git] / core / modules / user / user.install
1 <?php
2
3 /**
4 * @file
5 * Install, update and uninstall functions for the user module.
6 */
7
8 use Drupal\Component\Uuid\Uuid;
9 use Drupal\Core\Language\Language;
10
11 /**
12 * Implements hook_schema().
13 */
14 function user_schema() {
15 // The table name here is plural, despite Drupal table naming standards,
16 // because "user" is a reserved word in many databases.
17 $schema['users'] = array(
18 'description' => 'Stores user data.',
19 'fields' => array(
20 'uid' => array(
21 'type' => 'int',
22 'unsigned' => TRUE,
23 'not null' => TRUE,
24 'description' => 'Primary Key: Unique user ID.',
25 'default' => 0,
26 ),
27 'uuid' => array(
28 'description' => 'Unique Key: Universally unique identifier for this entity.',
29 'type' => 'varchar',
30 'length' => 128,
31 'not null' => FALSE,
32 ),
33 'name' => array(
34 'type' => 'varchar',
35 'length' => 60,
36 'not null' => TRUE,
37 'default' => '',
38 'description' => 'Unique user name.',
39 ),
40 'langcode' => array(
41 'type' => 'varchar',
42 'length' => 12,
43 'not null' => TRUE,
44 'default' => '',
45 'description' => "The {language}.langcode of the user's profile.",
46 ),
47 'pass' => array(
48 'type' => 'varchar',
49 'length' => 128,
50 'not null' => TRUE,
51 'default' => '',
52 'description' => "User's password (hashed).",
53 ),
54 'mail' => array(
55 'type' => 'varchar',
56 'length' => 254,
57 'not null' => FALSE,
58 'default' => '',
59 'description' => "User's e-mail address.",
60 ),
61 'theme' => array(
62 'type' => 'varchar',
63 'length' => 255,
64 'not null' => TRUE,
65 'default' => '',
66 'description' => "User's default theme.",
67 ),
68 'signature' => array(
69 'type' => 'varchar',
70 'length' => 255,
71 'not null' => TRUE,
72 'default' => '',
73 'description' => "User's signature.",
74 ),
75 'signature_format' => array(
76 'type' => 'varchar',
77 'length' => 255,
78 'not null' => FALSE,
79 'description' => 'The filter format ID of the signature.',
80 ),
81 'created' => array(
82 'type' => 'int',
83 'not null' => TRUE,
84 'default' => 0,
85 'description' => 'Timestamp for when user was created.',
86 ),
87 'access' => array(
88 'type' => 'int',
89 'not null' => TRUE,
90 'default' => 0,
91 'description' => 'Timestamp for previous time user accessed the site.',
92 ),
93 'login' => array(
94 'type' => 'int',
95 'not null' => TRUE,
96 'default' => 0,
97 'description' => "Timestamp for user's last login.",
98 ),
99 'status' => array(
100 'type' => 'int',
101 'not null' => TRUE,
102 'default' => 0,
103 'size' => 'tiny',
104 'description' => 'Whether the user is active(1) or blocked(0).',
105 ),
106 'timezone' => array(
107 'type' => 'varchar',
108 'length' => 32,
109 'not null' => FALSE,
110 'description' => "User's time zone.",
111 ),
112 'preferred_langcode' => array(
113 'type' => 'varchar',
114 'length' => 12,
115 'not null' => TRUE,
116 'default' => '',
117 'description' => 'The {language}.langcode that the user prefers for receiving emails and viewing the site.',
118 ),
119 'preferred_admin_langcode' => array(
120 'type' => 'varchar',
121 'length' => 12,
122 'not null' => TRUE,
123 'default' => '',
124 'description' => 'The {language}.langcode that the user prefers for viewing administration pages.',
125 ),
126 'init' => array(
127 'type' => 'varchar',
128 'length' => 254,
129 'not null' => FALSE,
130 'default' => '',
131 'description' => 'E-mail address used for initial account creation.',
132 ),
133 ),
134 'indexes' => array(
135 'access' => array('access'),
136 'created' => array('created'),
137 'mail' => array('mail'),
138 ),
139 'unique keys' => array(
140 'uuid' => array('uuid'),
141 'name' => array('name'),
142 ),
143 'primary key' => array('uid'),
144 'foreign keys' => array(
145 'signature_format' => array(
146 'table' => 'filter_format',
147 'columns' => array('signature_format' => 'format'),
148 ),
149 ),
150 );
151
152 $schema['role_permission'] = array(
153 'description' => 'Stores the permissions assigned to user roles.',
154 'fields' => array(
155 'rid' => array(
156 'type' => 'varchar',
157 'length' => 64,
158 'not null' => TRUE,
159 'description' => 'Foreign Key: {role}.rid.',
160 ),
161 'permission' => array(
162 'type' => 'varchar',
163 'length' => 128,
164 'not null' => TRUE,
165 'default' => '',
166 'description' => 'A single permission granted to the role identified by rid.',
167 ),
168 'module' => array(
169 'type' => 'varchar',
170 'length' => 255,
171 'not null' => TRUE,
172 'default' => '',
173 'description' => "The module declaring the permission.",
174 ),
175 ),
176 'primary key' => array('rid', 'permission'),
177 'indexes' => array(
178 'permission' => array('permission'),
179 ),
180 'foreign keys' => array(
181 'role' => array(
182 'table' => 'role',
183 'columns' => array('rid' => 'rid'),
184 ),
185 ),
186 );
187
188 $schema['users_data'] = array(
189 'description' => 'Stores module data as key/value pairs per user.',
190 'fields' => array(
191 'uid' => array(
192 'description' => 'Primary key: {users}.uid for user.',
193 'type' => 'int',
194 'unsigned' => TRUE,
195 'not null' => TRUE,
196 'default' => 0,
197 ),
198 'module' => array(
199 'description' => 'The name of the module declaring the variable.',
200 'type' => 'varchar',
201 'length' => 204,
202 'not null' => TRUE,
203 'default' => '',
204 ),
205 'name' => array(
206 'description' => 'The identifier of the data.',
207 'type' => 'varchar',
208 'length' => 128,
209 'not null' => TRUE,
210 'default' => '',
211 ),
212 'value' => array(
213 'description' => 'The value.',
214 'type' => 'blob',
215 'not null' => FALSE,
216 'size' => 'big',
217 ),
218 'serialized' => array(
219 'description' => 'Whether value is serialized.',
220 'type' => 'int',
221 'size' => 'tiny',
222 'unsigned' => TRUE,
223 'default' => 0,
224 ),
225 ),
226 'primary key' => array('uid', 'module', 'name'),
227 'indexes' => array(
228 'module' => array('module'),
229 'name' => array('name'),
230 ),
231 'foreign keys' => array(
232 'uid' => array('users' => 'uid'),
233 ),
234 );
235
236 $schema['users_roles'] = array(
237 'description' => 'Maps users to roles.',
238 'fields' => array(
239 'uid' => array(
240 'type' => 'int',
241 'unsigned' => TRUE,
242 'not null' => TRUE,
243 'default' => 0,
244 'description' => 'Primary Key: {users}.uid for user.',
245 ),
246 'rid' => array(
247 'type' => 'varchar',
248 'length' => 64,
249 'not null' => TRUE,
250 'description' => 'Primary Key: {role}.rid for role.',
251 ),
252 ),
253 'primary key' => array('uid', 'rid'),
254 'indexes' => array(
255 'rid' => array('rid'),
256 ),
257 'foreign keys' => array(
258 'user' => array(
259 'table' => 'users',
260 'columns' => array('uid' => 'uid'),
261 ),
262 'role' => array(
263 'table' => 'role',
264 'columns' => array('rid' => 'rid'),
265 ),
266 ),
267 );
268
269 return $schema;
270 }
271
272 /**
273 * Implements hook_install().
274 */
275 function user_install() {
276 // Insert a row for the anonymous user.
277 db_insert('users')
278 ->fields(array(
279 'uid' => 0,
280 'name' => '',
281 'mail' => '',
282 ))
283 ->execute();
284
285 // We need some placeholders here as name and mail are uniques and data is
286 // presumed to be a serialized array. This will be changed by the settings
287 // form in the installer.
288 db_insert('users')
289 ->fields(array(
290 'uid' => 1,
291 'name' => 'placeholder-for-uid-1',
292 'mail' => 'placeholder-for-uid-1',
293 'created' => REQUEST_TIME,
294 'status' => 1,
295 ))
296 ->execute();
297 }
298
299 /**
300 * Creates a user picture image field for the User entity.
301 *
302 * This is only used in core's standard.install, but is kept as a separate
303 * helper function so that other install profiles can reuse it.
304 */
305 function user_install_picture_field() {
306 $t = get_t();
307
308 $field = array(
309 'field_name' => 'user_picture',
310 'module' => 'image',
311 'type' => 'image',
312 'cardinality' => 1,
313 'locked' => FALSE,
314 'indexes' => array('fid' => array('fid')),
315 'settings' => array(
316 'uri_scheme' => 'public',
317 'default_image' => FALSE,
318 ),
319 );
320 $field = field_create_field($field);
321
322 $instance = array(
323 'field_name' => 'user_picture',
324 'entity_type' => 'user',
325 'label' => 'Picture',
326 'bundle' => 'user',
327 'description' => $t('Your virtual face or picture.'),
328 'required' => FALSE,
329 'settings' => array(
330 'file_extensions' => 'png gif jpg jpeg',
331 'file_directory' => 'pictures',
332 'max_filesize' => '30 KB',
333 'alt_field' => 0,
334 'title_field' => 0,
335 'max_resolution' => '85x85',
336 'min_resolution' => '',
337 'default_image' => 0,
338 ),
339 );
340 field_create_instance($instance);
341
342 // Assign form display settings for the 'default' view mode.
343 entity_get_form_display('user', 'user', 'default')
344 ->setComponent('user_picture', array(
345 'type' => 'image_image',
346 'settings' => array(
347 'progress_indicator' => 'throbber',
348 'preview_image_style' => 'thumbnail',
349 ),
350 'weight' => -1,
351 ))
352 ->save();
353
354 // Assign display settings for the 'default' and 'compact' view modes.
355 entity_get_display('user', 'user', 'default')
356 ->setComponent('user_picture', array(
357 'label' => 'hidden',
358 'type' => 'image',
359 'settings' => array(
360 'image_style' => 'thumbnail',
361 'image_link' => 'content',
362 ),
363 ))
364 ->save();
365 entity_get_display('user', 'user', 'compact')
366 ->setComponent('user_picture', array(
367 'label' => 'hidden',
368 'type' => 'image',
369 'settings' => array(
370 'image_style' => 'thumbnail',
371 'image_link' => 'content',
372 ),
373 ))
374 // Additionally, hide 'summary' pseudo-field from compact view mode..
375 ->removeComponent('member_for')
376 ->save();
377 }
378
379 /**
380 * @addtogroup updates-7.x-to-8.x
381 * @{
382 */
383
384 /**
385 * The 'Member for' extra field has moved one level up in the array.
386 */
387 function user_update_8000() {
388 $settings = field_bundle_settings('user', 'user');
389 if (isset($settings['extra_fields']['display']['summary'])) {
390 $settings['extra_fields']['display']['member_for'] = $settings['extra_fields']['display']['summary'];
391 unset($settings['extra_fields']['display']['summary']);
392 field_bundle_settings('user', 'user', $settings);
393 }
394 }
395
396 /**
397 * Splits {users}.language field to langcode and preferred_langcode.
398 *
399 * @see http://drupal.org/node/1454538
400 */
401 function user_update_8001() {
402 // The former language field is the language preference of the user. Rename
403 // this to preferred_langcode in order to distinguish it from the langcode
404 // field common to all entity types, used for identifying the language of the
405 // entity itself.
406 $preferred_langcode_field = array(
407 'type' => 'varchar',
408 'length' => 12,
409 'not null' => TRUE,
410 'default' => '',
411 'description' => 'The {language}.langcode that the user prefers for receiving emails and viewing the site.',
412 );
413 db_change_field('users', 'language', 'preferred_langcode', $preferred_langcode_field);
414
415 // Add the langcode field.
416 $langcode_field = array(
417 'type' => 'varchar',
418 'length' => 12,
419 'not null' => TRUE,
420 'default' => '',
421 'description' => "The {language}.langcode of the user's profile.",
422 );
423 db_add_field('users', 'langcode', $langcode_field);
424
425 // Since distinguishing the language of the user entity from the user's
426 // preferred language is a new feature in Drupal 8, assume that for updated
427 // sites, existing user entities are in the user's preferred language.
428 db_update('users')->expression('langcode', 'preferred_langcode')->execute();
429 }
430
431 /**
432 * Replace serial role IDs with machine name strings.
433 */
434 function user_update_8002() {
435 // Change serial rid columns into strings.
436 $column = array(
437 'type' => 'varchar',
438 'length' => 64,
439 'not null' => TRUE,
440 'description' => 'Primary Key: Unique role ID.',
441 );
442 db_change_field('role', 'rid', 'rid', $column);
443
444 $column['description'] = 'Foreign Key: {role}.rid.';
445 db_change_field('role_permission', 'rid', 'rid', $column);
446
447 $column['description'] = 'Primary Key: {role}.rid for role.';
448 db_change_field('users_roles', 'rid', 'rid', $column);
449
450 // Enlarge the role name (label) column.
451 $column = array(
452 'type' => 'varchar',
453 'length' => 255,
454 'not null' => TRUE,
455 'default' => '',
456 'description' => 'Role label.',
457 );
458 db_change_field('role', 'name', 'name', $column);
459 // Remove unique index.
460 db_drop_unique_key('role', 'name');
461
462 // Rename the built-in serial role IDs into the hardcoded machine names.
463 db_update('role')
464 ->fields(array('rid' => DRUPAL_ANONYMOUS_RID))
465 ->condition('rid', 1)
466 ->execute();
467 db_update('role')
468 ->fields(array('rid' => DRUPAL_AUTHENTICATED_RID))
469 ->condition('rid', 2)
470 ->execute();
471
472 db_update('role_permission')
473 ->fields(array('rid' => DRUPAL_ANONYMOUS_RID))
474 ->condition('rid', 1)
475 ->execute();
476 db_update('role_permission')
477 ->fields(array('rid' => DRUPAL_AUTHENTICATED_RID))
478 ->condition('rid', 2)
479 ->execute();
480
481 db_update('users_roles')
482 ->fields(array('rid' => DRUPAL_ANONYMOUS_RID))
483 ->condition('rid', 1)
484 ->execute();
485 db_update('users_roles')
486 ->fields(array('rid' => DRUPAL_AUTHENTICATED_RID))
487 ->condition('rid', 2)
488 ->execute();
489 }
490
491 /**
492 * Create a UUID column for users.
493 */
494 function user_update_8003() {
495 $spec = array(
496 'description' => 'Unique Key: Universally unique identifier for this entity.',
497 'type' => 'varchar',
498 'length' => 128,
499 'not null' => FALSE,
500 );
501 $keys = array(
502 'unique keys' => array(
503 'uuid' => array('uuid'),
504 ),
505 );
506 // Account for sites having the contributed UUID module installed.
507 if (db_field_exists('users', 'uuid')) {
508 db_change_field('users', 'uuid', 'uuid', $spec, $keys);
509 }
510 else {
511 db_add_field('users', 'uuid', $spec, $keys);
512 }
513 }
514
515 /**
516 * Moves account settings from variable to config.
517 *
518 * @ingroup config_upgrade
519 */
520 function user_update_8004() {
521 update_variables_to_config('user.settings', array(
522 'anonymous' => 'anonymous',
523 'user_admin_role' => 'admin_role',
524 'user_register' => 'register',
525 'user_signatures' => 'signatures',
526 'user_cancel_method' => 'cancel_method',
527 'user_mail_status_activated_notify' => 'notify.status_activated',
528 'user_mail_status_blocked_notify' => 'notify.status_blocked',
529 'user_mail_status_cancelled_notify' => 'notify.status_cancelled',
530 'user_email_verification' => 'verify_mail',
531 'user_password_reset_timeout' => 'password_reset_timeout',
532 ));
533
534 // Convert the user.settings:register numeric value to text value.
535 $map = array(
536 '0' => 'admin_only',
537 '1' => 'visitors',
538 '2' => 'visitors_admin_approval',
539 );
540
541 $config = config('user.settings');
542 $user_register = $config->get('register');
543 $user_cancel_method = $config->get('cancel_method');
544
545 if (is_numeric($user_register) && isset($map[$user_register])) {
546 $config->set('register', $map[$user_register])->save();
547 }
548
549 // Convert user.settings:cancel_method numeric value to text value.
550 $cancel_map = array(
551 '0' => 'user_cancel_block',
552 '1' => 'user_cancel_block_unpublish',
553 '2' => 'user_cancel_block_reassign',
554 '3' => 'user_cancel_block_delete',
555 );
556
557 if (is_numeric($user_cancel_method) && isset($cancel_map[$user_cancel_method])) {
558 $config->set('cancel_method', $$cancel_map[$user_cancel_method])->save();
559 }
560 }
561
562 /**
563 * Creates a preferred_admin_langcode column.
564 */
565 function user_update_8005() {
566 $spec = array(
567 'description' => 'The {language}.langcode that the user prefers for viewing administration pages.',
568 'type' => 'varchar',
569 'length' => 12,
570 'not null' => TRUE,
571 'default' => '',
572 );
573 db_add_field('users', 'preferred_admin_langcode', $spec);
574 }
575
576 /**
577 * Moves user mail settings from variable to config.
578 *
579 * @ingroup config_upgrade
580 */
581 function user_update_8006() {
582 update_variables_to_config('user.mail', array(
583 'register_admin_created_subject' => 'register_admin_created.subject',
584 'register_admin_created_body' => 'register_admin_created.body',
585 'register_pending_approval_subject' => 'register_pending_approval.subject',
586 'register_pending_approval_body' => 'register_pending_approval.body',
587 'register_pending_approval_admin_body' => 'register_pending_approval_admin.body',
588 'register_pending_approval_admin_subject' => 'register_pending_approval_admin.subject',
589 'register_no_approval_required_subject' => 'register_no_approval_required.subject',
590 'register_no_approval_required_body' => 'register_no_approval_required.body',
591 'password_reset_subject' => 'password_reset.subject',
592 'password_reset_body' => 'password_reset.body',
593 'status_activated_subject' => 'status_activated.subject',
594 'status_activated_body' => 'status_activated.body',
595 'status_blocked_subject' => 'status_blocked.subject',
596 'status_blocked_body' => 'status_blocked.body',
597 'cancel_confirm_subject' => 'cancel_confirm.subject',
598 'cancel_confirm_body' => 'cancel_confirm.body',
599 'status_canceled_subject' => 'status_canceled.subject',
600 'status_canceled_body' => 'status_canceled.body',
601 ));
602 }
603
604 /**
605 * Moves login flood settings from variable to config.
606 *
607 * @ingroup config_upgrade
608 */
609 function user_update_8007() {
610 update_variables_to_config('user.flood', array(
611 'user_failed_login_identifier_uid_only' => 'uid_only',
612 'user_failed_login_ip_limit' => 'ip_limit',
613 'user_failed_login_ip_window' => 'ip_window',
614 'user_failed_login_user_limit' => 'user_limit',
615 'user_failed_login_user_window' => 'user_window',
616 ));
617 }
618
619 /**
620 * Make *id fields unsigned.
621 */
622 function user_update_8008() {
623 db_change_field('authmap', 'uid', 'uid',
624 array(
625 'type' => 'int',
626 'unsigned' => TRUE,
627 'not null' => TRUE,
628 'default' => 0,
629 'description' => "User's {users}.uid.",
630 )
631 );
632 }
633
634 /**
635 * Generate a UUID for all users.
636 */
637 function user_update_8009(&$sandbox) {
638 if (!isset($sandbox['progress'])) {
639 $sandbox['progress'] = 0;
640 // The first user id is 0, so it needs to start with -1.
641 $sandbox['last'] = -1;
642 $sandbox['max'] = db_query('SELECT COUNT(uid) FROM {users} WHERE uuid IS NULL')->fetchField();
643 }
644
645 $uids = db_query_range('SELECT uid FROM {users} WHERE uid > :uid AND uuid IS NULL ORDER BY uid ASC', 0, 10, array(':uid' => $sandbox['last']))->fetchCol();
646 update_add_uuids($sandbox, 'users', 'uid', $uids);
647
648 $sandbox['#finished'] = empty($sandbox['max']) ? 1 : ($sandbox['progress'] / $sandbox['max']);
649 }
650
651 /**
652 * Create user picture field.
653 */
654 function user_update_8011() {
655 global $user;
656
657 // User pictures can only be migrated to the new user picture image field
658 // if Image module is installed.
659 if (!module_exists('image')) {
660 // Install image.module with schema version 8002 as a previous version
661 // would have to create tables that would be removed again.
662 $old_schema = update_module_enable(array('image'), 8002);
663 if ($old_schema['image'] == SCHEMA_UNINSTALLED) {
664 // If image.module was not installed before, install default
665 // configuration and run the install hook.
666 config_install_default_config('module', 'image');
667 // Inlined version of image_install(), make sure that the styles
668 // directory exists.
669 $directory = update_variable_get('file_default_scheme', 'public') . '://styles';
670 file_prepare_directory($directory, FILE_CREATE_DIRECTORY | FILE_MODIFY_PERMISSIONS);
671 }
672 }
673
674 if ($default_image = update_variable_get('user_picture_default', '')) {
675 $picture_directory = update_variable_get('file_default_scheme', 'public') . '://' . update_variable_get('user_picture_path', 'pictures');
676 file_prepare_directory($picture_directory, FILE_CREATE_DIRECTORY);
677 $destination = file_stream_wrapper_uri_normalize($picture_directory . '/' . drupal_basename($default_image));
678 // The file entity needs to be created manually as entities can not be
679 // created/saved during the upgrade path. Attempt to replicate the behavior
680 // of file_save_data() by updating an eventually existing record for that
681 // file.
682 file_unmanaged_save_data($default_image, $destination, FILE_EXISTS_REPLACE);
683 $uuid = new Uuid();
684 db_merge('file_managed')
685 ->key(array(
686 'uri' => $destination,
687 ))
688 ->fields(array(
689 'uid' => $user->uid,
690 'status' => FILE_STATUS_PERMANENT,
691 'filename' => drupal_basename($destination),
692 'uuid' => $uuid->generate(),
693 'langcode' => Language::LANGCODE_NOT_SPECIFIED,
694 'filesize' => filesize($destination),
695 'filemime' => file_get_mimetype($destination),
696 'timestamp' => REQUEST_TIME,
697 ))
698 ->execute();
699 $default_image_fid = db_query('SELECT fid FROM {file_managed} WHERE uri = :uri', array(':uri' => $destination))->fetchField();
700 }
701
702 // Create the field and instance.
703 $field = array(
704 'field_name' => 'user_picture',
705 'module' => 'image',
706 'type' => 'image',
707 'cardinality' => 1,
708 'locked' => FALSE,
709 'indexes' => array('fid' => array('fid')),
710 'settings' => array(
711 'uri_scheme' => 'public',
712 'default_image' => FALSE,
713 ),
714 'storage' => array(
715 'type' => 'field_sql_storage',
716 'settings' => array(),
717 ),
718 );
719 _update_7000_field_create_field($field);
720
721 $instance = array(
722 'field_name' => 'user_picture',
723 'entity_type' => 'user',
724 'label' => 'Picture',
725 'bundle' => 'user',
726 'description' => update_variable_get('user_picture_guidelines', ''),
727 'required' => FALSE,
728 'settings' => array(
729 'file_extensions' => 'png gif jpg jpeg',
730 'file_directory' => update_variable_get('user_picture_path', 'pictures'),
731 'max_filesize' => update_variable_get('user_picture_file_size', '30') . ' KB',
732 'alt_field' => 0,
733 'title_field' => 0,
734 'max_resolution' => update_variable_get('user_picture_dimensions', '85x85'),
735 'min_resolution' => '',
736 'default_image' => !empty($default_image_fid) ? $default_image_fid : 0,
737 ),
738 );
739 _update_7000_field_create_instance($field, $instance);
740
741 module_load_install('entity');
742 if (update_variable_get('user_pictures', 0)) {
743 $formatter = 'image';
744 $widget = 'image_image';
745 }
746 else {
747 $formatter = $widget = 'hidden';
748 }
749
750 // Assign form settings for the 'default' form mode.
751 $form_display = _update_8000_entity_get_form_display('user', 'user', 'default');
752 $form_display->set('content.user_picture', array(
753 'type' => $widget,
754 'settings' => array(
755 'progress_indicator' => 'throbber',
756 'preview_image_style' => 'thumbnail',
757 ),
758 'weight' => -1,
759 ))
760 ->save();
761 update_config_manifest_add('entity.form_display', array($form_display->get('id')));
762
763 // Assign display settings for the 'default' and 'compact' view modes.
764 $display = _update_8000_entity_get_display('user', 'user', 'default');
765 $display->set('content.user_picture', array(
766 'label' => 'hidden',
767 'type' => $formatter,
768 'settings' => array(
769 'image_style' => 'thumbnail',
770 'image_link' => 'content',
771 ),
772 'weight' => 0,
773 ))
774 ->save();
775 update_config_manifest_add('entity.display', array($display->get('id')));
776
777 $display = _update_8000_entity_get_display('user', 'user', 'compact');
778 $display->set('content.user_picture', array(
779 'label' => 'hidden',
780 'type' => $formatter,
781 'settings' => array(
782 'image_style' => update_variable_get('user_picture_style', ''),
783 'image_link' => 'content',
784 ),
785 'weight' => 0,
786 ))
787 ->save();
788 update_config_manifest_add('entity.display', array($display->get('id')));
789
790 // Add file usage for the default field.
791 if (!empty($default_image_fid)) {
792 db_insert('file_usage')
793 ->fields(array(
794 'fid' => $default_image_fid,
795 'module' => 'image',
796 'type' => 'default_image',
797 'id' => $field['id'],
798 'count' => 1,
799 ))
800 ->execute();
801 }
802
803 // Update the user bundle settings and hide the member_for extra field.
804 $settings = update_variable_get('field_bundle_settings_user__user');
805 $settings['extra_fields']['display']['member_for']['compact'] = array(
806 'weight' => 0,
807 'visible' => FALSE,
808 );
809 update_variable_set('field_bundle_settings_user__user', $settings);
810
811 // Delete old variables.
812 update_variable_del('user_pictures');
813 update_variable_del('user_picture_path');
814 update_variable_del('user_picture_default');
815 update_variable_del('user_picture_style');
816 update_variable_del('user_picture_dimensions');
817 update_variable_del('user_picture_file_size');
818 update_variable_del('user_picture_guidelines');
819 }
820
821 /**
822 * Migrate {users}.picture to 'user_picture' image field.
823 */
824 function user_update_8012(&$sandbox) {
825 // Initialize total values to process.
826 if (!isset($sandbox['total'])) {
827 $sandbox['total'] = (int) db_query('SELECT COUNT(picture) FROM {users} WHERE picture > 0')->fetchField();
828 $sandbox['processed'] = 0;
829 }
830
831 if ($sandbox['total']) {
832 // Retrieve next 20 rows to migrate.
833 $rows = db_query_range('SELECT uid, picture FROM {users} WHERE picture > 0', 0, 20)->fetchAllKeyed();
834 foreach ($rows as $uid => $fid) {
835 // Add a row to the field data and revision tables.
836 db_insert('field_data_user_picture')
837 ->fields(array(
838 'entity_type' => 'user',
839 'bundle' => 'user',
840 'entity_id' => $uid,
841 'revision_id' => $uid,
842 'langcode' => Language::LANGCODE_NOT_SPECIFIED,
843 'delta' => 0,
844 'user_picture_fid' => $fid,
845 ))
846 ->execute();
847 db_insert('field_revision_user_picture')
848 ->fields(array(
849 'entity_type' => 'user',
850 'bundle' => 'user',
851 'entity_id' => $uid,
852 'revision_id' => $uid,
853 'langcode' => Language::LANGCODE_NOT_SPECIFIED,
854 'delta' => 0,
855 'user_picture_fid' => $fid,
856 ))
857 ->execute();
858
859 // Update file usage from user to file module.
860 // @see file_field_insert()
861 // Old: file_usage_add($picture, 'user', 'user', $entity->uid);
862 // New: file_usage_add(file_load($item['fid']), 'file', $entity_type, $id);
863 db_update('file_usage')
864 ->condition('fid', $fid)
865 ->condition('module', 'user')
866 ->condition('type', 'user')
867 ->condition('id', $uid)
868 ->fields(array(
869 'module' => 'file',
870 ))
871 ->execute();
872 }
873
874 // Set picture column of the migrated users to 0.
875 db_update('users')
876 ->fields(array(
877 'picture' => 0,
878 ))
879 ->condition('uid', array_keys($rows))
880 ->execute();
881
882 // Report status.
883 $sandbox['processed'] += count($rows);
884 }
885 $sandbox['#finished'] = $sandbox['total'] ? $sandbox['processed'] / $sandbox['total'] : 1;
886
887 }
888
889 /**
890 * Deletes {users}.picture field.
891 */
892 function user_update_8013() {
893 db_drop_field('users', 'picture');
894 }
895
896 /**
897 * Create new {users_data} table.
898 */
899 function user_update_8014() {
900 // Create the {users_data} table.
901 db_create_table('users_data', array(
902 'description' => 'Stores module data as key/value pairs per user.',
903 'fields' => array(
904 'uid' => array(
905 'description' => 'Primary key: {users}.uid for user.',
906 'type' => 'int',
907 'unsigned' => TRUE,
908 'not null' => TRUE,
909 'default' => 0,
910 ),
911 'module' => array(
912 'description' => 'The name of the module declaring the variable.',
913 'type' => 'varchar',
914 'length' => 204,
915 'not null' => TRUE,
916 'default' => '',
917 ),
918 'name' => array(
919 'description' => 'The identifier of the data.',
920 'type' => 'varchar',
921 'length' => 128,
922 'not null' => TRUE,
923 'default' => '',
924 ),
925 'value' => array(
926 'description' => 'The value.',
927 'type' => 'blob',
928 'not null' => FALSE,
929 'size' => 'big',
930 ),
931 'serialized' => array(
932 'description' => 'Whether value is serialized.',
933 'type' => 'int',
934 'size' => 'tiny',
935 'unsigned' => TRUE,
936 'default' => 0,
937 ),
938 ),
939 'primary key' => array('uid', 'module', 'name'),
940 'indexes' => array(
941 'module' => array('module'),
942 'name' => array('name'),
943 ),
944 'foreign keys' => array(
945 'uid' => array('users' => 'uid'),
946 ),
947 ));
948
949 // Create backup table for data migration.
950 // Since the origin/owner of individual values in {users}.data is unknown,
951 // other modules need to migrate their existing values from {_d7_users_data}.
952 db_create_table('_d7_users_data', array(
953 'description' => 'Backup of {users}.data for migration.',
954 'fields' => array(
955 'uid' => array(
956 'description' => 'Primary Key: {users}.uid for user.',
957 'type' => 'int',
958 'unsigned' => TRUE,
959 'not null' => TRUE,
960 'default' => 0,
961 ),
962 'name' => array(
963 'description' => 'The name of the variable.',
964 'type' => 'varchar',
965 'length' => 128,
966 'not null' => TRUE,
967 'default' => '',
968 ),
969 'value' => array(
970 'description' => 'The serialized value of the variable.',
971 'type' => 'blob',
972 'not null' => FALSE,
973 'size' => 'big',
974 'serialize' => TRUE,
975 ),
976 ),
977 'primary key' => array('uid', 'name'),
978 'foreign keys' => array(
979 'uid' => array('users' => 'uid'),
980 ),
981 ));
982 }
983
984 /**
985 * Move existing {users}.data into {_d7_users_data} migration table.
986 */
987 function user_update_8015(&$sandbox) {
988 if (!isset($sandbox['progress'])) {
989 $sandbox['progress'] = 0;
990 // The anonymous user cannot have data, so start with uid 1.
991 $sandbox['last'] = 0;
992 $sandbox['max'] = db_query('SELECT COUNT(uid) FROM {users} WHERE uid > 0')->fetchField();
993 }
994
995 // Process 20 user records at a time. E.g., if there are 10 data keys per user
996 // record, that leads to an insert query with 200 values.
997 $result = db_query_range('SELECT uid, data FROM {users} WHERE uid > :uid ORDER BY uid ASC', 0, 20, array(':uid' => $sandbox['last']))->fetchAllKeyed();
998 $query = db_insert('_d7_users_data')->fields(array('uid', 'name', 'value'));
999 $has_values = FALSE;
1000 foreach ($result as $uid => $data) {
1001 $sandbox['progress']++;
1002 $sandbox['last'] = $uid;
1003 if (empty($data)) {
1004 continue;
1005 }
1006 $data = unserialize($data);
1007 if (!empty($data) && is_array($data)) {
1008 $has_values = TRUE;
1009 foreach ($data as $name => $value) {
1010 $query->values(array(
1011 'uid' => $uid,
1012 'name' => $name,
1013 'value' => serialize($value),
1014 ));
1015 }
1016 }
1017 }
1018 if ($has_values) {
1019 $query->execute();
1020 }
1021
1022 $sandbox['#finished'] = empty($sandbox['max']) ? 1 : ($sandbox['progress'] / $sandbox['max']);
1023 }
1024
1025 /**
1026 * Drop {users}.data column.
1027 */
1028 function user_update_8016() {
1029 db_drop_field('users', 'data');
1030 }
1031
1032 /**
1033 * Migrate user roles into configuration.
1034 *
1035 * @ingroup config_upgrade
1036 */
1037 function user_update_8017() {
1038 $uuid = new Uuid();
1039
1040 $roles = db_select('role', 'r')
1041 ->fields('r')
1042 ->execute()
1043 ->fetchAll();
1044
1045 foreach ($roles as $role) {
1046 config('user.role.' . $role->rid)
1047 ->set('id', $role->rid)
1048 ->set('uuid', $uuid->generate())
1049 ->set('label', $role->name)
1050 ->set('weight', $role->weight)
1051 ->set('langcode', Language::LANGCODE_NOT_SPECIFIED)
1052 ->save();
1053 }
1054
1055 update_config_manifest_add('user.role', array_map(function ($role) {
1056 return $role->rid;
1057 }, $roles));
1058 }
1059
1060 /**
1061 * @} End of "addtogroup updates-7.x-to-8.x".
1062 */