diff --git a/src/wp-admin/css/login.css b/src/wp-admin/css/login.css index 8f43504c1c..fe790f0b42 100644 --- a/src/wp-admin/css/login.css +++ b/src/wp-admin/css/login.css @@ -42,8 +42,8 @@ p { } .login .message, -.login .success, -.login #login_error { +.login .notice, +.login .success { border-left: 4px solid #72aee6; padding: 12px; margin-left: 0; @@ -57,10 +57,19 @@ p { border-left-color: #00a32a; } -.login #login_error { +/* Match border color from common.css */ +.login .notice-error { border-left-color: #d63638; } +.login .login-error-list { + list-style: none; +} + +.login .login-error-list li + li { + margin-top: 4px; +} + #loginform p.submit, .login-action-lostpassword p.submit { border: none; @@ -237,6 +246,11 @@ p { margin-bottom: 0; } +#login form .indicator-hint, +#login #reg_passmail { + margin-bottom: 16px; +} + #login form p.submit { margin: 0; padding: 0; @@ -342,9 +356,7 @@ p { font-family: Consolas, Monaco, monospace; } -.js.login input.password-input, -.js.login-action-rp form .input, -.js.login-action-rp input[type="text"] { +.js.login input.password-input { padding-right: 2.5rem; } @@ -354,6 +366,8 @@ p { background: #fff; } +.js.login-action-resetpass input[type="text"], +.js.login-action-resetpass input[type="password"], .js.login-action-rp input[type="text"], .js.login-action-rp input[type="password"] { margin-bottom: 0; diff --git a/src/wp-admin/includes/misc.php b/src/wp-admin/includes/misc.php index 8c4caa468d..090282062f 100644 --- a/src/wp-admin/includes/misc.php +++ b/src/wp-admin/includes/misc.php @@ -1642,147 +1642,3 @@ function wp_check_php_version() { return $response; } - -/** - * Creates and returns the markup for an admin notice. - * - * @since 6.4.0 - * - * @param string $message The message. - * @param array $args { - * Optional. An array of arguments for the admin notice. Default empty array. - * - * @type string $type Optional. The type of admin notice. - * For example, 'error', 'success', 'warning', 'info'. - * Default empty string. - * @type bool $dismissible Optional. Whether the admin notice is dismissible. Default false. - * @type string $id Optional. The value of the admin notice's ID attribute. Default empty string. - * @type string[] $additional_classes Optional. A string array of class names. Default empty array. - * @type string[] $attributes Optional. Additional attributes for the notice div. Default empty array. - * @type bool $paragraph_wrap Optional. Whether to wrap the message in paragraph tags. Default true. - * } - * @return string The markup for an admin notice. - */ -function wp_get_admin_notice( $message, $args = array() ) { - $defaults = array( - 'type' => '', - 'dismissible' => false, - 'id' => '', - 'additional_classes' => array(), - 'attributes' => array(), - 'paragraph_wrap' => true, - ); - - $args = wp_parse_args( $args, $defaults ); - - /** - * Filters the arguments for an admin notice. - * - * @since 6.4.0 - * - * @param array $args The arguments for the admin notice. - * @param string $message The message for the admin notice. - */ - $args = apply_filters( 'wp_admin_notice_args', $args, $message ); - $id = ''; - $classes = 'notice'; - $attributes = ''; - - if ( is_string( $args['id'] ) ) { - $trimmed_id = trim( $args['id'] ); - - if ( '' !== $trimmed_id ) { - $id = 'id="' . $trimmed_id . '" '; - } - } - - if ( is_string( $args['type'] ) ) { - $type = trim( $args['type'] ); - - if ( str_contains( $type, ' ' ) ) { - _doing_it_wrong( - __FUNCTION__, - sprintf( - /* translators: %s: The "type" key. */ - __( 'The %s key must be a string without spaces.' ), - 'type' - ), - '6.4.0' - ); - } - - if ( '' !== $type ) { - $classes .= ' notice-' . $type; - } - } - - if ( true === $args['dismissible'] ) { - $classes .= ' is-dismissible'; - } - - if ( is_array( $args['additional_classes'] ) && ! empty( $args['additional_classes'] ) ) { - $classes .= ' ' . implode( ' ', $args['additional_classes'] ); - } - - if ( is_array( $args['attributes'] ) && ! empty( $args['attributes'] ) ) { - $attributes = ''; - foreach ( $args['attributes'] as $attr => $val ) { - if ( is_bool( $val ) ) { - $attributes .= $val ? ' ' . $attr : ''; - } elseif ( is_int( $attr ) ) { - $attributes .= ' ' . esc_attr( trim( $val ) ); - } elseif ( $val ) { - $attributes .= ' ' . $attr . '="' . esc_attr( trim( $val ) ) . '"'; - } - } - } - - if ( false !== $args['paragraph_wrap'] ) { - $message = "

$message

"; - } - - $markup = sprintf( '
%4$s
', $id, $classes, $attributes, $message ); - - /** - * Filters the markup for an admin notice. - * - * @since 6.4.0 - * - * @param string $markup The HTML markup for the admin notice. - * @param string $message The message for the admin notice. - * @param array $args The arguments for the admin notice. - */ - return apply_filters( 'wp_admin_notice_markup', $markup, $message, $args ); -} - -/** - * Outputs an admin notice. - * - * @since 6.4.0 - * - * @param string $message The message to output. - * @param array $args { - * Optional. An array of arguments for the admin notice. Default empty array. - * - * @type string $type Optional. The type of admin notice. - * For example, 'error', 'success', 'warning', 'info'. - * Default empty string. - * @type bool $dismissible Optional. Whether the admin notice is dismissible. Default false. - * @type string $id Optional. The value of the admin notice's ID attribute. Default empty string. - * @type string[] $additional_classes Optional. A string array of class names. Default empty array. - * @type bool $paragraph_wrap Optional. Whether to wrap the message in paragraph tags. Default true. - * } - */ -function wp_admin_notice( $message, $args = array() ) { - /** - * Fires before an admin notice is output. - * - * @since 6.4.0 - * - * @param string $message The message for the admin notice. - * @param array $args The arguments for the admin notice. - */ - do_action( 'wp_admin_notice', $message, $args ); - - echo wp_kses_post( wp_get_admin_notice( $message, $args ) ); -} diff --git a/src/wp-includes/functions.php b/src/wp-includes/functions.php index f3c4af1405..d2c02abedd 100644 --- a/src/wp-includes/functions.php +++ b/src/wp-includes/functions.php @@ -8762,3 +8762,147 @@ function is_php_version_compatible( $required ) { function wp_fuzzy_number_match( $expected, $actual, $precision = 1 ) { return abs( (float) $expected - (float) $actual ) <= $precision; } + +/** + * Creates and returns the markup for an admin notice. + * + * @since 6.4.0 + * + * @param string $message The message. + * @param array $args { + * Optional. An array of arguments for the admin notice. Default empty array. + * + * @type string $type Optional. The type of admin notice. + * For example, 'error', 'success', 'warning', 'info'. + * Default empty string. + * @type bool $dismissible Optional. Whether the admin notice is dismissible. Default false. + * @type string $id Optional. The value of the admin notice's ID attribute. Default empty string. + * @type string[] $additional_classes Optional. A string array of class names. Default empty array. + * @type string[] $attributes Optional. Additional attributes for the notice div. Default empty array. + * @type bool $paragraph_wrap Optional. Whether to wrap the message in paragraph tags. Default true. + * } + * @return string The markup for an admin notice. + */ +function wp_get_admin_notice( $message, $args = array() ) { + $defaults = array( + 'type' => '', + 'dismissible' => false, + 'id' => '', + 'additional_classes' => array(), + 'attributes' => array(), + 'paragraph_wrap' => true, + ); + + $args = wp_parse_args( $args, $defaults ); + + /** + * Filters the arguments for an admin notice. + * + * @since 6.4.0 + * + * @param array $args The arguments for the admin notice. + * @param string $message The message for the admin notice. + */ + $args = apply_filters( 'wp_admin_notice_args', $args, $message ); + $id = ''; + $classes = 'notice'; + $attributes = ''; + + if ( is_string( $args['id'] ) ) { + $trimmed_id = trim( $args['id'] ); + + if ( '' !== $trimmed_id ) { + $id = 'id="' . $trimmed_id . '" '; + } + } + + if ( is_string( $args['type'] ) ) { + $type = trim( $args['type'] ); + + if ( str_contains( $type, ' ' ) ) { + _doing_it_wrong( + __FUNCTION__, + sprintf( + /* translators: %s: The "type" key. */ + __( 'The %s key must be a string without spaces.' ), + 'type' + ), + '6.4.0' + ); + } + + if ( '' !== $type ) { + $classes .= ' notice-' . $type; + } + } + + if ( true === $args['dismissible'] ) { + $classes .= ' is-dismissible'; + } + + if ( is_array( $args['additional_classes'] ) && ! empty( $args['additional_classes'] ) ) { + $classes .= ' ' . implode( ' ', $args['additional_classes'] ); + } + + if ( is_array( $args['attributes'] ) && ! empty( $args['attributes'] ) ) { + $attributes = ''; + foreach ( $args['attributes'] as $attr => $val ) { + if ( is_bool( $val ) ) { + $attributes .= $val ? ' ' . $attr : ''; + } elseif ( is_int( $attr ) ) { + $attributes .= ' ' . esc_attr( trim( $val ) ); + } elseif ( $val ) { + $attributes .= ' ' . $attr . '="' . esc_attr( trim( $val ) ) . '"'; + } + } + } + + if ( false !== $args['paragraph_wrap'] ) { + $message = "

$message

"; + } + + $markup = sprintf( '
%4$s
', $id, $classes, $attributes, $message ); + + /** + * Filters the markup for an admin notice. + * + * @since 6.4.0 + * + * @param string $markup The HTML markup for the admin notice. + * @param string $message The message for the admin notice. + * @param array $args The arguments for the admin notice. + */ + return apply_filters( 'wp_admin_notice_markup', $markup, $message, $args ); +} + +/** + * Outputs an admin notice. + * + * @since 6.4.0 + * + * @param string $message The message to output. + * @param array $args { + * Optional. An array of arguments for the admin notice. Default empty array. + * + * @type string $type Optional. The type of admin notice. + * For example, 'error', 'success', 'warning', 'info'. + * Default empty string. + * @type bool $dismissible Optional. Whether the admin notice is dismissible. Default false. + * @type string $id Optional. The value of the admin notice's ID attribute. Default empty string. + * @type string[] $additional_classes Optional. A string array of class names. Default empty array. + * @type bool $paragraph_wrap Optional. Whether to wrap the message in paragraph tags. Default true. + * } + */ +function wp_admin_notice( $message, $args = array() ) { + /** + * Fires before an admin notice is output. + * + * @since 6.4.0 + * + * @param string $message The message for the admin notice. + * @param array $args The arguments for the admin notice. + */ + do_action( 'wp_admin_notice', $message, $args ); + + echo wp_kses_post( wp_get_admin_notice( $message, $args ) ); +} diff --git a/src/wp-login.php b/src/wp-login.php index de2ee486c7..60877bdb70 100644 --- a/src/wp-login.php +++ b/src/wp-login.php @@ -228,21 +228,35 @@ function login_header( $title = 'Log In', $message = '', $wp_error = null ) { } if ( $wp_error->has_errors() ) { - $errors = ''; - $messages = ''; + $error_list = array(); + $messages = ''; foreach ( $wp_error->get_error_codes() as $code ) { $severity = $wp_error->get_error_data( $code ); foreach ( $wp_error->get_error_messages( $code ) as $error_message ) { if ( 'message' === $severity ) { - $messages .= ' ' . $error_message . "
\n"; + $messages .= '

' . $error_message . '

'; } else { - $errors .= ' ' . $error_message . "
\n"; + $error_list[] = $error_message; } } } - if ( ! empty( $errors ) ) { + if ( ! empty( $error_list ) ) { + $errors = ''; + + if ( count( $error_list ) > 1 ) { + $errors .= ''; + } else { + $errors .= '

' . $error_message . '

'; + } + /** * Filters the error messages displayed above the login form. * @@ -250,7 +264,15 @@ function login_header( $title = 'Log In', $message = '', $wp_error = null ) { * * @param string $errors Login error message. */ - echo '
' . apply_filters( 'login_errors', $errors ) . "
\n"; + $errors = apply_filters( 'login_errors', $errors ); + wp_admin_notice( + $errors, + array( + 'type' => 'error', + 'id' => 'login_error', + 'paragraph_wrap' => false, + ) + ); } if ( ! empty( $messages ) ) { @@ -261,7 +283,16 @@ function login_header( $title = 'Log In', $message = '', $wp_error = null ) { * * @param string $messages Login messages. */ - echo '

' . apply_filters( 'login_messages', $messages ) . "

\n"; + $messages = apply_filters( 'login_messages', $messages ); + wp_admin_notice( + $messages, + array( + 'type' => 'info', + 'id' => 'login-message', + 'additional_classes' => array( 'message' ), + 'paragraph_wrap' => false, + ) + ); } } } // End of login_header(). @@ -399,7 +430,6 @@ function login_footer( $input_id = '' ) { do_action( 'login_footer' ); ?> -
' . __( 'Please enter your username or email address. You will receive an email message with instructions on how to reset your password.' ) . '

', $errors ); + login_header( + __( 'Lost Password' ), + wp_get_admin_notice( + __( 'Please enter your username or email address. You will receive an email message with instructions on how to reset your password.' ), + array( + 'type' => 'info', + 'additional_classes' => array( 'message' ), + ) + ), + $errors + ); $user_login = ''; @@ -946,7 +986,16 @@ switch ( $action ) { if ( ( ! $errors->has_errors() ) && isset( $_POST['pass1'] ) && ! empty( $_POST['pass1'] ) ) { reset_password( $user, $_POST['pass1'] ); setcookie( $rp_cookie, ' ', time() - YEAR_IN_SECONDS, $rp_path, COOKIE_DOMAIN, is_ssl(), true ); - login_header( __( 'Password Reset' ), '

' . __( 'Your password has been reset.' ) . ' ' . __( 'Log in' ) . '

' ); + login_header( + __( 'Password Reset' ), + wp_get_admin_notice( + __( 'Your password has been reset.' ) . ' ' . __( 'Log in' ) . '', + array( + 'type' => 'info', + 'additional_classes' => array( 'message', 'reset-pass' ), + ) + ) + ); login_footer(); exit; } @@ -954,7 +1003,17 @@ switch ( $action ) { wp_enqueue_script( 'utils' ); wp_enqueue_script( 'user-profile' ); - login_header( __( 'Reset Password' ), '

' . __( 'Enter your new password below or generate one.' ) . '

', $errors ); + login_header( + __( 'Reset Password' ), + wp_get_admin_notice( + __( 'Enter your new password below or generate one.' ), + array( + 'type' => 'info', + 'additional_classes' => array( 'message', 'reset-pass' ), + ) + ), + $errors + ); ?>
@@ -985,7 +1044,6 @@ switch ( $action ) {

-
' . __( 'Register For This Site' ) . '

', $errors ); + login_header( + __( 'Registration Form' ), + wp_get_admin_notice( + __( 'Register For This Site' ), + array( + 'type' => 'info', + 'additional_classes' => array( 'message', 'register' ), + ) + ), + $errors + ); ?> @@ -1104,7 +1172,6 @@ switch ( $action ) {

-

diff --git a/tests/phpunit/tests/admin/wpAdminNotice.php b/tests/phpunit/tests/functions/wpAdminNotice.php similarity index 96% rename from tests/phpunit/tests/admin/wpAdminNotice.php rename to tests/phpunit/tests/functions/wpAdminNotice.php index d882c93457..2756ab1de9 100644 --- a/tests/phpunit/tests/admin/wpAdminNotice.php +++ b/tests/phpunit/tests/functions/wpAdminNotice.php @@ -3,11 +3,11 @@ /** * Tests for `wp_admin_notice()`. * - * @group admin + * @group functions.php * * @covers ::wp_admin_notice */ -class Tests_Admin_WpAdminNotice extends WP_UnitTestCase { +class Tests_Functions_WpAdminNotice extends WP_UnitTestCase { /** * Tests that `wp_admin_notice()` outputs the expected admin notice markup. diff --git a/tests/phpunit/tests/admin/wpGetAdminNotice.php b/tests/phpunit/tests/functions/wpGetAdminNotice.php similarity index 96% rename from tests/phpunit/tests/admin/wpGetAdminNotice.php rename to tests/phpunit/tests/functions/wpGetAdminNotice.php index 718fdf3d94..aeeadff96d 100644 --- a/tests/phpunit/tests/admin/wpGetAdminNotice.php +++ b/tests/phpunit/tests/functions/wpGetAdminNotice.php @@ -3,11 +3,11 @@ /** * Tests for `wp_get_admin_notice()`. * - * @group admin + * @group functions.php * * @covers ::wp_get_admin_notice */ -class Tests_Admin_WpGetAdminNotice extends WP_UnitTestCase { +class Tests_Functions_WpGetAdminNotice extends WP_UnitTestCase { /** * Tests that `wp_get_admin_notice()` returns the expected admin notice markup.