@@ -206,6 +206,148 @@ function gutenberg_block_type_metadata_multiple_view_scripts( $metadata ) {
206206}
207207add_filter ( 'block_type_metadata ' , 'gutenberg_block_type_metadata_multiple_view_scripts ' );
208208
209+ /**
210+ * Helper function that constructs a WP_Query args array from
211+ * a `Query` block properties.
212+ *
213+ * It's used in QueryLoop, QueryPaginationNumbers and QueryPaginationNext blocks.
214+ *
215+ * `build_query_vars_from_query_block` was introduced in 5.8, for 6.1 we just need
216+ * to update that function and not create a new one.
217+ *
218+ * @param WP_Block $block Block instance.
219+ * @param int $page Current query's page.
220+ *
221+ * @return array Returns the constructed WP_Query arguments.
222+ */
223+ function gutenberg_build_query_vars_from_query_block ( $ block , $ page ) {
224+ $ query = array (
225+ 'post_type ' => 'post ' ,
226+ 'order ' => 'DESC ' ,
227+ 'orderby ' => 'date ' ,
228+ 'post__not_in ' => array (),
229+ );
230+
231+ if ( isset ( $ block ->context ['query ' ] ) ) {
232+ if ( ! empty ( $ block ->context ['query ' ]['postType ' ] ) ) {
233+ $ post_type_param = $ block ->context ['query ' ]['postType ' ];
234+ if ( is_post_type_viewable ( $ post_type_param ) ) {
235+ $ query ['post_type ' ] = $ post_type_param ;
236+ }
237+ }
238+ if ( isset ( $ block ->context ['query ' ]['sticky ' ] ) && ! empty ( $ block ->context ['query ' ]['sticky ' ] ) ) {
239+ $ sticky = get_option ( 'sticky_posts ' );
240+ if ( 'only ' === $ block ->context ['query ' ]['sticky ' ] ) {
241+ /**
242+ * Passing an empty array to post__in will return have_posts() as true (and all posts will be returned).
243+ * Logic should be used before hand to determine if WP_Query should be used in the event that the array
244+ * being passed to post__in is empty.
245+ *
246+ * @see https://core.trac.wordpress.org/ticket/28099
247+ */
248+ $ query ['post__in ' ] = ! empty ( $ sticky ) ? $ sticky : array ( 0 );
249+ $ query ['ignore_sticky_posts ' ] = 1 ;
250+ } else {
251+ $ query ['post__not_in ' ] = array_merge ( $ query ['post__not_in ' ], $ sticky );
252+ }
253+ }
254+ if ( ! empty ( $ block ->context ['query ' ]['exclude ' ] ) ) {
255+ $ excluded_post_ids = array_map ( 'intval ' , $ block ->context ['query ' ]['exclude ' ] );
256+ $ excluded_post_ids = array_filter ( $ excluded_post_ids );
257+ $ query ['post__not_in ' ] = array_merge ( $ query ['post__not_in ' ], $ excluded_post_ids );
258+ }
259+ if (
260+ isset ( $ block ->context ['query ' ]['perPage ' ] ) &&
261+ is_numeric ( $ block ->context ['query ' ]['perPage ' ] )
262+ ) {
263+ $ per_page = absint ( $ block ->context ['query ' ]['perPage ' ] );
264+ $ offset = 0 ;
265+
266+ if (
267+ isset ( $ block ->context ['query ' ]['offset ' ] ) &&
268+ is_numeric ( $ block ->context ['query ' ]['offset ' ] )
269+ ) {
270+ $ offset = absint ( $ block ->context ['query ' ]['offset ' ] );
271+ }
272+
273+ $ query ['offset ' ] = ( $ per_page * ( $ page - 1 ) ) + $ offset ;
274+ $ query ['posts_per_page ' ] = $ per_page ;
275+ }
276+
277+ // We need to migrate `categoryIds` and `tagIds` to `tax_query` for backwards compatibility.
278+ if ( ! empty ( $ block ->context ['query ' ]['categoryIds ' ] ) || ! empty ( $ block ->context ['query ' ]['tagIds ' ] ) ) {
279+ $ tax_query = array ();
280+ if ( ! empty ( $ block ->context ['query ' ]['categoryIds ' ] ) ) {
281+ $ tax_query [] = array (
282+ 'taxonomy ' => 'category ' ,
283+ 'terms ' => array_filter ( array_map ( 'intval ' , $ block ->context ['query ' ]['categoryIds ' ] ) ),
284+ 'include_children ' => false ,
285+ );
286+ }
287+ if ( ! empty ( $ block ->context ['query ' ]['tagIds ' ] ) ) {
288+ $ tax_query [] = array (
289+ 'taxonomy ' => 'post_tag ' ,
290+ 'terms ' => array_filter ( array_map ( 'intval ' , $ block ->context ['query ' ]['tagIds ' ] ) ),
291+ 'include_children ' => false ,
292+ );
293+ }
294+ $ query ['tax_query ' ] = $ tax_query ;
295+ }
296+ if ( ! empty ( $ block ->context ['query ' ]['taxQuery ' ] ) ) {
297+ $ query ['tax_query ' ] = array ();
298+ foreach ( $ block ->context ['query ' ]['taxQuery ' ] as $ taxonomy => $ terms ) {
299+ if ( is_taxonomy_viewable ( $ taxonomy ) && ! empty ( $ terms ) ) {
300+ $ query ['tax_query ' ][] = array (
301+ 'taxonomy ' => $ taxonomy ,
302+ 'terms ' => array_filter ( array_map ( 'intval ' , $ terms ) ),
303+ 'include_children ' => false ,
304+ );
305+ }
306+ }
307+ }
308+ if (
309+ isset ( $ block ->context ['query ' ]['order ' ] ) &&
310+ in_array ( strtoupper ( $ block ->context ['query ' ]['order ' ] ), array ( 'ASC ' , 'DESC ' ), true )
311+ ) {
312+ $ query ['order ' ] = strtoupper ( $ block ->context ['query ' ]['order ' ] );
313+ }
314+ if ( isset ( $ block ->context ['query ' ]['orderBy ' ] ) ) {
315+ $ query ['orderby ' ] = $ block ->context ['query ' ]['orderBy ' ];
316+ }
317+ if ( ! empty ( $ block ->context ['query ' ]['author ' ] ) ) {
318+ $ query ['author ' ] = $ block ->context ['query ' ]['author ' ];
319+ }
320+ if ( ! empty ( $ block ->context ['query ' ]['search ' ] ) ) {
321+ $ query ['s ' ] = $ block ->context ['query ' ]['search ' ];
322+ }
323+ if ( ! empty ( $ block ->context ['query ' ]['parents ' ] ) && is_post_type_hierarchical ( $ query ['post_type ' ] ) ) {
324+ $ query ['post_parent__in ' ] = array_filter ( array_map ( 'intval ' , $ block ->context ['query ' ]['parents ' ] ) );
325+ }
326+ }
327+
328+ /**
329+ * Filters the arguments which will be passed to `WP_Query` for the Query Loop Block.
330+ *
331+ * Anything to this filter should be compatible with the `WP_Query` API to form
332+ * the query context which will be passed down to the Query Loop Block's children.
333+ * This can help, for example, to include additional settings or meta queries not
334+ * directly supported by the core Query Loop Block, and extend its capabilities.
335+ *
336+ * Please note that this will only influence the query that will be rendered on the
337+ * front-end. The editor preview is not affected by this filter. Also, worth noting
338+ * that the editor preview uses the REST API, so, ideally, one should aim to provide
339+ * attributes which are also compatible with the REST API, in order to be able to
340+ * implement identical queries on both sides.
341+ *
342+ * @since 6.1.0
343+ *
344+ * @param array $query Array containing parameters for `WP_Query` as parsed by the block context.
345+ * @param WP_Block $block Block instance.
346+ * @param int $page Current query's page.
347+ */
348+ return apply_filters ( 'query_loop_block_query_vars ' , $ query , $ block , $ page );
349+ }
350+
209351/**
210352 * Register render template for core blocks if handling is missing in WordPress core.
211353 *
0 commit comments