<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[58041] branches/6.5: Block Hooks: Pass correct context to filters.</title>
</head>
<body>
<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; }
#msg dl a { font-weight: bold}
#msg dl a:link { color:#fc3; }
#msg dl a:active { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { white-space: pre-line; overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta" style="font-size: 105%">
<dt style="float: left; width: 6em; font-weight: bold">Revision</dt> <dd><a style="font-weight: bold" href="https://core.trac.wordpress.org/changeset/58041">58041</a><script type="application/ld+json">{"@context":"http://schema.org","@type":"EmailMessage","description":"Review this Commit","action":{"@type":"ViewAction","url":"https://core.trac.wordpress.org/changeset/58041","name":"Review Commit"}}</script></dd>
<dt style="float: left; width: 6em; font-weight: bold">Author</dt> <dd>Bernhard Reiter</dd>
<dt style="float: left; width: 6em; font-weight: bold">Date</dt> <dd>2024-04-24 12:00:29 +0000 (Wed, 24 Apr 2024)</dd>
</dl>
<pre style='padding-left: 1em; margin: 2em 0; border-left: 2px solid #ccc; line-height: 1.25; font-size: 105%; font-family: sans-serif'>Block Hooks: Pass correct context to filters.
The `$context` argument passed to filters such as `hooked_block_types`, `hooked_block`, and `hooked_block_{$hooked_block_type}` allows them to conditionally insert a hooked block. If the anchor block is contained in a template or template part, `$context` will be set to a `WP_Block_Template` object reflecting that template or part.
The aforementioned filters are applied when hooked block insertion is run upon reading a template (or part) from the DB (and before sending the template/part content with hooked blocks inserted over the REST API to the client), but also upon writing to the DB, as that's when the `ignoredHookedBlocks` metadata attribute is set.
Prior to this changeset, the `$context` passed to Block Hooks related filters in the latter case reflected the template/part that was already stored in the database (if any), which is a bug; instead, it needs to reflect the template/part that will result from the incoming `POST` network request that will trigger a database update.
Those incoming changes are encapsulated in the `$changes` argument passed to the `reset_pre_insert_template` and `reset_pre_insert_template_part` filters, respectively, and thus to the `inject_ignored_hooked_blocks_metadata_attributes` function that is hooked to them. `$changes` is of type `stdClass` and only contains the fields that need to be updated. That means that in order to create a `WP_Block_Template` object, a two-step process is needed:
- Emulate what the updated `wp_template` or `wp_template_part` post object in the database will look like by merging `$changes` on top of the existing `$post` object fetched from the DB, or from the theme's block template (part) file, if any.
- Create a `WP_Block_Template` from the resulting object.
To achieve the latter, a new helper method (`_build_block_template_object_from_post_object`) is extracted from the existing `_build_block_template_result_from_post` function. (The latter cannot be used directly as it includes a few database calls that will fail if no post object for the template has existed yet in the database.)
While somewhat complicated to implement, the overall change allows for better separation of concerns and isolation of entities. This is visible e.g. in the fact that `inject_ignored_hooked_blocks_metadata_attributes` no longer requires a `$request` argument, which is reflected by unit tests no longer needing to create a `$request` object to pass to it, thus decoupling the function from the templates endpoint controller.
Unit tests for `inject_ignored_hooked_blocks_metadata_attributes` have been moved to a new, separate file. Test coverage has been added such that now, all three relevant scenarios are covered:
- The template doesn't exist in the DB, nor is there a block theme template file for it.
- The template doesn't exist in the DB, but there is a block theme template file for it.
- The template already exists in the DB.
Those scenarios also correspond to the logical branching inside `WP_REST_Templates_Controller::prepare_item_for_database`, which is where `inject_ignored_hooked_blocks_metadata_attributes` gets its data from.
Reviewed by gziolo.
Merges <a href="https://core.trac.wordpress.org/changeset/57919">[57919]</a> to the to the 6.5 branch.
Props tomjcafferkey, bernhard-reiter, gziolo, swissspidy.
Fixes <a href="https://core.trac.wordpress.org/ticket/60754">#60754</a>.</pre>
<h3>Modified Paths</h3>
<ul>
<li><a href="#branches65srcwpincludesblocktemplateutilsphp">branches/6.5/src/wp-includes/block-template-utils.php</a></li>
<li><a href="#branches65srcwpincludesdefaultfiltersphp">branches/6.5/src/wp-includes/default-filters.php</a></li>
<li><a href="#branches65srcwpincludesrestapiendpointsclasswpresttemplatescontrollerphp">branches/6.5/src/wp-includes/rest-api/endpoints/class-wp-rest-templates-controller.php</a></li>
<li><a href="#branches65testsphpunittestsblocktemplateutilsphp">branches/6.5/tests/phpunit/tests/block-template-utils.php</a></li>
<li><a href="#branches65testsphpunittestsrestapiwpRestTemplatesControllerphp">branches/6.5/tests/phpunit/tests/rest-api/wpRestTemplatesController.php</a></li>
</ul>
<h3>Added Paths</h3>
<ul>
<li><a href="#branches65testsphpunittestsblocktemplatesinjectIgnoredHookedBlocksMetadataAttributesphp">branches/6.5/tests/phpunit/tests/block-templates/injectIgnoredHookedBlocksMetadataAttributes.php</a></li>
</ul>
</div>
<div id="patch">
<h3>Diff</h3>
<a id="branches65srcwpincludesblocktemplateutilsphp"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: branches/6.5/src/wp-includes/block-template-utils.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- branches/6.5/src/wp-includes/block-template-utils.php 2024-04-24 07:43:02 UTC (rev 58040)
+++ branches/6.5/src/wp-includes/block-template-utils.php 2024-04-24 12:00:29 UTC (rev 58041)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -723,74 +723,115 @@
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> /**
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * Builds a unified template object based a post Object.
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * Builds a block template object from a post object.
</ins><span class="cx" style="display: block; padding: 0 10px"> *
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * @since 5.9.0
- * @since 6.3.0 Added `modified` property to template objects.
- * @since 6.4.0 Added support for a revision post to be passed to this function.
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * This is a helper function that creates a block template object from a given post object.
+ * It is self-sufficient in that it only uses information passed as arguments; it does not
+ * query the database for additional information.
+ *
+ * @since 6.5.1
</ins><span class="cx" style="display: block; padding: 0 10px"> * @access private
</span><span class="cx" style="display: block; padding: 0 10px"> *
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * @param WP_Post $post Template post.
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * @param WP_Post $post Template post.
+ * @param array $terms Additional terms to inform the template object.
+ * @param array $meta Additional meta fields to inform the template object.
</ins><span class="cx" style="display: block; padding: 0 10px"> * @return WP_Block_Template|WP_Error Template or error object.
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-function _build_block_template_result_from_post( $post ) {
- $default_template_types = get_default_block_template_types();
-
- $post_id = wp_is_post_revision( $post );
- if ( ! $post_id ) {
- $post_id = $post;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+function _build_block_template_object_from_post_object( $post, $terms = array(), $meta = array() ) {
+ if ( empty( $terms['wp_theme'] ) ) {
+ return new WP_Error( 'template_missing_theme', __( 'No theme is defined for this template.' ) );
</ins><span class="cx" style="display: block; padding: 0 10px"> }
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- $parent_post = get_post( $post_id );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $theme = $terms['wp_theme'];
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- $terms = get_the_terms( $parent_post, 'wp_theme' );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $default_template_types = get_default_block_template_types();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if ( is_wp_error( $terms ) ) {
- return $terms;
- }
-
- if ( ! $terms ) {
- return new WP_Error( 'template_missing_theme', __( 'No theme is defined for this template.' ) );
- }
-
- $theme = $terms[0]->name;
</del><span class="cx" style="display: block; padding: 0 10px"> $template_file = _get_block_template_file( $post->post_type, $post->post_name );
</span><span class="cx" style="display: block; padding: 0 10px"> $has_theme_file = get_stylesheet() === $theme && null !== $template_file;
</span><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- $origin = get_post_meta( $parent_post->ID, 'origin', true );
- $is_wp_suggestion = get_post_meta( $parent_post->ID, 'is_wp_suggestion', true );
-
</del><span class="cx" style="display: block; padding: 0 10px"> $template = new WP_Block_Template();
</span><span class="cx" style="display: block; padding: 0 10px"> $template->wp_id = $post->ID;
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- $template->id = $theme . '//' . $parent_post->post_name;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $template->id = $theme . '//' . $post->post_name;
</ins><span class="cx" style="display: block; padding: 0 10px"> $template->theme = $theme;
</span><span class="cx" style="display: block; padding: 0 10px"> $template->content = $post->post_content;
</span><span class="cx" style="display: block; padding: 0 10px"> $template->slug = $post->post_name;
</span><span class="cx" style="display: block; padding: 0 10px"> $template->source = 'custom';
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- $template->origin = ! empty( $origin ) ? $origin : null;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $template->origin = ! empty( $meta['origin'] ) ? $meta['origin'] : null;
</ins><span class="cx" style="display: block; padding: 0 10px"> $template->type = $post->post_type;
</span><span class="cx" style="display: block; padding: 0 10px"> $template->description = $post->post_excerpt;
</span><span class="cx" style="display: block; padding: 0 10px"> $template->title = $post->post_title;
</span><span class="cx" style="display: block; padding: 0 10px"> $template->status = $post->post_status;
</span><span class="cx" style="display: block; padding: 0 10px"> $template->has_theme_file = $has_theme_file;
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- $template->is_custom = empty( $is_wp_suggestion );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $template->is_custom = empty( $meta['is_wp_suggestion'] );
</ins><span class="cx" style="display: block; padding: 0 10px"> $template->author = $post->post_author;
</span><span class="cx" style="display: block; padding: 0 10px"> $template->modified = $post->post_modified;
</span><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if ( 'wp_template' === $parent_post->post_type && $has_theme_file && isset( $template_file['postTypes'] ) ) {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if ( 'wp_template' === $post->post_type && $has_theme_file && isset( $template_file['postTypes'] ) ) {
</ins><span class="cx" style="display: block; padding: 0 10px"> $template->post_types = $template_file['postTypes'];
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if ( 'wp_template' === $parent_post->post_type && isset( $default_template_types[ $template->slug ] ) ) {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if ( 'wp_template' === $post->post_type && isset( $default_template_types[ $template->slug ] ) ) {
</ins><span class="cx" style="display: block; padding: 0 10px"> $template->is_custom = false;
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px">
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if ( 'wp_template_part' === $post->post_type && isset( $terms['wp_template_part_area'] ) ) {
+ $template->area = $terms['wp_template_part_area'];
+ }
+
+ return $template;
+}
+
+/**
+ * Builds a unified template object based a post Object.
+ *
+ * @since 5.9.0
+ * @since 6.3.0 Added `modified` property to template objects.
+ * @since 6.4.0 Added support for a revision post to be passed to this function.
+ * @access private
+ *
+ * @param WP_Post $post Template post.
+ * @return WP_Block_Template|WP_Error Template or error object.
+ */
+function _build_block_template_result_from_post( $post ) {
+ $post_id = wp_is_post_revision( $post );
+ if ( ! $post_id ) {
+ $post_id = $post;
+ }
+ $parent_post = get_post( $post_id );
+ $post->post_name = $parent_post->post_name;
+ $post->post_type = $parent_post->post_type;
+
+ $terms = get_the_terms( $parent_post, 'wp_theme' );
+
+ if ( is_wp_error( $terms ) ) {
+ return $terms;
+ }
+
+ if ( ! $terms ) {
+ return new WP_Error( 'template_missing_theme', __( 'No theme is defined for this template.' ) );
+ }
+
+ $terms = array(
+ 'wp_theme' => $terms[0]->name,
+ );
+
</ins><span class="cx" style="display: block; padding: 0 10px"> if ( 'wp_template_part' === $parent_post->post_type ) {
</span><span class="cx" style="display: block; padding: 0 10px"> $type_terms = get_the_terms( $parent_post, 'wp_template_part_area' );
</span><span class="cx" style="display: block; padding: 0 10px"> if ( ! is_wp_error( $type_terms ) && false !== $type_terms ) {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- $template->area = $type_terms[0]->name;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $terms['wp_template_part_area'] = $type_terms[0]->name;
</ins><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px">
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $meta = array(
+ 'origin' => get_post_meta( $parent_post->ID, 'origin', true ),
+ 'is_wp_suggestion' => get_post_meta( $parent_post->ID, 'is_wp_suggestion', true ),
+ );
+
+ $template = _build_block_template_object_from_post_object( $post, $terms, $meta );
+
+ if ( is_wp_error( $template ) ) {
+ return $template;
+ }
+
</ins><span class="cx" style="display: block; padding: 0 10px"> // Check for a block template without a description and title or with a title equal to the slug.
</span><span class="cx" style="display: block; padding: 0 10px"> if ( 'wp_template' === $parent_post->post_type && empty( $template->description ) && ( empty( $template->title ) || $template->title === $template->slug ) ) {
</span><span class="cx" style="display: block; padding: 0 10px"> $matches = array();
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1442,36 +1483,70 @@
</span><span class="cx" style="display: block; padding: 0 10px"> * @since 6.5.0
</span><span class="cx" style="display: block; padding: 0 10px"> * @access private
</span><span class="cx" style="display: block; padding: 0 10px"> *
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * @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.
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * @param stdClass $changes An object representing a template or template part
+ * prepared for inserting or updating the database.
+ * @param WP_REST_Request $deprecated Deprecated. Not used.
+ * @return stdClass|WP_Error The updated object representing a template or template part.
</ins><span class="cx" style="display: block; padding: 0 10px"> */
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-function inject_ignored_hooked_blocks_metadata_attributes( $post, $request ) {
- $filter_name = current_filter();
- if ( ! str_starts_with( $filter_name, 'rest_pre_insert_' ) ) {
- return $post;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+function inject_ignored_hooked_blocks_metadata_attributes( $changes, $deprecated = null ) {
+ if ( null !== $deprecated ) {
+ _deprecated_argument( __FUNCTION__, '6.5.1' );
</ins><span class="cx" style="display: block; padding: 0 10px"> }
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- $post_type = str_replace( 'rest_pre_insert_', '', $filter_name );
</del><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> $hooked_blocks = get_hooked_blocks();
</span><span class="cx" style="display: block; padding: 0 10px"> if ( empty( $hooked_blocks ) && ! has_filter( 'hooked_block_types' ) ) {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return $post;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return $changes;
</ins><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // 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 = $request['id'] ? get_block_template( $request['id'], $post_type ) : null;
- remove_filter( 'hooked_block_types', '__return_empty_array', 99999 );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $meta = isset( $changes->meta_input ) ? $changes->meta_input : array();
+ $terms = isset( $changes->tax_input ) ? $changes->tax_input : array();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if ( empty( $changes->ID ) ) {
+ // There's no post object for this template in the database for this template yet.
+ $post = $changes;
+ } else {
+ // Find the existing post object.
+ $post = get_post( $changes->ID );
+
+ // If the post is a revision, use the parent post's post_name and post_type.
+ $post_id = wp_is_post_revision( $post );
+ if ( $post_id ) {
+ $parent_post = get_post( $post_id );
+ $post->post_name = $parent_post->post_name;
+ $post->post_type = $parent_post->post_type;
+ }
+
+ // Apply the changes to the existing post object.
+ $post = (object) array_merge( (array) $post, (array) $changes );
+
+ $type_terms = get_the_terms( $changes->ID, 'wp_theme' );
+ $terms['wp_theme'] = ! is_wp_error( $type_terms ) && ! empty( $type_terms ) ? $type_terms[0]->name : null;
+ }
+
+ // Required for the WP_Block_Template. Update the post object with the current time.
+ $post->post_modified = current_time( 'mysql' );
+
+ // If the post_author is empty, set it to the current user.
+ if ( empty( $post->post_author ) ) {
+ $post->post_author = get_current_user_id();
+ }
+
+ if ( 'wp_template_part' === $post->post_type && ! isset( $terms['wp_template_part_area'] ) ) {
+ $area_terms = get_the_terms( $changes->ID, 'wp_template_part_area' );
+ $terms['wp_template_part_area'] = ! is_wp_error( $area_terms ) && ! empty( $area_terms ) ? $area_terms[0]->name : null;
+ }
+
+ $template = _build_block_template_object_from_post_object( new WP_Post( $post ), $terms, $meta );
+
+ if ( is_wp_error( $template ) ) {
+ return $template;
+ }
+
</ins><span class="cx" style="display: block; padding: 0 10px"> $before_block_visitor = make_before_block_visitor( $hooked_blocks, $template, 'set_ignored_hooked_blocks_metadata' );
</span><span class="cx" style="display: block; padding: 0 10px"> $after_block_visitor = make_after_block_visitor( $hooked_blocks, $template, 'set_ignored_hooked_blocks_metadata' );
</span><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- $blocks = parse_blocks( $post->post_content );
- $content = traverse_and_serialize_blocks( $blocks, $before_block_visitor, $after_block_visitor );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $blocks = parse_blocks( $changes->post_content );
+ $changes->post_content = traverse_and_serialize_blocks( $blocks, $before_block_visitor, $after_block_visitor );
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- $post->post_content = $content;
- return $post;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return $changes;
</ins><span class="cx" style="display: block; padding: 0 10px"> }
</span></span></pre></div>
<a id="branches65srcwpincludesdefaultfiltersphp"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: branches/6.5/src/wp-includes/default-filters.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- branches/6.5/src/wp-includes/default-filters.php 2024-04-24 07:43:02 UTC (rev 58040)
+++ branches/6.5/src/wp-includes/default-filters.php 2024-04-24 12:00:29 UTC (rev 58041)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -753,7 +753,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> add_action( 'init', '_wp_register_default_font_collections' );
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> // Add ignoredHookedBlocks metadata attribute to the template and template part post types.
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-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 );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+add_filter( 'rest_pre_insert_wp_template', 'inject_ignored_hooked_blocks_metadata_attributes' );
+add_filter( 'rest_pre_insert_wp_template_part', 'inject_ignored_hooked_blocks_metadata_attributes' );
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> unset( $filter, $action );
</span></span></pre></div>
<a id="branches65srcwpincludesrestapiendpointsclasswpresttemplatescontrollerphp"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: branches/6.5/src/wp-includes/rest-api/endpoints/class-wp-rest-templates-controller.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- branches/6.5/src/wp-includes/rest-api/endpoints/class-wp-rest-templates-controller.php 2024-04-24 07:43:02 UTC (rev 58040)
+++ branches/6.5/src/wp-includes/rest-api/endpoints/class-wp-rest-templates-controller.php 2024-04-24 12:00:29 UTC (rev 58041)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -532,7 +532,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> * @since 5.8.0
</span><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * @param WP_REST_Request $request Request object.
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * @return stdClass Changes to pass to wp_update_post.
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * @return stdClass|WP_Error Changes to pass to wp_update_post.
</ins><span class="cx" style="display: block; padding: 0 10px"> */
</span><span class="cx" style="display: block; padding: 0 10px"> protected function prepare_item_for_database( $request ) {
</span><span class="cx" style="display: block; padding: 0 10px"> $template = $request['id'] ? get_block_template( $request['id'], $this->post_type ) : null;
</span></span></pre></div>
<a id="branches65testsphpunittestsblocktemplateutilsphp"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: branches/6.5/tests/phpunit/tests/block-template-utils.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- branches/6.5/tests/phpunit/tests/block-template-utils.php 2024-04-24 07:43:02 UTC (rev 58040)
+++ branches/6.5/tests/phpunit/tests/block-template-utils.php 2024-04-24 12:00:29 UTC (rev 58041)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -403,72 +403,4 @@
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px"> $this->assertTrue( $has_html_files, 'contains at least one html file' );
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-
- /**
- * @ticket 60671
- *
- * @covers inject_ignored_hooked_blocks_metadata_attributes
- */
- public function test_inject_ignored_hooked_blocks_metadata_attributes_into_template() {
- global $wp_current_filter;
- // Mock currently set filter. The $wp_current_filter global is reset during teardown by
- // WP_UnitTestCase_Base::_restore_hooks() in tests/phpunit/includes/abstract-testcase.php.
- $wp_current_filter[] = 'rest_pre_insert_wp_template';
-
- register_block_type(
- 'tests/hooked-block',
- array(
- 'block_hooks' => array(
- 'tests/anchor-block' => 'after',
- ),
- )
- );
-
- $id = self::TEST_THEME . '//' . 'my_template';
- $request = new WP_REST_Request( 'POST', '/wp/v2/templates/' . $id );
-
- $changes = new stdClass();
- $changes->post_content = '<!-- wp:tests/anchor-block -->Hello<!-- /wp:tests/anchor-block -->';
-
- $post = inject_ignored_hooked_blocks_metadata_attributes( $changes, $request );
- $this->assertSame(
- '<!-- wp:tests/anchor-block {"metadata":{"ignoredHookedBlocks":["tests/hooked-block"]}} -->Hello<!-- /wp:tests/anchor-block -->',
- $post->post_content,
- 'The hooked block was not injected into the anchor block\'s ignoredHookedBlocks metadata.'
- );
- }
-
- /**
- * @ticket 60671
- *
- * @covers inject_ignored_hooked_blocks_metadata_attributes
- */
- public function test_inject_ignored_hooked_blocks_metadata_attributes_into_template_part() {
- global $wp_current_filter;
- // Mock currently set filter. The $wp_current_filter global is reset during teardown by
- // WP_UnitTestCase_Base::_restore_hooks() in tests/phpunit/includes/abstract-testcase.php.
- $wp_current_filter[] = 'rest_pre_insert_wp_template_part';
-
- register_block_type(
- 'tests/hooked-block',
- array(
- 'block_hooks' => array(
- 'tests/anchor-block' => 'after',
- ),
- )
- );
-
- $id = self::TEST_THEME . '//' . 'my_template_part';
- $request = new WP_REST_Request( 'POST', '/wp/v2/template-parts/' . $id );
-
- $changes = new stdClass();
- $changes->post_content = '<!-- wp:tests/anchor-block -->Hello<!-- /wp:tests/anchor-block -->';
-
- $post = inject_ignored_hooked_blocks_metadata_attributes( $changes, $request );
- $this->assertSame(
- '<!-- wp:tests/anchor-block {"metadata":{"ignoredHookedBlocks":["tests/hooked-block"]}} -->Hello<!-- /wp:tests/anchor-block -->',
- $post->post_content,
- 'The hooked block was not injected into the anchor block\'s ignoredHookedBlocks metadata.'
- );
- }
</del><span class="cx" style="display: block; padding: 0 10px"> }
</span></span></pre></div>
<a id="branches65testsphpunittestsblocktemplatesinjectIgnoredHookedBlocksMetadataAttributesphp"></a>
<div class="addfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Added: branches/6.5/tests/phpunit/tests/block-templates/injectIgnoredHookedBlocksMetadataAttributes.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- branches/6.5/tests/phpunit/tests/block-templates/injectIgnoredHookedBlocksMetadataAttributes.php (rev 0)
+++ branches/6.5/tests/phpunit/tests/block-templates/injectIgnoredHookedBlocksMetadataAttributes.php 2024-04-24 12:00:29 UTC (rev 58041)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -0,0 +1,422 @@
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+<?php
+
+require_once __DIR__ . '/base.php';
+
+/**
+ * @group block-templates
+ * @covers ::inject_ignored_hooked_blocks_metadata_attributes
+ */
+class Tests_Block_Templates_InjectIgnoredHookedBlocksMetadataAttributes extends WP_Block_Templates_UnitTestCase {
+
+ /**
+ * Tear down after each test.
+ *
+ * @since 6.5.1
+ */
+ public function tear_down() {
+ if ( WP_Block_Type_Registry::get_instance()->is_registered( 'tests/hooked-block' ) ) {
+ unregister_block_type( 'tests/hooked-block' );
+ }
+
+ parent::tear_down();
+ }
+
+ /**
+ * @ticket 60754
+ */
+ public function test_hooked_block_types_filter_with_newly_created_template() {
+ $action = new MockAction();
+ add_filter( 'hooked_block_types', array( $action, 'filter' ), 10, 4 );
+
+ $changes = new stdClass();
+ $changes->post_type = 'wp_template';
+ $changes->post_status = 'publish';
+ $changes->post_content = '<!-- wp:tests/anchor-block -->Hello<!-- /wp:tests/anchor-block -->';
+ $changes->tax_input = array(
+ 'wp_theme' => get_stylesheet(),
+ );
+
+ inject_ignored_hooked_blocks_metadata_attributes( $changes );
+
+ $args = $action->get_args();
+ $anchor_block_type = end( $args )[2];
+ $context = end( $args )[3];
+
+ $this->assertSame( 'tests/anchor-block', $anchor_block_type );
+
+ $this->assertInstanceOf( 'WP_Block_Template', $context );
+
+ $this->assertSame(
+ $changes->post_type,
+ $context->type,
+ 'The type field of the context passed to the hooked_block_types filter doesn\'t match the template changes.'
+ );
+ $this->assertSame(
+ $changes->post_status,
+ $context->status,
+ 'The status field of the context passed to the hooked_block_types filter doesn\'t match the template changes.'
+ );
+ $this->assertSame(
+ $changes->post_content,
+ $context->content,
+ 'The content field of the context passed to the hooked_block_types filter doesn\'t match the template changes.'
+ );
+ $this->assertFalse(
+ $context->has_theme_file,
+ 'The has_theme_file field of the context passed to the hooked_block_types filter isn\'t set to false.'
+ );
+ }
+
+ /**
+ * @ticket 60754
+ */
+ public function test_hooked_block_types_filter_with_newly_created_template_part() {
+ $action = new MockAction();
+ add_filter( 'hooked_block_types', array( $action, 'filter' ), 10, 4 );
+
+ $changes = new stdClass();
+ $changes->post_type = 'wp_template_part';
+ $changes->post_status = 'publish';
+ $changes->post_content = '<!-- wp:tests/anchor-block -->Hello<!-- /wp:tests/anchor-block -->';
+ $changes->tax_input = array(
+ 'wp_theme' => get_stylesheet(),
+ 'wp_template_part_area' => WP_TEMPLATE_PART_AREA_HEADER,
+ );
+
+ inject_ignored_hooked_blocks_metadata_attributes( $changes );
+
+ $args = $action->get_args();
+ $anchor_block_type = end( $args )[2];
+ $context = end( $args )[3];
+
+ $this->assertSame( 'tests/anchor-block', $anchor_block_type );
+
+ $this->assertInstanceOf( 'WP_Block_Template', $context );
+
+ $this->assertSame(
+ $changes->post_type,
+ $context->type,
+ 'The type field of the context passed to the hooked_block_types filter doesn\'t match the template changes.'
+ );
+ $this->assertSame(
+ $changes->post_status,
+ $context->status,
+ 'The status field of the context passed to the hooked_block_types filter doesn\'t match the template changes.'
+ );
+ $this->assertSame(
+ $changes->post_content,
+ $context->content,
+ 'The content field of the context passed to the hooked_block_types filter doesn\'t match the template changes.'
+ );
+ $this->assertFalse(
+ $context->has_theme_file,
+ 'The has_theme_file field of the context passed to the hooked_block_types filter isn\'t set to false.'
+ );
+ $this->assertSame(
+ $changes->tax_input['wp_template_part_area'],
+ $context->area,
+ 'The area field of the context passed to the hooked_block_types filter doesn\'t match the template changes.'
+ );
+ }
+
+ /**
+ * @ticket 60754
+ */
+ public function test_hooked_block_types_filter_with_existing_template_file() {
+ $action = new MockAction();
+ add_filter( 'hooked_block_types', array( $action, 'filter' ), 10, 4 );
+
+ $changes = new stdClass();
+ $changes->post_name = 'index';
+ $changes->post_type = 'wp_template';
+ $changes->post_status = 'publish';
+ $changes->post_content = '<!-- wp:tests/anchor-block -->Hello<!-- /wp:tests/anchor-block -->';
+ $changes->meta_input = array(
+ 'origin' => 'theme',
+ );
+ $changes->tax_input = array(
+ 'wp_theme' => get_stylesheet(),
+ );
+
+ inject_ignored_hooked_blocks_metadata_attributes( $changes );
+
+ $args = $action->get_args();
+ $anchor_block_type = end( $args )[2];
+ $context = end( $args )[3];
+
+ $this->assertSame( 'tests/anchor-block', $anchor_block_type );
+
+ $this->assertInstanceOf( 'WP_Block_Template', $context );
+
+ $this->assertSame(
+ $changes->post_name,
+ $context->slug,
+ 'The slug field of the context passed to the hooked_block_types filter doesn\'t match the template changes.'
+ );
+ $this->assertSame(
+ $changes->post_type,
+ $context->type,
+ 'The type field of the context passed to the hooked_block_types filter doesn\'t match the template changes.'
+ );
+ $this->assertSame(
+ $changes->post_status,
+ $context->status,
+ 'The status field of the context passed to the hooked_block_types filter doesn\'t match the template changes.'
+ );
+ $this->assertSame(
+ $changes->post_content,
+ $context->content,
+ 'The content field of the context passed to the hooked_block_types filter doesn\'t match the template changes.'
+ );
+ $this->assertTrue(
+ $context->has_theme_file,
+ 'The has_theme_file field of the context passed to the hooked_block_types filter isn\'t set to true.'
+ );
+ $this->assertSame(
+ $changes->meta_input['origin'],
+ $context->origin,
+ 'The origin field of the context passed to the hooked_block_types filter doesn\'t match the template changes.'
+ );
+ }
+
+ /**
+ * @ticket 60754
+ */
+ public function test_hooked_block_types_filter_with_existing_template_part_file() {
+ $action = new MockAction();
+ add_filter( 'hooked_block_types', array( $action, 'filter' ), 10, 4 );
+
+ $changes = new stdClass();
+ $changes->post_name = 'small-header';
+ $changes->post_type = 'wp_template_part';
+ $changes->post_status = 'publish';
+ $changes->post_content = '<!-- wp:tests/anchor-block -->Hello<!-- /wp:tests/anchor-block -->';
+ $changes->meta_input = array(
+ 'origin' => 'theme',
+ );
+ $changes->tax_input = array(
+ 'wp_theme' => get_stylesheet(),
+ 'wp_template_part_area' => WP_TEMPLATE_PART_AREA_HEADER,
+ );
+
+ inject_ignored_hooked_blocks_metadata_attributes( $changes );
+
+ $args = $action->get_args();
+ $anchor_block_type = end( $args )[2];
+ $context = end( $args )[3];
+
+ $this->assertSame( 'tests/anchor-block', $anchor_block_type );
+
+ $this->assertInstanceOf( 'WP_Block_Template', $context );
+
+ $this->assertSame(
+ $changes->post_name,
+ $context->slug,
+ 'The slug field of the context passed to the hooked_block_types filter doesn\'t match the template changes.'
+ );
+ $this->assertSame(
+ $changes->post_type,
+ $context->type,
+ 'The type field of the context passed to the hooked_block_types filter doesn\'t match the template changes.'
+ );
+ $this->assertSame(
+ $changes->post_status,
+ $context->status,
+ 'The status field of the context passed to the hooked_block_types filter doesn\'t match the template changes.'
+ );
+ $this->assertSame(
+ $changes->post_content,
+ $context->content,
+ 'The content field of the context passed to the hooked_block_types filter doesn\'t match the template changes.'
+ );
+ $this->assertTrue(
+ $context->has_theme_file,
+ 'The has_theme_file field of the context passed to the hooked_block_types filter isn\'t set to true.'
+ );
+ $this->assertSame(
+ $changes->meta_input['origin'],
+ $context->origin,
+ 'The origin field of the context passed to the hooked_block_types filter doesn\'t match the template changes.'
+ );
+ $this->assertSame(
+ $changes->tax_input['wp_template_part_area'],
+ $context->area,
+ 'The area field of the context passed to the hooked_block_types filter doesn\'t match the template changes.'
+ );
+ }
+
+ /**
+ * @ticket 60754
+ */
+ public function test_hooked_block_types_filter_with_existing_template_post() {
+ $action = new MockAction();
+ add_filter( 'hooked_block_types', array( $action, 'filter' ), 10, 4 );
+
+ $changes = new stdClass();
+ $changes->post_name = 'my-updated-template';
+ $changes->ID = self::$template_post->ID;
+ $changes->post_content = '<!-- wp:tests/anchor-block -->Hello<!-- /wp:tests/anchor-block -->';
+
+ inject_ignored_hooked_blocks_metadata_attributes( $changes );
+
+ $args = $action->get_args();
+ $anchor_block_type = end( $args )[2];
+ $context = end( $args )[3];
+
+ $this->assertSame( 'tests/anchor-block', $anchor_block_type );
+
+ $this->assertInstanceOf( 'WP_Block_Template', $context );
+
+ $this->assertSame(
+ $changes->post_name,
+ $context->slug,
+ 'The slug field of the context passed to the hooked_block_types filter doesn\'t match the template changes.'
+ );
+ $this->assertSame(
+ $changes->ID,
+ $context->wp_id,
+ 'The wp_id field of the context passed to the hooked_block_types filter doesn\'t match the template changes.'
+ );
+ $this->assertSame(
+ 'publish',
+ $context->status,
+ 'The status field of the context passed to the hooked_block_types filter isn\'t set to publish.'
+ );
+ $this->assertSame(
+ $changes->post_content,
+ $context->content,
+ 'The content field of the context passed to the hooked_block_types filter doesn\'t match the template changes.'
+ );
+
+ $this->assertSame(
+ self::$template_post->post_title,
+ $context->title,
+ 'The title field of the context passed to the hooked_block_types filter doesn\'t match the template post object.'
+ );
+ $this->assertSame(
+ self::$template_post->post_excerpt,
+ $context->description,
+ 'The description field of the context passed to the hooked_block_types filter doesn\'t match the template post object.'
+ );
+ }
+
+ /**
+ * @ticket 60754
+ */
+ public function test_hooked_block_types_filter_with_existing_template_part_post() {
+ $action = new MockAction();
+ add_filter( 'hooked_block_types', array( $action, 'filter' ), 10, 4 );
+
+ $changes = new stdClass();
+ $changes->post_name = 'my-updated-template-part';
+ $changes->ID = self::$template_part_post->ID;
+ $changes->post_content = '<!-- wp:tests/anchor-block -->Hello<!-- /wp:tests/anchor-block -->';
+
+ $changes->tax_input = array(
+ 'wp_template_part_area' => WP_TEMPLATE_PART_AREA_FOOTER,
+ );
+
+ inject_ignored_hooked_blocks_metadata_attributes( $changes );
+
+ $args = $action->get_args();
+ $anchor_block_type = end( $args )[2];
+ $context = end( $args )[3];
+
+ $this->assertSame( 'tests/anchor-block', $anchor_block_type );
+
+ $this->assertInstanceOf( 'WP_Block_Template', $context );
+
+ $this->assertSame(
+ $changes->post_name,
+ $context->slug,
+ 'The slug field of the context passed to the hooked_block_types filter doesn\'t match the template changes.'
+ );
+ $this->assertSame(
+ $changes->ID,
+ $context->wp_id,
+ 'The wp_id field of the context passed to the hooked_block_types filter doesn\'t match the template changes.'
+ );
+ $this->assertSame(
+ 'publish',
+ $context->status,
+ 'The status field of the context passed to the hooked_block_types filter isn\'t set to publish.'
+ );
+ $this->assertSame(
+ $changes->post_content,
+ $context->content,
+ 'The content field of the context passed to the hooked_block_types filter doesn\'t match the template changes.'
+ );
+ $this->assertSame(
+ $changes->tax_input['wp_template_part_area'],
+ $context->area,
+ 'The area field of the context passed to the hooked_block_types filter doesn\'t match the template changes.'
+ );
+
+ $this->assertSame(
+ self::$template_part_post->post_title,
+ $context->title,
+ 'The title field of the context passed to the hooked_block_types filter doesn\'t match the template post object.'
+ );
+ $this->assertSame(
+ self::$template_part_post->post_excerpt,
+ $context->description,
+ 'The description field of the context passed to the hooked_block_types filter doesn\'t match the template post object.'
+ );
+ }
+
+ /**
+ * @ticket 60671
+ */
+ public function test_inject_ignored_hooked_blocks_metadata_attributes_into_template() {
+ register_block_type(
+ 'tests/hooked-block',
+ array(
+ 'block_hooks' => array(
+ 'tests/anchor-block' => 'after',
+ ),
+ )
+ );
+
+ $id = self::TEST_THEME . '//' . 'my_template';
+ $template = get_block_template( $id, 'wp_template' );
+
+ $changes = new stdClass();
+ $changes->ID = $template->wp_id;
+ $changes->post_content = '<!-- wp:tests/anchor-block -->Hello<!-- /wp:tests/anchor-block -->';
+
+ $post = inject_ignored_hooked_blocks_metadata_attributes( $changes );
+ $this->assertSame(
+ '<!-- wp:tests/anchor-block {"metadata":{"ignoredHookedBlocks":["tests/hooked-block"]}} -->Hello<!-- /wp:tests/anchor-block -->',
+ $post->post_content,
+ 'The hooked block was not injected into the anchor block\'s ignoredHookedBlocks metadata.'
+ );
+ }
+
+ /**
+ * @ticket 60671
+ */
+ public function test_inject_ignored_hooked_blocks_metadata_attributes_into_template_part() {
+ register_block_type(
+ 'tests/hooked-block',
+ array(
+ 'block_hooks' => array(
+ 'tests/anchor-block' => 'after',
+ ),
+ )
+ );
+
+ $id = self::TEST_THEME . '//' . 'my_template_part';
+ $template = get_block_template( $id, 'wp_template_part' );
+
+ $changes = new stdClass();
+ $changes->ID = $template->wp_id;
+ $changes->post_content = '<!-- wp:tests/anchor-block -->Hello<!-- /wp:tests/anchor-block -->';
+
+ $post = inject_ignored_hooked_blocks_metadata_attributes( $changes );
+ $this->assertSame(
+ '<!-- wp:tests/anchor-block {"metadata":{"ignoredHookedBlocks":["tests/hooked-block"]}} -->Hello<!-- /wp:tests/anchor-block -->',
+ $post->post_content,
+ 'The hooked block was not injected into the anchor block\'s ignoredHookedBlocks metadata.'
+ );
+ }
+}
</ins></span></pre></div>
<a id="branches65testsphpunittestsrestapiwpRestTemplatesControllerphp"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: branches/6.5/tests/phpunit/tests/rest-api/wpRestTemplatesController.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- branches/6.5/tests/phpunit/tests/rest-api/wpRestTemplatesController.php 2024-04-24 07:43:02 UTC (rev 58040)
+++ branches/6.5/tests/phpunit/tests/rest-api/wpRestTemplatesController.php 2024-04-24 12:00:29 UTC (rev 58041)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -14,7 +14,8 @@
</span><span class="cx" style="display: block; padding: 0 10px"> * @var int
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><span class="cx" style="display: block; padding: 0 10px"> protected static $admin_id;
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- private static $post;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ private static $template_post;
+ private static $template_part_post;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> /**
</span><span class="cx" style="display: block; padding: 0 10px"> * Create fake data before our tests run.
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -29,7 +30,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> );
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> // Set up template post.
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- $args = array(
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $args = array(
</ins><span class="cx" style="display: block; padding: 0 10px"> 'post_type' => 'wp_template',
</span><span class="cx" style="display: block; padding: 0 10px"> 'post_name' => 'my_template',
</span><span class="cx" style="display: block; padding: 0 10px"> 'post_title' => 'My Template',
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -41,12 +42,32 @@
</span><span class="cx" style="display: block; padding: 0 10px"> ),
</span><span class="cx" style="display: block; padding: 0 10px"> ),
</span><span class="cx" style="display: block; padding: 0 10px"> );
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self::$post = self::factory()->post->create_and_get( $args );
- wp_set_post_terms( self::$post->ID, get_stylesheet(), 'wp_theme' );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ self::$template_post = self::factory()->post->create_and_get( $args );
+ wp_set_post_terms( self::$template_post->ID, get_stylesheet(), 'wp_theme' );
+
+ // Set up template part post.
+ $args = array(
+ 'post_type' => 'wp_template_part',
+ 'post_name' => 'my_template_part',
+ 'post_title' => 'My Template Part',
+ 'post_content' => 'Content',
+ 'post_excerpt' => 'Description of my template part.',
+ 'tax_input' => array(
+ 'wp_theme' => array(
+ get_stylesheet(),
+ ),
+ 'wp_template_part_area' => array(
+ WP_TEMPLATE_PART_AREA_HEADER,
+ ),
+ ),
+ );
+ self::$template_part_post = self::factory()->post->create_and_get( $args );
+ wp_set_post_terms( self::$template_part_post->ID, get_stylesheet(), 'wp_theme' );
+ wp_set_post_terms( self::$template_part_post->ID, WP_TEMPLATE_PART_AREA_HEADER, 'wp_template_part_area' );
</ins><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> public static function wpTearDownAfterClass() {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- wp_delete_post( self::$post->ID );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ wp_delete_post( self::$template_post->ID );
</ins><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> /**
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -56,7 +77,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><span class="cx" style="display: block; padding: 0 10px"> public function tear_down() {
</span><span class="cx" style="display: block; padding: 0 10px"> if ( has_filter( 'rest_pre_insert_wp_template_part', 'inject_ignored_hooked_blocks_metadata_attributes' ) ) {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- remove_filter( 'rest_pre_insert_wp_template_part', 'inject_ignored_hooked_blocks_metadata_attributes', 10 );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ remove_filter( 'rest_pre_insert_wp_template_part', 'inject_ignored_hooked_blocks_metadata_attributes' );
</ins><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px"> if ( WP_Block_Type_Registry::get_instance()->is_registered( 'tests/block' ) ) {
</span><span class="cx" style="display: block; padding: 0 10px"> unregister_block_type( 'tests/hooked-block' );
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -130,11 +151,11 @@
</span><span class="cx" style="display: block; padding: 0 10px"> 'rendered' => 'My Template',
</span><span class="cx" style="display: block; padding: 0 10px"> ),
</span><span class="cx" style="display: block; padding: 0 10px"> 'status' => 'publish',
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- 'wp_id' => self::$post->ID,
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ 'wp_id' => self::$template_post->ID,
</ins><span class="cx" style="display: block; padding: 0 10px"> 'has_theme_file' => false,
</span><span class="cx" style="display: block; padding: 0 10px"> 'is_custom' => true,
</span><span class="cx" style="display: block; padding: 0 10px"> 'author' => 0,
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- 'modified' => mysql_to_rfc3339( self::$post->post_modified ),
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ 'modified' => mysql_to_rfc3339( self::$template_post->post_modified ),
</ins><span class="cx" style="display: block; padding: 0 10px"> 'author_text' => 'Test Blog',
</span><span class="cx" style="display: block; padding: 0 10px"> 'original_source' => 'site',
</span><span class="cx" style="display: block; padding: 0 10px"> ),
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -177,11 +198,11 @@
</span><span class="cx" style="display: block; padding: 0 10px"> 'rendered' => 'My Template',
</span><span class="cx" style="display: block; padding: 0 10px"> ),
</span><span class="cx" style="display: block; padding: 0 10px"> 'status' => 'publish',
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- 'wp_id' => self::$post->ID,
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ 'wp_id' => self::$template_post->ID,
</ins><span class="cx" style="display: block; padding: 0 10px"> 'has_theme_file' => false,
</span><span class="cx" style="display: block; padding: 0 10px"> 'is_custom' => true,
</span><span class="cx" style="display: block; padding: 0 10px"> 'author' => 0,
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- 'modified' => mysql_to_rfc3339( self::$post->post_modified ),
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ 'modified' => mysql_to_rfc3339( self::$template_post->post_modified ),
</ins><span class="cx" style="display: block; padding: 0 10px"> 'author_text' => 'Test Blog',
</span><span class="cx" style="display: block; padding: 0 10px"> 'original_source' => 'site',
</span><span class="cx" style="display: block; padding: 0 10px"> ),
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -216,11 +237,11 @@
</span><span class="cx" style="display: block; padding: 0 10px"> 'rendered' => 'My Template',
</span><span class="cx" style="display: block; padding: 0 10px"> ),
</span><span class="cx" style="display: block; padding: 0 10px"> 'status' => 'publish',
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- 'wp_id' => self::$post->ID,
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ 'wp_id' => self::$template_post->ID,
</ins><span class="cx" style="display: block; padding: 0 10px"> 'has_theme_file' => false,
</span><span class="cx" style="display: block; padding: 0 10px"> 'is_custom' => true,
</span><span class="cx" style="display: block; padding: 0 10px"> 'author' => 0,
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- 'modified' => mysql_to_rfc3339( self::$post->post_modified ),
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ 'modified' => mysql_to_rfc3339( self::$template_post->post_modified ),
</ins><span class="cx" style="display: block; padding: 0 10px"> 'author_text' => 'Test Blog',
</span><span class="cx" style="display: block; padding: 0 10px"> 'original_source' => 'site',
</span><span class="cx" style="display: block; padding: 0 10px"> ),
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -944,7 +965,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> )
</span><span class="cx" style="display: block; padding: 0 10px"> );
</span><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- add_filter( 'rest_pre_insert_wp_template_part', 'inject_ignored_hooked_blocks_metadata_attributes', 10, 2 );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ add_filter( 'rest_pre_insert_wp_template_part', 'inject_ignored_hooked_blocks_metadata_attributes' );
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> $endpoint = new WP_REST_Templates_Controller( 'wp_template_part' );
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -951,9 +972,10 @@
</span><span class="cx" style="display: block; padding: 0 10px"> $prepare_item_for_database = new ReflectionMethod( $endpoint, 'prepare_item_for_database' );
</span><span class="cx" style="display: block; padding: 0 10px"> $prepare_item_for_database->setAccessible( true );
</span><span class="cx" style="display: block; padding: 0 10px">
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $id = get_stylesheet() . '//' . 'my_template_part';
</ins><span class="cx" style="display: block; padding: 0 10px"> $body_params = array(
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- 'title' => 'Untitled Template Part',
- 'slug' => 'untitled-template-part',
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ 'id' => $id,
+ 'slug' => 'my_template_part',
</ins><span class="cx" style="display: block; padding: 0 10px"> 'content' => '<!-- wp:tests/anchor-block -->Hello<!-- /wp:tests/anchor-block -->',
</span><span class="cx" style="display: block; padding: 0 10px"> );
</span><span class="cx" style="display: block; padding: 0 10px">
</span></span></pre>
</div>
</div>
</body>
</html>