diff --git a/core/modules/user/src/AccountSettingsForm.php b/core/modules/user/src/AccountSettingsForm.php index 0c5aed846a..22f01ad6f4 100644 --- a/core/modules/user/src/AccountSettingsForm.php +++ b/core/modules/user/src/AccountSettingsForm.php @@ -107,8 +107,8 @@ public function buildForm(array $form, FormStateInterface $form_state) { '#title' => $this->t('Administrator role'), '#open' => TRUE, ]; - // Do not allow users to set the anonymous or authenticated user roles as the - // administrator role. + // Do not allow users to set the anonymous or authenticated user roles as + // the administrator role. $roles = user_role_names(TRUE); unset($roles[RoleInterface::AUTHENTICATED_ID]); @@ -188,7 +188,11 @@ public function buildForm(array $form, FormStateInterface $form_state) { '#type' => 'radios', '#title' => $this->t('When cancelling a user account'), '#default_value' => $config->get('cancel_method'), - '#description' => $this->t('Users with the %select-cancel-method or %administer-users permissions can override this default method.', ['%select-cancel-method' => $this->t('Select method for cancelling account'), '%administer-users' => $this->t('Administer users'), ':permissions-url' => Url::fromRoute('user.admin_permissions')->toString()]), + '#description' => $this->t('Users with the %select-cancel-method or %administer-users permissions can override this default method.', [ + '%select-cancel-method' => $this->t('Select method for cancelling account'), + '%administer-users' => $this->t('Administer users'), + ':permissions-url' => Url::fromRoute('user.admin_permissions')->toString(), + ]), ]; $form['registration_cancellation']['user_cancel_method'] += user_cancel_methods(); foreach (Element::children($form['registration_cancellation']['user_cancel_method']) as $key) { @@ -320,7 +324,7 @@ public function buildForm(array $form, FormStateInterface $form_state) { '#type' => 'details', '#title' => $this->t('Account activation (password set at registration)'), '#collapsed' => TRUE, - '#description' => t('Edit the activation e-mail messages sent to new members upon registering, when no administrator approval is required and password has already been set during registration.') . ' ' . $email_token_help, + '#description' => $this->t('Edit the activation e-mail messages sent to new members upon registering, when no administrator approval is required and password has already been set during registration.') . ' ' . $email_token_help, '#group' => 'email', ]; $form['email_password_set']['user_mail_register_password_set_subject'] = [ diff --git a/core/modules/user/src/Entity/User.php b/core/modules/user/src/Entity/User.php index fc91d4cdf8..c5120762e6 100644 --- a/core/modules/user/src/Entity/User.php +++ b/core/modules/user/src/Entity/User.php @@ -97,7 +97,10 @@ public function preSave(EntityStorageInterface $storage) { // Make sure that the authenticated/anonymous roles are not persisted. foreach ($this->get('roles') as $index => $item) { - if (in_array($item->target_id, [RoleInterface::ANONYMOUS_ID, RoleInterface::AUTHENTICATED_ID])) { + if (in_array($item->target_id, [ + RoleInterface::ANONYMOUS_ID, + RoleInterface::AUTHENTICATED_ID, + ])) { $this->get('roles')->offsetUnset($index); } } @@ -198,7 +201,10 @@ public function hasRole($rid) { */ public function addRole($rid) { - if (in_array($rid, [RoleInterface::AUTHENTICATED_ID, RoleInterface::ANONYMOUS_ID])) { + if (in_array($rid, [ + RoleInterface::AUTHENTICATED_ID, + RoleInterface::ANONYMOUS_ID, + ])) { throw new \InvalidArgumentException('Anonymous or authenticated role ID must not be assigned manually.'); } diff --git a/core/modules/user/src/RegisterForm.php b/core/modules/user/src/RegisterForm.php index 4c05bcd427..72db4089e3 100644 --- a/core/modules/user/src/RegisterForm.php +++ b/core/modules/user/src/RegisterForm.php @@ -15,7 +15,6 @@ class RegisterForm extends AccountForm { * {@inheritdoc} */ public function form(array $form, FormStateInterface $form_state) { - $user = $this->currentUser(); /** @var \Drupal\user\UserInterface $account */ $account = $this->entity; @@ -69,7 +68,7 @@ protected function actions(array $form, FormStateInterface $form_state) { * {@inheritdoc} */ public function submitForm(array &$form, FormStateInterface $form_state) { - $config = \Drupal::config('user.settings'); + $config = $this->config('user.settings'); $admin = $form_state->getValue('administer_users'); if (!$config->get('verify_mail') || ($config->get('verify_mail') && $config->get('password_register')) || $admin) { @@ -99,7 +98,7 @@ public function submitForm(array &$form, FormStateInterface $form_state) { * {@inheritdoc} */ public function save(array $form, FormStateInterface $form_state) { - $config = \Drupal::config('user.settings'); + $config = $this->config('user.settings'); $account = $this->entity; $pass = $account->getPassword(); $admin = $form_state->getValue('administer_users'); @@ -112,16 +111,23 @@ public function save(array $form, FormStateInterface $form_state) { $form_state->set('user', $account); $form_state->setValue('uid', $account->id()); - $this->logger('user')->notice('New user: %name %email.', ['%name' => $form_state->getValue('name'), '%email' => '<' . $form_state->getValue('mail') . '>', 'type' => $account->toLink($this->t('Edit'), 'edit-form')->toString()]); + $this->logger('user')->notice('New user: %name %email.', [ + '%name' => $form_state->getValue('name'), + '%email' => '<' . $form_state->getValue('mail') . '>', + 'type' => $account->toLink($this->t('Edit'), 'edit-form')->toString(), + ]); // Add plain text password into user account to generate mail tokens. $account->password = $pass; // New administrative account without notification. if ($admin && !$notify) { - $this->messenger()->addStatus($this->t('Created a new user account for %name. No email has been sent.', [':url' => $account->toUrl()->toString(), '%name' => $account->getAccountName()])); + $this->messenger()->addStatus($this->t('Created a new user account for %name. No email has been sent.', [ + ':url' => $account->toUrl()->toString(), + '%name' => $account->getAccountName(), + ])); } - // E-mail verification enabled, but users set a password during registration. + // Email verification enabled, but users set a password during registration. elseif (!$admin && $config->get('register') == UserInterface::REGISTER_VISITORS && $config->get('password_register') && !$account->isActive()) { // Notify the user. _user_mail_notify('register_password_set', $account); @@ -129,7 +135,7 @@ public function save(array $form, FormStateInterface $form_state) { $form_state->setRedirect(''); } // No email verification required; log in user immediately. - elseif (!$admin && !\Drupal::config('user.settings')->get('verify_mail') && $account->isActive()) { + elseif (!$admin && !$config->get('verify_mail') && $account->isActive()) { _user_mail_notify('register_no_approval_required', $account); user_login_finalize($account); $this->messenger()->addStatus($this->t('Registration successful. You are now logged in.')); @@ -138,13 +144,19 @@ public function save(array $form, FormStateInterface $form_state) { // No administrator approval required. elseif ($account->isActive() || $notify) { if (!$account->getEmail() && $notify) { - $this->messenger()->addStatus($this->t('The new user %name was created without an email address, so no welcome message was sent.', [':url' => $account->toUrl()->toString(), '%name' => $account->getAccountName()])); + $this->messenger()->addStatus($this->t('The new user %name was created without an email address, so no welcome message was sent.', [ + ':url' => $account->toUrl()->toString(), + '%name' => $account->getAccountName(), + ])); } else { $op = $notify ? 'register_admin_created' : 'register_no_approval_required'; if (_user_mail_notify($op, $account)) { if ($notify) { - $this->messenger()->addStatus($this->t('A welcome message with further instructions has been emailed to the new user %name.', [':url' => $account->toUrl()->toString(), '%name' => $account->getAccountName()])); + $this->messenger()->addStatus($this->t('A welcome message with further instructions has been emailed to the new user %name.', [ + ':url' => $account->toUrl()->toString(), + '%name' => $account->getAccountName(), + ])); } else { $this->messenger()->addStatus($this->t('A welcome message with further instructions has been sent to your email address.')); diff --git a/core/modules/user/tests/src/Functional/UserRegistrationTest.php b/core/modules/user/tests/src/Functional/UserRegistrationTest.php index 3f040883e5..0a55dbbb0c 100644 --- a/core/modules/user/tests/src/Functional/UserRegistrationTest.php +++ b/core/modules/user/tests/src/Functional/UserRegistrationTest.php @@ -5,6 +5,7 @@ use Drupal\Component\Render\FormattableMarkup; use Drupal\Core\Entity\Entity\EntityFormDisplay; use Drupal\Core\Field\FieldStorageDefinitionInterface; +use Drupal\Core\StringTranslation\StringTranslationTrait; use Drupal\Core\Test\AssertMailTrait; use Drupal\field\Entity\FieldConfig; use Drupal\field\Entity\FieldStorageConfig; @@ -18,6 +19,8 @@ */ class UserRegistrationTest extends BrowserTestBase { + use StringTranslationTrait; + use AssertMailTrait { getMails as drupalGetMails; } @@ -34,6 +37,9 @@ class UserRegistrationTest extends BrowserTestBase { */ protected $defaultTheme = 'stark'; + /** + * Tests registration form with email verification. + */ public function testRegistrationWithEmailVerification() { $config = $this->config('user.settings'); // Require email verification. @@ -50,8 +56,8 @@ public function testRegistrationWithEmailVerification() { $edit = []; $edit['name'] = $name = $this->randomMachineName(); $edit['mail'] = $mail = $edit['name'] . '@example.com'; - $this->drupalPostForm('user/register', $edit, t('Create new account')); - $this->assertText(t('A welcome message with further instructions has been sent to your email address.'), 'User registered successfully.'); + $this->drupalPostForm('user/register', $edit, $this->t('Create new account')); + $this->assertText($this->t('A welcome message with further instructions has been sent to your email address.'), 'User registered successfully.'); /** @var EntityStorageInterface $storage */ $storage = $this->container->get('entity_type.manager')->getStorage('user'); @@ -67,13 +73,16 @@ public function testRegistrationWithEmailVerification() { $edit = []; $edit['name'] = $name = $this->randomMachineName(); $edit['mail'] = $mail = $edit['name'] . '@example.com'; - $this->drupalPostForm('user/register', $edit, t('Create new account')); + $this->drupalPostForm('user/register', $edit, $this->t('Create new account')); $this->container->get('entity_type.manager')->getStorage('user')->resetCache(); $accounts = $storage->loadByProperties(['name' => $name, 'mail' => $mail]); $new_user = reset($accounts); $this->assertFalse($new_user->isActive(), 'New account is blocked until approved by an administrator.'); } + /** + * Tests registration form without email varification. + */ public function testRegistrationWithoutEmailVerification() { $config = $this->config('user.settings'); // Don't require email verification and allow registration by site visitors @@ -90,19 +99,19 @@ public function testRegistrationWithoutEmailVerification() { // Try entering a mismatching password. $edit['pass[pass1]'] = '99999.0'; $edit['pass[pass2]'] = '99999'; - $this->drupalPostForm('user/register', $edit, t('Create new account')); - $this->assertText(t('The specified passwords do not match.'), 'Typing mismatched passwords displays an error message.'); + $this->drupalPostForm('user/register', $edit, $this->t('Create new account')); + $this->assertText($this->t('The specified passwords do not match.'), 'Typing mismatched passwords displays an error message.'); // Enter a correct password. $edit['pass[pass1]'] = $new_pass = $this->randomMachineName(); $edit['pass[pass2]'] = $new_pass; - $this->drupalPostForm('user/register', $edit, t('Create new account')); + $this->drupalPostForm('user/register', $edit, $this->t('Create new account')); $this->container->get('entity_type.manager')->getStorage('user')->resetCache(); $accounts = $this->container->get('entity_type.manager')->getStorage('user') ->loadByProperties(['name' => $name, 'mail' => $mail]); $new_user = reset($accounts); $this->assertNotNull($new_user, 'New account successfully created with matching passwords.'); - $this->assertText(t('Registration successful. You are now logged in.'), 'Users are logged in after registering.'); + $this->assertText($this->t('Registration successful. You are now logged in.'), 'Users are logged in after registering.'); $this->drupalLogout(); // Allow registration by site visitors, but require administrator approval. @@ -112,16 +121,16 @@ public function testRegistrationWithoutEmailVerification() { $edit['mail'] = $mail = $edit['name'] . '@example.com'; $edit['pass[pass1]'] = $pass = $this->randomMachineName(); $edit['pass[pass2]'] = $pass; - $this->drupalPostForm('user/register', $edit, t('Create new account')); - $this->assertText(t('Thank you for applying for an account. Your account is currently pending approval by the site administrator.'), 'Users are notified of pending approval'); + $this->drupalPostForm('user/register', $edit, $this->t('Create new account')); + $this->assertText($this->t('Thank you for applying for an account. Your account is currently pending approval by the site administrator.'), 'Users are notified of pending approval'); // Try to log in before administrator approval. $auth = [ 'name' => $name, 'pass' => $pass, ]; - $this->drupalPostForm('user/login', $auth, t('Log in')); - $this->assertText(t('The username @name has not been activated or is blocked.', ['@name' => $name]), 'User cannot log in yet.'); + $this->drupalPostForm('user/login', $auth, $this->t('Log in')); + $this->assertText($this->t('The username @name has not been activated or is blocked.', ['@name' => $name]), 'User cannot log in yet.'); // Activate the new account. $accounts = $this->container->get('entity_type.manager')->getStorage('user') @@ -132,17 +141,21 @@ public function testRegistrationWithoutEmailVerification() { $edit = [ 'status' => 1, ]; - $this->drupalPostForm('user/' . $new_user->id() . '/edit', $edit, t('Save')); + $this->drupalPostForm('user/' . $new_user->id() . '/edit', $edit, $this->t('Save')); $this->drupalLogout(); // Log in after administrator approval. - $this->drupalPostForm('user/login', $auth, t('Log in')); - $this->assertText(t('Member for'), 'User can log in after administrator approval.'); + $this->drupalPostForm('user/login', $auth, $this->t('Log in')); + $this->assertText($this->t('Member for'), 'User can log in after administrator approval.'); } + /** + * Tests registration form with password set. + */ public function testRegistrationWithPasswordSet() { - // Require e-mail verification, but let's users choose a password during registration - // and allow registration by site visitors without administrator approval. + // Require e-mail verification, but let's users choose a password during + // registration and allow registration by site visitors without + // administrator approval. $this->config('user.settings') ->set('verify_mail', TRUE) ->set('register', UserInterface::REGISTER_VISITORS) @@ -156,12 +169,15 @@ public function testRegistrationWithPasswordSet() { $edit['pass[pass2]'] = $new_pass; // Create a new user. - $this->drupalPostForm('user/register', $edit, t('Create new account')); - $this->assertText(t('A welcome message with further instructions has been sent to your email address.'), 'Send e-mail to user after registering.'); + $this->drupalPostForm('user/register', $edit, $this->t('Create new account')); + $this->assertText($this->t('A welcome message with further instructions has been sent to your email address.'), 'Send e-mail to user after registering.'); // Make sure the user is still blocked. $this->container->get('entity_type.manager')->getStorage('user')->resetCache(); - $accounts = $this->container->get('entity_type.manager')->getStorage('user')->loadByProperties(['name' => $name, 'mail' => $mail]); + $accounts = $this->container->get('entity_type.manager')->getStorage('user')->loadByProperties([ + 'name' => $name, + 'mail' => $mail, + ]); $new_user = reset($accounts); $this->assertEmpty($new_user->status->value, 'New account is blocked until approved via e-mail confirmation.'); @@ -169,8 +185,8 @@ public function testRegistrationWithPasswordSet() { $edit2 = []; $edit2['name'] = $name; $edit2['pass'] = $new_pass; - $this->drupalPostForm('user/login', $edit2, t('Log in')); - $this->assertRaw(t('The username %name has not been activated or is blocked.', ['%name' => $name]), t('User cannot login yet.')); + $this->drupalPostForm('user/login', $edit2, $this->t('Log in')); + $this->assertRaw($this->t('The username %name has not been activated or is blocked.', ['%name' => $name]), $this->t('User cannot login yet.')); // Try to activate the user. $_emails = $this->drupalGetMails(); @@ -180,9 +196,12 @@ public function testRegistrationWithPasswordSet() { $_uid = $new_user->id(); $this->drupalGet("user/reset/$_uid/$one_time_link[1]/$one_time_link[2]"); - $this->assertText(t('You have just used your one-time login link. Your account is now active.'), t('User account activated.')); + $this->assertText($this->t('You have just used your one-time login link. Your account is now active.'), $this->t('User account activated.')); } + /** + * Tests default registration form for email duplicates. + */ public function testRegistrationEmailDuplicates() { // Don't require email verification and allow registration by site visitors // without administrator approval. @@ -199,14 +218,14 @@ public function testRegistrationEmailDuplicates() { $edit['mail'] = $duplicate_user->getEmail(); // Attempt to create a new account using an existing email address. - $this->drupalPostForm('user/register', $edit, t('Create new account')); - $this->assertText(t('The email address @email is already taken.', ['@email' => $duplicate_user->getEmail()]), 'Supplying an exact duplicate email address displays an error message'); + $this->drupalPostForm('user/register', $edit, $this->t('Create new account')); + $this->assertText($this->t('The email address @email is already taken.', ['@email' => $duplicate_user->getEmail()]), 'Supplying an exact duplicate email address displays an error message'); - // Attempt to bypass duplicate email registration validation by adding spaces. + // Attempt to bypass duplicate email validation by adding spaces. $edit['mail'] = ' ' . $duplicate_user->getEmail() . ' '; - $this->drupalPostForm('user/register', $edit, t('Create new account')); - $this->assertText(t('The email address @email is already taken.', ['@email' => $duplicate_user->getEmail()]), 'Supplying a duplicate email address with added whitespace displays an error message'); + $this->drupalPostForm('user/register', $edit, $this->t('Create new account')); + $this->assertText($this->t('The email address @email is already taken.', ['@email' => $duplicate_user->getEmail()]), 'Supplying a duplicate email address with added whitespace displays an error message'); } /** @@ -258,7 +277,7 @@ public function testUuidFormState() { $edit['pass[pass2]'] = $edit['pass[pass1]'] = $this->randomMachineName(); // Create one account. - $this->drupalPostForm('user/register', $edit, t('Create new account')); + $this->drupalPostForm('user/register', $edit, $this->t('Create new account')); $this->assertSession()->statusCodeEquals(200); $user_storage = \Drupal::entityTypeManager()->getStorage('user'); @@ -271,12 +290,15 @@ public function testUuidFormState() { $edit['mail'] = $edit['name'] . '@example.com'; $edit['pass[pass2]'] = $edit['pass[pass1]'] = $this->randomMachineName(); - $this->drupalPostForm('user/register', $edit, t('Create new account')); + $this->drupalPostForm('user/register', $edit, $this->t('Create new account')); $this->assertSession()->statusCodeEquals(200); $this->assertNotEmpty($user_storage->loadByProperties(['name' => $edit['name']])); } + /** + * Tests default registration form values. + */ public function testRegistrationDefaultValues() { // Don't require email verification and allow registration by site visitors // without administrator approval. @@ -300,7 +322,7 @@ public function testRegistrationDefaultValues() { $edit['mail'] = $mail = $edit['name'] . '@example.com'; $edit['pass[pass1]'] = $new_pass = $this->randomMachineName(); $edit['pass[pass2]'] = $new_pass; - $this->drupalPostForm(NULL, $edit, t('Create new account')); + $this->drupalPostForm(NULL, $edit, $this->t('Create new account')); // Check user fields. $accounts = $this->container->get('entity_type.manager')->getStorage('user') @@ -325,12 +347,15 @@ public function testRegistrationDefaultValues() { public function testUniqueFields() { $account = $this->drupalCreateUser(); - $edit = ['mail' => 'test@example.com', 'name' => $account->getAccountName()]; - $this->drupalPostForm('user/register', $edit, t('Create new account')); + $edit = [ + 'mail' => 'test@example.com', + 'name' => $account->getAccountName(), + ]; + $this->drupalPostForm('user/register', $edit, $this->t('Create new account')); $this->assertRaw(new FormattableMarkup('The username %value is already taken.', ['%value' => $account->getAccountName()])); $edit = ['mail' => $account->getEmail(), 'name' => $this->randomString()]; - $this->drupalPostForm('user/register', $edit, t('Create new account')); + $this->drupalPostForm('user/register', $edit, $this->t('Create new account')); $this->assertRaw(new FormattableMarkup('The email address %value is already taken.', ['%value' => $account->getEmail()])); } @@ -384,19 +409,19 @@ public function testRegistrationWithUserFields() { $edit['mail'] = $mail = $edit['name'] . '@example.com'; // Missing input in required field. $edit['test_user_field[0][value]'] = ''; - $this->drupalPostForm(NULL, $edit, t('Create new account')); + $this->drupalPostForm(NULL, $edit, $this->t('Create new account')); $this->assertRegistrationFormCacheTagsWithUserFields(); - $this->assertRaw(t('@name field is required.', ['@name' => $field->label()])); + $this->assertRaw($this->t('@name field is required.', ['@name' => $field->label()])); // Invalid input. $edit['test_user_field[0][value]'] = '-1'; - $this->drupalPostForm(NULL, $edit, t('Create new account')); + $this->drupalPostForm(NULL, $edit, $this->t('Create new account')); $this->assertRegistrationFormCacheTagsWithUserFields(); - $this->assertRaw(t('%name does not accept the value -1.', ['%name' => $field->label()])); + $this->assertRaw($this->t('%name does not accept the value -1.', ['%name' => $field->label()])); // Submit with valid data. $value = rand(1, 255); $edit['test_user_field[0][value]'] = $value; - $this->drupalPostForm(NULL, $edit, t('Create new account')); + $this->drupalPostForm(NULL, $edit, $this->t('Create new account')); // Check user fields. $accounts = $this->container->get('entity_type.manager')->getStorage('user') ->loadByProperties(['name' => $name, 'mail' => $mail]); @@ -412,14 +437,14 @@ public function testRegistrationWithUserFields() { $value = rand(1, 255); $edit = []; $edit['test_user_field[0][value]'] = $value; - $this->drupalPostForm(NULL, $edit, t('Add another item')); - $this->drupalPostForm(NULL, $edit, t('Add another item')); + $this->drupalPostForm(NULL, $edit, $this->t('Add another item')); + $this->drupalPostForm(NULL, $edit, $this->t('Add another item')); // Submit with three values. $edit['test_user_field[1][value]'] = $value + 1; $edit['test_user_field[2][value]'] = $value + 2; $edit['name'] = $name = $this->randomMachineName(); $edit['mail'] = $mail = $edit['name'] . '@example.com'; - $this->drupalPostForm(NULL, $edit, t('Create new account')); + $this->drupalPostForm(NULL, $edit, $this->t('Create new account')); // Check user fields. $accounts = $this->container->get('entity_type.manager')->getStorage('user') ->loadByProperties(['name' => $name, 'mail' => $mail]);