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

Add support for the format property in query #7314

Closed
wants to merge 27 commits into from

Conversation

carolinan
Copy link
Contributor

Adds handling the format property ($request['format'] ) in the class WP_REST_Posts_Controller.
Adds handling the format property ($block->context['query']['format']) in the function build_query_vars_from_query_block.

Trac ticket: https://core.trac.wordpress.org/ticket/62014


This Pull Request is for code review only. Please keep all other discussion in the Trac ticket. Do not merge this Pull Request. See GitHub Pull Requests for Code Review in the Core Handbook for more details.

Adds handling the format property ($request['format'] ) in the class WP_REST_Posts_Controller.

Adds handling the format property ($block->context['query']['format'])  in the function build_query_vars_from_query_block.
Copy link

github-actions bot commented Sep 9, 2024

The following accounts have interacted with this PR and/or linked issues. I will continue to update these lists as activity occurs. You can also manually ask me to refresh this list by adding the props-bot label.

Core Committers: Use this line as a base for the props when committing in SVN:

Props poena, peterwilsoncc, mukesh27, mamaduka, noisysocks.

To understand the WordPress project's expectations around crediting contributors, please review the Contributor Attribution page in the Core Handbook.

Copy link

github-actions bot commented Sep 9, 2024

Test using WordPress Playground

The changes in this pull request can previewed and tested using a WordPress Playground instance.

WordPress Playground is an experimental project that creates a full WordPress instance entirely within the browser.

Some things to be aware of

  • The Plugin and Theme Directories cannot be accessed within Playground.
  • All changes will be lost when closing a tab with a Playground instance.
  • All changes will be lost when refreshing the page.
  • A fresh instance is created each time the link below is clicked.
  • Every time this pull request is updated, a new ZIP file containing all changes is created. If changes are not reflected in the Playground instance,
    it's possible that the most recent build failed, or has not completed. Check the list of workflow runs to be sure.

For more details about these limitations and more, check out the Limitations page in the WordPress Playground documentation.

Test this pull request with WordPress Playground.

…oken logic

In `build_query_vars_from_query_block`, the variable that contains the format attribute had the wrong name, which caused a PHP warning. The variable name was updated to `$formats`.

One of the if-statements was closed incorrectly, which meant that all the logic for handling the format property was not used. Because of this, the wrong posts showed in the query loop block on the front of the site.
The closing curly bracket for the if-statement was moved to solve this.

One additional check was added to the wrapping if-statement:
It now checks that `$block->context['query']['format']` is not empty, and is an array, before running the rest of the code.
Generated an updated fixture in `wp-api-generated.js` by running the PHPUnit tests.
The update adds `format` to `mockedApiResponse.Schema`
… post formats.

`WP_REST_Posts_Controller`: remove unnecessary array conversion for the `format` parameter.
This addresses feedback that was left on the Gutenberg pull request.
… to `$query_params['format']`

In `WP_REST_Posts_Controller` `get_collection_params` class method; add `uniqueItems` to the `$query_params['format']` array.

The purpose is to require all items in the array to be unique.
This will help manage user errors, if duplicate items are passed in the `format` parameter.

This change addresses feedback left on the Gutenberg pull request.
Adds the regenerated fixtures which includes `uniqueItems` in the `format` array in `mockedApiResponse.Schema`.

The fixture was regenerated by running the PHPUNit tests.
Use multiline comments instead of multiple single line comments.
Copy link
Contributor

@peterwilsoncc peterwilsoncc left a comment

Choose a reason for hiding this comment

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

I've added some note inline, the most important being for validating the values when generating the query within the block. I'll leave it up to you to decide on how to handle invalid data.

It would also be good to see some unit tests added to ensure that the REST endpoint is returning an expected set of posts. Particularly for standard as the need to query for a non-existent taxomomy is a little unusual.

src/wp-includes/blocks.php Outdated Show resolved Hide resolved
@@ -2420,6 +2421,52 @@ function build_query_vars_from_query_block( $block, $page ) {
}
}
}
if ( ! empty( $block->context['query']['format'] ) && is_array( $block->context['query']['format'] ) ) {
$formats = $block->context['query']['format'];
Copy link
Contributor

Choose a reason for hiding this comment

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

Validation: Ensure that the formats come from the supported values only provided by get_post_format_slugs().

⚠️ Untested but I think you want something along the lines of:

$formats = array_intersect( $formats, get_post_format_slugs() );

@@ -2420,6 +2421,52 @@ function build_query_vars_from_query_block( $block, $page ) {
}
}
}
if ( ! empty( $block->context['query']['format'] ) && is_array( $block->context['query']['format'] ) ) {
$formats = $block->context['query']['format'];
$tax_query = array( 'relation' => 'OR' );
Copy link
Contributor

Choose a reason for hiding this comment

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

My reading of this code is that if someone sets up a query for both formats and taxomomies, this will return posts that contain either.

Eg a query for post format: link; category: rest-api will return:

  • Any posts with the post format link, regardless of category
  • Any posts in the category rest-api, regardless of format.

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 something is not working correctly.
If I use OR or AND, the result is the same: Posts that have both the category and the format.
I think the correct use is AND.
But then why is not OR returning all posts that have either the format or the category?

Copy link
Contributor Author

@carolinan carolinan Sep 16, 2024

Choose a reason for hiding this comment

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

Here is an example query loop for listing posts in category 4, with either the gallery or link format. The category id needs to be updated to match a category available on the installation.

<!-- wp:query {"queryId":1,"query":{"perPage":10,"pages":0,"offset":0,"postType":"post","order":"desc","orderBy":"date","author":"","search":"","exclude":[],"sticky":"","inherit":false,"format":["link","gallery"],"taxQuery":{"category":[4]}}} -->
<div class="wp-block-query"><!-- wp:post-template -->
<!-- wp:post-title /-->
<!-- /wp:post-template --></div>
<!-- /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.

I have changed it to AND though it bothers me why OR is working the way I am seeing it in testing 😄

Copy link
Contributor Author

Choose a reason for hiding this comment

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

🤔 In the WP_REST_Posts_Controller class, there is also:

// Enable filtering by both post formats and other taxonomies by combining them with `AND`.
			if ( isset( $args['tax_query'] ) ) {
				$args['tax_query'][] = array(
					'relation' => 'AND',
					$tax_query,
				);
			} else {
				$args['tax_query'] = $tax_query;
			}

https://github.com/WordPress/wordpress-develop/pull/7314/files#diff-48cfdad3b747164ac4b6857186399519dabf913026235575b00ebe5b0dc7169bR383

Copy link
Contributor Author

@carolinan carolinan Sep 18, 2024

Choose a reason for hiding this comment

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

I am badly regretting not documenting why I added this relation in the first place.

Once I get back to work I will continue doing more logging of the different queries:
But I am now thinking that I meant for this to be the relation between the formats.
That I choose 'OR' because the user can query for both 'video' and 'link' and it needs to be 'OR' because a post can only have one format. It always have to list posts that has either 'video' or 'link', never both.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Also I think $tax_query was not a good name for the variable, it too can cause confusion.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

After more testing and logging of $args['tax_query'] in the WP_REST_Posts_Controller class, I found that:

  • Setting the relation on the array to either OR or AND works when the query has two formats such as link and gallery. Because there is only one condition; the relation is not actually used, there are no conditions to create a relation between.

  • Using OR is needed when the query includes standard and a non-default format such as link and gallery, because now there are two conditions.

So that is why the testing earlier showed the same results: I was not testing with a combination of standard.

In the `build_query_vars_from_query_block` function and the `WP_REST_Posts_Controller` class, a query with the `NOT EXISTS` operator is used to exclude all items that have a post format assigned.

This commit removes a `terms` parameter from the two queries, because the terms are redundant when `NOT EXISTS` is used.
When querying for the `format` property in the `build_query_vars_from_query_block` function and the `WP_REST_Posts_Controller` class, the query may be combined with other taxonomy queries. For example, the user may expect the result to be posts with a specific format and a specific category.

Previously, the `relation` parameter in the query was set to `OR`, which should return items that has either the format or the taxonomy.

This commit changes the `relation` to `AND` with the intention to limit the result to items that have both the queried taxonomy and the format.
Validate the that the `format` property passed to the query using the block context is either the default (standard) or a supported post format, registered with `add_theme_support()`.

Compare `format` to the supported formats in  `get_post_format_slugs()` and remove invalid formats.
…en querying for the `format`

When querying for the `format` property in the `WP_REST_Posts_Controller` class,  the `relation` parameter in the query was incorrectly set to `AND`.
This commit changes the relation back to `OR`.

This is needed because when a user queries for a combination of the `standard` post format and any other format, the result should include items with either the given format, or no format (standard).
A post item can not have more than one format.

The commit also renames the variable `$tax_query` to `$formats_query` to improve the readability.
…g for the `format`

When querying for the `format` property in `build_query_vars_from_query_block`, the `relation` parameter in the query was incorrectly set to `AND`.
This commit changes the relation back to `OR`.

This is needed because when a user queries for a combination of the `standard` post format and any other format, the result should include items with either the given format, or no format (standard).
A post item can not have more than one format.

The commit also renames the variable `$tax_query` to `$formats_query` to improve the readability.
This commit corrects inline docBlocks, removes unnecessary string concatenations, and tries to resolve a PHP coding standard issue about the formatting of an array.
When querying for formats, the relation between the format and other taxonomies like categoryíes and tags should be `AND`.

The intention is to allow users to query for a post with a specific category and a specific format.
@noisysocks
Copy link
Member

Hey @carolinan. JavaScript packages were updated in r59072 so you might wish to rebase this for easier testing. The deadline to commit this backport is 6.7 Beta 1 which is scheduled for 1 October.

@peterwilsoncc
Copy link
Contributor

I tested this with the updated packages and was getting a block error when I tried to add the format. Is there something that needs to be merged to the packages in the GB repo before it should work?

query-loop

It's a little confusing with the same variable name in both the legacy query, the tax query so I'm wondering if we can do a little more tidying up there:

diff --git a/src/wp-includes/blocks.php b/src/wp-includes/blocks.php
index f3d138475f..25cb1c0d24 100644
--- a/src/wp-includes/blocks.php
+++ b/src/wp-includes/blocks.php
@@ -2346,6 +2346,7 @@ function build_query_vars_from_query_block( $block, $page ) {
 		'order'        => 'DESC',
 		'orderby'      => 'date',
 		'post__not_in' => array(),
+		'tax_query'    => array(),
 	);
 
 	if ( isset( $block->context['query'] ) ) {
@@ -2395,34 +2396,35 @@ function build_query_vars_from_query_block( $block, $page ) {
 		}
 		// Migrate `categoryIds` and `tagIds` to `tax_query` for backwards compatibility.
 		if ( ! empty( $block->context['query']['categoryIds'] ) || ! empty( $block->context['query']['tagIds'] ) ) {
-			$tax_query = array();
+			$tax_query_back_compat = array();
 			if ( ! empty( $block->context['query']['categoryIds'] ) ) {
-				$tax_query[] = array(
+				$tax_query_back_compat[] = array(
 					'taxonomy'         => 'category',
 					'terms'            => array_filter( array_map( 'intval', $block->context['query']['categoryIds'] ) ),
 					'include_children' => false,
 				);
 			}
 			if ( ! empty( $block->context['query']['tagIds'] ) ) {
-				$tax_query[] = array(
+				$tax_query_back_compat[] = array(
 					'taxonomy'         => 'post_tag',
 					'terms'            => array_filter( array_map( 'intval', $block->context['query']['tagIds'] ) ),
 					'include_children' => false,
 				);
 			}
-			$query['tax_query'] = $tax_query;
+			$query['tax_query'] = array_merge( $query['tax_query'], $tax_query_back_compat );
 		}
 		if ( ! empty( $block->context['query']['taxQuery'] ) ) {
-			$query['tax_query'] = array();
+			$tax_query = array();
 			foreach ( $block->context['query']['taxQuery'] as $taxonomy => $terms ) {
 				if ( is_taxonomy_viewable( $taxonomy ) && ! empty( $terms ) ) {
-					$query['tax_query'][] = array(
+					$tax_query[] = array(
 						'taxonomy'         => $taxonomy,
 						'terms'            => array_filter( array_map( 'intval', $terms ) ),
 						'include_children' => false,
 					);
 				}
 			}
+			$query['tax_query'] = array_merge( $query['tax_query'], $tax_query );
 		}
 		if ( ! empty( $block->context['query']['format'] ) && is_array( $block->context['query']['format'] ) ) {
 			$formats = $block->context['query']['format'];
@@ -2479,13 +2481,14 @@ function build_query_vars_from_query_block( $block, $page ) {
 			 */
 			if ( count( $formats_query ) > 1 ) {
 				// Enable filtering by both post formats and other taxonomies by combining them with `AND`.
-				if ( isset( $query['tax_query'] ) ) {
-					$query['tax_query'][] = array(
+				if ( empty( $query['tax_query'] ) ) {
+					$query['tax_query'] = $formats_query;
+				} else {
+					$query['tax_query'] = array(
 						'relation' => 'AND',
+						$query['tax_query'],
 						$formats_query,
 					);
-				} else {
-					$query['tax_query'] = $formats_query;
 				}
 			}
 		}

However, the code looks good to me in terms of PHP, it's just the blcok crashing that needs to be figured out.

@carolinan
Copy link
Contributor Author

I have submitted a pull request that fixes this bug and it is waiting for review.

@carolinan
Copy link
Contributor Author

carolinan commented Sep 25, 2024

I'm wondering if we can do a little more tidying up there:

I don't mind :)

@carolinan
Copy link
Contributor Author

@peterwilsoncc My only question is about the first array_merge. The previous code replaced $query['tax_query'], the suggested update merges them, I would like to understand why?

-			$query['tax_query'] = $tax_query;
+			$query['tax_query'] = array_merge( $query['tax_query'], $tax_query_back_compat );

carolinan and others added 5 commits September 25, 2024 07:40
…logic

In function `build_query_vars_from_query_block`:
Address feedback from the code review.

- Update the variable name used for the tax query to improve readability.
Inside the condition that migrates category- and tag id's for backwards compatibility, the new variable name for the tax query is `$tax_query_back_compat`.

- Use `array_merge` to merge `$query['tax_query']` with the edited queries inside each condition.

-Update the logic of the if/else statement used to determine wether the `format` parameter should combined with an existing tax query.
The purpose of the update is to:
-Ensure that the `AND` relation between the taxonomies and the post formats is nested at the correct level in the array.
- Improve readability.
One change was not included in the previous commit.
This commit removes the left over `else` because it is incorrect.
In `Tests_Blocks_wpBlock`, five test assertions were failing because the arrays used in the `assertSame` no longer matched the `$query` variable.

The missmatch was caused by an update to the function `build_query_vars_from_query_block`.
This commit updates the arrays in the test to match the function.
@peterwilsoncc
Copy link
Contributor

peterwilsoncc commented Sep 29, 2024

@peterwilsoncc My only question is about the first array_merge. The previous code replaced $query['tax_query'], the suggested update merges them, I would like to understand why?

The suggested change always defined $query['tax_query'] and renamed the variables so they differed for the legacy queries, current query and formats. As a result it needed to merge rather than append the item.

However, I'm glad you asked because I want to double check I didn't just introduce a bug. I'll double check that prior to merge.

@peterwilsoncc
Copy link
Contributor

Merged r59115 / b1db74a

carolinan added a commit to WordPress/gutenberg that referenced this pull request Oct 11, 2024
…oop filter

This pull request copies changes that were made in WordPress core in WordPress/wordpress-develop#7314: The pull request that added the PHP changes related to #64167.

- Improved logic for the use of the `AND`  `relation` key when a user queries for both a format and a taxonomy.
- Improved inline documentation, for clarity and readability.
- Improved validation of the queried formats against the registered formats.
- Misc: renaming of variables for better readability.
carolinan added a commit to WordPress/gutenberg that referenced this pull request Oct 30, 2024
…oop filter (#66037)

This pull request copies changes that were made in WordPress core in WordPress/wordpress-develop#7314: The pull request that added the PHP changes related to #64167.

- Improved logic for the use of the `AND`  `relation` key when a user queries for both a format and a taxonomy.
- Improved inline documentation, for clarity and readability.
- Improved validation of the queried formats against the registered formats.
- Misc: renaming of variables for better readability.


Co-authored-by: carolinan <poena@git.wordpress.org>
Co-authored-by: Mamaduka <mamaduka@git.wordpress.org>
peterwilsoncc pushed a commit to peterwilsoncc/gutenberg-build that referenced this pull request Oct 30, 2024
…oop filter (#66037)

This pull request copies changes that were made in WordPress core in WordPress/wordpress-develop#7314: The pull request that added the PHP changes related to WordPress/gutenberg#64167.

- Improved logic for the use of the `AND`  `relation` key when a user queries for both a format and a taxonomy.
- Improved inline documentation, for clarity and readability.
- Improved validation of the queried formats against the registered formats.
- Misc: renaming of variables for better readability.

Co-authored-by: carolinan <poena@git.wordpress.org>
Co-authored-by: Mamaduka <mamaduka@git.wordpress.org>

Source: WordPress/gutenberg@b95553f
karthick-murugan pushed a commit to karthick-murugan/gutenberg that referenced this pull request Nov 13, 2024
…oop filter (WordPress#66037)

This pull request copies changes that were made in WordPress core in WordPress/wordpress-develop#7314: The pull request that added the PHP changes related to WordPress#64167.

- Improved logic for the use of the `AND`  `relation` key when a user queries for both a format and a taxonomy.
- Improved inline documentation, for clarity and readability.
- Improved validation of the queried formats against the registered formats.
- Misc: renaming of variables for better readability.


Co-authored-by: carolinan <poena@git.wordpress.org>
Co-authored-by: Mamaduka <mamaduka@git.wordpress.org>
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.

5 participants