abstract class AccountFormController

Form controller for the user account forms.

Hierarchy

Expanded class hierarchy of AccountFormController

File

drupal/core/modules/user/lib/Drupal/user/AccountFormController.php, line 16
Definition of Drupal\user\AccountFormController.

Namespace

Drupal\user
View source
abstract class AccountFormController extends EntityFormController {

  /**
   * Overrides Drupal\Core\Entity\EntityFormController::form().
   */
  public function form(array $form, array &$form_state) {
    $account = $this->entity;
    global $user;
    $config = config('user.settings');
    $language_interface = language(Language::TYPE_INTERFACE);
    $register = empty($account->uid);
    $admin = user_access('administer users');

    // Account information.
    $form['account'] = array(
      '#type' => 'container',
      '#weight' => -10,
    );

    // Only show name field on registration form or user can change own username.
    $form['account']['name'] = array(
      '#type' => 'textfield',
      '#title' => t('Username'),
      '#maxlength' => USERNAME_MAX_LENGTH,
      '#description' => t('Spaces are allowed; punctuation is not allowed except for periods, hyphens, apostrophes, and underscores.'),
      '#required' => TRUE,
      '#attributes' => array(
        'class' => array(
          'username',
        ),
        'autocorrect' => 'off',
        'autocomplete' => 'off',
        'autocapitalize' => 'off',
        'spellcheck' => 'false',
      ),
      '#default_value' => !$register ? $account->name : '',
      '#access' => $register || $user->uid == $account->uid && user_access('change own username') || $admin,
      '#weight' => -10,
    );

    // The mail field is NOT required if account originally had no mail set
    // and the user performing the edit has 'administer users' permission.
    // This allows users without e-mail address to be edited and deleted.
    $form['account']['mail'] = array(
      '#type' => 'email',
      '#title' => t('E-mail address'),
      '#description' => t('A valid e-mail address. All e-mails from the system will be sent to this address. The e-mail address is not made public and will only be used if you wish to receive a new password or wish to receive certain news or notifications by e-mail.'),
      '#required' => !(empty($account->mail) && user_access('administer users')),
      '#default_value' => !$register ? $account->mail : '',
      '#attributes' => array(
        'autocomplete' => 'off',
      ),
    );

    // Display password field only for existing users or when user is allowed to
    // assign a password during registration.
    if (!$register) {
      $form['account']['pass'] = array(
        '#type' => 'password_confirm',
        '#size' => 25,
        '#description' => t('To change the current user password, enter the new password in both fields.'),
      );

      // To skip the current password field, the user must have logged in via a
      // one-time link and have the token in the URL.
      $pass_reset = isset($_SESSION['pass_reset_' . $account->uid]) && isset($_GET['pass-reset-token']) && $_GET['pass-reset-token'] == $_SESSION['pass_reset_' . $account->uid];
      $protected_values = array();
      $current_pass_description = '';

      // The user may only change their own password without their current
      // password if they logged in via a one-time login link.
      if (!$pass_reset) {
        $protected_values['mail'] = $form['account']['mail']['#title'];
        $protected_values['pass'] = t('Password');
        $request_new = l(t('Request new password'), 'user/password', array(
          'attributes' => array(
            'title' => t('Request new password via e-mail.'),
          ),
        ));
        $current_pass_description = t('Required if you want to change the %mail or %pass below. !request_new.', array(
          '%mail' => $protected_values['mail'],
          '%pass' => $protected_values['pass'],
          '!request_new' => $request_new,
        ));
      }

      // The user must enter their current password to change to a new one.
      if ($user->uid == $account->uid) {
        $form['account']['current_pass_required_values'] = array(
          '#type' => 'value',
          '#value' => $protected_values,
        );
        $form['account']['current_pass'] = array(
          '#type' => 'password',
          '#title' => t('Current password'),
          '#size' => 25,
          '#access' => !empty($protected_values),
          '#description' => $current_pass_description,
          '#weight' => -5,
          // Do not let web browsers remember this password, since we are
          // trying to confirm that the person submitting the form actually
          // knows the current one.
          '#attributes' => array(
            'autocomplete' => 'off',
          ),
        );
        $form_state['user'] = $account;
        $form['#validate'][] = 'user_validate_current_pass';
      }
    }
    elseif (!$config
      ->get('verify_mail') || $admin) {
      $form['account']['pass'] = array(
        '#type' => 'password_confirm',
        '#size' => 25,
        '#description' => t('Provide a password for the new account in both fields.'),
        '#required' => TRUE,
      );
    }
    if ($admin) {
      $status = isset($account->status) ? $account->status : 1;
    }
    else {
      $status = $register ? $config
        ->get('register') == USER_REGISTER_VISITORS : $account->status;
    }
    $form['account']['status'] = array(
      '#type' => 'radios',
      '#title' => t('Status'),
      '#default_value' => $status,
      '#options' => array(
        t('Blocked'),
        t('Active'),
      ),
      '#access' => $admin,
    );
    $roles = array_map('check_plain', user_role_names(TRUE));

    // The disabled checkbox subelement for the 'authenticated user' role
    // must be generated separately and added to the checkboxes element,
    // because of a limitation in Form API not supporting a single disabled
    // checkbox within a set of checkboxes.
    // @todo This should be solved more elegantly. See issue #119038.
    $checkbox_authenticated = array(
      '#type' => 'checkbox',
      '#title' => $roles[DRUPAL_AUTHENTICATED_RID],
      '#default_value' => TRUE,
      '#disabled' => TRUE,
    );
    unset($roles[DRUPAL_AUTHENTICATED_RID]);
    $form['account']['roles'] = array(
      '#type' => 'checkboxes',
      '#title' => t('Roles'),
      '#default_value' => !$register ? $account->roles : array(),
      '#options' => $roles,
      '#access' => $roles && user_access('administer permissions'),
      DRUPAL_AUTHENTICATED_RID => $checkbox_authenticated,
    );
    $form['account']['notify'] = array(
      '#type' => 'checkbox',
      '#title' => t('Notify user of new account'),
      '#access' => $register && $admin,
    );

    // Signature.
    $form['signature_settings'] = array(
      '#type' => 'details',
      '#title' => t('Signature settings'),
      '#weight' => 1,
      '#access' => !$register && $config
        ->get('signatures'),
    );
    $form['signature_settings']['signature'] = array(
      '#type' => 'text_format',
      '#title' => t('Signature'),
      '#default_value' => isset($account->signature) ? $account->signature : '',
      '#description' => t('Your signature will be publicly displayed at the end of your comments.'),
      '#format' => isset($account->signature_format) ? $account->signature_format : NULL,
    );
    $user_preferred_langcode = $register ? $language_interface->langcode : user_preferred_langcode($account);
    $user_preferred_admin_langcode = $register ? $language_interface->langcode : user_preferred_langcode($account, 'admin');

    // Is default the interface language?
    include_once DRUPAL_ROOT . '/core/includes/language.inc';
    $interface_language_is_default = language_negotiation_method_get_first(Language::TYPE_INTERFACE) != LANGUAGE_NEGOTIATION_SELECTED;
    $form['language'] = array(
      '#type' => language_multilingual() ? 'details' : 'container',
      '#title' => t('Language settings'),
      // Display language selector when either creating a user on the admin
      // interface or editing a user account.
      '#access' => !$register || user_access('administer users'),
    );
    $form['language']['preferred_langcode'] = array(
      '#type' => 'language_select',
      '#title' => t('Site language'),
      '#languages' => Language::STATE_CONFIGURABLE,
      '#default_value' => $user_preferred_langcode,
      '#description' => $interface_language_is_default ? t("This account's preferred language for e-mails and site presentation.") : t("This account's preferred language for e-mails."),
    );
    $form['language']['preferred_admin_langcode'] = array(
      '#type' => 'language_select',
      '#title' => t('Administration pages language'),
      '#languages' => Language::STATE_CONFIGURABLE,
      '#default_value' => $user_preferred_admin_langcode,
      '#access' => user_access('access administration pages', $account),
    );

    // User entities contain both a langcode property (for identifying the
    // language of the entity data) and a preferred_langcode property (see
    // above). Rather than provide a UI forcing the user to choose both
    // separately, assume that the user profile data is in the user's preferred
    // language. This element provides that synchronization. For use-cases where
    // this synchronization is not desired, a module can alter or remove this
    // element.
    $form['language']['langcode'] = array(
      '#type' => 'value',
      '#value_callback' => '_user_language_selector_langcode_value',
      // For the synchronization to work, this element must have a larger weight
      // than the preferred_langcode element. Set a large weight here in case
      // a module alters the weight of the other element.
      '#weight' => 100,
    );
    return parent::form($form, $form_state, $account);
  }

  /**
   * {@inheritdoc}
   */
  public function buildEntity(array $form, array &$form_state) {

    // Change the roles array to a list of enabled roles.
    // @todo: Alter the form state as the form values are directly extracted and
    //   set on the field, which throws an exception as the list requires
    //   numeric keys. Allow to override this per field. As this function is
    //   called twice, we have to prevent it from getting the array keys twice.
    if (empty($this->roles_filtered)) {
      $form_state['values']['roles'] = array_keys(array_filter($form_state['values']['roles']));
      $this->roles_filtered = TRUE;
    }
    return parent::buildEntity($form, $form_state);
  }

  /**
   * Overrides Drupal\Core\Entity\EntityFormController::submit().
   */
  public function validate(array $form, array &$form_state) {
    parent::validate($form, $form_state);
    $account = $this->entity;

    // Validate new or changing username.
    if (isset($form_state['values']['name'])) {
      if ($error = user_validate_name($form_state['values']['name'])) {
        form_set_error('name', $error);
      }
      else {
        $name_taken = (bool) db_select('users')
          ->fields('users', array(
          'uid',
        ))
          ->condition('uid', (int) $account->uid, '<>')
          ->condition('name', db_like($form_state['values']['name']), 'LIKE')
          ->range(0, 1)
          ->execute()
          ->fetchField();
        if ($name_taken) {
          form_set_error('name', t('The name %name is already taken.', array(
            '%name' => $form_state['values']['name'],
          )));
        }
      }
    }
    $mail = $form_state['values']['mail'];
    if (!empty($mail)) {
      $mail_taken = (bool) db_select('users')
        ->fields('users', array(
        'uid',
      ))
        ->condition('uid', (int) $account->uid, '<>')
        ->condition('mail', db_like($mail), 'LIKE')
        ->range(0, 1)
        ->execute()
        ->fetchField();
      if ($mail_taken) {

        // Format error message dependent on whether the user is logged in or not.
        if ($GLOBALS['user']->uid) {
          form_set_error('mail', t('The e-mail address %email is already taken.', array(
            '%email' => $mail,
          )));
        }
        else {
          form_set_error('mail', t('The e-mail address %email is already registered. <a href="@password">Have you forgotten your password?</a>', array(
            '%email' => $mail,
            '@password' => url('user/password'),
          )));
        }
      }
    }

    // Make sure the signature isn't longer than the size of the database field.
    // Signatures are disabled by default, so make sure it exists first.
    if (isset($form_state['values']['signature'])) {

      // Move text format for user signature into 'signature_format'.
      $form_state['values']['signature_format'] = $form_state['values']['signature']['format'];

      // Move text value for user signature into 'signature'.
      $form_state['values']['signature'] = $form_state['values']['signature']['value'];
      $user_schema = drupal_get_schema('users');
      if (drupal_strlen($form_state['values']['signature']) > $user_schema['fields']['signature']['length']) {
        form_set_error('signature', t('The signature is too long: it must be %max characters or less.', array(
          '%max' => $user_schema['fields']['signature']['length'],
        )));
      }
    }
  }

}

Members

Namesort descending Modifiers Type Description Overrides
AccountFormController::buildEntity public function Implements \Drupal\Core\Entity\EntityFormControllerInterface::buildEntity(). Overrides EntityFormController::buildEntity
AccountFormController::form public function Overrides Drupal\Core\Entity\EntityFormController::form(). Overrides EntityFormController::form 1
AccountFormController::validate public function Overrides Drupal\Core\Entity\EntityFormController::submit(). Overrides EntityFormController::validate
EntityFormController::$entity protected property The entity being used by this form.
EntityFormController::$operation protected property The name of the current operation.
EntityFormController::actions protected function Returns an array of supported actions for the current entity form. 17
EntityFormController::actionsElement protected function Returns the action form element for the current entity form.
EntityFormController::buildForm public function Form constructor. Overrides FormInterface::buildForm 1
EntityFormController::delete public function Form submission handler for the 'delete' action. 12
EntityFormController::getBaseFormID public function Returns a string identifying the base form. Overrides BaseFormIdInterface::getBaseFormID
EntityFormController::getEntity public function Implements \Drupal\Core\Entity\EntityFormControllerInterface::getEntity(). Overrides EntityFormControllerInterface::getEntity
EntityFormController::getFormDisplay public function Returns the form display. Overrides EntityFormControllerInterface::getFormDisplay
EntityFormController::getFormID public function Returns a unique string identifying the form. Overrides FormInterface::getFormID
EntityFormController::getFormLangcode public function Implements \Drupal\Core\Entity\EntityFormControllerInterface::getFormLangcode(). Overrides EntityFormControllerInterface::getFormLangcode
EntityFormController::getOperation public function Implements \Drupal\Core\Entity\EntityFormControllerInterface::getOperation(). Overrides EntityFormControllerInterface::getOperation
EntityFormController::init protected function Initialize the form state and the entity before the first form build. 1
EntityFormController::isDefaultFormLangcode public function Implements \Drupal\Core\Entity\EntityFormControllerInterface::isDefaultFormLangcode(). Overrides EntityFormControllerInterface::isDefaultFormLangcode
EntityFormController::prepareEntity protected function Prepares the entity object before the form is built first. 3
EntityFormController::save public function Form submission handler for the 'save' action. 20
EntityFormController::setEntity public function Implements \Drupal\Core\Entity\EntityFormControllerInterface::setEntity(). Overrides EntityFormControllerInterface::setEntity
EntityFormController::setFormDisplay public function Sets the form display. Overrides EntityFormControllerInterface::setFormDisplay
EntityFormController::setOperation public function Sets the operation for this form.
EntityFormController::submit public function Implements \Drupal\Core\Entity\EntityFormControllerInterface::submit(). Overrides EntityFormControllerInterface::submit 13
EntityFormController::submitEntityLanguage protected function Handle possible entity language changes. 1
EntityFormController::submitForm public function Form submission handler. Overrides FormInterface::submitForm
EntityFormController::updateFormLangcode protected function Updates the form language to reflect any change to the entity language.
EntityFormController::validateForm public function Form validation handler. Overrides FormInterface::validateForm
EntityFormController::__construct public function Constructs an EntityFormController object. 5