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

Block Library: Add Query block. #22199

Merged
merged 16 commits into from
May 13, 2020
Merged

Block Library: Add Query block. #22199

merged 16 commits into from
May 13, 2020

Conversation

epiqueras
Copy link
Contributor

Description

This PR introduces a new Query block, which can be described as the block version of the WordPress post loop. Right now, it only supports basic query parameters, but the goal is for it to expose all the relevant parameters of a WP query so that it can be used in any template that needs to render lists of posts.

The implementation has a parent Query block that manages the query and can contain any combination of inner blocks.

Inside the Query block, the Query Loop block reads the query from context and uses it to render the resulting posts using its inner blocks as layout. In the editor, this is achieved by rendering the selected post using InnerBlocks and the others using a new live BlockPreview. This lets us switch between editing the layout as used by each different post and have it sync across all of the posts.

The Query Pagination block similarly reads the query from context but just uses it to render pagination buttons. In the future, it could be expanded to have its own inner blocks so that you can more freely position the different components of a pagination UI.

All of the new block APIs enabled the implementation to go smoothly. Still, I did have to add a couple of things to the server rendering process: A way to skip inner blocks when rendering a block so that the Query Loop block doesn't recurse infinitely when it has a child Post Content block, and a way to skip dynamic rendering so that the Query Loop block can call its render function without recursing.

This PR is merely the big chunk infrastructure needed for the block, and there is still a lot of UI work to be done in follow-ups. Namely, the design and development of the query toolbar and sidebar controls.

How to test this?

With the full site editing experiment enabled and some published posts, insert a query block into a new post and play around with the pagination settings while making sure the editor and front end outputs match each other.

Try adding content to the templates and make sure they sync. Also, try moving around the Query Loop and Query Pagination blocks.

Screenshots

gif

Types of Changes

New Feature: There is a new set of query (post loop) blocks for full site editing.

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.

@github-actions
Copy link

github-actions bot commented May 8, 2020

Size Change: +1.76 kB (0%)

Total Size: 833 kB

Filename Size Change
build/block-editor/index.js 104 kB +72 B (0%)
build/block-library/index.js 118 kB +1.69 kB (1%)
ℹ️ 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.59 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/style-rtl.css 10.8 kB 0 B
build/block-editor/style.css 10.8 kB 0 B
build/block-library/editor-rtl.css 7.25 kB 0 B
build/block-library/editor.css 7.25 kB 0 B
build/block-library/style-rtl.css 7.48 kB 0 B
build/block-library/style.css 7.49 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 182 kB 0 B
build/components/style-rtl.css 17.1 kB 0 B
build/components/style.css 17 kB 0 B
build/compose/index.js 6.68 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 5.59 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 733 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.13 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 712 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.13 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

@@ -48,6 +48,9 @@ function gutenberg_reregister_core_block_types() {
'post-tags.php' => 'core/post-tags',
'site-title.php' => 'core/site-title',
'template-part.php' => 'core/template-part',
'query.php' => 'core/query',
'query-loop.php' => 'core/query-loop',
Copy link
Member

Choose a reason for hiding this comment

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

Is there ever going to be a query without a loop? Could it be absorbed?

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 do you mean by absorbed? It needs to be movable against its pagination.

Copy link
Member

Choose a reason for hiding this comment

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

I thought pagination would sit outside in most cases

add_query_arg( $page_key, $page + 1 )
);
}
return $content;
Copy link
Member

Choose a reason for hiding this comment

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

Is this block meant to handle post navigation when on single contexts as well?

If so, it'd make sense to replicate or borrow some of https://developer.wordpress.org/reference/functions/get_the_post_navigation/

Otherwise: https://developer.wordpress.org/reference/functions/get_posts_nav_link/

Copy link
Contributor

@ockham ockham May 8, 2020

Choose a reason for hiding this comment

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

I think these queries/paginations need to be independent of their surrounding template's 'default' context, since they could otherwise 'break out' of the template -- e.g. we could have a query in a post that shows a category archive, in which case the prev/next navigation needs to go through that category's pages, rather than the adjacent posts.

(I hope I understood your question correctly 😅 )

We should however probably make sure to use the 'proper' navigation for the template's default context. So if we're editing a category archive template, and we use an (implied or explicit) query at the top level, we should make sure that the next/prev buttons use the 'correct' links to the next/prev page in the archive. (Edit: See e.g. #19257 (comment) for context)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

If so, it'd make sense to replicate or borrow some of

Yeah, we can't use the functions directly because we can't easily manipulate the generated links, but we can borrow.

I think these queries/paginations need to be independent of their surrounding template's 'default' context

The Query block can set its own query or inherit the global one.

$content = '';
if ( 1 !== $page ) {
$content .= sprintf(
'<div><a href="%s">Previous</a></div>',
Copy link
Member

Choose a reason for hiding this comment

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

"Next" and "Previous" strings should be translatable and customizable in the editor.

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 made it translatable, but customization should be done in follow-ups.

}
if ( $page < $block->context['query']['pages'] ) {
$content .= sprintf(
'<div><a href="%s">Next</a></div>',
Copy link
Member

Choose a reason for hiding this comment

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

The div seems superfluos wrapping the link?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The styles that align the content in the front end need it.

@pablohoneyhoney
Copy link

@epiqueras here is a first pass at the loop icon, we need to polish it but it's a good start. File in Figma

icon-loop

@mtias
Copy link
Member

mtias commented May 8, 2020

Love the icon. It's a nice homage to "The Loop" :)

@ockham
Copy link
Contributor

ockham commented May 8, 2020

Inside the Query block, the Query Loop block reads the query from context and uses it to render the resulting posts using its inner blocks as layout. In the editor, this is achieved by rendering the selected post using InnerBlocks and the others using a new live BlockPreview. This lets us switch between editing the layout as used by each different post and have it sync across all of the posts.

I think my gut reaction to seeing this was that editing each post's layout inside of the Query Loop block kind of calls for using a template part. Should we maybe consider equipping the Query Loop block with a UI to load a template part (in a follow-up PR)? (And define entity specific defaults? E.g. a post template part. This would need to happen on a per-theme basis I guess, and we'd need to provide fallbacks.)

@ockham
Copy link
Contributor

ockham commented May 8, 2020

All of the new block APIs enabled the implementation to go smoothly. Still, I did have to add a couple of things to the server rendering process: A way to skip inner blocks when rendering a block so that the Query Loop block doesn't recurse infinitely when it has a child Post Content block and a way to skip dynamic rendering so that the Query Loop block can call its render function without recursing.

I'm not totally sure I understand the problem(s) -- is this about that child Post Content block potentially including itself? Is that something that can happen when the query part is used inside of a template, or only when it's instead used in the post editor (in a post/page/content-type CPT)? If the latter, would an alternative solution be to remove certain blocks (such as Query) from the post editor's block picker? (Just trying to get a grasp of the problem, and maybe avoid the $no_dynamic arg.)

@epiqueras
Copy link
Contributor Author

I think my gut reaction to seeing this was that editing each post's layout inside of the Query Loop block kind of calls for using a template part. Should we maybe consider equipping the Query Loop block with a UI to load a template part (in a follow-up PR)? (And define entity specific defaults? E.g. a post template part. This would need to happen on a per-theme basis I guess, and we'd need to provide fallbacks.)

The only reason you would use a template part here is if you want to reuse the same query layout across different query blocks with different queries. An advanced use case that can be achieved manually and should not be a default.

I'm not totally sure I understand the problem(s) -- is this about that child Post Content block potentially including itself? Is that something that can happen when the query part is used inside of a template, or only when it's instead used in the post editor (in a post/page/content-type CPT)? If the latter, would an alternative solution be to remove certain blocks (such as Query) from the post editor's block picker? (Just trying to get a grasp of the problem, and maybe avoid the $no_dynamic arg.)

Inner blocks are mapped before the block's callback is called, so we end up rendering inner blocks twice, once with the parent context, and once with the overridden one. If the parent context is a template part, reusable block, or content CPT, then it would recurse forever as the post content blocks would start rendering from the top again.

@epiqueras
Copy link
Contributor Author

^^That's actually better for performance as well.

@epiqueras
Copy link
Contributor Author

@pablohoneyhoney The icon looks great. Added!

@gziolo gziolo added the [Type] Feature New feature to highlight in changelogs. label May 12, 2020
@epiqueras epiqueras merged commit b58eb66 into master May 13, 2020
@epiqueras epiqueras deleted the add/query-block-2 branch May 13, 2020 20:11
@github-actions github-actions bot added this to the Gutenberg 8.2 milestone May 13, 2020
new WP_Block(
$block->parsed_block,
array_merge(
$block->available_context ? $block->available_context : array(),
Copy link
Member

Choose a reason for hiding this comment

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

Noting that, as merged, this code won't work as intended.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Can we make it public for now without committing to it in terms of backward compatibility?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
New Block Suggestion for a new block [Type] Feature New feature to highlight in changelogs.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants