diff --git a/src/wp-content/themes/twentytwentyfour/theme.json b/src/wp-content/themes/twentytwentyfour/theme.json
index 7988b1af5c15f..2586fcab0a7ec 100644
--- a/src/wp-content/themes/twentytwentyfour/theme.json
+++ b/src/wp-content/themes/twentytwentyfour/theme.json
@@ -247,7 +247,7 @@
{
"fontFamily": "Iowan Old Style, Apple Garamond, Baskerville, Times New Roman, Droid Serif, Times, Source Serif Pro, serif, Apple Color Emoji, Segoe UI Emoji, Segoe UI Symbol",
"name": "System Serif",
- "slug": "system-Serif"
+ "slug": "system-serif"
}
],
"fontSizes": [
diff --git a/src/wp-includes/block-patterns.php b/src/wp-includes/block-patterns.php
index 66bdfd68e7caa..e5c770e1d4330 100644
--- a/src/wp-includes/block-patterns.php
+++ b/src/wp-includes/block-patterns.php
@@ -135,6 +135,20 @@ function _register_core_block_patterns_and_categories() {
'description' => __( 'Different layouts containing video or audio.' ),
)
);
+ register_block_pattern_category(
+ 'videos',
+ array(
+ 'label' => _x( 'Videos', 'Block pattern category' ),
+ 'description' => __( 'Different layouts containing videos.' ),
+ )
+ );
+ register_block_pattern_category(
+ 'audio',
+ array(
+ 'label' => _x( 'Audio', 'Block pattern category' ),
+ 'description' => __( 'Different layouts containing audio.' ),
+ )
+ );
register_block_pattern_category(
'posts',
array(
diff --git a/src/wp-includes/block-template-utils.php b/src/wp-includes/block-template-utils.php
index e2cd7c1587b9f..3f912ad0611b6 100644
--- a/src/wp-includes/block-template-utils.php
+++ b/src/wp-includes/block-template-utils.php
@@ -251,7 +251,7 @@ function _get_block_templates_paths( $base_directory ) {
* @param string $template_type 'wp_template' or 'wp_template_part'.
* @param string $slug Template slug.
* @return array|null {
- * Array with template metadata if $template_type is one of 'wp_template' or 'wp_template_part'.
+ * Array with template metadata if $template_type is one of 'wp_template' or 'wp_template_part',
* null otherwise.
*
* @type string $slug Template slug.
diff --git a/src/wp-includes/blocks.php b/src/wp-includes/blocks.php
index 431e2b015332c..dcb899c9e532d 100644
--- a/src/wp-includes/blocks.php
+++ b/src/wp-includes/blocks.php
@@ -758,22 +758,28 @@ function get_hooked_blocks() {
}
/**
- * Conditionally returns the markup for a given hooked block type.
+ * Conditionally returns the markup for a given hooked block.
*
- * Accepts two arguments: A reference to an anchor block, and the name of a hooked block type.
+ * Accepts three arguments: A hooked block, its type, and a reference to an anchor block.
* If the anchor block has already been processed, and the given hooked block type is in the list
* of ignored hooked blocks, an empty string is returned.
*
+ * The hooked block type is specified separately as it's possible that a filter might've modified
+ * the hooked block such that `$hooked_block['blockName']` does no longer reflect the original type.
+ *
* This function is meant for internal use only.
*
* @since 6.5.0
* @access private
*
- * @param array $anchor_block The anchor block. Passed by reference.
- * @param string $hooked_block_type The name of the hooked block type.
- * @return string The markup for the given hooked block type, or an empty string if the block is ignored.
+ * @param array $hooked_block The hooked block, represented as a parsed block array.
+ * @param string $hooked_block_type The type of the hooked block. This could be different from
+ * $hooked_block['blockName'], as a filter might've modified the latter.
+ * @param array $anchor_block The anchor block, represented as a parsed block array.
+ * Passed by reference.
+ * @return string The markup for the given hooked block, or an empty string if the block is ignored.
*/
-function get_hooked_block_markup( &$anchor_block, $hooked_block_type ) {
+function get_hooked_block_markup( $hooked_block, $hooked_block_type, &$anchor_block ) {
if ( ! isset( $anchor_block['attrs']['metadata']['ignoredHookedBlocks'] ) ) {
$anchor_block['attrs']['metadata']['ignoredHookedBlocks'] = array();
}
@@ -786,7 +792,70 @@ function get_hooked_block_markup( &$anchor_block, $hooked_block_type ) {
// However, its presence does not affect the frontend.
$anchor_block['attrs']['metadata']['ignoredHookedBlocks'][] = $hooked_block_type;
- return get_comment_delimited_block_content( $hooked_block_type, array(), '' );
+ return serialize_block( $hooked_block );
+}
+
+/**
+ * Returns the markup for blocks hooked to the given anchor block in a specific relative position.
+ *
+ * @since 6.5.0
+ * @access private
+ *
+ * @param array $parsed_anchor_block The anchor block, in parsed block array format.
+ * @param string $relative_position The relative position of the hooked blocks.
+ * Can be one of 'before', 'after', 'first_child', or 'last_child'.
+ * @param array $hooked_blocks An array of hooked block types, grouped by anchor block and relative position.
+ * @param WP_Block_Template|array $context The block template, template part, or pattern that the anchor block belongs to.
+ * @return string
+ */
+function insert_hooked_blocks( &$parsed_anchor_block, $relative_position, $hooked_blocks, $context ) {
+ $anchor_block_type = $parsed_anchor_block['blockName'];
+ $hooked_block_types = isset( $hooked_blocks[ $anchor_block_type ][ $relative_position ] )
+ ? $hooked_blocks[ $anchor_block_type ][ $relative_position ]
+ : array();
+
+ /**
+ * Filters the list of hooked block types for a given anchor block type and relative position.
+ *
+ * @since 6.4.0
+ *
+ * @param string[] $hooked_block_types The list of hooked block types.
+ * @param string $relative_position The relative position of the hooked blocks.
+ * Can be one of 'before', 'after', 'first_child', or 'last_child'.
+ * @param string $anchor_block_type The anchor block type.
+ * @param WP_Block_Template|array $context The block template, template part, or pattern that the anchor block belongs to.
+ */
+ $hooked_block_types = apply_filters( 'hooked_block_types', $hooked_block_types, $relative_position, $anchor_block_type, $context );
+
+ $markup = '';
+ foreach ( $hooked_block_types as $hooked_block_type ) {
+ $parsed_hooked_block = array(
+ 'blockName' => $hooked_block_type,
+ 'attrs' => array(),
+ 'innerBlocks' => array(),
+ 'innerContent' => array(),
+ );
+
+ /**
+ * Filters the parsed block array for a given hooked block.
+ *
+ * The dynamic portion of the hook name, `$hooked_block_type`, refers to the block type name of the specific hooked block.
+ *
+ * @since 6.5.0
+ *
+ * @param array $parsed_hooked_block The parsed block array for the given hooked block type.
+ * @param string $relative_position The relative position of the hooked block.
+ * @param array $parsed_anchor_block The anchor block, in parsed block array format.
+ * @param WP_Block_Template|array $context The block template, template part, or pattern that the anchor block belongs to.
+ */
+ $parsed_hooked_block = apply_filters( "hooked_block_{$hooked_block_type}", $parsed_hooked_block, $relative_position, $parsed_anchor_block, $context );
+
+ // It's possible that the `hooked_block_{$hooked_block_type}` filter returned a block of a different type,
+ // so we need to pass the original $hooked_block_type as well.
+ $markup .= get_hooked_block_markup( $parsed_hooked_block, $hooked_block_type, $parsed_anchor_block );
+ }
+
+ return $markup;
}
/**
@@ -826,40 +895,10 @@ function make_before_block_visitor( $hooked_blocks, $context ) {
if ( $parent_block && ! $prev ) {
// Candidate for first-child insertion.
- $relative_position = 'first_child';
- $anchor_block_type = $parent_block['blockName'];
- $hooked_block_types = isset( $hooked_blocks[ $anchor_block_type ][ $relative_position ] )
- ? $hooked_blocks[ $anchor_block_type ][ $relative_position ]
- : array();
-
- /**
- * Filters the list of hooked block types for a given anchor block type and relative position.
- *
- * @since 6.4.0
- *
- * @param string[] $hooked_block_types The list of hooked block types.
- * @param string $relative_position The relative position of the hooked blocks.
- * Can be one of 'before', 'after', 'first_child', or 'last_child'.
- * @param string $anchor_block_type The anchor block type.
- * @param WP_Block_Template|array $context The block template, template part, or pattern that the anchor block belongs to.
- */
- $hooked_block_types = apply_filters( 'hooked_block_types', $hooked_block_types, $relative_position, $anchor_block_type, $context );
- foreach ( $hooked_block_types as $hooked_block_type ) {
- $markup .= get_hooked_block_markup( $parent_block, $hooked_block_type );
- }
+ $markup .= insert_hooked_blocks( $parent_block, 'first_child', $hooked_blocks, $context );
}
- $relative_position = 'before';
- $anchor_block_type = $block['blockName'];
- $hooked_block_types = isset( $hooked_blocks[ $anchor_block_type ][ $relative_position ] )
- ? $hooked_blocks[ $anchor_block_type ][ $relative_position ]
- : array();
-
- /** This filter is documented in wp-includes/blocks.php */
- $hooked_block_types = apply_filters( 'hooked_block_types', $hooked_block_types, $relative_position, $anchor_block_type, $context );
- foreach ( $hooked_block_types as $hooked_block_type ) {
- $markup .= get_hooked_block_markup( $block, $hooked_block_type );
- }
+ $markup .= insert_hooked_blocks( $block, 'before', $hooked_blocks, $context );
return $markup;
};
@@ -895,33 +934,11 @@ function make_after_block_visitor( $hooked_blocks, $context ) {
* @return string The serialized markup for the given block, with the markup for any hooked blocks appended to it.
*/
return function ( &$block, &$parent_block = null, $next = null ) use ( $hooked_blocks, $context ) {
- $markup = '';
-
- $relative_position = 'after';
- $anchor_block_type = $block['blockName'];
- $hooked_block_types = isset( $hooked_blocks[ $anchor_block_type ][ $relative_position ] )
- ? $hooked_blocks[ $anchor_block_type ][ $relative_position ]
- : array();
-
- /** This filter is documented in wp-includes/blocks.php */
- $hooked_block_types = apply_filters( 'hooked_block_types', $hooked_block_types, $relative_position, $anchor_block_type, $context );
- foreach ( $hooked_block_types as $hooked_block_type ) {
- $markup .= get_hooked_block_markup( $block, $hooked_block_type );
- }
+ $markup = insert_hooked_blocks( $block, 'after', $hooked_blocks, $context );
if ( $parent_block && ! $next ) {
// Candidate for last-child insertion.
- $relative_position = 'last_child';
- $anchor_block_type = $parent_block['blockName'];
- $hooked_block_types = isset( $hooked_blocks[ $anchor_block_type ][ $relative_position ] )
- ? $hooked_blocks[ $anchor_block_type ][ $relative_position ]
- : array();
-
- /** This filter is documented in wp-includes/blocks.php */
- $hooked_block_types = apply_filters( 'hooked_block_types', $hooked_block_types, $relative_position, $anchor_block_type, $context );
- foreach ( $hooked_block_types as $hooked_block_type ) {
- $markup .= get_hooked_block_markup( $parent_block, $hooked_block_type );
- }
+ $markup .= insert_hooked_blocks( $parent_block, 'last_child', $hooked_blocks, $context );
}
return $markup;
diff --git a/src/wp-includes/blocks/image.php b/src/wp-includes/blocks/image.php
index acefd5714bbd4..7df0949c8dfa0 100644
--- a/src/wp-includes/blocks/image.php
+++ b/src/wp-includes/blocks/image.php
@@ -229,26 +229,32 @@ function block_core_image_render_lightbox( $block_content, $block ) {
$body_content = $w->get_updated_html();
// Add a button alongside image in the body content.
- $img = null;
- preg_match( '/]+>/', $body_content, $img );
-
- $button =
- $img[0]
- . '';
-
- $body_content = preg_replace( '/
]+>/', $button, $body_content );
+ $body_content = preg_replace_callback(
+ '/
]+>/',
+ static function ( $img_match ) use ( $aria_label ) {
+ $button_html = WP_HTML::render(
+ <<<'HTML'
+
+HTML,
+ array(
+ 'label' => $aria_label,
+ 'interactivity' => array(
+ 'data-wp-on--click' => 'actions.core.image.showLightbox',
+ 'data-wp-style--right' => 'context.core.image.imageButtonRight',
+ 'data-wp-style--top' => 'context.core.image.imageButtonTop',
+ ),
+ )
+ );
+
+ return $img_match[0] . $button_html;
+ },
+ $body_content,
+ 1
+ );
// We need both a responsive image and an enlarged image to animate
// the zoom seamlessly on slow internet connections; the responsive
@@ -295,40 +301,46 @@ class="lightbox-trigger"
if ( wp_theme_has_theme_json() ) {
$global_styles_color = wp_get_global_styles( array( 'color' ) );
if ( ! empty( $global_styles_color['background'] ) ) {
- $background_color = esc_attr( $global_styles_color['background'] );
+ $background_color = $global_styles_color['background'];
}
if ( ! empty( $global_styles_color['text'] ) ) {
- $close_button_color = esc_attr( $global_styles_color['text'] );
+ $close_button_color = $global_styles_color['text'];
}
}
- $close_button_icon = '';
- $close_button_label = esc_attr__( 'Close' );
-
- $lightbox_html = <<
-
-