diff -u b/core/modules/user/src/AccountForm.php b/core/modules/user/src/AccountForm.php --- b/core/modules/user/src/AccountForm.php +++ b/core/modules/user/src/AccountForm.php @@ -115,24 +115,6 @@ // 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', - '#prefix' => '

' . $this->t('Change password') . '

', - '#title1' => $this->t('New password'), - '#title2' => $this->t('Confirm new password'), - '#size' => 25, - '#description' => $this->t('To change the current user password, enter the new password here. To be allowed to do this you also need to confirm your current password.'), - '#weight' => -7, - ); - - // 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. - if (!$form_state->get('user_pass_reset') && ($token = $this->getRequest()->get('pass-reset-token'))) { - $session_key = 'pass_reset_' . $account->id(); - $user_pass_reset = isset($_SESSION[$session_key]) && Crypt::hashEquals($_SESSION[$session_key], $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()) { @@ -171,6 +153,25 @@ ]; } } + + $form['account']['pass'] = array( + '#type' => 'password_confirm', + '#prefix' => '

' . $this->t('Change password') . '

', + '#title1' => $this->t('New password'), + '#title2' => $this->t('Confirm new password'), + '#size' => 25, + '#description' => $this->t('To change the current user password, enter the new password here. To be allowed to do this you also need to confirm your current password.'), + '#weight' => -7, + ); + + // 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. + if (!$form_state->get('user_pass_reset') && ($token = $this->getRequest()->get('pass-reset-token'))) { + $session_key = 'pass_reset_' . $account->id(); + $user_pass_reset = isset($_SESSION[$session_key]) && Crypt::hashEquals($_SESSION[$session_key], $token); + $form_state->set('user_pass_reset', $user_pass_reset); + } } elseif (!$config->get('verify_mail') || $admin) { $form['account']['pass'] = array( only in patch2: unchanged: --- a/core/modules/user/tests/src/Kernel/UserAccountFormFieldsTest.php +++ b/core/modules/user/tests/src/Kernel/UserAccountFormFieldsTest.php @@ -33,7 +33,7 @@ function testInstallConfigureForm() { ->buildForm('Drupal\Core\Installer\Form\SiteConfigureForm', $form_state); // Verify name and pass field order. - $this->assertFieldOrder($form['admin_account']['account']); + $this->assertSiteConfigureFormFieldOrder($form['admin_account']['account']); // Verify that web browsers may autocomplete the email value and // autofill/prefill the name and pass values. @@ -56,8 +56,8 @@ function testUserRegistrationForm() { $form = $this->buildAccountForm('register'); - // Verify name and pass field order. - $this->assertFieldOrder($form['account']); + // Verify name, email and pass field order. + $this->assertAccountFieldOrder($form['account']); // Verify that web browsers may autocomplete the email value and // autofill/prefill the name and pass values. @@ -78,8 +78,8 @@ function testUserEditForm() { $form = $this->buildAccountForm('default'); - // Verify name and pass field order. - $this->assertFieldOrder($form['account']); + // Verify name, mail and pass field order. + $this->assertAccountFieldOrder($form['account']); // Verify that autocomplete is off on all account fields. foreach (array('mail', 'name', 'pass') as $key) { @@ -93,7 +93,7 @@ function testUserEditForm() { * @param array $elements * A form array section that contains the user account form elements. */ - protected function assertFieldOrder(array $elements) { + protected function assertSiteConfigureFormFieldOrder(array $elements) { $name_index = 0; $name_weight = 0; $pass_index = 0; @@ -112,11 +112,56 @@ protected function assertFieldOrder(array $elements) { } $index++; } - $this->assertEqual($name_index, $pass_index - 1, "'name' field ($name_index) appears before 'pass' field ($pass_index)."); + $this->assertEquals($name_index, $pass_index - 1, "'name' field ($name_index) appears before 'pass' field ($pass_index)."); $this->assertTrue($name_weight < $pass_weight, "'name' field weight ($name_weight) is smaller than 'pass' field weight ($pass_weight)."); } /** + * Asserts the correct order of name, mail and pass fields. + * + * @param array $elements + * A form array section that contains the user account form elements. + */ + protected function assertAccountFieldOrder(array $elements) { + $name_index = 0; + $name_weight = 0; + $mail_index = 0; + $mail_weight = 0; + $pass_index = 0; + $pass_weight = 0; + $index = 0; + + foreach ($elements as $key => $element) { + switch ($key) { + case 'name': + $name_index = $index; + $name_weight = $element['#weight']; + $this->assertTrue($element['#sorted'], "'name' field is #sorted."); + break; + + case 'mail': + $mail_index = $index; + $mail_weight = $element['#weight']; + $this->assertTrue($element['#sorted'], "'mail' field is #sorted."); + break; + + case 'pass': + $pass_index = $index; + $pass_weight = $element['#weight']; + $this->assertTrue($element['#sorted'], "'pass' field is #sorted."); + break; + } + $index++; + } + + $this->assertEquals($name_index, $mail_index - 1, "'name' field ($name_index) appears before 'mail' field ($mail_index)."); + $this->assertEquals($mail_index, $pass_index - 1, "'mail' field ($mail_index) appears before 'pass' field ($pass_index)."); + $this->assertTrue($name_weight < $mail_weight, "'name' field weight ($name_weight) is smaller than 'mail' field weight ($mail_weight)."); + $this->assertTrue($mail_weight < $pass_weight, "'mail' field weight ($mail_weight) is smaller than 'pass' field weight ($pass_weight)."); + } + + + /** * Builds the user account form for a given operation. * * @param string $operation