From 8648d062842e07f949c1aa751d49ced117432365 Mon Sep 17 00:00:00 2001 From: Bernhard Reiter Date: Thu, 7 Mar 2024 14:12:11 +0000 Subject: [PATCH] Block Hooks: Use new Templates Controller filter instead of action. This changeset adds a new `rest_pre_insert_{$this->post_type}` filter in the `WP_REST_Templates_Controller`, where it is applied to the return value of the `prepare_item_for_database` method. (This is consistent with the `WP_REST_Post_Controller`, where that filter has existed before.) The new filter is then used to inject hooked blocks into the template (or template part) content received via the endpoint, prior to persisting it to the database. This supersedes the previous mechanism, which was using the `rest_after_insert_{$this->post_type}` ''action'', from which it performed an additional `wp_update_post` call to update the template (part) content with the hooked blocks injected. The new technique eschews that additional call and the resulting extra revision it created, as well as a problem with regard to duplicated escaping and sanitization, which had caused some special characters to be garbled. Props tomjcafferkey, gziolo, swissspidy, karolmanijak. Fixes #60671. Built from https://develop.svn.wordpress.org/trunk@57790 git-svn-id: http://core.svn.wordpress.org/trunk@57291 1a063a9b-81f0-0310-95a4-ce76da25c4cd --- wp-includes/block-template-utils.php | 35 ++++++++++++------- wp-includes/default-filters.php | 7 ++-- .../class-wp-rest-templates-controller.php | 3 +- wp-includes/version.php | 2 +- 4 files changed, 28 insertions(+), 19 deletions(-) diff --git a/wp-includes/block-template-utils.php b/wp-includes/block-template-utils.php index 75e664ad9b..cfae702dd6 100644 --- a/wp-includes/block-template-utils.php +++ b/wp-includes/block-template-utils.php @@ -1432,39 +1432,48 @@ function get_template_hierarchy( $slug, $is_custom = false, $template_prefix = ' $template_hierarchy[] = 'index'; return $template_hierarchy; } + /** * Inject ignoredHookedBlocks metadata attributes into a template or template part. * - * Given a `wp_template` or `wp_template_part` post object, locate all blocks that have + * Given an object that represents a `wp_template` or `wp_template_part` post object + * prepared for inserting or updating the database, locate all blocks that have * hooked blocks, and inject a `metadata.ignoredHookedBlocks` attribute into the anchor * blocks to reflect the latter. * - * @param WP_Post $post A post object with post type set to `wp_template` or `wp_template_part`. - * @return WP_Post The updated post object. + * @since 6.5.0 + * @access private + * + * @param stdClass $post An object representing a template or template part + * prepared for inserting or updating the database. + * @param WP_REST_Request $request Request object. + * @return stdClass The updated object representing a template or template part. */ -function inject_ignored_hooked_blocks_metadata_attributes( $post ) { +function inject_ignored_hooked_blocks_metadata_attributes( $post, $request ) { + $filter_name = current_filter(); + if ( ! str_starts_with( $filter_name, 'rest_pre_insert_' ) ) { + return $post; + } + $post_type = str_replace( 'rest_pre_insert_', '', $filter_name ); + $hooked_blocks = get_hooked_blocks(); if ( empty( $hooked_blocks ) && ! has_filter( 'hooked_block_types' ) ) { - return; + return $post; } // At this point, the post has already been created. // We need to build the corresponding `WP_Block_Template` object as context argument for the visitor. // To that end, we need to suppress hooked blocks from getting inserted into the template. add_filter( 'hooked_block_types', '__return_empty_array', 99999, 0 ); - $template = _build_block_template_result_from_post( $post ); + $template = $request['id'] ? get_block_template( $request['id'], $post_type ) : null; remove_filter( 'hooked_block_types', '__return_empty_array', 99999 ); $before_block_visitor = make_before_block_visitor( $hooked_blocks, $template, 'set_ignored_hooked_blocks_metadata' ); $after_block_visitor = make_after_block_visitor( $hooked_blocks, $template, 'set_ignored_hooked_blocks_metadata' ); - $blocks = parse_blocks( $template->content ); + $blocks = parse_blocks( $post->post_content ); $content = traverse_and_serialize_blocks( $blocks, $before_block_visitor, $after_block_visitor ); - wp_update_post( - array( - 'ID' => $post->ID, - 'post_content' => $content, - ) - ); + $post->post_content = $content; + return $post; } diff --git a/wp-includes/default-filters.php b/wp-includes/default-filters.php index 3f7e43f861..884357f413 100644 --- a/wp-includes/default-filters.php +++ b/wp-includes/default-filters.php @@ -752,9 +752,8 @@ add_action( 'deleted_post', '_wp_after_delete_font_family', 10, 2 ); add_action( 'before_delete_post', '_wp_before_delete_font_face', 10, 2 ); add_action( 'init', '_wp_register_default_font_collections' ); -// It might be nice to use a filter instead of an action, but the `WP_REST_Templates_Controller` doesn't -// provide one (unlike e.g. `WP_REST_Posts_Controller`, which has `rest_pre_insert_{$this->post_type}`). -add_action( 'rest_after_insert_wp_template', 'inject_ignored_hooked_blocks_metadata_attributes', 10, 3 ); -add_action( 'rest_after_insert_wp_template_part', 'inject_ignored_hooked_blocks_metadata_attributes', 10, 3 ); +// Add ignoredHookedBlocks metadata attribute to the template and template part post types. +add_filter( 'rest_pre_insert_wp_template', 'inject_ignored_hooked_blocks_metadata_attributes', 10, 2 ); +add_filter( 'rest_pre_insert_wp_template_part', 'inject_ignored_hooked_blocks_metadata_attributes', 10, 2 ); unset( $filter, $action ); diff --git a/wp-includes/rest-api/endpoints/class-wp-rest-templates-controller.php b/wp-includes/rest-api/endpoints/class-wp-rest-templates-controller.php index 1549fd4295..cec8a77e04 100644 --- a/wp-includes/rest-api/endpoints/class-wp-rest-templates-controller.php +++ b/wp-includes/rest-api/endpoints/class-wp-rest-templates-controller.php @@ -619,7 +619,8 @@ class WP_REST_Templates_Controller extends WP_REST_Controller { $changes->post_author = $post_author; } - return $changes; + /** This filter is documented in wp-includes/rest-api/endpoints/class-wp-rest-posts-controller.php */ + return apply_filters( "rest_pre_insert_{$this->post_type}", $changes, $request ); } /** diff --git a/wp-includes/version.php b/wp-includes/version.php index a17e834371..d705527d49 100644 --- a/wp-includes/version.php +++ b/wp-includes/version.php @@ -16,7 +16,7 @@ * * @global string $wp_version */ -$wp_version = '6.6-alpha-57789'; +$wp_version = '6.6-alpha-57790'; /** * Holds the WordPress DB revision, increments when changes are made to the WordPress DB schema.