function AccountForm::form

Same name and namespace in other branches
  1. 9 core/modules/user/src/AccountForm.php \Drupal\user\AccountForm::form()
  2. 8.9.x core/modules/user/src/AccountForm.php \Drupal\user\AccountForm::form()
  3. 10 core/modules/user/src/AccountForm.php \Drupal\user\AccountForm::form()

Overrides ContentEntityForm::form

1 call to AccountForm::form()
RegisterForm::form in core/modules/user/src/RegisterForm.php
Gets the actual form array to be built.
1 method overrides AccountForm::form()
RegisterForm::form in core/modules/user/src/RegisterForm.php
Gets the actual form array to be built.

File

core/modules/user/src/AccountForm.php, line 67

Class

AccountForm
Form controller for the user account forms.

Namespace

Drupal\user

Code

public function form(array $form, FormStateInterface $form_state) {
    
    /** @var \Drupal\user\UserInterface $account */
    $account = $this->entity;
    $user = $this->currentUser();
    $config = \Drupal::config('user.settings');
    $form['#cache']['tags'] = $config->getCacheTags();
    $language_interface = \Drupal::languageManager()->getCurrentLanguage();
    // Check for new account.
    $register = $account->isNew();
    // For a new account, there are 2 sub-cases:
    // $self_register: A user creates their own, new, account
    // (path '/user/register')
    // $admin_create: An administrator creates a new account for another user
    // (path '/admin/people/create')
    // If the current user is logged in and has permission to create users
    // then it must be the second case.
    $admin_create = $register && $account->access('create');
    $self_register = $register && !$admin_create;
    // Account information.
    $form['account'] = [
        '#type' => 'container',
        '#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 email address to be edited and deleted.
    // Also see \Drupal\user\Plugin\Validation\Constraint\UserMailRequired.
    $form['account']['mail'] = [
        '#type' => 'email',
        '#title' => $this->t('Email address'),
        '#description' => $this->t('The email address is not made public. It will only be used if you need to be contacted about your account or for opted-in notifications.'),
        '#required' => !(!$account->getEmail() && $user->hasPermission('administer users')),
        '#default_value' => !$register ? $account->getEmail() : '',
        '#access' => $account->mail
            ->access('edit'),
    ];
    // Only show name field on registration form or user can change own username.
    $form['account']['name'] = [
        '#type' => 'textfield',
        '#title' => $this->t('Username'),
        '#maxlength' => UserInterface::USERNAME_MAX_LENGTH,
        '#description' => $this->t("Several special characters are allowed, including space, period (.), hyphen (-), apostrophe ('), underscore (_), and the @ sign."),
        '#required' => TRUE,
        '#attributes' => [
            'class' => [
                'username',
            ],
            'autocorrect' => 'off',
            'autocapitalize' => 'off',
            'spellcheck' => 'false',
        ],
        '#default_value' => !$register ? $account->getAccountName() : '',
        '#access' => $account->name
            ->access('edit'),
    ];
    // Display password field only for existing users or when user is allowed to
    // assign a password during registration.
    if (!$register) {
        $form['account']['pass'] = [
            '#type' => 'password_confirm',
            '#size' => 25,
            '#description' => $this->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. Store this in $form_state
        // so it persists even on subsequent Ajax requests.
        $request = $this->getRequest();
        if (!$form_state->get('user_pass_reset') && ($token = $request->query
            ->get('pass-reset-token'))) {
            $session_key = 'pass_reset_' . $account->id();
            $session_value = $request->getSession()
                ->get($session_key);
            $user_pass_reset = isset($session_value) && hash_equals($session_value, $token);
            $form_state->set('user_pass_reset', $user_pass_reset);
        }
        // The user must enter their current password to change to a new one.
        if ($user->id() == $account->id()) {
            $form['account']['current_pass'] = [
                '#type' => 'password',
                '#title' => $this->t('Current password'),
                '#size' => 25,
                '#access' => !$form_state->get('user_pass_reset'),
                '#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' => [
                    'autocomplete' => 'off',
                ],
            ];
            $form_state->set('user', $account);
            // The user may only change their own password without their current
            // password if they logged in via a one-time login link.
            if (!$form_state->get('user_pass_reset')) {
                $form['account']['current_pass']['#description'] = $this->t('Required if you want to change the %mail or %pass below. <a href=":request_new_url" title="Send password reset instructions via email.">Reset your password</a>.', [
                    '%mail' => $form['account']['mail']['#title'],
                    '%pass' => $this->t('Password'),
                    ':request_new_url' => Url::fromRoute('user.pass')->toString(),
                ]);
            }
        }
    }
    elseif (!$config->get('verify_mail') || $admin_create) {
        $form['account']['pass'] = [
            '#type' => 'password_confirm',
            '#size' => 25,
            '#description' => $this->t('Provide a password for the new account in both fields.'),
            '#required' => TRUE,
        ];
    }
    // When not building the user registration form, prevent web browsers from
    // auto-filling/prefilling the email, username, and password fields.
    if (!$register) {
        foreach ([
            'mail',
            'name',
            'pass',
        ] as $key) {
            if (isset($form['account'][$key])) {
                $form['account'][$key]['#attributes']['autocomplete'] = 'off';
            }
        }
    }
    if (!$self_register) {
        $status = $account->get('status')->value;
    }
    else {
        $status = $config->get('register') == UserInterface::REGISTER_VISITORS ? 1 : 0;
    }
    $form['account']['status'] = [
        '#type' => 'radios',
        '#title' => $this->t('Status'),
        '#default_value' => $status,
        '#options' => [
            $this->t('Blocked'),
            $this->t('Active'),
        ],
        '#access' => $account->status
            ->access('edit'),
    ];
    $roles = Role::loadMultiple();
    unset($roles[RoleInterface::ANONYMOUS_ID]);
    $roles = array_map(fn(RoleInterface $role) => Html::escape($role->label()), $roles);
    $form['account']['roles'] = [
        '#type' => 'checkboxes',
        '#title' => $this->t('Roles'),
        '#default_value' => !$register ? $account->getRoles() : [],
        '#options' => $roles,
        '#access' => $roles && $user->hasPermission('administer permissions'),
    ];
    // Special handling for the inevitable "Authenticated user" role.
    $form['account']['roles'][RoleInterface::AUTHENTICATED_ID] = [
        '#default_value' => TRUE,
        '#disabled' => TRUE,
    ];
    $form['account']['notify'] = [
        '#type' => 'checkbox',
        '#title' => $this->t('Notify user of new account'),
        '#access' => $admin_create,
    ];
    $user_preferred_langcode = $register ? $language_interface->getId() : $account->getPreferredLangcode();
    $user_preferred_admin_langcode = $register ? $language_interface->getId() : $account->getPreferredAdminLangcode(FALSE);
    // Is the user preferred language added?
    $user_language_added = FALSE;
    if ($this->languageManager instanceof ConfigurableLanguageManagerInterface) {
        $negotiator = $this->languageManager
            ->getNegotiator();
        $user_language_added = $negotiator && $negotiator->isNegotiationMethodEnabled(LanguageNegotiationUser::METHOD_ID, LanguageInterface::TYPE_INTERFACE);
    }
    $form['language'] = [
        '#type' => $this->languageManager
            ->isMultilingual() ? 'details' : 'container',
        '#title' => $this->t('Language settings'),
        '#open' => TRUE,
        // Display language selector when either creating a user on the admin
        // interface or editing a user account.
'#access' => !$self_register,
    ];
    $form['language']['preferred_langcode'] = [
        '#type' => 'language_select',
        '#title' => $this->t('Site language'),
        '#languages' => LanguageInterface::STATE_CONFIGURABLE,
        '#default_value' => $user_preferred_langcode,
        '#description' => $user_language_added ? $this->t("This account's preferred language for emails and site presentation.") : $this->t("This account's preferred language for emails."),
        // This is used to explain that user preferred language and entity
        // language are synchronized. It can be removed if a different behavior is
        // desired.
'#pre_render' => [
            'user_langcode' => [
                $this,
                'alterPreferredLangcodeDescription',
            ],
        ],
    ];
    // Only show the account setting for Administration pages language to users
    // if one of the detection and selection methods uses it.
    $show_admin_language = FALSE;
    if (($account->hasPermission('access administration pages') || $account->hasPermission('view the administration theme')) && $this->languageManager instanceof ConfigurableLanguageManagerInterface) {
        $negotiator = $this->languageManager
            ->getNegotiator();
        $show_admin_language = $negotiator && $negotiator->isNegotiationMethodEnabled(LanguageNegotiationUserAdmin::METHOD_ID);
    }
    $form['language']['preferred_admin_langcode'] = [
        '#type' => 'language_select',
        '#title' => $this->t('Administration pages language'),
        '#languages' => LanguageInterface::STATE_CONFIGURABLE,
        '#default_value' => $user_preferred_admin_langcode,
        '#access' => $show_admin_language,
        '#empty_option' => $this->t('- No preference -'),
        '#empty_value' => '',
    ];
    // 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 entity builder provides that synchronization. For
    // use-cases where this synchronization is not desired, a module can alter
    // or remove this item. Sync user langcode only when a user registers and
    // not when a user is updated or translated.
    if ($register) {
        $form['#entity_builders']['sync_user_langcode'] = '::syncUserLangcode';
    }
    $system_date_config = \Drupal::config('system.date');
    $form['timezone'] = [
        '#type' => 'details',
        '#title' => $this->t('Locale settings'),
        '#open' => TRUE,
        '#weight' => 6,
        '#access' => $system_date_config->get('timezone.user.configurable'),
    ];
    if ($self_register && $system_date_config->get('timezone.user.default') != UserInterface::TIMEZONE_SELECT) {
        $form['timezone']['#access'] = FALSE;
    }
    $form['timezone']['timezone'] = [
        '#type' => 'select',
        '#title' => $this->t('Time zone'),
        '#default_value' => $account->getTimezone() ?: $system_date_config->get('timezone.default'),
        '#options' => TimeZoneFormHelper::getOptionsListByRegion($account->id() != $user->id()),
        '#description' => $this->t('Select the desired local time and time zone. Dates and times throughout this site will be displayed using this time zone.'),
    ];
    // If not set or selected yet, detect timezone for the current user only.
    $user_input = $form_state->getUserInput();
    if (!$account->getTimezone() && $account->id() == $user->id() && empty($user_input['timezone'])) {
        $form['timezone']['#attached']['library'][] = 'core/drupal.timezone';
        $form['timezone']['timezone']['#attributes'] = [
            'class' => [
                'timezone-detect',
            ],
        ];
    }
    return parent::form($form, $form_state);
}

Buggy or inaccurate documentation? Please file an issue. Need support? Need help programming? Connect with the Drupal community.