PasswordConfirm.php 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121
  1. <?php
  2. namespace Drupal\Core\Render\Element;
  3. use Drupal\Core\Form\FormStateInterface;
  4. /**
  5. * Provides a form element for double-input of passwords.
  6. *
  7. * Formats as a pair of password fields, which do not validate unless the two
  8. * entered passwords match.
  9. *
  10. * Properties:
  11. * - #size: The size of the input element in characters.
  12. *
  13. * Usage example:
  14. * @code
  15. * $form['pass'] = array(
  16. * '#type' => 'password_confirm',
  17. * '#title' => $this->t('Password'),
  18. * '#size' => 25,
  19. * );
  20. * @endcode
  21. *
  22. * @see \Drupal\Core\Render\Element\Password
  23. *
  24. * @FormElement("password_confirm")
  25. */
  26. class PasswordConfirm extends FormElement {
  27. /**
  28. * {@inheritdoc}
  29. */
  30. public function getInfo() {
  31. $class = get_class($this);
  32. return [
  33. '#input' => TRUE,
  34. '#markup' => '',
  35. '#process' => [
  36. [$class, 'processPasswordConfirm'],
  37. ],
  38. '#theme_wrappers' => ['form_element'],
  39. ];
  40. }
  41. /**
  42. * {@inheritdoc}
  43. */
  44. public static function valueCallback(&$element, $input, FormStateInterface $form_state) {
  45. if ($input === FALSE) {
  46. $element += ['#default_value' => []];
  47. return $element['#default_value'] + ['pass1' => '', 'pass2' => ''];
  48. }
  49. $value = ['pass1' => '', 'pass2' => ''];
  50. // Throw out all invalid array keys; we only allow pass1 and pass2.
  51. foreach ($value as $allowed_key => $default) {
  52. // These should be strings, but allow other scalars since they might be
  53. // valid input in programmatic form submissions. Any nested array values
  54. // are ignored.
  55. if (isset($input[$allowed_key]) && is_scalar($input[$allowed_key])) {
  56. $value[$allowed_key] = (string) $input[$allowed_key];
  57. }
  58. }
  59. return $value;
  60. }
  61. /**
  62. * Expand a password_confirm field into two text boxes.
  63. */
  64. public static function processPasswordConfirm(&$element, FormStateInterface $form_state, &$complete_form) {
  65. $element['pass1'] = [
  66. '#type' => 'password',
  67. '#title' => t('Password'),
  68. '#value' => empty($element['#value']) ? NULL : $element['#value']['pass1'],
  69. '#required' => $element['#required'],
  70. '#attributes' => ['class' => ['password-field', 'js-password-field']],
  71. '#error_no_message' => TRUE,
  72. ];
  73. $element['pass2'] = [
  74. '#type' => 'password',
  75. '#title' => t('Confirm password'),
  76. '#value' => empty($element['#value']) ? NULL : $element['#value']['pass2'],
  77. '#required' => $element['#required'],
  78. '#attributes' => ['class' => ['password-confirm', 'js-password-confirm']],
  79. '#error_no_message' => TRUE,
  80. ];
  81. $element['#element_validate'] = [[get_called_class(), 'validatePasswordConfirm']];
  82. $element['#tree'] = TRUE;
  83. if (isset($element['#size'])) {
  84. $element['pass1']['#size'] = $element['pass2']['#size'] = $element['#size'];
  85. }
  86. return $element;
  87. }
  88. /**
  89. * Validates a password_confirm element.
  90. */
  91. public static function validatePasswordConfirm(&$element, FormStateInterface $form_state, &$complete_form) {
  92. $pass1 = trim($element['pass1']['#value']);
  93. $pass2 = trim($element['pass2']['#value']);
  94. if (strlen($pass1) > 0 || strlen($pass2) > 0) {
  95. if (strcmp($pass1, $pass2)) {
  96. $form_state->setError($element, t('The specified passwords do not match.'));
  97. }
  98. }
  99. elseif ($element['#required'] && $form_state->getUserInput()) {
  100. $form_state->setError($element, t('Password field is required.'));
  101. }
  102. // Password field must be converted from a two-element array into a single
  103. // string regardless of validation results.
  104. $form_state->setValueForElement($element['pass1'], NULL);
  105. $form_state->setValueForElement($element['pass2'], NULL);
  106. $form_state->setValueForElement($element, $pass1);
  107. return $element;
  108. }
  109. }