user.admin.inc 40.2 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13
<?php

/**
 * @file
 * Admin page callback file for the user module.
 */

function user_admin($callback_arg = '') {
  $op = isset($_POST['op']) ? $_POST['op'] : $callback_arg;

  switch ($op) {
    case t('Create new account'):
    case 'create':
14 15
      $account = entity_create('user', array());
      $build['user_register'] = entity_get_form($account, 'register');
16 17
      break;
    default:
18
      if (!empty($_POST['accounts']) && isset($_POST['operation']) && ($_POST['operation'] == 'cancel')) {
19
        $build['user_multiple_cancel_confirm'] = drupal_get_form('user_multiple_cancel_confirm');
20 21
      }
      else {
22 23
        $build['user_filter_form'] = drupal_get_form('user_filter_form');
        $build['user_admin_account'] = drupal_get_form('user_admin_account');
24 25
      }
  }
26
  return $build;
27 28 29 30
}

/**
 * Form builder; Return form for user administration filters.
31
 *
32
 * @ingroup forms
33
 * @see user_filter_form_submit()
34 35
 */
function user_filter_form() {
36
  $session = isset($_SESSION['user_overview_filter']) ? $_SESSION['user_overview_filter'] : array();
37 38 39
  $filters = user_filters();

  $i = 0;
40 41 42
  $form['filters'] = array(
    '#type' => 'fieldset',
    '#title' => t('Show only users where'),
43
    '#theme' => 'exposed_filters__user',
44
  );
45 46
  foreach ($session as $filter) {
    list($type, $value) = $filter;
47 48 49 50 51 52 53 54 55
    if ($type == 'permission') {
      // Merge arrays of module permissions into one.
      // Slice past the first element '[any]' whose value is not an array.
      $options = call_user_func_array('array_merge', array_slice($filters[$type]['options'], 1));
      $value = $options[$value];
    }
    else {
      $value = $filters[$type]['options'][$value];
    }
56
    $t_args = array('%property' => $filters[$type]['title'], '%value' => $value);
57
    if ($i++) {
58
      $form['filters']['current'][] = array('#markup' => t('and where %property is %value', $t_args));
59 60
    }
    else {
61
      $form['filters']['current'][] = array('#markup' => t('%property is %value', $t_args));
62
    }
63 64
  }

65 66 67 68 69 70 71 72 73
  $form['filters']['status'] = array(
    '#type' => 'container',
    '#attributes' => array('class' => array('clearfix')),
    '#prefix' => ($i ? '<div class="additional-filters">' . t('and where') . '</div>' : ''),
  );
  $form['filters']['status']['filters'] = array(
    '#type' => 'container',
    '#attributes' => array('class' => array('filters')),
  );
74
  foreach ($filters as $key => $filter) {
75
    $form['filters']['status']['filters'][$key] = array(
76 77
      '#type' => 'select',
      '#options' => $filter['options'],
78 79
      '#title' => $filter['title'],
      '#default_value' => '[any]',
80
    );
81 82
  }

83
  $form['filters']['status']['actions'] = array(
84 85
    '#type' => 'actions',
    '#attributes' => array('class' => array('container-inline')),
86
  );
87
  $form['filters']['status']['actions']['submit'] = array(
88 89 90
    '#type' => 'submit',
    '#value' => (count($session) ? t('Refine') : t('Filter')),
  );
91
  if (count($session)) {
92
    $form['filters']['status']['actions']['undo'] = array(
93 94 95
      '#type' => 'submit',
      '#value' => t('Undo'),
    );
96
    $form['filters']['status']['actions']['reset'] = array(
97 98 99
      '#type' => 'submit',
      '#value' => t('Reset'),
    );
100 101
  }

102
  drupal_add_library('system', 'drupal.form');
103

104 105 106 107 108 109 110 111 112 113
  return $form;
}

/**
 * Process result from user administration filter form.
 */
function user_filter_form_submit($form, &$form_state) {
  $op = $form_state['values']['op'];
  $filters = user_filters();
  switch ($op) {
114 115 116 117 118
    case t('Filter'):
    case t('Refine'):
      // Apply every filter that has a choice selected other than 'any'.
      foreach ($filters as $filter => $options) {
        if (isset($form_state['values'][$filter]) && $form_state['values'][$filter] != '[any]') {
119
          $_SESSION['user_overview_filter'][] = array($filter, $form_state['values'][$filter]);
120 121 122 123 124 125 126
        }
      }
      break;
    case t('Undo'):
      array_pop($_SESSION['user_overview_filter']);
      break;
    case t('Reset'):
127
      $_SESSION['user_overview_filter'] = array();
128 129 130 131 132
      break;
    case t('Update'):
      return;
  }

133
  $form_state['redirect'] = 'admin/people';
134 135 136 137 138 139 140
  return;
}

/**
 * Form builder; User administration page.
 *
 * @ingroup forms
141 142
 * @see user_admin_account_validate()
 * @see user_admin_account_submit()
143 144 145 146
 */
function user_admin_account() {

  $header = array(
147
    'username' => array('data' => t('Username'), 'field' => 'u.name'),
148 149 150 151
    'status' => array('data' => t('Status'), 'field' => 'u.status', 'class' => array(RESPONSIVE_PRIORITY_LOW)),
    'roles' => array('data' => t('Roles'), 'class' => array(RESPONSIVE_PRIORITY_LOW)),
    'member_for' => array('data' => t('Member for'), 'field' => 'u.created', 'sort' => 'desc', 'class' => array(RESPONSIVE_PRIORITY_LOW)),
    'access' => array('data' => t('Last access'), 'field' => 'u.access', 'class' => array(RESPONSIVE_PRIORITY_LOW)),
152
    'operations' => t('Operations'),
153 154
  );

155
  $query = db_select('users', 'u');
156 157
  $query->condition('u.uid', 0, '<>');
  user_build_filter_query($query);
158

159
  $count_query = clone $query;
160
  $count_query->addExpression('COUNT(u.uid)');
161

162 163
  $query = $query
    ->extend('Drupal\Core\Database\Query\PagerSelectExtender')
164
    ->extend('Drupal\Core\Database\Query\TableSortExtender');
165 166 167
  $query
    ->fields('u', array('uid', 'name', 'status', 'created', 'access'))
    ->limit(50)
168
    ->orderByHeader($header)
169 170
    ->setCountQuery($count_query);
  $result = $query->execute();
171 172 173 174

  $form['options'] = array(
    '#type' => 'fieldset',
    '#title' => t('Update options'),
175
    '#attributes' => array('class' => array('container-inline')),
176 177 178 179 180 181 182
  );
  $options = array();
  foreach (module_invoke_all('user_operations') as $operation => $array) {
    $options[$operation] = $array['label'];
  }
  $form['options']['operation'] = array(
    '#type' => 'select',
183 184
    '#title' => t('Operation'),
    '#title_display' => 'invisible',
185 186 187
    '#options' => $options,
    '#default_value' => 'unblock',
  );
188
  $options = array();
189 190 191 192 193 194 195 196
  $form['options']['submit'] = array(
    '#type' => 'submit',
    '#value' => t('Update'),
  );

  $destination = drupal_get_destination();

  $status = array(t('blocked'), t('active'));
197
  $roles = array_map('check_plain', user_roles(TRUE));
198
  $accounts = array();
199
  foreach ($result as $account) {
200
    $users_roles = array();
201 202
    $roles_result = db_query('SELECT rid FROM {users_roles} WHERE uid = :uid', array(':uid' => $account->uid));
    foreach ($roles_result as $user_role) {
203
      $users_roles[] = $roles[$user_role->rid];
204
    }
205
    asort($users_roles);
206

207
    $options[$account->uid] = array(
208
      'username' => theme('username', array('account' => $account)),
209
      'status' =>  $status[$account->status],
210
      'roles' => theme('item_list', array('items' => $users_roles)),
211 212
      'member_for' => format_interval(REQUEST_TIME - $account->created),
      'access' =>  $account->access ? t('@time ago', array('@time' => format_interval(REQUEST_TIME - $account->access))) : t('never'),
213 214 215 216 217 218 219 220 221 222
    );
    $links = array();
    $links['edit'] = array(
      'title' => t('edit'),
      'href' => "user/$account->uid/edit",
      'query' => $destination,
    );
    $options[$account->uid]['operations']['data'] = array(
      '#type' => 'operations',
      '#links' => $links,
223
    );
224
  }
225

226
  $form['accounts'] = array(
227 228 229 230
    '#type' => 'tableselect',
    '#header' => $header,
    '#options' => $options,
    '#empty' => t('No people available.'),
231
  );
232
  $form['pager'] = array('#markup' => theme('pager'));
233 234 235 236 237 238 239 240

  return $form;
}

/**
 * Submit the user administration update form.
 */
function user_admin_account_submit($form, &$form_state) {
241
  $operations = module_invoke_all('user_operations', $form, $form_state);
242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269
  $operation = $operations[$form_state['values']['operation']];
  // Filter out unchecked accounts.
  $accounts = array_filter($form_state['values']['accounts']);
  if ($function = $operation['callback']) {
    // Add in callback arguments if present.
    if (isset($operation['callback arguments'])) {
      $args = array_merge(array($accounts), $operation['callback arguments']);
    }
    else {
      $args = array($accounts);
    }
    call_user_func_array($function, $args);

    drupal_set_message(t('The update has been performed.'));
  }
}

function user_admin_account_validate($form, &$form_state) {
  $form_state['values']['accounts'] = array_filter($form_state['values']['accounts']);
  if (count($form_state['values']['accounts']) == 0) {
    form_set_error('', t('No users selected.'));
  }
}

/**
 * Form builder; Configure user settings for this site.
 *
 * @ingroup forms
270
 * @see user_admin_settings_submit()
271
 */
272 273
function user_admin_settings($form, &$form_state) {
  $config = config('user.settings');
274 275
  $mail_config = config('user.mail');

276 277 278 279 280 281 282 283
  // Settings for anonymous users.
  $form['anonymous_settings'] = array(
    '#type' => 'fieldset',
    '#title' => t('Anonymous users'),
  );
  $form['anonymous_settings']['anonymous'] = array(
    '#type' => 'textfield',
    '#title' => t('Name'),
284
    '#default_value' => $config->get('anonymous'),
285 286 287
    '#description' => t('The name used to indicate anonymous users.'),
    '#required' => TRUE,
  );
288

289 290 291
  // Administrative role option.
  $form['admin_role'] = array(
    '#type' => 'fieldset',
292
    '#title' => t('Administrator role'),
293 294
  );

295
  // Do not allow users to set the anonymous or authenticated user roles as the
296 297
  // administrator role.
  $roles = user_roles();
298 299
  unset($roles[DRUPAL_ANONYMOUS_RID]);
  unset($roles[DRUPAL_AUTHENTICATED_RID]);
300 301 302 303 304
  $roles[0] = t('disabled');

  $form['admin_role']['user_admin_role'] = array(
    '#type' => 'select',
    '#title' => t('Administrator role'),
305
    '#default_value' => $config->get('admin_role'),
306 307 308 309
    '#options' => $roles,
    '#description' => t('This role will be automatically assigned new permissions whenever a module is enabled. Changing this setting will not affect existing permissions.'),
  );

310 311 312 313 314 315 316 317 318 319 320
  // @todo Remove this check once language settings are generalized.
  if (module_exists('translation_entity')) {
    $form['language'] = array(
      '#type' => 'fieldset',
      '#title' => t('Language settings'),
      '#tree' => TRUE,
    );
    $form_state['translation_entity']['key'] = 'language';
    $form['language'] += translation_entity_enable_widget('user', 'user', $form, $form_state);
  }

321 322
  // User registration settings.
  $form['registration_cancellation'] = array(
323
    '#type' => 'fieldset',
324 325 326 327 328
    '#title' => t('Registration and cancellation'),
  );
  $form['registration_cancellation']['user_register'] = array(
    '#type' => 'radios',
    '#title' => t('Who can register accounts?'),
329
    '#default_value' => $config->get('register'),
330
    '#options' => array(
331 332 333
      USER_REGISTER_ADMINISTRATORS_ONLY => t('Administrators only'),
      USER_REGISTER_VISITORS => t('Visitors'),
      USER_REGISTER_VISITORS_ADMINISTRATIVE_APPROVAL => t('Visitors, but administrator approval is required'),
334 335 336 337 338
    )
  );
  $form['registration_cancellation']['user_email_verification'] = array(
    '#type' => 'checkbox',
    '#title' => t('Require e-mail verification when a visitor creates an account.'),
339
    '#default_value' => $config->get('verify_mail'),
340
    '#description' => t('New users will be required to validate their e-mail address prior to logging into the site, and will be assigned a system-generated password. With this setting disabled, users will be logged in immediately upon registering, and may select their own passwords during registration.')
341
  );
342 343
  module_load_include('inc', 'user', 'user.pages');
  $form['registration_cancellation']['user_cancel_method'] = array(
344 345
    '#type' => 'item',
    '#title' => t('When cancelling a user account'),
346
    '#default_value' => $config->get('cancel_method'),
347
    '#description' => t('Users with the %select-cancel-method or %administer-users <a href="@permissions-url">permissions</a> can override this default method.', array('%select-cancel-method' => t('Select method for cancelling account'), '%administer-users' => t('Administer users'), '@permissions-url' => url('admin/people/permissions'))),
348
  );
349 350
  $form['registration_cancellation']['user_cancel_method'] += user_cancel_methods();
  foreach (element_children($form['registration_cancellation']['user_cancel_method']) as $element) {
351 352
    // Remove all account cancellation methods that have #access defined, as
    // those cannot be configured as default method.
353 354
    if (isset($form['registration_cancellation']['user_cancel_method'][$element]['#access'])) {
      $form['registration_cancellation']['user_cancel_method'][$element]['#access'] = FALSE;
355 356 357
    }
    // Remove the description (only displayed on the confirmation form).
    else {
358
      unset($form['registration_cancellation']['user_cancel_method'][$element]['#description']);
359 360 361
    }
  }

362 363
  // Account settings.
  $form['personalization'] = array(
364
    '#type' => 'fieldset',
365 366 367 368 369
    '#title' => t('Personalization'),
  );
  $form['personalization']['user_signatures'] = array(
    '#type' => 'checkbox',
    '#title' => t('Enable signatures.'),
370
    '#default_value' => $config->get('signatures'),
371 372 373
  );
  // If picture support is enabled, check whether the picture directory exists.
  if (variable_get('user_pictures', 0)) {
374
    $picture_path =  file_default_scheme() . '://' . variable_get('user_picture_path', 'pictures');
375 376
    if (!file_prepare_directory($picture_path, FILE_CREATE_DIRECTORY)) {
      form_set_error('user_picture_path', t('The directory %directory does not exist or is not writable.', array('%directory' => $picture_path)));
377
      watchdog('file system', 'The directory %directory does not exist or is not writable.', array('%directory' => $picture_path), WATCHDOG_ERROR);
378
    }
379 380 381 382 383 384 385
  }
  $picture_support = variable_get('user_pictures', 0);
  $form['personalization']['user_pictures'] = array(
    '#type' => 'checkbox',
    '#title' => t('Enable user pictures.'),
    '#default_value' => $picture_support,
  );
386
  $form['#attached']['library'][] = array('user', 'drupal.user');
387
  $form['personalization']['pictures'] = array(
388 389 390 391 392 393 394
    '#type' => 'container',
    '#states' => array(
      // Hide the additional picture settings when user pictures are disabled.
      'invisible' => array(
        'input[name="user_pictures"]' => array('checked' => FALSE),
      ),
    ),
395 396 397 398 399 400 401
  );
  $form['personalization']['pictures']['user_picture_path'] = array(
    '#type' => 'textfield',
    '#title' => t('Picture directory'),
    '#default_value' => variable_get('user_picture_path', 'pictures'),
    '#size' => 30,
    '#maxlength' => 255,
402
    '#description' => t('Subdirectory in the file upload directory where pictures will be stored.'),
403 404 405 406 407 408 409 410 411
  );
  $form['personalization']['pictures']['user_picture_default'] = array(
    '#type' => 'textfield',
    '#title' => t('Default picture'),
    '#default_value' => variable_get('user_picture_default', ''),
    '#size' => 30,
    '#maxlength' => 255,
    '#description' => t('URL of picture to display for users with no custom picture selected. Leave blank for none.'),
  );
412 413 414
  if (module_exists('image')) {
    $form['personalization']['pictures']['settings']['user_picture_style'] = array(
      '#type' => 'select',
415
      '#title' => t('Picture display style'),
416 417
      '#options' => image_style_options(TRUE),
      '#default_value' => variable_get('user_picture_style', ''),
418
      '#description' => t('The style selected will be used on display, while the original image is retained. Styles may be configured in the <a href="!url">Image styles</a> administration area.', array('!url' => url('admin/config/media/image-styles'))),
419 420
    );
  }
421 422
  $form['personalization']['pictures']['user_picture_dimensions'] = array(
    '#type' => 'textfield',
423
    '#title' => t('Picture upload dimensions'),
424
    '#default_value' => variable_get('user_picture_dimensions', '85x85'),
425
    '#size' => 10,
426
    '#maxlength' => 10,
427
    '#field_suffix' => ' ' . t('pixels'),
428
    '#description' => t('Pictures larger than this will be scaled down to this size.'),
429 430
  );
  $form['personalization']['pictures']['user_picture_file_size'] = array(
431
    '#type' => 'number',
432
    '#title' => t('Picture upload file size'),
433
    '#default_value' => variable_get('user_picture_file_size', '30'),
434
    '#min' => 0,
435
    '#field_suffix' => ' ' . t('KB'),
436
    '#description' => t('Maximum allowed file size for uploaded pictures. Upload size is normally limited only by the PHP maximum post and file upload settings, and images are automatically scaled down to the dimensions specified above.'),
437 438 439 440 441 442 443 444 445 446 447 448 449 450
  );
  $form['personalization']['pictures']['user_picture_guidelines'] = array(
    '#type' => 'textarea',
    '#title' => t('Picture guidelines'),
    '#default_value' => variable_get('user_picture_guidelines', ''),
    '#description' => t("This text is displayed at the picture upload form in addition to the default guidelines. It's useful for helping or instructing your users."),
  );

  $form['email_title'] = array(
    '#type' => 'item',
    '#title' => t('E-mails'),
  );
  $form['email'] = array(
    '#type' => 'vertical_tabs',
451 452 453
  );
  // These email tokens are shared for all settings, so just define
  // the list once to help ensure they stay in sync.
454
  $email_token_help = t('Available variables are: [site:name], [site:url], [user:name], [user:mail], [site:login-url], [site:url-brief], [user:edit-url], [user:one-time-login-url], [user:cancel-url].');
455

456
  $form['email_admin_created'] = array(
457
    '#type' => 'fieldset',
458
    '#title' => t('Welcome (new user created by administrator)'),
459
    '#collapsible' => TRUE,
460
    '#collapsed' => ($config->get('register') != USER_REGISTER_ADMINISTRATORS_ONLY),
461
    '#description' => t('Edit the welcome e-mail messages sent to new member accounts created by an administrator.') . ' ' . $email_token_help,
462
    '#group' => 'email',
463
  );
464
  $form['email_admin_created']['user_mail_register_admin_created_subject'] = array(
465 466
    '#type' => 'textfield',
    '#title' => t('Subject'),
467
    '#default_value' => $mail_config->get('register_admin_created.subject'),
468 469
    '#maxlength' => 180,
  );
470
  $form['email_admin_created']['user_mail_register_admin_created_body'] = array(
471 472
    '#type' => 'textarea',
    '#title' => t('Body'),
473
    '#default_value' =>  $mail_config->get('register_admin_created.body'),
474 475 476
    '#rows' => 15,
  );

477
  $form['email_pending_approval'] = array(
478
    '#type' => 'fieldset',
479
    '#title' => t('Welcome (awaiting approval)'),
480
    '#collapsible' => TRUE,
481
    '#collapsed' => ($config->get('register') != USER_REGISTER_VISITORS_ADMINISTRATIVE_APPROVAL),
482
    '#description' => t('Edit the welcome e-mail messages sent to new members upon registering, when administrative approval is required.') . ' ' . $email_token_help,
483
    '#group' => 'email',
484
  );
485
  $form['email_pending_approval']['user_mail_register_pending_approval_subject'] = array(
486 487
    '#type' => 'textfield',
    '#title' => t('Subject'),
488
    '#default_value' => $mail_config->get('register_pending_approval.subject'),
489 490
    '#maxlength' => 180,
  );
491
  $form['email_pending_approval']['user_mail_register_pending_approval_body'] = array(
492 493
    '#type' => 'textarea',
    '#title' => t('Body'),
494
    '#default_value' => $mail_config->get('register_pending_approval.body'),
495
    '#rows' => 8,
496 497
  );

498
  $form['email_no_approval_required'] = array(
499
    '#type' => 'fieldset',
500
    '#title' => t('Welcome (no approval required)'),
501
    '#collapsible' => TRUE,
502
    '#collapsed' => ($config->get('register') != USER_REGISTER_VISITORS),
503
    '#description' => t('Edit the welcome e-mail messages sent to new members upon registering, when no administrator approval is required.') . ' ' . $email_token_help,
504
    '#group' => 'email',
505
  );
506
  $form['email_no_approval_required']['user_mail_register_no_approval_required_subject'] = array(
507 508
    '#type' => 'textfield',
    '#title' => t('Subject'),
509
    '#default_value' => $mail_config->get('register_no_approval_required.subject'),
510 511
    '#maxlength' => 180,
  );
512
  $form['email_no_approval_required']['user_mail_register_no_approval_required_body'] = array(
513 514
    '#type' => 'textarea',
    '#title' => t('Body'),
515
    '#default_value' => $mail_config->get('register_no_approval_required.body'),
516
    '#rows' => 15,
517
  );
518

519
  $form['email_password_reset'] = array(
520
    '#type' => 'fieldset',
521
    '#title' => t('Password recovery'),
522 523
    '#collapsible' => TRUE,
    '#collapsed' => TRUE,
524
    '#description' => t('Edit the e-mail messages sent to users who request a new password.') . ' ' . $email_token_help,
525 526
    '#group' => 'email',
    '#weight' => 10,
527
  );
528
  $form['email_password_reset']['user_mail_password_reset_subject'] = array(
529 530
    '#type' => 'textfield',
    '#title' => t('Subject'),
531
    '#default_value' => $mail_config->get('password_reset.subject'),
532 533
    '#maxlength' => 180,
  );
534
  $form['email_password_reset']['user_mail_password_reset_body'] = array(
535 536
    '#type' => 'textarea',
    '#title' => t('Body'),
537
    '#default_value' => $mail_config->get('password_reset.body'),
538 539 540
    '#rows' => 12,
  );

541
  $form['email_activated'] = array(
542
    '#type' => 'fieldset',
543
    '#title' => t('Account activation'),
544 545
    '#collapsible' => TRUE,
    '#collapsed' => TRUE,
546
    '#description' => t('Enable and edit e-mail messages sent to users upon account activation (when an administrator activates an account of a user who has already registered, on a site where administrative approval is required).') . ' ' . $email_token_help,
547
    '#group' => 'email',
548
  );
549
  $form['email_activated']['user_mail_status_activated_notify'] = array(
550 551
    '#type' => 'checkbox',
    '#title' => t('Notify user when account is activated.'),
552
    '#default_value' => $config->get('notify.status_activated'),
553
  );
554 555 556 557 558 559 560 561 562 563
  $form['email_activated']['settings'] = array(
    '#type' => 'container',
    '#states' => array(
      // Hide the additional settings when this email is disabled.
      'invisible' => array(
        'input[name="user_mail_status_activated_notify"]' => array('checked' => FALSE),
      ),
    ),
  );
  $form['email_activated']['settings']['user_mail_status_activated_subject'] = array(
564 565
    '#type' => 'textfield',
    '#title' => t('Subject'),
566
    '#default_value' => $mail_config->get('status_activated.subject'),
567 568
    '#maxlength' => 180,
  );
569
  $form['email_activated']['settings']['user_mail_status_activated_body'] = array(
570 571
    '#type' => 'textarea',
    '#title' => t('Body'),
572
    '#default_value' => $mail_config->get('status_activated.body'),
573 574 575
    '#rows' => 15,
  );

576
  $form['email_blocked'] = array(
577
    '#type' => 'fieldset',
578
    '#title' => t('Account blocked'),
579 580
    '#collapsible' => TRUE,
    '#collapsed' => TRUE,
581
    '#description' => t('Enable and edit e-mail messages sent to users when their accounts are blocked.') . ' ' . $email_token_help,
582
    '#group' => 'email',
583
  );
584
  $form['email_blocked']['user_mail_status_blocked_notify'] = array(
585 586
    '#type' => 'checkbox',
    '#title' => t('Notify user when account is blocked.'),
587
    '#default_value' => $config->get('notify.status_blocked'),
588
  );
589 590 591 592 593 594 595 596 597 598
  $form['email_blocked']['settings'] = array(
    '#type' => 'container',
    '#states' => array(
      // Hide the additional settings when the blocked email is disabled.
      'invisible' => array(
        'input[name="user_mail_status_blocked_notify"]' => array('checked' => FALSE),
      ),
    ),
  );
  $form['email_blocked']['settings']['user_mail_status_blocked_subject'] = array(
599 600
    '#type' => 'textfield',
    '#title' => t('Subject'),
601
    '#default_value' => $mail_config->get('status_blocked.subject'),
602 603
    '#maxlength' => 180,
  );
604
  $form['email_blocked']['settings']['user_mail_status_blocked_body'] = array(
605 606
    '#type' => 'textarea',
    '#title' => t('Body'),
607
    '#default_value' => $mail_config->get('status_blocked.body'),
608 609 610
    '#rows' => 3,
  );

611
  $form['email_cancel_confirm'] = array(
612
    '#type' => 'fieldset',
613
    '#title' => t('Account cancellation confirmation'),
614 615
    '#collapsible' => TRUE,
    '#collapsed' => TRUE,
616
    '#description' => t('Edit the e-mail messages sent to users when they attempt to cancel their accounts.') . ' ' . $email_token_help,
617
    '#group' => 'email',
618
  );
619
  $form['email_cancel_confirm']['user_mail_cancel_confirm_subject'] = array(
620 621
    '#type' => 'textfield',
    '#title' => t('Subject'),
622
    '#default_value' => $mail_config->get('cancel_confirm.subject'),
623 624
    '#maxlength' => 180,
  );
625
  $form['email_cancel_confirm']['user_mail_cancel_confirm_body'] = array(
626 627
    '#type' => 'textarea',
    '#title' => t('Body'),
628
    '#default_value' => $mail_config->get('cancel_confirm.body'),
629 630 631
    '#rows' => 3,
  );

632
  $form['email_canceled'] = array(
633
    '#type' => 'fieldset',
634
    '#title' => t('Account canceled'),
635 636
    '#collapsible' => TRUE,
    '#collapsed' => TRUE,
637
    '#description' => t('Enable and edit e-mail messages sent to users when their accounts are canceled.') . ' ' . $email_token_help,
638
    '#group' => 'email',
639
  );
640
  $form['email_canceled']['user_mail_status_canceled_notify'] = array(
641
    '#type' => 'checkbox',
642
    '#title' => t('Notify user when account is canceled.'),
643
    '#default_value' => $config->get('notify.status_canceled'),
644
  );
645 646 647
  $form['email_canceled']['settings'] = array(
    '#type' => 'container',
    '#states' => array(
648
      // Hide the settings when the cancel notify checkbox is disabled.
649 650 651 652 653 654
      'invisible' => array(
        'input[name="user_mail_status_canceled_notify"]' => array('checked' => FALSE),
      ),
    ),
  );
  $form['email_canceled']['settings']['user_mail_status_canceled_subject'] = array(
655 656
    '#type' => 'textfield',
    '#title' => t('Subject'),
657
    '#default_value' => $mail_config->get('status_canceled.subject'),
658 659
    '#maxlength' => 180,
  );
660
  $form['email_canceled']['settings']['user_mail_status_canceled_body'] = array(
661 662
    '#type' => 'textarea',
    '#title' => t('Body'),
663
    '#default_value' => $mail_config->get('status_canceled.body'),
664 665 666
    '#rows' => 3,
  );

667 668 669 670 671 672 673 674 675 676 677 678 679
  return system_config_form($form, $form_state);
}

/**
 * Form submission handler for user_admin_settings().
 */
function user_admin_settings_submit($form, &$form_state) {
  config('user.settings')
    ->set('anonymous', $form_state['values']['anonymous'])
    ->set('admin_role', $form_state['values']['user_admin_role'])
    ->set('register', $form_state['values']['user_register'])
    ->set('verify_mail', $form_state['values']['user_email_verification'])
    ->set('signatures', $form_state['values']['user_signatures'])
680
    ->set('cancel_method', $form_state['values']['user_cancel_method'])
681 682 683 684
    ->set('notify.status_activated', $form_state['values']['user_mail_status_activated_notify'])
    ->set('notify.status_blocked', $form_state['values']['user_mail_status_blocked_notify'])
    ->set('notify.status_canceled', $form_state['values']['user_mail_status_canceled_notify'])
    ->save();
685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702
  config('user.mail')
    ->set('cancel_confirm.body', $form_state['values']['user_mail_cancel_confirm_body'])
    ->set('cancel_confirm.subject', $form_state['values']['user_mail_cancel_confirm_subject'])
    ->set('password_reset.body', $form_state['values']['user_mail_password_reset_body'])
    ->set('password_reset.subject', $form_state['values']['user_mail_password_reset_subject'])
    ->set('register_admin_created.body', $form_state['values']['user_mail_register_admin_created_body'])
    ->set('register_admin_created.subject', $form_state['values']['user_mail_register_admin_created_subject'])
    ->set('register_no_approval_required.body', $form_state['values']['user_mail_register_no_approval_required_body'])
    ->set('register_no_approval_required.subject', $form_state['values']['user_mail_register_no_approval_required_subject'])
    ->set('register_pending_approval.body', $form_state['values']['user_mail_register_pending_approval_body'])
    ->set('register_pending_approval.subject', $form_state['values']['user_mail_register_pending_approval_subject'])
    ->set('status_activated.body', $form_state['values']['user_mail_status_activated_body'])
    ->set('status_activated.subject', $form_state['values']['user_mail_status_activated_subject'])
    ->set('status_blocked.body', $form_state['values']['user_mail_status_blocked_body'])
    ->set('status_blocked.subject', $form_state['values']['user_mail_status_blocked_subject'])
    ->set('status_canceled.body', $form_state['values']['user_mail_status_canceled_body'])
    ->set('status_canceled.subject', $form_state['values']['user_mail_status_canceled_subject'])
    ->save();
703 704 705 706
}

/**
 * Menu callback: administer permissions.
707
 *
708
 * @ingroup forms
709 710
 * @see user_admin_permissions_submit()
 * @see theme_user_admin_permissions()
711
 */
712
function user_admin_permissions($form, $form_state, $rid = NULL) {
713

714 715
  // Retrieve role names for columns.
  $role_names = user_roles();
716
  if (isset($rid)) {
717
    $role_names = array($rid => $role_names[$rid]);
718
  }
719 720
  // Fetch permissions for all roles or the one selected role.
  $role_permissions = user_role_permissions($role_names);
721

722 723 724 725 726
  // Store $role_names for use when saving the data.
  $form['role_names'] = array(
    '#type' => 'value',
    '#value' => $role_names,
  );
727 728
  // Render role/permission overview:
  $options = array();
729
  $module_info = system_get_info('module');
730
  $hide_descriptions = system_admin_compact_mode();
731 732 733 734

  // Get a list of all the modules implementing a hook_permission() and sort by
  // display name.
  $modules = array();
735
  foreach (module_implements('permission') as $module) {
736
    $modules[$module] = $module_info[$module]['name'];
737
  }
738
  asort($modules);
739

740
  foreach ($modules as $module => $display_name) {
741
    if ($permissions = module_invoke($module, 'permission')) {
742
      $form['permission'][] = array(
743
        '#markup' => $module_info[$module]['name'],
744
        '#id' => $module,
745
      );
746
      foreach ($permissions as $perm => $perm_item) {
747 748 749 750 751 752
        // Fill in default values for the permission.
        $perm_item += array(
          'description' => '',
          'restrict access' => FALSE,
          'warning' => !empty($perm_item['restrict access']) ? t('Warning: Give to trusted roles only; this permission has security implications.') : '',
        );
753
        $options[$perm] = '';
754 755
        $form['permission'][$perm] = array(
          '#type' => 'item',
756
          '#markup' => $perm_item['title'],
757
          '#description' => theme('user_permission_description', array('permission_item' => $perm_item, 'hide' => $hide_descriptions)),
758
        );
759 760
        foreach ($role_names as $rid => $name) {
          // Builds arrays for checked boxes for each role
761
          if (isset($role_permissions[$rid][$perm])) {
762 763 764 765 766 767 768 769 770
            $status[$rid][] = $perm;
          }
        }
      }
    }
  }

  // Have to build checkboxes here after checkbox arrays are built
  foreach ($role_names as $rid => $name) {
771 772 773 774 775 776
    $form['checkboxes'][$rid] = array(
      '#type' => 'checkboxes',
      '#options' => $options,
      '#default_value' => isset($status[$rid]) ? $status[$rid] : array(),
      '#attributes' => array('class' => array('rid-' . $rid)),
    );
777
    $form['role_names'][$rid] = array('#markup' => check_plain($name), '#tree' => TRUE);
778
  }
779

780
  $form['actions'] = array('#type' => 'actions');
781
  $form['actions']['submit'] = array('#type' => 'submit', '#value' => t('Save permissions'));
782

783
  $form['#attached']['library'][] = array('user', 'drupal.user.permissions');
784

785 786 787
  return $form;
}

788 789 790
/**
 * Save permissions selected on the administer permissions page.
 *
791
 * @see user_admin_permissions()
792
 */
793
function user_admin_permissions_submit($form, &$form_state) {
794
  foreach ($form_state['values']['role_names'] as $rid => $name) {
795
    user_role_change_permissions($rid, $form_state['values'][$rid]);
796 797 798 799
  }

  drupal_set_message(t('The changes have been saved.'));

800
  // Clear the cached pages and blocks.
801
  cache_invalidate(array('content' => TRUE));
802 803 804
}

/**
805 806 807 808 809
 * Returns HTML for the administer permissions page.
 *
 * @param $variables
 *   An associative array containing:
 *   - form: A render element representing the form.
810 811 812
 *
 * @ingroup themeable
 */
813 814 815
function theme_user_admin_permissions($variables) {
  $form = $variables['form'];

816
  $roles = user_roles();
817
  foreach (element_children($form['permission']) as $key) {
818 819 820
    $row = array();
    // Module name
    if (is_numeric($key)) {
821
      $row[] = array('data' => drupal_render($form['permission'][$key]), 'class' => array('module'), 'id' => 'module-' . $form['permission'][$key]['#id'], 'colspan' => count($form['role_names']['#value']) + 1);
822 823 824 825 826
    }
    else {
      // Permission row.
      $row[] = array(
        'data' => drupal_render($form['permission'][$key]),