<!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>[54269] trunk: Editor: Adds template types, `is_wp_suggestion`, and fallback template content.</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/54269">54269</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/54269","name":"Review Commit"}}</script></dd>
<dt style="float: left; width: 6em; font-weight: bold">Author</dt> <dd>hellofromTonya</dd>
<dt style="float: left; width: 6em; font-weight: bold">Date</dt> <dd>2022-09-20 21:19:10 +0000 (Tue, 20 Sep 2022)</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'>Editor: Adds template types, `is_wp_suggestion`, and fallback template content.
This commit improves site editor templates by:
* Adds a post meta `is_wp_suggestion` to templates created from the site editor.
Why? To differentiate the templates created from the post editor in the Template panel in inspector controls and the templates suggested in site editor.
See [https://github.com/WordPress/gutenberg/pull/41387 Gutenberg PR 41387] for more details.
* Expands the template types that can be added to the site editor to include single custom post type and specific posts templates.
See [https://github.com/WordPress/gutenberg/pull/41189 Gutenberg PR 41189] for more details.
* Adds fallback template content on creation in site editor:
* Introduces `get_template_hierarchy()` to get the template hierarchy for a given template slug to be created.
* Adds a `lookup` route to `WP_REST_Templates_Controller` to get the fallback template content.
See [https://github.com/WordPress/gutenberg/pull/42520 Gutenberg PR 42520] for more details.
* Fixes a typo in default category template's description within `get_default_block_template_types()`.
See [https://github.com/WordPress/gutenberg/pull/42586 Gutenberg PR 42586] for more details.
* Changes field checks from `in_array()` to `rest_is_field_included()` in `WP_REST_Post_Types_Controller`.
* Adds an `icon` field to `WP_REST_Post_Types_Controller`
Follow-up to <a href="https://core.trac.wordpress.org/changeset/53129">[53129]</a>, <a href="https://core.trac.wordpress.org/changeset/52331">[52331]</a>, <a href="https://core.trac.wordpress.org/changeset/52275">[52275]</a>, <a href="https://core.trac.wordpress.org/changeset/52062">[52062]</a>, <a href="https://core.trac.wordpress.org/changeset/51962">[51962]</a>, <a href="https://core.trac.wordpress.org/changeset/43087">[43087]</a>.
Props ntsekouras, spacedmonkey, mamaduka, mburridge, jameskoster, bernhard-reiter, mcsf, hellofromTonya.
See <a href="https://core.trac.wordpress.org/ticket/56467">#56467</a>.</pre>
<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkphpcsxmldist">trunk/phpcs.xml.dist</a></li>
<li><a href="#trunksrcwpincludesblocktemplateutilsphp">trunk/src/wp-includes/block-template-utils.php</a></li>
<li><a href="#trunksrcwpincludesrestapiendpointsclasswprestposttypescontrollerphp">trunk/src/wp-includes/rest-api/endpoints/class-wp-rest-post-types-controller.php</a></li>
<li><a href="#trunksrcwpincludesrestapiendpointsclasswpresttemplatescontrollerphp">trunk/src/wp-includes/rest-api/endpoints/class-wp-rest-templates-controller.php</a></li>
<li><a href="#trunktestsphpunittestsrestapirestposttypescontrollerphp">trunk/tests/phpunit/tests/rest-api/rest-post-types-controller.php</a></li>
<li><a href="#trunktestsphpunittestsrestapirestschemasetupphp">trunk/tests/phpunit/tests/rest-api/rest-schema-setup.php</a></li>
<li><a href="#trunktestsphpunittestsrestapiwpRestTemplatesControllerphp">trunk/tests/phpunit/tests/rest-api/wpRestTemplatesController.php</a></li>
<li><a href="#trunktestsqunitfixtureswpapigeneratedjs">trunk/tests/qunit/fixtures/wp-api-generated.js</a></li>
</ul>
<h3>Added Paths</h3>
<ul>
<li>trunk/tests/phpunit/tests/block-templates/</li>
<li><a href="#trunktestsphpunittestsblocktemplatesbasephp">trunk/tests/phpunit/tests/block-templates/base.php</a></li>
<li><a href="#trunktestsphpunittestsblocktemplatesgetTemplateHierarchyphp">trunk/tests/phpunit/tests/block-templates/getTemplateHierarchy.php</a></li>
</ul>
</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkphpcsxmldist"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/phpcs.xml.dist</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/phpcs.xml.dist 2022-09-20 21:12:39 UTC (rev 54268)
+++ trunk/phpcs.xml.dist 2022-09-20 21:19:10 UTC (rev 54269)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -237,6 +237,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> <!-- Test case parent classes outside of the "includes" folder. -->
</span><span class="cx" style="display: block; padding: 0 10px"> <element value="Tests_Query_Conditionals"/>
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ <element value="WP_Block_Templates_UnitTestCase"/>
</ins><span class="cx" style="display: block; padding: 0 10px"> <element value="WP_Filesystem_UnitTestCase"/>
</span><span class="cx" style="display: block; padding: 0 10px"> <element value="WP_HTTP_UnitTestCase"/>
</span><span class="cx" style="display: block; padding: 0 10px"> <element value="WP_Image_UnitTestCase"/>
</span></span></pre></div>
<a id="trunksrcwpincludesblocktemplateutilsphp"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/src/wp-includes/block-template-utils.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/src/wp-includes/block-template-utils.php 2022-09-20 21:12:39 UTC (rev 54268)
+++ trunk/src/wp-includes/block-template-utils.php 2022-09-20 21:19:10 UTC (rev 54269)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -147,7 +147,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> ),
</span><span class="cx" style="display: block; padding: 0 10px"> 'category' => array(
</span><span class="cx" style="display: block; padding: 0 10px"> 'title' => _x( 'Category', 'Template name' ),
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- 'description' => __( 'Displays latest posts in single post category.' ),
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ 'description' => __( 'Displays latest posts from a single post category.' ),
</ins><span class="cx" style="display: block; padding: 0 10px"> ),
</span><span class="cx" style="display: block; padding: 0 10px"> 'taxonomy' => array(
</span><span class="cx" style="display: block; padding: 0 10px"> 'title' => _x( 'Taxonomy', 'Template name' ),
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -555,7 +555,8 @@
</span><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 = wp_get_theme()->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( $post->ID, 'origin', true );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $origin = get_post_meta( $post->ID, 'origin', true );
+ $is_wp_suggestion = get_post_meta( $post->ID, 'is_wp_suggestion', true );
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><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><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -570,7 +571,7 @@
</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 = true;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $template->is_custom = empty( $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">
</span><span class="cx" style="display: block; padding: 0 10px"> if ( 'wp_template' === $post->post_type && $has_theme_file && isset( $template_file['postTypes'] ) ) {
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -679,7 +680,8 @@
</span><span class="cx" style="display: block; padding: 0 10px"> continue;
</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 ( $post_type &&
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (
+ $post_type &&
</ins><span class="cx" style="display: block; padding: 0 10px"> isset( $template->post_types ) &&
</span><span class="cx" style="display: block; padding: 0 10px"> ! in_array( $post_type, $template->post_types, true )
</span><span class="cx" style="display: block; padding: 0 10px"> ) {
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -912,9 +914,10 @@
</span><span class="cx" style="display: block; padding: 0 10px"> * @return Bool Whether this file is in an ignored directory.
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><span class="cx" style="display: block; padding: 0 10px"> function wp_is_theme_directory_ignored( $path ) {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- $directories_to_ignore = array( '.svn', '.git', '.hg', '.bzr', 'node_modules', 'vendor' );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $directories_to_ignore = array( '.DS_Store', '.svn', '.git', '.hg', '.bzr', 'node_modules', 'vendor' );
+
</ins><span class="cx" style="display: block; padding: 0 10px"> foreach ( $directories_to_ignore as $directory ) {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if ( strpos( $path, $directory ) === 0 ) {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if ( str_starts_with( $path, $directory ) ) {
</ins><span class="cx" style="display: block; padding: 0 10px"> return true;
</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">@@ -1023,3 +1026,74 @@
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> return $filename;
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+
+/**
+ * Gets the template hierarchy for the given template slug to be created.
+ *
+ *
+ * Note: Always add `index` as the last fallback template.
+ *
+ * @since 6.1.0
+ *
+ * @param string $slug The template slug to be created.
+ * @param boolean $is_custom Optional. Indicates if a template is custom or
+ * part of the template hierarchy. Default false.
+ * @param string $template_prefix Optional. The template prefix for the created template.
+ * Used to extract the main template type, e.g.
+ * in `taxonomy-books` the `taxonomy` is extracted.
+ * Default empty string.
+ * @return string[] The template hierarchy.
+ */
+function get_template_hierarchy( $slug, $is_custom = false, $template_prefix = '' ) {
+ if ( 'index' === $slug ) {
+ return array( 'index' );
+ }
+ if ( $is_custom ) {
+ return array( 'page', 'singular', 'index' );
+ }
+ if ( 'front-page' === $slug ) {
+ return array( 'front-page', 'home', 'index' );
+ }
+
+ $template_hierarchy = array( $slug );
+
+ // Most default templates don't have `$template_prefix` assigned.
+ if ( $template_prefix ) {
+ list( $type ) = explode( '-', $template_prefix );
+ // These checks are needed because the `$slug` above is always added.
+ if ( ! in_array( $template_prefix, array( $slug, $type ), true ) ) {
+ $template_hierarchy[] = $template_prefix;
+ }
+ if ( $slug !== $type ) {
+ $template_hierarchy[] = $type;
+ }
+ }
+
+ // Handle `archive` template.
+ if (
+ str_starts_with( $slug, 'author' ) ||
+ str_starts_with( $slug, 'taxonomy' ) ||
+ str_starts_with( $slug, 'category' ) ||
+ str_starts_with( $slug, 'tag' ) ||
+ 'date' === $slug
+ ) {
+ $template_hierarchy[] = 'archive';
+ }
+ // Handle `single` template.
+ if ( 'attachment' === $slug ) {
+ $template_hierarchy[] = 'single';
+ }
+
+ // Handle `singular` template.
+ if (
+ str_starts_with( $slug, 'single' ) ||
+ str_starts_with( $slug, 'page' ) ||
+ 'attachment' === $slug
+ ) {
+ $template_hierarchy[] = 'singular';
+ }
+
+ $template_hierarchy[] = 'index';
+
+ return $template_hierarchy;
+};
</ins></span></pre></div>
<a id="trunksrcwpincludesrestapiendpointsclasswprestposttypescontrollerphp"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/src/wp-includes/rest-api/endpoints/class-wp-rest-post-types-controller.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/src/wp-includes/rest-api/endpoints/class-wp-rest-post-types-controller.php 2022-09-20 21:12:39 UTC (rev 54268)
+++ trunk/src/wp-includes/rest-api/endpoints/class-wp-rest-post-types-controller.php 2022-09-20 21:19:10 UTC (rev 54269)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -186,19 +186,19 @@
</span><span class="cx" style="display: block; padding: 0 10px"> $fields = $this->get_fields_for_response( $request );
</span><span class="cx" style="display: block; padding: 0 10px"> $data = array();
</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 ( in_array( 'capabilities', $fields, true ) ) {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if ( rest_is_field_included( 'capabilities', $fields ) ) {
</ins><span class="cx" style="display: block; padding: 0 10px"> $data['capabilities'] = $post_type->cap;
</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 ( in_array( 'description', $fields, true ) ) {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if ( rest_is_field_included( 'description', $fields ) ) {
</ins><span class="cx" style="display: block; padding: 0 10px"> $data['description'] = $post_type->description;
</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 ( in_array( 'hierarchical', $fields, true ) ) {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if ( rest_is_field_included( 'hierarchical', $fields ) ) {
</ins><span class="cx" style="display: block; padding: 0 10px"> $data['hierarchical'] = $post_type->hierarchical;
</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 ( in_array( 'visibility', $fields, true ) ) {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if ( rest_is_field_included( 'visibility', $fields ) ) {
</ins><span class="cx" style="display: block; padding: 0 10px"> $data['visibility'] = array(
</span><span class="cx" style="display: block; padding: 0 10px"> 'show_in_nav_menus' => (bool) $post_type->show_in_nav_menus,
</span><span class="cx" style="display: block; padding: 0 10px"> 'show_ui' => (bool) $post_type->show_ui,
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -205,35 +205,39 @@
</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">- if ( in_array( 'viewable', $fields, true ) ) {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if ( rest_is_field_included( 'viewable', $fields ) ) {
</ins><span class="cx" style="display: block; padding: 0 10px"> $data['viewable'] = is_post_type_viewable( $post_type );
</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 ( in_array( 'labels', $fields, true ) ) {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if ( rest_is_field_included( 'labels', $fields ) ) {
</ins><span class="cx" style="display: block; padding: 0 10px"> $data['labels'] = $post_type->labels;
</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 ( in_array( 'name', $fields, true ) ) {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if ( rest_is_field_included( 'name', $fields ) ) {
</ins><span class="cx" style="display: block; padding: 0 10px"> $data['name'] = $post_type->label;
</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 ( in_array( 'slug', $fields, true ) ) {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if ( rest_is_field_included( 'slug', $fields ) ) {
</ins><span class="cx" style="display: block; padding: 0 10px"> $data['slug'] = $post_type->name;
</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 ( in_array( 'supports', $fields, true ) ) {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if ( rest_is_field_included( 'icon', $fields ) ) {
+ $data['icon'] = $post_type->menu_icon;
+ }
+
+ if ( rest_is_field_included( 'supports', $fields ) ) {
</ins><span class="cx" style="display: block; padding: 0 10px"> $data['supports'] = $supports;
</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 ( in_array( 'taxonomies', $fields, true ) ) {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if ( rest_is_field_included( 'taxonomies', $fields ) ) {
</ins><span class="cx" style="display: block; padding: 0 10px"> $data['taxonomies'] = array_values( $taxonomies );
</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 ( in_array( 'rest_base', $fields, true ) ) {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if ( rest_is_field_included( 'rest_base', $fields ) ) {
</ins><span class="cx" style="display: block; padding: 0 10px"> $data['rest_base'] = $base;
</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 ( in_array( 'rest_namespace', $fields, true ) ) {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if ( rest_is_field_included( 'rest_namespace', $fields ) ) {
</ins><span class="cx" style="display: block; padding: 0 10px"> $data['rest_namespace'] = $namespace;
</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">@@ -287,6 +291,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> * @since 4.7.0
</span><span class="cx" style="display: block; padding: 0 10px"> * @since 4.8.0 The `supports` property was added.
</span><span class="cx" style="display: block; padding: 0 10px"> * @since 5.9.0 The `visibility` and `rest_namespace` properties were added.
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * @since 6.1.0 The `icon` property was added.
</ins><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * @return array Item schema data.
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -385,6 +390,12 @@
</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><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ 'icon' => array(
+ 'description' => __( 'The icon for the post type.' ),
+ 'type' => array( 'string', 'null' ),
+ 'context' => array( 'view', 'edit', 'embed' ),
+ 'readonly' => true,
+ ),
</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></pre></div>
<a id="trunksrcwpincludesrestapiendpointsclasswpresttemplatescontrollerphp"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/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">--- trunk/src/wp-includes/rest-api/endpoints/class-wp-rest-templates-controller.php 2022-09-20 21:12:39 UTC (rev 54268)
+++ trunk/src/wp-includes/rest-api/endpoints/class-wp-rest-templates-controller.php 2022-09-20 21:19:10 UTC (rev 54269)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -42,6 +42,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> * Registers the controllers routes.
</span><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * @since 5.8.0
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * @since 6.1.0 Endpoint for fallback template content.
</ins><span class="cx" style="display: block; padding: 0 10px"> */
</span><span class="cx" style="display: block; padding: 0 10px"> public function register_routes() {
</span><span class="cx" style="display: block; padding: 0 10px"> // Lists all templates.
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -65,6 +66,34 @@
</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><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Get fallback template content.
+ register_rest_route(
+ $this->namespace,
+ '/' . $this->rest_base . '/lookup',
+ array(
+ array(
+ 'methods' => WP_REST_Server::READABLE,
+ 'callback' => array( $this, 'get_template_fallback' ),
+ 'permission_callback' => array( $this, 'get_item_permissions_check' ),
+ 'args' => array(
+ 'slug' => array(
+ 'description' => __( 'The slug of the template to get the fallback for' ),
+ 'type' => 'string',
+ 'required' => true,
+ ),
+ 'is_custom' => array(
+ 'description' => __( ' Indicates if a template is custom or part of the template hierarchy' ),
+ 'type' => 'boolean',
+ ),
+ 'template_prefix' => array(
+ 'description' => __( 'The template prefix for the created template. This is used to extract the main template type, e.g. in `taxonomy-books` extracts the `taxonomy`' ),
+ 'type' => 'string',
+ ),
+ ),
+ ),
+ )
+ );
+
</ins><span class="cx" style="display: block; padding: 0 10px"> // Lists/updates a single template based on the given id.
</span><span class="cx" style="display: block; padding: 0 10px"> register_rest_route(
</span><span class="cx" style="display: block; padding: 0 10px"> $this->namespace,
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -118,6 +147,21 @@
</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><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * Returns the fallback template for the given slug.
+ *
+ * @since 6.1.0
+ *
+ * @param WP_REST_Request $request The request instance.
+ * @return WP_REST_Response|WP_Error
+ */
+ public function get_template_fallback( $request ) {
+ $hierarchy = get_template_hierarchy( $request['slug'], $request['is_custom'], $request['template_prefix'] );
+ $fallback_template = resolve_block_template( $request['slug'], $hierarchy, '' );
+ $response = $this->prepare_item_for_response( $fallback_template, $request );
+ return rest_ensure_response( $response );
+ }
+
+ /**
</ins><span class="cx" style="display: block; padding: 0 10px"> * Checks if the user has permissions to make the request.
</span><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * @since 5.8.0
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -525,6 +569,15 @@
</span><span class="cx" style="display: block; padding: 0 10px"> $changes->post_excerpt = $template->description;
</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' === $this->post_type && isset( $request['is_wp_suggestion'] ) ) {
+ $changes->meta_input = wp_parse_args(
+ array(
+ 'is_wp_suggestion' => $request['is_wp_suggestion'],
+ ),
+ $changes->meta_input = array()
+ );
+ }
+
</ins><span class="cx" style="display: block; padding: 0 10px"> if ( 'wp_template_part' === $this->post_type ) {
</span><span class="cx" style="display: block; padding: 0 10px"> if ( isset( $request['area'] ) ) {
</span><span class="cx" style="display: block; padding: 0 10px"> $changes->tax_input['wp_template_part_area'] = _filter_block_template_part_area( $request['area'] );
</span></span></pre></div>
<a id="trunktestsphpunittestsblocktemplatesbasephp"></a>
<div class="addfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Added: trunk/tests/phpunit/tests/block-templates/base.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/tests/phpunit/tests/block-templates/base.php (rev 0)
+++ trunk/tests/phpunit/tests/block-templates/base.php 2022-09-20 21:19:10 UTC (rev 54269)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -0,0 +1,86 @@
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+<?php
+
+/**
+ * @group block-templates
+ * @covers ::get_template_hierarchy
+ */
+abstract class WP_Block_Templates_UnitTestCase extends WP_UnitTestCase {
+ const TEST_THEME = 'block-theme';
+
+ protected static $template_post;
+ protected static $template_part_post;
+
+ public static function wpSetUpBeforeClass( WP_UnitTest_Factory $factory ) {
+ /*
+ * Set up a template post corresponding to a different theme.
+ * Do this to ensure resolution and slug creation works as expected,
+ * even with another post of that same name present for another theme.
+ */
+ self::$template_post = $factory->post->create_and_get(
+ array(
+ 'post_type' => 'wp_template',
+ 'post_name' => 'my_template',
+ 'post_title' => 'My Template',
+ 'post_content' => 'Content',
+ 'post_excerpt' => 'Description of my template',
+ 'tax_input' => array(
+ 'wp_theme' => array(
+ 'this-theme-should-not-resolve',
+ ),
+ ),
+ )
+ );
+
+ wp_set_post_terms( self::$template_post->ID, 'this-theme-should-not-resolve', 'wp_theme' );
+
+ // Set up template post.
+ self::$template_post = $factory->post->create_and_get(
+ array(
+ 'post_type' => 'wp_template',
+ 'post_name' => 'my_template',
+ 'post_title' => 'My Template',
+ 'post_content' => 'Content',
+ 'post_excerpt' => 'Description of my template',
+ 'tax_input' => array(
+ 'wp_theme' => array(
+ self::TEST_THEME,
+ ),
+ ),
+ )
+ );
+
+ wp_set_post_terms( self::$template_post->ID, self::TEST_THEME, 'wp_theme' );
+
+ // Set up template part post.
+ self::$template_part_post = $factory->post->create_and_get(
+ 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(
+ self::TEST_THEME,
+ ),
+ 'wp_template_part_area' => array(
+ WP_TEMPLATE_PART_AREA_HEADER,
+ ),
+ ),
+ )
+ );
+
+ wp_set_post_terms( self::$template_part_post->ID, WP_TEMPLATE_PART_AREA_HEADER, 'wp_template_part_area' );
+ wp_set_post_terms( self::$template_part_post->ID, self::TEST_THEME, 'wp_theme' );
+ }
+
+ public static function wpTearDownAfterClass() {
+ wp_delete_post( self::$template_post->ID );
+ wp_delete_post( self::$template_part_post->ID );
+ }
+
+ public function set_up() {
+ parent::set_up();
+ switch_theme( self::TEST_THEME );
+ }
+}
</ins><span class="cx" style="display: block; padding: 0 10px">Property changes on: trunk/tests/phpunit/tests/block-templates/base.php
</span><span class="cx" style="display: block; padding: 0 10px">___________________________________________________________________
</span></span></pre></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Added: svn:eol-style</h4></div>
<ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+native
</ins><span class="cx" style="display: block; padding: 0 10px">\ No newline at end of property
</span><a id="trunktestsphpunittestsblocktemplatesgetTemplateHierarchyphp"></a>
<div class="addfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Added: trunk/tests/phpunit/tests/block-templates/getTemplateHierarchy.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/tests/phpunit/tests/block-templates/getTemplateHierarchy.php (rev 0)
+++ trunk/tests/phpunit/tests/block-templates/getTemplateHierarchy.php 2022-09-20 21:19:10 UTC (rev 54269)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -0,0 +1,124 @@
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+<?php
+
+require_once __DIR__ . '/base.php';
+
+/**
+ * @group block-templates
+ * @covers ::get_template_hierarchy
+ */
+class Tests_Block_Templates_GetTemplate_Hierarchy extends WP_Block_Templates_UnitTestCase {
+
+ /**
+ * @dataProvider data_get_template_hierarchy
+ *
+ * @ticket 56467
+ *
+ * @param array $args Test arguments.
+ * @param array $expected Expected results.
+ */
+ public function test_get_template_hierarchy( array $args, array $expected ) {
+ $this->assertSame( $expected, get_template_hierarchy( ...$args ) );
+ }
+
+ /**
+ * Data provider.
+ *
+ * @return array
+ */
+ public function data_get_template_hierarchy() {
+ return array(
+ 'front-page' => array(
+ 'args' => array( 'front-page' ),
+ 'expected' => array( 'front-page', 'home', 'index' ),
+ ),
+ 'custom template' => array(
+ 'args' => array( 'whatever-slug', true ),
+ 'expected' => array( 'page', 'singular', 'index' ),
+ ),
+ 'page' => array(
+ 'args' => array( 'page' ),
+ 'expected' => array( 'page', 'singular', 'index' ),
+ ),
+ 'tag' => array(
+ 'args' => array( 'tag' ),
+ 'expected' => array( 'tag', 'archive', 'index' ),
+ ),
+ 'author' => array(
+ 'args' => array( 'author' ),
+ 'expected' => array( 'author', 'archive', 'index' ),
+ ),
+ 'date' => array(
+ 'args' => array( 'date' ),
+ 'expected' => array( 'date', 'archive', 'index' ),
+ ),
+ 'taxonomy' => array(
+ 'args' => array( 'taxonomy' ),
+ 'expected' => array( 'taxonomy', 'archive', 'index' ),
+ ),
+ 'attachment' => array(
+ 'args' => array( 'attachment' ),
+ 'expected' => array( 'attachment', 'single', 'singular', 'index' ),
+ ),
+ 'singular' => array(
+ 'args' => array( 'singular' ),
+ 'expected' => array( 'singular', 'index' ),
+ ),
+ 'single' => array(
+ 'args' => array( 'single' ),
+ 'expected' => array( 'single', 'singular', 'index' ),
+ ),
+ 'archive' => array(
+ 'args' => array( 'archive' ),
+ 'expected' => array( 'archive', 'index' ),
+ ),
+ 'index' => array(
+ 'args' => array( 'index' ),
+ 'expected' => array( 'index' ),
+ ),
+ 'specific taxonomies' => array(
+ 'args' => array( 'taxonomy-books', false, 'taxonomy-books' ),
+ 'expected' => array( 'taxonomy-books', 'taxonomy', 'archive', 'index' ),
+ ),
+ 'single word categories' => array(
+ 'args' => array( 'category-fruits', false, 'category' ),
+ 'expected' => array( 'category-fruits', 'category', 'archive', 'index' ),
+ ),
+ 'multi word categories' => array(
+ 'args' => array( 'category-fruits-yellow', false, 'category' ),
+ 'expected' => array( 'category-fruits-yellow', 'category', 'archive', 'index' ),
+ ),
+ 'single word taxonomy and term' => array(
+ 'args' => array( 'taxonomy-books-action', false, 'taxonomy-books' ),
+ 'expected' => array( 'taxonomy-books-action', 'taxonomy-books', 'taxonomy', 'archive', 'index' ),
+ ),
+ 'single word taxonomy and multi word term' => array(
+ 'args' => array( 'taxonomy-books-action-adventure', false, 'taxonomy-books' ),
+ 'expected' => array( 'taxonomy-books-action-adventure', 'taxonomy-books', 'taxonomy', 'archive', 'index' ),
+ ),
+ 'multi word taxonomy and term' => array(
+ 'args' => array( 'taxonomy-greek-books-action-adventure', false, 'taxonomy-greek-books' ),
+ 'expected' => array( 'taxonomy-greek-books-action-adventure', 'taxonomy-greek-books', 'taxonomy', 'archive', 'index' ),
+ ),
+ 'single word post type' => array(
+ 'args' => array( 'single-book', false, 'single-book' ),
+ 'expected' => array( 'single-book', 'single', 'singular', 'index' ),
+ ),
+ 'multi word post type' => array(
+ 'args' => array( 'single-art-project', false, 'single-art-project' ),
+ 'expected' => array( 'single-art-project', 'single', 'singular', 'index' ),
+ ),
+ 'single post with multi word post type' => array(
+ 'args' => array( 'single-art-project-imagine', false, 'single-art-project' ),
+ 'expected' => array( 'single-art-project-imagine', 'single-art-project', 'single', 'singular', 'index' ),
+ ),
+ 'single page' => array(
+ 'args' => array( 'page-hi', false, 'page' ),
+ 'expected' => array( 'page-hi', 'page', 'singular', 'index' ),
+ ),
+ 'authors' => array(
+ 'args' => array( 'author-rigas', false, 'author' ),
+ 'expected' => array( 'author-rigas', 'author', 'archive', 'index' ),
+ ),
+ );
+ }
+}
</ins><span class="cx" style="display: block; padding: 0 10px">Property changes on: trunk/tests/phpunit/tests/block-templates/getTemplateHierarchy.php
</span><span class="cx" style="display: block; padding: 0 10px">___________________________________________________________________
</span></span></pre></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Added: svn:eol-style</h4></div>
<ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+native
</ins><span class="cx" style="display: block; padding: 0 10px">\ No newline at end of property
</span><a id="trunktestsphpunittestsrestapirestposttypescontrollerphp"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/tests/phpunit/tests/rest-api/rest-post-types-controller.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/tests/phpunit/tests/rest-api/rest-post-types-controller.php 2022-09-20 21:12:39 UTC (rev 54268)
+++ trunk/tests/phpunit/tests/rest-api/rest-post-types-controller.php 2022-09-20 21:19:10 UTC (rev 54269)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -156,24 +156,31 @@
</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><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * @ticket 56467
+ *
+ * @covers WP_REST_Post_Types_Controller::get_item_schema
+ */
</ins><span class="cx" style="display: block; padding: 0 10px"> public function test_get_item_schema() {
</span><span class="cx" style="display: block; padding: 0 10px"> $request = new WP_REST_Request( 'OPTIONS', '/wp/v2/types' );
</span><span class="cx" style="display: block; padding: 0 10px"> $response = rest_get_server()->dispatch( $request );
</span><span class="cx" style="display: block; padding: 0 10px"> $data = $response->get_data();
</span><span class="cx" style="display: block; padding: 0 10px"> $properties = $data['schema']['properties'];
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- $this->assertCount( 12, $properties );
- $this->assertArrayHasKey( 'capabilities', $properties );
- $this->assertArrayHasKey( 'description', $properties );
- $this->assertArrayHasKey( 'hierarchical', $properties );
- $this->assertArrayHasKey( 'viewable', $properties );
- $this->assertArrayHasKey( 'labels', $properties );
- $this->assertArrayHasKey( 'name', $properties );
- $this->assertArrayHasKey( 'slug', $properties );
- $this->assertArrayHasKey( 'supports', $properties );
- $this->assertArrayHasKey( 'taxonomies', $properties );
- $this->assertArrayHasKey( 'rest_base', $properties );
- $this->assertArrayHasKey( 'rest_namespace', $properties );
- $this->assertArrayHasKey( 'visibility', $properties );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+
+ $this->assertCount( 13, $properties, 'Schema should have 13 properties' );
+ $this->assertArrayHasKey( 'capabilities', $properties, '`capabilities` should be included in the schema' );
+ $this->assertArrayHasKey( 'description', $properties, '`description` should be included in the schema' );
+ $this->assertArrayHasKey( 'hierarchical', $properties, '`hierarchical` should be included in the schema' );
+ $this->assertArrayHasKey( 'viewable', $properties, '`viewable` should be included in the schema' );
+ $this->assertArrayHasKey( 'labels', $properties, '`labels` should be included in the schema' );
+ $this->assertArrayHasKey( 'name', $properties, '`name` should be included in the schema' );
+ $this->assertArrayHasKey( 'slug', $properties, '`slug` should be included in the schema' );
+ $this->assertArrayHasKey( 'supports', $properties, '`supports` should be included in the schema' );
+ $this->assertArrayHasKey( 'taxonomies', $properties, '`taxonomies` should be included in the schema' );
+ $this->assertArrayHasKey( 'rest_base', $properties, '`rest_base` should be included in the schema' );
+ $this->assertArrayHasKey( 'rest_namespace', $properties, '`rest_namespace` should be included in the schema' );
+ $this->assertArrayHasKey( 'visibility', $properties, '`visibility` should be included in the schema' );
+ $this->assertArrayHasKey( 'icon', $properties, '`icon` should be included in the schema' );
</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 function test_get_additional_field_registration() {
</span></span></pre></div>
<a id="trunktestsphpunittestsrestapirestschemasetupphp"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/tests/phpunit/tests/rest-api/rest-schema-setup.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/tests/phpunit/tests/rest-api/rest-schema-setup.php 2022-09-20 21:12:39 UTC (rev 54268)
+++ trunk/tests/phpunit/tests/rest-api/rest-schema-setup.php 2022-09-20 21:19:10 UTC (rev 54269)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -150,6 +150,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> '/wp/v2/template-parts/(?P<parent>[\d]+)/autosaves/(?P<id>[\d]+)',
</span><span class="cx" style="display: block; padding: 0 10px"> '/wp/v2/template-parts/(?P<parent>[\d]+)/revisions',
</span><span class="cx" style="display: block; padding: 0 10px"> '/wp/v2/template-parts/(?P<parent>[\d]+)/revisions/(?P<id>[\d]+)',
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ '/wp/v2/template-parts/lookup',
</ins><span class="cx" style="display: block; padding: 0 10px"> '/wp/v2/templates',
</span><span class="cx" style="display: block; padding: 0 10px"> '/wp/v2/templates/(?P<id>[\d]+)/autosaves',
</span><span class="cx" style="display: block; padding: 0 10px"> '/wp/v2/templates/(?P<id>([^\/:<>\*\?"\|]+(?:\/[^\/:<>\*\?"\|]+)?)[\/\w-]+)',
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -156,6 +157,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> '/wp/v2/templates/(?P<parent>[\d]+)/autosaves/(?P<id>[\d]+)',
</span><span class="cx" style="display: block; padding: 0 10px"> '/wp/v2/templates/(?P<parent>[\d]+)/revisions',
</span><span class="cx" style="display: block; padding: 0 10px"> '/wp/v2/templates/(?P<parent>[\d]+)/revisions/(?P<id>[\d]+)',
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ '/wp/v2/templates/lookup',
</ins><span class="cx" style="display: block; padding: 0 10px"> '/wp/v2/themes',
</span><span class="cx" style="display: block; padding: 0 10px"> '/wp/v2/themes/(?P<stylesheet>[^\/:<>\*\?"\|]+(?:\/[^\/:<>\*\?"\|]+)?)',
</span><span class="cx" style="display: block; padding: 0 10px"> '/wp/v2/plugins',
</span></span></pre></div>
<a id="trunktestsphpunittestsrestapiwpRestTemplatesControllerphp"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/tests/phpunit/tests/rest-api/wpRestTemplatesController.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/tests/phpunit/tests/rest-api/wpRestTemplatesController.php 2022-09-20 21:12:39 UTC (rev 54268)
+++ trunk/tests/phpunit/tests/rest-api/wpRestTemplatesController.php 2022-09-20 21:19:10 UTC (rev 54269)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -56,6 +56,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> /**
</span><span class="cx" style="display: block; padding: 0 10px"> * @covers WP_REST_Templates_Controller::register_routes
</span><span class="cx" style="display: block; padding: 0 10px"> * @ticket 54596
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * @ticket 56467
</ins><span class="cx" style="display: block; padding: 0 10px"> */
</span><span class="cx" style="display: block; padding: 0 10px"> public function test_register_routes() {
</span><span class="cx" style="display: block; padding: 0 10px"> $routes = rest_get_server()->get_routes();
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -69,6 +70,11 @@
</span><span class="cx" style="display: block; padding: 0 10px"> $routes,
</span><span class="cx" style="display: block; padding: 0 10px"> 'Single template based on the given ID route does not exist'
</span><span class="cx" style="display: block; padding: 0 10px"> );
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $this->assertArrayHasKey(
+ '/wp/v2/templates/lookup',
+ $routes,
+ 'Get template fallback content route does not exist'
+ );
</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">@@ -678,4 +684,109 @@
</span><span class="cx" style="display: block; padding: 0 10px"> return null;
</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">+ /**
+ * @dataProvider data_create_item_with_is_wp_suggestion
+ * @ticket 56467
+ * @covers WP_REST_Templates_Controller::create_item
+ *
+ * @param array $body_params Data set to test.
+ * @param array $expected Expected results.
+ */
+ public function test_create_item_with_is_wp_suggestion( array $body_params, array $expected ) {
+ // Set up the user.
+ $body_params['author'] = self::$admin_id;
+ $expected['author'] = self::$admin_id;
+ wp_set_current_user( self::$admin_id );
+
+ $request = new WP_REST_Request( 'POST', '/wp/v2/templates' );
+ $request->set_body_params( $body_params );
+ $response = rest_get_server()->dispatch( $request );
+ $data = $response->get_data();
+ unset( $data['_links'] );
+ unset( $data['wp_id'] );
+
+ $this->assertSame( $expected, $data );
+ }
+
+ /**
+ * Data provider.
+ *
+ * @return array
+ */
+ public function data_create_item_with_is_wp_suggestion() {
+ $expected = array(
+ 'id' => 'default//page-rigas',
+ 'theme' => 'default',
+ 'content' => array(
+ 'raw' => 'Content',
+ ),
+ 'slug' => 'page-rigas',
+ 'source' => 'custom',
+ 'origin' => null,
+ 'type' => 'wp_template',
+ 'description' => 'Just a description',
+ 'title' => array(
+ 'raw' => 'My Template',
+ 'rendered' => 'My Template',
+ ),
+ 'status' => 'publish',
+ 'has_theme_file' => false,
+ 'is_custom' => false,
+ 'author' => null,
+ );
+
+ return array(
+ 'is_wp_suggestion: true' => array(
+ 'body_params' => array(
+ 'slug' => 'page-rigas',
+ 'description' => 'Just a description',
+ 'title' => 'My Template',
+ 'content' => 'Content',
+ 'is_wp_suggestion' => true,
+ 'author' => null,
+ ),
+ 'expected' => $expected,
+ ),
+ 'is_wp_suggestion: false' => array(
+ 'body_params' => array(
+ 'slug' => 'page-hi',
+ 'description' => 'Just a description',
+ 'title' => 'My Template',
+ 'content' => 'Content',
+ 'is_wp_suggestion' => false,
+ 'author' => null,
+ ),
+ 'expected' => array_merge(
+ $expected,
+ array(
+ 'id' => 'default//page-hi',
+ 'slug' => 'page-hi',
+ 'is_custom' => true,
+ )
+ ),
+ ),
+ );
+ }
+
+ /**
+ * @ticket 56467
+ * @covers WP_REST_Templates_Controller::get_template_fallback
+ */
+ public function test_get_template_fallback() {
+ wp_set_current_user( self::$admin_id );
+ switch_theme( 'block-theme' );
+ $request = new WP_REST_Request( 'GET', '/wp/v2/templates/lookup' );
+ // Should fallback to `index.html`.
+ $request->set_param( 'slug', 'tag-status' );
+ $request->set_param( 'is_custom', false );
+ $request->set_param( 'template_prefix', 'tag' );
+ $response = rest_get_server()->dispatch( $request );
+ $this->assertSame( 'index', $response->get_data()['slug'], 'Should fallback to `index.html`.' );
+ // Should fallback to `page.html`.
+ $request->set_param( 'slug', 'page-hello' );
+ $request->set_param( 'is_custom', false );
+ $request->set_param( 'template_prefix', 'page' );
+ $response = rest_get_server()->dispatch( $request );
+ $this->assertSame( 'page', $response->get_data()['slug'], 'Should fallback to `page.html`.' );
+ }
</ins><span class="cx" style="display: block; padding: 0 10px"> }
</span></span></pre></div>
<a id="trunktestsqunitfixtureswpapigeneratedjs"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/tests/qunit/fixtures/wp-api-generated.js</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/tests/qunit/fixtures/wp-api-generated.js 2022-09-20 21:12:39 UTC (rev 54268)
+++ trunk/tests/qunit/fixtures/wp-api-generated.js 2022-09-20 21:19:10 UTC (rev 54269)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -5140,6 +5140,43 @@
</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><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ "/wp/v2/templates/lookup": {
+ "namespace": "wp/v2",
+ "methods": [
+ "GET"
+ ],
+ "endpoints": [
+ {
+ "methods": [
+ "GET"
+ ],
+ "args": {
+ "slug": {
+ "description": "The slug of the template to get the fallback for",
+ "type": "string",
+ "required": true
+ },
+ "is_custom": {
+ "description": " Indicates if a template is custom or part of the template hierarchy",
+ "type": "boolean",
+ "required": false
+ },
+ "template_prefix": {
+ "description": "The template prefix for the created template. This is used to extract the main template type, e.g. in `taxonomy-books` extracts the `taxonomy`",
+ "type": "string",
+ "required": false
+ }
+ }
+ }
+ ],
+ "_links": {
+ "self": [
+ {
+ "href": "http://example.org/index.php?rest_route=/wp/v2/templates/lookup"
+ }
+ ]
+ }
+ },
</ins><span class="cx" style="display: block; padding: 0 10px"> "/wp/v2/templates/(?P<id>([^\\/:<>\\*\\?\"\\|]+(?:\\/[^\\/:<>\\*\\?\"\\|]+)?)[\\/\\w-]+)": {
</span><span class="cx" style="display: block; padding: 0 10px"> "namespace": "wp/v2",
</span><span class="cx" style="display: block; padding: 0 10px"> "methods": [
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -5792,6 +5829,43 @@
</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><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ "/wp/v2/template-parts/lookup": {
+ "namespace": "wp/v2",
+ "methods": [
+ "GET"
+ ],
+ "endpoints": [
+ {
+ "methods": [
+ "GET"
+ ],
+ "args": {
+ "slug": {
+ "description": "The slug of the template to get the fallback for",
+ "type": "string",
+ "required": true
+ },
+ "is_custom": {
+ "description": " Indicates if a template is custom or part of the template hierarchy",
+ "type": "boolean",
+ "required": false
+ },
+ "template_prefix": {
+ "description": "The template prefix for the created template. This is used to extract the main template type, e.g. in `taxonomy-books` extracts the `taxonomy`",
+ "type": "string",
+ "required": false
+ }
+ }
+ }
+ ],
+ "_links": {
+ "self": [
+ {
+ "href": "http://example.org/index.php?rest_route=/wp/v2/template-parts/lookup"
+ }
+ ]
+ }
+ },
</ins><span class="cx" style="display: block; padding: 0 10px"> "/wp/v2/template-parts/(?P<id>([^\\/:<>\\*\\?\"\\|]+(?:\\/[^\\/:<>\\*\\?\"\\|]+)?)[\\/\\w-]+)": {
</span><span class="cx" style="display: block; padding: 0 10px"> "namespace": "wp/v2",
</span><span class="cx" style="display: block; padding: 0 10px"> "methods": [
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -11591,6 +11665,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> "hierarchical": false,
</span><span class="cx" style="display: block; padding: 0 10px"> "name": "Posts",
</span><span class="cx" style="display: block; padding: 0 10px"> "slug": "post",
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ "icon": "dashicons-admin-post",
</ins><span class="cx" style="display: block; padding: 0 10px"> "taxonomies": [
</span><span class="cx" style="display: block; padding: 0 10px"> "category",
</span><span class="cx" style="display: block; padding: 0 10px"> "post_tag"
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -11622,6 +11697,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> "hierarchical": true,
</span><span class="cx" style="display: block; padding: 0 10px"> "name": "Pages",
</span><span class="cx" style="display: block; padding: 0 10px"> "slug": "page",
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ "icon": "dashicons-admin-page",
</ins><span class="cx" style="display: block; padding: 0 10px"> "taxonomies": [],
</span><span class="cx" style="display: block; padding: 0 10px"> "rest_base": "pages",
</span><span class="cx" style="display: block; padding: 0 10px"> "rest_namespace": "wp/v2",
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -11650,6 +11726,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> "hierarchical": false,
</span><span class="cx" style="display: block; padding: 0 10px"> "name": "Media",
</span><span class="cx" style="display: block; padding: 0 10px"> "slug": "attachment",
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ "icon": "dashicons-admin-media",
</ins><span class="cx" style="display: block; padding: 0 10px"> "taxonomies": [],
</span><span class="cx" style="display: block; padding: 0 10px"> "rest_base": "media",
</span><span class="cx" style="display: block; padding: 0 10px"> "rest_namespace": "wp/v2",
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -11678,6 +11755,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> "hierarchical": false,
</span><span class="cx" style="display: block; padding: 0 10px"> "name": "Navigation Menu Items",
</span><span class="cx" style="display: block; padding: 0 10px"> "slug": "nav_menu_item",
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ "icon": null,
</ins><span class="cx" style="display: block; padding: 0 10px"> "taxonomies": [
</span><span class="cx" style="display: block; padding: 0 10px"> "nav_menu"
</span><span class="cx" style="display: block; padding: 0 10px"> ],
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -11708,6 +11786,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> "hierarchical": false,
</span><span class="cx" style="display: block; padding: 0 10px"> "name": "Reusable blocks",
</span><span class="cx" style="display: block; padding: 0 10px"> "slug": "wp_block",
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ "icon": null,
</ins><span class="cx" style="display: block; padding: 0 10px"> "taxonomies": [],
</span><span class="cx" style="display: block; padding: 0 10px"> "rest_base": "blocks",
</span><span class="cx" style="display: block; padding: 0 10px"> "rest_namespace": "wp/v2",
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -11736,6 +11815,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> "hierarchical": false,
</span><span class="cx" style="display: block; padding: 0 10px"> "name": "Templates",
</span><span class="cx" style="display: block; padding: 0 10px"> "slug": "wp_template",
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ "icon": null,
</ins><span class="cx" style="display: block; padding: 0 10px"> "taxonomies": [],
</span><span class="cx" style="display: block; padding: 0 10px"> "rest_base": "templates",
</span><span class="cx" style="display: block; padding: 0 10px"> "rest_namespace": "wp/v2",
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -11764,6 +11844,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> "hierarchical": false,
</span><span class="cx" style="display: block; padding: 0 10px"> "name": "Template Parts",
</span><span class="cx" style="display: block; padding: 0 10px"> "slug": "wp_template_part",
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ "icon": null,
</ins><span class="cx" style="display: block; padding: 0 10px"> "taxonomies": [],
</span><span class="cx" style="display: block; padding: 0 10px"> "rest_base": "template-parts",
</span><span class="cx" style="display: block; padding: 0 10px"> "rest_namespace": "wp/v2",
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -11792,6 +11873,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> "hierarchical": false,
</span><span class="cx" style="display: block; padding: 0 10px"> "name": "Navigation Menus",
</span><span class="cx" style="display: block; padding: 0 10px"> "slug": "wp_navigation",
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ "icon": null,
</ins><span class="cx" style="display: block; padding: 0 10px"> "taxonomies": [],
</span><span class="cx" style="display: block; padding: 0 10px"> "rest_base": "navigation",
</span><span class="cx" style="display: block; padding: 0 10px"> "rest_namespace": "wp/v2",
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -11822,6 +11904,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> "hierarchical": false,
</span><span class="cx" style="display: block; padding: 0 10px"> "name": "Posts",
</span><span class="cx" style="display: block; padding: 0 10px"> "slug": "post",
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ "icon": "dashicons-admin-post",
</ins><span class="cx" style="display: block; padding: 0 10px"> "taxonomies": [
</span><span class="cx" style="display: block; padding: 0 10px"> "category",
</span><span class="cx" style="display: block; padding: 0 10px"> "post_tag"
</span></span></pre>
</div>
</div>
</body>
</html>