From db7e33fa9587177a9c20348c1d557baabd49577f Mon Sep 17 00:00:00 2001
From: Carolina Nymark <myazalea@hotmail.com>
Date: Wed, 30 Oct 2024 12:00:50 +0100
Subject: [PATCH] Backport from WordPres core: Improvements for the post format
 query loop filter (#66037)

This pull request copies changes that were made in WordPress core in https://github.com/WordPress/wordpress-develop/pull/7314/: The pull request that added the PHP changes related to https://github.com/WordPress/gutenberg/pull/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>
---
 lib/compat/wordpress-6.7/blocks.php           | 62 +++++++++++++------
 ...ss-gutenberg-rest-posts-controller-6-7.php | 38 +++++++-----
 2 files changed, 65 insertions(+), 35 deletions(-)

diff --git a/lib/compat/wordpress-6.7/blocks.php b/lib/compat/wordpress-6.7/blocks.php
index 6b9526f8056fd3..1a8e7f5741c0a1 100644
--- a/lib/compat/wordpress-6.7/blocks.php
+++ b/lib/compat/wordpress-6.7/blocks.php
@@ -59,34 +59,46 @@ function gutenberg_add_format_query_vars_to_query_loop_block( $query, $block ) {
 		return $query;
 	}
 
-	$formats   = $block->context['query']['format'];
-	$tax_query = array( 'relation' => 'OR' );
+	$formats = $block->context['query']['format'];
+	/*
+	 * Validate that the format is either `standard` or a supported post format.
+	 * - First, add `standard` to the array of valid formats.
+	 * - Then, remove any invalid formats.
+	 */
+	$valid_formats = array_merge( array( 'standard' ), get_post_format_slugs() );
+	$formats       = array_intersect( $formats, $valid_formats );
 
-	// The default post format, 'standard', is not stored in the database.
-	// If 'standard' is part of the request, the query needs to exclude all post items that
-	// have a format assigned.
+	/*
+	 * The relation needs to be set to `OR` since the request can contain
+	 * two separate conditions. The user may be querying for items that have
+	 * either the `standard` format or a specific format.
+	 */
+	$formats_query = array( 'relation' => 'OR' );
+
+	/*
+	 * The default post format, `standard`, is not stored in the database.
+	 * If `standard` is part of the request, the query needs to exclude all post items that
+	 * have a format assigned.
+	 */
 	if ( in_array( 'standard', $formats, true ) ) {
-		$tax_query[] = array(
+		$formats_query[] = array(
 			'taxonomy' => 'post_format',
 			'field'    => 'slug',
-			'terms'    => array(),
 			'operator' => 'NOT EXISTS',
 		);
-		// Remove the standard format, since it cannot be queried.
+		// Remove the `standard` format, since it cannot be queried.
 		unset( $formats[ array_search( 'standard', $formats, true ) ] );
 	}
-
-	// Add any remaining formats to the tax query.
+	// Add any remaining formats to the formats query.
 	if ( ! empty( $formats ) ) {
-		// Add the post-format- prefix.
-		$terms = array_map(
+		// Add the `post-format-` prefix.
+		$terms           = array_map(
 			static function ( $format ) {
-				return 'post-format-' . $format;
+				return "post-format-$format";
 			},
 			$formats
 		);
-
-		$tax_query[] = array(
+		$formats_query[] = array(
 			'taxonomy' => 'post_format',
 			'field'    => 'slug',
 			'terms'    => $terms,
@@ -94,10 +106,22 @@ static function ( $format ) {
 		);
 	}
 
-	// This condition is intended to prevent $tax_query from being added to $query
-	// if it only contains the relation.
-	if ( count( $tax_query ) > 1 ) {
-		$query['tax_query'][] = $tax_query;
+	/*
+	 * Add `$formats_query` to `$query`, as long as it contains more than one key:
+	 * If `$formats_query` only contains the initial `relation` key, there are no valid formats to query,
+	 * and the query should not be modified.
+	 */
+	if ( count( $formats_query ) > 1 ) {
+		// Enable filtering by both post formats and other taxonomies by combining them with `AND`.
+		if ( empty( $query['tax_query'] ) ) {
+			$query['tax_query'] = $formats_query;
+		} else {
+			$query['tax_query'] = array(
+				'relation' => 'AND',
+				$query['tax_query'],
+				$formats_query,
+			);
+		}
 	}
 
 	return $query;
diff --git a/lib/compat/wordpress-6.7/class-gutenberg-rest-posts-controller-6-7.php b/lib/compat/wordpress-6.7/class-gutenberg-rest-posts-controller-6-7.php
index c7de4371c94f56..5d3795cf68db76 100644
--- a/lib/compat/wordpress-6.7/class-gutenberg-rest-posts-controller-6-7.php
+++ b/lib/compat/wordpress-6.7/class-gutenberg-rest-posts-controller-6-7.php
@@ -157,34 +157,40 @@ public function get_items( $request ) {
 		$args = $this->prepare_tax_query( $args, $request );
 
 		if ( ! empty( $request['format'] ) ) {
-			$formats   = $request['format'];
-			$tax_query = array( 'relation' => 'OR' );
-
-			// The default post format, 'standard', is not stored in the database.
-			// If 'standard' is part of the request, the query needs to exclude all post items that
-			// have a format assigned.
+			$formats = $request['format'];
+			/*
+			 * The relation needs to be set to `OR` since the request can contain
+			 * two separate conditions. The user may be querying for items that have
+			 * either the `standard` format or a specific format.
+			 */
+			$formats_query = array( 'relation' => 'OR' );
+
+			/*
+			 * The default post format, `standard`, is not stored in the database.
+			 * If `standard` is part of the request, the query needs to exclude all post items that
+			 * have a format assigned.
+			 */
 			if ( in_array( 'standard', $formats, true ) ) {
-				$tax_query[] = array(
+				$formats_query[] = array(
 					'taxonomy' => 'post_format',
 					'field'    => 'slug',
-					'terms'    => array(),
 					'operator' => 'NOT EXISTS',
 				);
-				// Remove the standard format, since it cannot be queried.
+				// Remove the `standard` format, since it cannot be queried.
 				unset( $formats[ array_search( 'standard', $formats, true ) ] );
 			}
 
-			// Add any remaining formats to the tax query.
+			// Add any remaining formats to the formats query.
 			if ( ! empty( $formats ) ) {
-				// Add the post-format- prefix.
+				// Add the `post-format-` prefix.
 				$terms = array_map(
 					static function ( $format ) {
-						return 'post-format-' . $format;
+						return "post-format-$format";
 					},
 					$formats
 				);
 
-				$tax_query[] = array(
+				$formats_query[] = array(
 					'taxonomy' => 'post_format',
 					'field'    => 'slug',
 					'terms'    => $terms,
@@ -192,14 +198,14 @@ static function ( $format ) {
 				);
 			}
 
-			// Enable filtering by both post formats and other taxonomies by combining them with AND.
+			// 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,
+					$formats_query,
 				);
 			} else {
-				$args['tax_query'] = $tax_query;
+				$args['tax_query'] = $formats_query;
 			}
 		}