Skip to content

Commit

Permalink
Login and Registration: Improve HTML for errors and notices.
Browse files Browse the repository at this point in the history
Improve markup on Login and Registration errors. Use list markup for multiple issues, paragraph when only one to reduce semantic burden in the most common case. Normalize classes and markup for wrapper using `wp_admin_notice()` and `wp_get_admin_notice()` functions. Move definition of those functions from `wp-admin\includes\misc.php` to `wp-includes\functions.php`. Move tests to functions group. 

Props extendwings, sabernhardt, afercia, lukecavanagh, rianrietveld, oglekler, sergeybiryukov, costdev, joedolson.
Fixes #30685.

git-svn-id: https://develop.svn.wordpress.org/trunk@56654 602fd350-edb4-49c9-b593-d223f7449a82
  • Loading branch information
joedolson committed Sep 21, 2023
1 parent fa0969d commit b9adbb3
Show file tree
Hide file tree
Showing 6 changed files with 249 additions and 168 deletions.
26 changes: 20 additions & 6 deletions src/wp-admin/css/login.css
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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;
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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;
}

Expand All @@ -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;
Expand Down
144 changes: 0 additions & 144 deletions src/wp-admin/includes/misc.php
Original file line number Diff line number Diff line change
Expand Up @@ -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.' ),
'<code>type</code>'
),
'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 = "<p>$message</p>";
}

$markup = sprintf( '<div %1$sclass="%2$s"%3$s>%4$s</div>', $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 ) );
}
144 changes: 144 additions & 0 deletions src/wp-includes/functions.php
Original file line number Diff line number Diff line change
Expand Up @@ -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.' ),
'<code>type</code>'
),
'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 = "<p>$message</p>";
}

$markup = sprintf( '<div %1$sclass="%2$s"%3$s>%4$s</div>', $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 ) );
}
Loading

0 comments on commit b9adbb3

Please sign in to comment.