-
Notifications
You must be signed in to change notification settings - Fork 3.6k
HTML API: Refactor wp_get_admin_notice()
#13273
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
d15c355
7c17d6e
2a58ee4
77b40f2
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -9233,23 +9233,26 @@ function wp_get_admin_notice( $message, $args = array() ) { | |
| * @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 = ''; | ||
| $args = apply_filters( 'wp_admin_notice_args', $args, $message ); | ||
|
|
||
| $wrap_with_p = false !== $args['paragraph_wrap']; | ||
| $wrap_opener = $wrap_with_p ? '<p>' : ''; | ||
| $wrap_closer = $wrap_with_p ? '</p>' : ''; | ||
| $html_builder = new WP_HTML_Tag_Processor( "<div class=\"notice\">{$wrap_opener}" ); | ||
| $html_builder->next_token(); | ||
|
|
||
| if ( is_string( $args['id'] ) ) { | ||
| $trimmed_id = trim( $args['id'] ); | ||
|
|
||
| if ( '' !== $trimmed_id ) { | ||
| $id = 'id="' . $trimmed_id . '" '; | ||
| $html_builder->set_attribute( 'id', $trimmed_id ); | ||
| } | ||
| } | ||
|
|
||
| if ( is_string( $args['type'] ) ) { | ||
| $type = trim( $args['type'] ); | ||
|
|
||
| if ( str_contains( $type, ' ' ) ) { | ||
| if ( strlen( $type ) !== strcspn( $type, " \f\t\r\n" ) ) { | ||
| _doing_it_wrong( | ||
| __FUNCTION__, | ||
| sprintf( | ||
|
|
@@ -9262,36 +9265,40 @@ function wp_get_admin_notice( $message, $args = array() ) { | |
| } | ||
|
|
||
| if ( '' !== $type ) { | ||
| $classes .= ' notice-' . $type; | ||
| $html_builder->add_class( "notice-{$type}" ); | ||
| } | ||
| } | ||
|
|
||
| if ( true === $args['dismissible'] ) { | ||
| $classes .= ' is-dismissible'; | ||
| $html_builder->add_class( 'is-dismissible' ); | ||
| } | ||
|
|
||
| if ( is_array( $args['additional_classes'] ) && ! empty( $args['additional_classes'] ) ) { | ||
| $classes .= ' ' . implode( ' ', $args['additional_classes'] ); | ||
| foreach ( $args['additional_classes'] as $class_name ) { | ||
| $html_builder->add_class( $class_name ); | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I assume that
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. yeah that’s a good point to consider inside the HTML API. we could call in fact, if no existing classes are on the item, it won’t even add the class attribute when an empty class name is passed. php > require __DIR__ . '/src/wp-load.php';
php > $p = new WP_HTML_Tag_Processor( '<div>' );
php > $p->next_token();
php > var_dump( $p->add_class( '' ) );
bool(true)
php > var_dump( $p->get_updated_html() );
string(5) "<div>"
php > var_dump( $p->add_class( 'bar' ) );
bool(true)
php > var_dump( $p->get_updated_html() );
string(17) "<div class="bar">"
php > var_dump( $p->add_class( null ) );
bool(true)
php > var_dump( $p->get_updated_html() );
string(18) "<div class="bar ">"
php > var_dump( $p->add_class( [] ) );
PHP Warning: Uncaught TypeError: Cannot access offset of type array on array in /Users/dmsnell/code/WordPress-develop/src/wp-includes/html-api/class-wp-html-tag-processor.php:4824
Stack trace:
#0 php shell code(1): WP_HTML_Tag_Processor->add_class(Array)
#1 {main}
thrown in /Users/dmsnell/code/WordPress-develop/src/wp-includes/html-api/class-wp-html-tag-processor.php on line 4824
Warning: Uncaught TypeError: Cannot access offset of type array on array in /Users/dmsnell/code/WordPress-develop/src/wp-includes/html-api/class-wp-html-tag-processor.php:4824
Stack trace:
#0 php shell code(1): WP_HTML_Tag_Processor->add_class(Array)
#1 {main}
thrown in /Users/dmsnell/code/WordPress-develop/src/wp-includes/html-api/class-wp-html-tag-processor.php on line 4824some of these deep internals do pass non-strings at times when we expect them. we might add hardening, though I think that in this case we have a similar behavior as the legacy |
||
| } | ||
| } | ||
|
|
||
| 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 ) ) . '"'; | ||
| foreach ( $args['attributes'] as $name => $value ) { | ||
| if ( is_int( $name ) ) { | ||
| /* | ||
| * Boolean attributes may have been appended as numeric list items, | ||
| * for example, with `$args['attributes'][] = 'disabled'`. They should | ||
| * be recorded with the value serving as their name. | ||
| */ | ||
| $html_builder->set_attribute( $value, true ); | ||
| } elseif ( true === $value ) { | ||
| $html_builder->set_attribute( $name, true ); | ||
| } elseif ( false !== $value ) { | ||
| $html_builder->set_attribute( $name, trim( (string) $value ) ); | ||
| } | ||
| } | ||
| } | ||
|
|
||
| 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 ); | ||
| $markup = $html_builder->get_updated_html(); | ||
| $markup .= $message; | ||
| $markup .= "{$wrap_closer}</div>"; | ||
|
|
||
| /** | ||
| * Filters the markup for an admin notice. | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Aside: This feels like it could be a good helper function.
grep -rnE --include='*.php' "str_contains\(.*,[[:space:]]*' '[[:space:]]*\)" .found 5 additional places where we do str_contains on an empty string.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
it’s an abstraction that has been sitting in the wing, so to speak. one thing we discovered was that we have to be attentive to where we apply the
\fform feed character. in HTML-sourced strings it’s part of whitespace, but in CSS content it’s not.this means it’s different for class names going into HTML vs. class names going into a block attribute as JSON.
wp_contains_html_whitespace()andwp_contains_css_whitespace()could do it, but then we also havewp_contains_linear_whitespace()from RFC specs…and I just don’t know if the abstractions are actually worth it, which is why I haven’t pushed any.this is good thought; my comment here is mostly to share the context of what has kept it from being born yet.
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@aaronjorbin some context we have from the HTML API development, which I mostly maintain as practice these days, is that abstracting low-level text operations like this is a hefty operation which showed up surprisingly well in performance benchmarking for the HTML API. it’s not likely to be in the hot-path here, so the risk is lower, but there’s an outsized impact on abstracting these calls compared to languages whose compilers inline them, or languages with cheap function calls (PHP’s remain fairly expensive, for reasons I don’t understand)