diff --git a/src/wp-admin/includes/template.php b/src/wp-admin/includes/template.php index b535b3acbfc66..93428dcc4ae6d 100644 --- a/src/wp-admin/includes/template.php +++ b/src/wp-admin/includes/template.php @@ -1974,6 +1974,8 @@ function get_settings_errors( $setting = '', $sanitize = false ) { * @since 3.0.0 * @since 5.3.0 Legacy `error` and `updated` CSS classes are mapped to * `notice-error` and `notice-success`. + * @since 7.2.0 Uses `wp_admin_notice()` to echo the notices so that the CSS + * classes, filters, and hooks are handled consistently. * * @param string $setting Optional slug title of a specific setting whose errors you want. * @param bool $sanitize Whether to re-sanitize the setting value before returning errors. @@ -1992,32 +1994,49 @@ function settings_errors( $setting = '', $sanitize = false, $hide_on_update = fa return; } - $output = ''; - foreach ( $settings_errors as $key => $details ) { - if ( 'updated' === $details['type'] ) { - $details['type'] = 'success'; + $type = trim( $details['type'] ); + + if ( 'updated' === $type ) { + $type = 'success'; } - if ( in_array( $details['type'], array( 'error', 'success', 'warning', 'info' ), true ) ) { - $details['type'] = 'notice-' . $details['type']; + $additional_classes = array( 'settings-error' ); + + /* + * Backward compatibility: `wp_admin_notice()` generates the admin notice + * CSS classes based on the passed message type. For example, 'error', + * 'success', 'warning', 'info'. Custom types will be treated as + * additional classes and appended to the end of the CSS classes. + */ + if ( ! in_array( $type, array( 'error', 'success', 'warning', 'info' ), true ) ) { + $additional_classes = array_merge( $additional_classes, explode( ' ', $type ) ); + $type = ''; } - $css_id = sprintf( + /* + * Note that the setting error code contains underscores, for example: + * `settings_updated`. This will build a CSS ID selector that contains + * underscores, which are currently not allowed by the WordPress CSS + * Coding Standards. Kept for backwards compatibility. + */ + $css_id = sprintf( 'setting-error-%s', - esc_attr( $details['code'] ) - ); - $css_class = sprintf( - 'notice %s settings-error is-dismissible', - esc_attr( $details['type'] ) + $details['code'], ); - $output .= "
\n"; - $output .= "

{$details['message']}

"; - $output .= "
\n"; + wp_admin_notice( + "{$details['message']}", + array( + 'type' => $type, + 'code' => $details['code'], + 'id' => $css_id, + 'paragraph_wrap' => true, + 'dismissible' => true, + 'additional_classes' => $additional_classes, + ) + ); } - - echo $output; } /** diff --git a/tests/phpunit/tests/admin/includesTemplate.php b/tests/phpunit/tests/admin/includesTemplate.php index 4b9b8bc68034e..5e50cf8180e98 100644 --- a/tests/phpunit/tests/admin/includesTemplate.php +++ b/tests/phpunit/tests/admin/includesTemplate.php @@ -442,21 +442,28 @@ public function test_settings_errors_css_classes( $type, $expected ) { $wp_settings_errors = null; - $expected = sprintf( 'notice %s settings-error is-dismissible', $expected ); - $this->assertStringContainsString( $expected, $output ); $this->assertStringNotContainsString( 'notice-notice-', $output ); } public function data_settings_errors_css_classes() { return array( - array( 'error', 'notice-error' ), - array( 'success', 'notice-success' ), - array( 'warning', 'notice-warning' ), - array( 'info', 'notice-info' ), - array( 'updated', 'notice-success' ), - array( 'notice-error', 'notice-error' ), - array( 'error my-own-css-class hello world', 'error my-own-css-class hello world' ), + // The admin notices default types will generate CSS classes in this order. + array( 'error', 'notice notice-error is-dismissible settings-error' ), + array( 'success', 'notice notice-success is-dismissible settings-error' ), + array( 'warning', 'notice notice-warning is-dismissible settings-error' ), + array( 'info', 'notice notice-info is-dismissible settings-error' ), + array( 'updated', 'notice notice-success is-dismissible settings-error' ), + /* + * Backward compatibility: custom types and anything else (e.g. + * strings with spaces) are now passed as additional_classes. As + * such, the classes will be appended to the end of the generated + * class attribute. + */ + array( 'notice-error', 'notice is-dismissible settings-error notice-error' ), + array( 'custom', 'notice is-dismissible settings-error custom' ), + array( 'error my-own-css-class hello world', 'notice is-dismissible settings-error error my-own-css-class hello world' ), + array( 'error my-notice-is-awesome hello world', 'notice is-dismissible settings-error error my-notice-is-awesome hello world' ), ); }