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