diff --git a/src/wp-includes/default-filters.php b/src/wp-includes/default-filters.php index 5581828a10b61..c8b08cc62b957 100644 --- a/src/wp-includes/default-filters.php +++ b/src/wp-includes/default-filters.php @@ -702,6 +702,10 @@ add_action( 'load-post-new.php', 'wp_set_up_cross_origin_isolation' ); add_action( 'load-site-editor.php', 'wp_set_up_cross_origin_isolation' ); add_action( 'load-widgets.php', 'wp_set_up_cross_origin_isolation' ); + +// Move the admin notices below the heading tag via server-side processing. +add_action( 'admin_init', 'wp_move_notice_after_heading' ); + // Nav menu. add_filter( 'nav_menu_item_id', '_nav_menu_item_id_use_once', 10, 2 ); add_filter( 'nav_menu_css_class', 'wp_nav_menu_remove_menu_item_has_children_class', 10, 4 ); diff --git a/src/wp-includes/functions.php b/src/wp-includes/functions.php index 355d9f8a1ec37..424a9ae26a0c6 100644 --- a/src/wp-includes/functions.php +++ b/src/wp-includes/functions.php @@ -9280,6 +9280,41 @@ function wp_fast_hash( return '$generic$' . sodium_bin2base64( $hashed, SODIUM_BASE64_VARIANT_URLSAFE_NO_PADDING ); } +/** + * Moves the admin notices below the heading tag via server-side processing. + * This prevents the visual glitch caused by JavaScript processing in the original fix. + * + * @since 7.x.x + */ +function wp_move_notice_after_heading() { + ob_start( + function ( $html ) { + global $pagenow; + if ( ! class_exists( '\Dom\HTMLDocument' ) || empty( $html ) || ! is_string( $html ) || wp_doing_ajax() || ! is_user_logged_in() ) { + return $html; + } + + if ( 'admin-post.php' === $pagenow || ( defined( 'WP_CLI' ) && WP_CLI ) ) { + return $html; + } + + $dom = \Dom\HTMLDocument::createFromString( $html, LIBXML_NOERROR ); + $headerEnd = $dom->querySelector( '.wrap :is( h1, h2 )' ); + + $notices = $dom->querySelectorAll( 'div:is( .updated, .error, .notice ):not( .inline, .below-h2 )' ); + if ( $headerEnd && $notices->length > 0 ) { + foreach ( $notices as $notice ) { + $headerEnd->parentNode->insertBefore( $notice, $headerEnd->nextSibling ); // phpcs:ignore WordPress.NamingConventions.ValidVariableName.UsedPropertyNotSnakeCase -- DOM API property name, cannot be renamed. + } + + return $dom->saveHTML(); + } + + return $html; + } + ); +} + /** * Checks whether a plaintext message matches the hashed value. Used to verify values hashed via wp_fast_hash(). *