Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Templates Endpoint: Add resolved query arg to return only relevant templates #21981

Merged
merged 7 commits into from
May 13, 2020

Conversation

ockham
Copy link
Contributor

@ockham ockham commented Apr 29, 2020

Description

Implements https://github.com/WordPress/gutenberg/pull/21877/files#r416075231 and unblocks #21877.

This PR changes gutenberg_find_template_post_and_parts() to accept a $template_type arg, and make the $template_hierarchy arg optional. $template_hierarchy will be used as a hint if it's present (e.g. when called from a {$type}_template hook); if it isn't, the template hierarchy will be looked up for $template_type.

This allows writing the code in edit-site-page.php in a more succinct way. More importantly, it allows us to add a rest_wp_template_query filter for the wp_template collection endpoint to accept a resolved bool arg that will cause the endpoint to reflect the behavior of the template resolution algorithm that's used to populate the $settings[ 'templateIds' ] (see):

Published templates are always used first and mean the template was customized. Auto drafts are only used when the templates haven't been customized. We should preferably use the latest ones

How has this been tested?

As always, make sure that the Full-Site Editing experiment and demo templates are enabled.

We'll compare the results the wp_template collections REST API endpoint gives to $settings['templateIds']. To that end, apply the following patch and re-build the app (npm run build):

diff --git a/packages/edit-site/src/index.js b/packages/edit-site/src/index.js
index e6dec20771..ea72bee4c9 100644
--- a/packages/edit-site/src/index.js
+++ b/packages/edit-site/src/index.js
@@ -26,6 +26,7 @@ export function initialize( id, settings ) {
        if ( process.env.GUTENBERG_PHASE === 2 ) {
                __experimentalRegisterExperimentalCoreBlocks( settings );
        }
+       console.log( 'settings', settings );
        render( <Editor settings={ settings } />, document.getElementById( id ) );
 }

Next, in wp-admin, navigate to the Appearance > Templates section, and create a few dummy templates whose names are not actually part of the template hierarchy (e.g. some-template etc).

Now go to Full-Site Editing and open your browser console. You should see the output of the settings variable there. Compare the templateIds property to the output of the following commands you run in the console (twice each!). Icons ✔️ and ❌ indicate whether the output is expected to match settings.templateIds, or not.

  • wp.data.select('core').getEntityRecords('postType', 'wp_template' ) should return the list of all wp_template CPTs, including those that are not part of the template hierarchy.
  • ✔️ wp.data.select('core').getEntityRecords('postType', 'wp_template', { resolved: true } ) should return the list of templates that match the template hierarchy.
  • wp.data.select('core').getEntityRecords('postType', 'wp_template', { slug: 'some-template' } ) should return the wp_template part whose slug is some-template.
  • ✔️ wp.data.select('core').getEntityRecords('postType', 'wp_template', { slug: 'some-template', resolved: true } ) should return an empty array, as some-template is not part of the template hierarchy.

Types of changes

Add an arg to an existing endpoint; plus a minor refactor.

Checklist:

  • My code is tested.
  • My code follows the WordPress code style.
  • My code follows the accessibility standards.
  • My code has proper inline documentation.
  • I've included developer documentation if appropriate.
  • I've updated all React Native files affected by any refactorings/renamings in this PR.

@ockham ockham self-assigned this Apr 29, 2020
@ockham ockham changed the title Templates Endpoint: Add resolved filter Templates Endpoint: Add resolved query arg to return only relevant templates Apr 29, 2020
@github-actions
Copy link

github-actions bot commented Apr 29, 2020

Size Change: 0 B

Total Size: 827 kB

ℹ️ View Unchanged
Filename Size Change
build/a11y/index.js 1.02 kB 0 B
build/annotations/index.js 3.62 kB 0 B
build/api-fetch/index.js 4.08 kB 0 B
build/autop/index.js 2.82 kB 0 B
build/blob/index.js 620 B 0 B
build/block-directory/index.js 6.63 kB 0 B
build/block-directory/style-rtl.css 764 B 0 B
build/block-directory/style.css 764 B 0 B
build/block-editor/index.js 104 kB 0 B
build/block-editor/style-rtl.css 10.6 kB 0 B
build/block-editor/style.css 10.6 kB 0 B
build/block-library/editor-rtl.css 7.12 kB 0 B
build/block-library/editor.css 7.12 kB 0 B
build/block-library/index.js 115 kB 0 B
build/block-library/style-rtl.css 7.38 kB 0 B
build/block-library/style.css 7.38 kB 0 B
build/block-library/theme-rtl.css 683 B 0 B
build/block-library/theme.css 685 B 0 B
build/block-serialization-default-parser/index.js 1.88 kB 0 B
build/block-serialization-spec-parser/index.js 3.1 kB 0 B
build/blocks/index.js 48.1 kB 0 B
build/components/index.js 181 kB 0 B
build/components/style-rtl.css 17 kB 0 B
build/components/style.css 16.9 kB 0 B
build/compose/index.js 6.66 kB 0 B
build/core-data/index.js 11.4 kB 0 B
build/data-controls/index.js 1.29 kB 0 B
build/data/index.js 8.43 kB 0 B
build/date/index.js 5.47 kB 0 B
build/deprecated/index.js 772 B 0 B
build/dom-ready/index.js 568 B 0 B
build/dom/index.js 3.1 kB 0 B
build/edit-navigation/index.js 4.42 kB 0 B
build/edit-navigation/style-rtl.css 618 B 0 B
build/edit-navigation/style.css 617 B 0 B
build/edit-post/index.js 28 kB 0 B
build/edit-post/style-rtl.css 12.2 kB 0 B
build/edit-post/style.css 12.2 kB 0 B
build/edit-site/index.js 12.1 kB 0 B
build/edit-site/style-rtl.css 5.22 kB 0 B
build/edit-site/style.css 5.22 kB 0 B
build/edit-widgets/index.js 8.37 kB 0 B
build/edit-widgets/style-rtl.css 4.69 kB 0 B
build/edit-widgets/style.css 4.69 kB 0 B
build/editor/editor-styles-rtl.css 425 B 0 B
build/editor/editor-styles.css 428 B 0 B
build/editor/index.js 44.3 kB 0 B
build/editor/style-rtl.css 5.07 kB 0 B
build/editor/style.css 5.08 kB 0 B
build/element/index.js 4.65 kB 0 B
build/escape-html/index.js 734 B 0 B
build/format-library/index.js 7.63 kB 0 B
build/format-library/style-rtl.css 502 B 0 B
build/format-library/style.css 502 B 0 B
build/hooks/index.js 2.14 kB 0 B
build/html-entities/index.js 622 B 0 B
build/i18n/index.js 3.56 kB 0 B
build/is-shallow-equal/index.js 710 B 0 B
build/keyboard-shortcuts/index.js 2.51 kB 0 B
build/keycodes/index.js 1.94 kB 0 B
build/list-reusable-blocks/index.js 3.12 kB 0 B
build/list-reusable-blocks/style-rtl.css 226 B 0 B
build/list-reusable-blocks/style.css 226 B 0 B
build/media-utils/index.js 5.29 kB 0 B
build/notices/index.js 1.79 kB 0 B
build/nux/index.js 3.4 kB 0 B
build/nux/style-rtl.css 616 B 0 B
build/nux/style.css 613 B 0 B
build/plugins/index.js 2.56 kB 0 B
build/primitives/index.js 1.5 kB 0 B
build/priority-queue/index.js 789 B 0 B
build/redux-routine/index.js 2.85 kB 0 B
build/rich-text/index.js 14.8 kB 0 B
build/server-side-render/index.js 2.68 kB 0 B
build/shortcode/index.js 1.7 kB 0 B
build/token-list/index.js 1.28 kB 0 B
build/url/index.js 4.02 kB 0 B
build/viewport/index.js 1.84 kB 0 B
build/warning/index.js 1.14 kB 0 B
build/wordcount/index.js 1.18 kB 0 B

compressed-size-action

@ockham ockham force-pushed the add/templates-endpoint-resolved-arg branch 5 times, most recently from 772cff9 to 301ec43 Compare May 12, 2020 12:20
@ockham ockham marked this pull request as ready for review May 12, 2020 12:51
@ockham ockham requested a review from TimothyBJacobs as a code owner May 12, 2020 12:51
lib/template-loader.php Outdated Show resolved Hide resolved
Comment on lines 237 to 239
// TODO: We could consider moving the following logic to a hook like `posts_results` that is run
// after query results have been fetched. That might allow us to absorb filtering logic
// (as e.g. found in `filter_rest_wp_template_query`) into the generic querying logic.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This comment is confusing. How would moving this into a hook allow for filter_rest_wp_template_query to be in the "generic querying logic."?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What I meant is to move the auto-draft creation logic into a post_results filter, and to filter the results returned by the query to only return the template(s) that are relevant for the requested template hierarchy -- similar to what filter_rest_wp_template_query does in this PR.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The auto-drafts are not created for the templates that are returned by the query. They are created for spots in the template hierarchy that don't have a returned template but have a theme file. You would have to create the auto-drafts before making the query so that they show up, but give preference to non-auto-drafts. That could work, but I doubt it will be more straightforward.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, I think we're basically on the same page. <y thinking was basically:

  • We tap into the post_results hook to watch out for a query for one (or many) wp_template(s), possibly with a post_name or post_name__in param, akin to this:
    // Find most specific 'wp_template' post matching the hierarchy.
    $template_query = new WP_Query(
    array(
    'post_type' => 'wp_template',
    'post_status' => 'publish',
    'post_name__in' => $slugs,
    'orderby' => 'post_name__in',
    'posts_per_page' => 1,
    'no_found_rows' => true,
    )
    );
  • In our filter, we create the auto-drafts from theme files, and if there's one that matches the template hierarchy better than our query result, we return that -- that's basically
    $current_template_post = $template_query->have_posts() ? $template_query->next_post() : null;
    // Build map of template slugs to their priority in the current hierarchy.
    $slug_priorities = array_flip( $slugs );
    // See if there is a theme block template with higher priority than the resolved template post.
    $higher_priority_block_template_path = null;
    $higher_priority_block_template_priority = PHP_INT_MAX;
    $block_template_files = glob( get_stylesheet_directory() . '/block-templates/*.html' );
    $block_template_files = is_array( $block_template_files ) ? $block_template_files : array();
    if ( is_child_theme() ) {
    $child_block_template_files = glob( get_template_directory() . '/block-templates/*.html' );
    $child_block_template_files = is_array( $child_block_template_files ) ? $child_block_template_files : array();
    $block_template_files = array_merge( $block_template_files, $child_block_template_files );
    }
    if ( gutenberg_is_experiment_enabled( 'gutenberg-full-site-editing-demo' ) ) {
    $demo_block_template_files = glob( dirname( __FILE__ ) . '/demo-block-templates/*.html' );
    $demo_block_template_files = is_array( $demo_block_template_files ) ? $demo_block_template_files : array();
    $block_template_files = array_merge( $block_template_files, $demo_block_template_files );
    }
    foreach ( $block_template_files as $path ) {
    if ( ! isset( $slug_priorities[ basename( $path, '.html' ) ] ) ) {
    continue;
    }
    $theme_block_template_priority = $slug_priorities[ basename( $path, '.html' ) ];
    if (
    $theme_block_template_priority < $higher_priority_block_template_priority &&
    ( empty( $current_template_post ) || $theme_block_template_priority < $slug_priorities[ $current_template_post->post_name ] )
    ) {
    $higher_priority_block_template_path = $path;
    $higher_priority_block_template_priority = $theme_block_template_priority;
    }
    }
    // If there is, use it instead.
    if ( isset( $higher_priority_block_template_path ) ) {
    $post_name = basename( $higher_priority_block_template_path, '.html' );
    $current_template_post = array(
    'post_content' => file_get_contents( $higher_priority_block_template_path ),
    'post_title' => $post_name,
    'post_status' => 'auto-draft',
    'post_type' => 'wp_template',
    'post_name' => $post_name,
    );
    if ( is_admin() ) {
    // Only create auto-draft of block template for editing
    // in admin screens, similarly to how we do it for new
    // posts in the editor.
    $current_template_post = get_post(
    wp_insert_post( $current_template_post )
    );
    } else {
    $current_template_post = new WP_Post(
    (object) $current_template_post
    );
    }
    }

While it mangles the query logic quite a bit, it's arguable that we'd pretty much always like to perform these steps whenever a template is queried (whether for rendering or through the REST API). I think it might be worth experimenting with.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We could also just call the new functions directly for rendering.

lib/templates.php Outdated Show resolved Hide resolved
Comment on lines 195 to 198
// TODO: gutenberg_find_template_post_and_parts() internally performs a query.
// This means that there's room for optimization, and we might be able to
// generalize the logic found here into something that runs upon every `wp_template`
// query (not just those coming from the REST API).
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why would we want that? We still need a way to use the regular querying logic.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was thinking of adding some kind of flag, similar to the resolved bool we're adding to the REST API endpoint in this PR. The same technique might not carry over 1:1 to WP_Query, but maybe we could add e.g. a dummy meta field.

I think that we could consider manipulating all queries for wp_template. If you look at the querying and auto-draft creation logic in gutenberg_find_template_post_and_parts, and where it's used, it's arguable that we'll always want to create those auto-drafts when querying a wp_template.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But, you need to query the templates to figure out which ones you need to create auto-drafts for. The only way I see to get around that is to generate auto-drafts for all files before queries are made. Still, then we have to make sure we always update them when the underlying files change and that we give priority to actual customized non-auto-draft counterparts. All in all, I don't see it being much more straightforward, and we introduce a lot of magic into the very standardized functionality of WP_Query.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But, you need to query the templates to figure out which ones you need to create auto-drafts for. The only way I see to get around that is to generate auto-drafts for all files before queries are made.

That depends on the query, doesn't it? If there's no post_name or post_name__in param, then that's true -- but that means it'd be pretty similar to what we have now in edit-site-page.php or in the new REST API filter I'm adding here -- where we just loop over template hierarchies.

Still, then we have to make sure we always update them when the underlying files change and that we give priority to actual customized non-auto-draft counterparts.

That should be feasible by splitting what we now have in gutenberg_find_template_post_and_parts along sensible lines (like I sketched here), no?

All in all, I don't see it being much more straightforward, and we introduce a lot of magic into the very standardized functionality of WP_Query.

Yeah, I think the magic vs. expected behavior is the biggest concern.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, I don't see it as a definite net improvement.

We can explore it, but I wouldn't prioritize it.

@ockham
Copy link
Contributor Author

ockham commented May 12, 2020

Addressed feedback. If the TODO comments are the main concern, I'm happy to revert them. Also happy to demo what I meant with them in a separate PR (since I'd rather not block this one on it).

Copy link
Contributor

@epiqueras epiqueras left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's remove the TODOs, and merge.

@ockham ockham force-pushed the add/templates-endpoint-resolved-arg branch from ed88f8c to b0ea6f4 Compare May 12, 2020 19:36
@epiqueras epiqueras merged commit a390df4 into master May 13, 2020
@epiqueras epiqueras deleted the add/templates-endpoint-resolved-arg branch May 13, 2020 00:19
@github-actions github-actions bot added this to the Gutenberg 8.2 milestone May 13, 2020
@ellatrix ellatrix mentioned this pull request Jun 16, 2020
12 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants