From 32c3a3ba8829c1b68f9c0acd0cc81032269c7a8a Mon Sep 17 00:00:00 2001 From: Ryan Welcher Date: Thu, 16 Nov 2023 18:38:55 -0500 Subject: [PATCH 01/36] Basic taxonomy controls Updating the query for the block editor. --- includes/query-loop.php | 18 +++- includes/taxonomy.php | 30 ++++++ index.php | 1 + src/components/taxonomy-select.js | 166 ++++++++++++++++++++++++++++++ src/variations/controls.js | 2 + 5 files changed, 214 insertions(+), 3 deletions(-) create mode 100644 includes/taxonomy.php create mode 100644 src/components/taxonomy-select.js diff --git a/includes/query-loop.php b/includes/query-loop.php index a11186d..5f2eebf 100644 --- a/includes/query-loop.php +++ b/includes/query-loop.php @@ -7,6 +7,8 @@ namespace AdvancedQueryLoop; +use function AdvancedQueryLoop\Taxonomy\parse_taxonomy_query; + /** * Adds the custom query attributes to the Query Loop block. * @@ -38,7 +40,7 @@ function parse_meta_query( $meta_query_data ) { /** * Returns an array with Post IDs that should be excluded from the Query. - * + * * @param array * @return array */ @@ -227,6 +229,7 @@ function add_more_sort_by( $query_params, $post_type ) { $query_params['orderby']['enum'][] = 'meta_value'; $query_params['orderby']['enum'][] = 'meta_value_num'; $query_params['orderby']['enum'][] = 'rand'; + // die( '
' .print_r( $query_params , 1 ) .'
' ); return $query_params; } @@ -240,6 +243,12 @@ function add_custom_query_params( $args, $request ) { // Generate a new custom query will all potential query vars. $custom_args = array(); + // Taxonomy Related + $tax_query = $request->get_param( 'tax_query' ); + if ( $tax_query ) { + $custom_args['tax_query'] = parse_taxonomy_query( $tax_query ); + } + // Post Related. $multiple_post_types = $request->get_param( 'multiple_posts' ); if ( $multiple_post_types ) { @@ -313,10 +322,13 @@ function add_custom_query_params( $args, $request ) { $request->get_params(), false, ); - // Merge all queries. - return array_merge( + $merged = array_merge( $args, array_filter( $filtered_query_args ) ); + + // die( var_dump( $request->get_params() ) ); + + return $merged; } diff --git a/includes/taxonomy.php b/includes/taxonomy.php new file mode 100644 index 0000000..2a358e6 --- /dev/null +++ b/includes/taxonomy.php @@ -0,0 +1,30 @@ +term_id; + } + } + return $rtn; +} + +function parse_taxonomy_query( $tax_query_data ) { + return [ + [ + 'taxonomy' => $tax_query_data['taxonomy'], + 'terms' => convert_names_to_ids( $tax_query_data['terms'], $tax_query_data['taxonomy'] ), + 'include_children' => ( ! isset( $tax_query_data['include_children'] ) || 'true' === $tax_query_data['include_children'] ) ? true : false, + 'operator' => $tax_query_data['operator'], + ], + ]; +} diff --git a/index.php b/index.php index 81768e8..f4be303 100644 --- a/index.php +++ b/index.php @@ -25,3 +25,4 @@ // Require some files. require_once __DIR__ . '/includes/enqueues.php'; require_once __DIR__ . '/includes/query-loop.php'; +require_once __DIR__ . '/includes/taxonomy.php'; diff --git a/src/components/taxonomy-select.js b/src/components/taxonomy-select.js new file mode 100644 index 0000000..0a0d6cf --- /dev/null +++ b/src/components/taxonomy-select.js @@ -0,0 +1,166 @@ +/** + * WordPress dependencies + */ +import { + FormTokenField, + SelectControl, + ToggleControl, +} from '@wordpress/components'; +import { __ } from '@wordpress/i18n'; +import { useSelect } from '@wordpress/data'; +import { store as coreStore, useEntityRecords } from '@wordpress/core-data'; +import { useState, useMemo, useEffect } from '@wordpress/element'; +import { useDebounce } from '@wordpress/compose'; + +const operatorOptions = [ 'IN', 'NOT IN', 'EXISTS', 'NOT EXISTS', 'AND' ]; + +export const TaxonomySelect = ( { attributes, setAttributes } ) => { + const { query: { postType, tax_query: taxQuery = {} } = {} } = attributes; + const { + taxonomy = '', + terms = [], + operator, + include_children: includeChildren = true, + } = taxQuery; + + const [ searchTerm, setSearchTerm ] = useState( '' ); + const [ isHierarchical, setIsHierarchical ] = useState( false ); + const debouncedSetSearchTerm = useDebounce( setSearchTerm, 500 ); + + // When there is only 1 term, we need to use the IN operator. + useEffect( () => { + if ( taxonomy && terms.length < 2 && operator !== 'IN' ) { + setAttributes( { + query: { + ...attributes.query, + tax_query: { + ...attributes.query.tax_query, + operator: 'IN', + }, + }, + } ); + } + }, [ attributes, terms, setAttributes, operator, taxonomy ] ); + + useEffect( () => { + if ( ! taxonomy ) { + setAttributes( { + query: { + ...attributes.query, + tax_query: {}, + }, + } ); + } + }, [ taxonomy, setAttributes ] ); + + const taxonomies = useSelect( ( select ) => + select( coreStore ) + .getTaxonomies() + .filter( ( { types } ) => types.includes( postType ) ) + ); + + const { records } = useEntityRecords( 'taxonomy', taxonomy, { + per_page: 10, + search: searchTerm, + _fields: 'id,name', + context: 'view', + } ); + + const suggestions = useMemo( () => { + return ( records ?? [] ).map( ( term ) => term.name ); + }, [ records ] ); + + return ( + <> +

{ __( 'Taxonomy Query', 'advanced-query-loop' ) }

+ { + return { label: name, value: slug }; + } ), + ] } + onChange={ ( newTaxonomy ) => { + setAttributes( { + query: { + ...attributes.query, + tax_query: { + ...attributes.query.taxQuery, + taxonomy: newTaxonomy, + }, + }, + } ); + } } + /> + { taxonomy.length > 1 && ( + <> + { + debouncedSetSearchTerm( newInput ); + } } + onChange={ ( newTerms ) => { + setAttributes( { + query: { + ...attributes.query, + tax_query: { + ...attributes.query.tax_query, + terms: newTerms, + }, + }, + } ); + } } + /> + { + setAttributes( { + query: { + ...attributes.query, + tax_query: { + ...attributes.query.tax_query, + include_children: ! includeChildren, + }, + }, + } ); + } } + help={ __( + 'For hierarchical taxonomies only', + 'advanced-query-loop' + ) } + disabled={ ! isHierarchical } + /> + { + return { label: value, value }; + } ), + ] } + disabled={ terms.length < 2 } + onChange={ ( newOperator ) => { + setAttributes( { + query: { + ...attributes.query, + tax_query: { + ...attributes.query.tax_query, + operator: newOperator, + }, + }, + } ); + } } + /> + + ) } + + ); +}; diff --git a/src/variations/controls.js b/src/variations/controls.js index 7bef066..d278112 100644 --- a/src/variations/controls.js +++ b/src/variations/controls.js @@ -18,6 +18,7 @@ import { PostDateQueryControls } from '../components/post-date-query-controls'; import { MultiplePostSelect } from '../components/multiple-post-select'; import { PostOrderControls } from '../components/post-order-controls'; import { PostExcludeControls } from '../components/post-exclude-controls'; +import { TaxonomySelect } from '../components/taxonomy-select'; /** * Determines if the active variation is this one @@ -54,6 +55,7 @@ const withAdvancedQueryControls = ( BlockEdit ) => ( props ) => { 'advanced-query-loop' ) } > + From 3444cee51ed9898abc70ed2f28c10a76db01cce4 Mon Sep 17 00:00:00 2001 From: Vanja Jelic <1101520+jvanja@users.noreply.github.com> Date: Thu, 21 Sep 2023 14:17:34 +0200 Subject: [PATCH 02/36] Added ACF to the registeredMeta array --- src/components/post-meta-query-controls.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/post-meta-query-controls.js b/src/components/post-meta-query-controls.js index 8ad5c2a..7644294 100644 --- a/src/components/post-meta-query-controls.js +++ b/src/components/post-meta-query-controls.js @@ -31,7 +31,7 @@ export const PostMetaQueryControls = ( { attributes, setAttributes } ) => { const [ selectedPostType ] = useState( postType ); - const registeredMeta = records?.[ 0 ]?.meta || {}; + const registeredMeta = records?.[ 0 ]?.meta || records?.[ 0 ]?.acf || {}; useEffect( () => { // If the post type changes, reset the meta query. From 213dd80af67c794a828b8427f0e85e60cf278e18 Mon Sep 17 00:00:00 2001 From: Ryan Welcher Date: Fri, 29 Dec 2023 14:54:49 -0500 Subject: [PATCH 03/36] Combine multiple custom field sources for the post meta query. --- src/components/post-meta-query-controls.js | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/src/components/post-meta-query-controls.js b/src/components/post-meta-query-controls.js index 7644294..6521e26 100644 --- a/src/components/post-meta-query-controls.js +++ b/src/components/post-meta-query-controls.js @@ -16,6 +16,19 @@ import { useEffect, useState } from '@wordpress/element'; */ import { PostMetaControl } from './post-meta-control'; +/** + * Converts the meta keys from the all sources into a single array. + * + * @param {Array} records + * @return {Array} meta keys + */ +const combineMetaKeys = ( records ) => { + return { + ...records?.[ 0 ]?.meta, + ...records?.[ 0 ]?.acf, + }; +}; + // A component to render a select control for the post meta query. export const PostMetaQueryControls = ( { attributes, setAttributes } ) => { const { @@ -31,7 +44,7 @@ export const PostMetaQueryControls = ( { attributes, setAttributes } ) => { const [ selectedPostType ] = useState( postType ); - const registeredMeta = records?.[ 0 ]?.meta || records?.[ 0 ]?.acf || {}; + const registeredMeta = combineMetaKeys( records ); useEffect( () => { // If the post type changes, reset the meta query. From 4f96c8957ce5af3c90fbbc4907cbc2ee5a68672a Mon Sep 17 00:00:00 2001 From: Ryan Welcher Date: Fri, 17 Nov 2023 10:19:36 -0500 Subject: [PATCH 04/36] Adds order by post ID and fixes a duplicate Order in label. --- src/components/post-order-controls.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/components/post-order-controls.js b/src/components/post-order-controls.js index 3dfeece..967460b 100644 --- a/src/components/post-order-controls.js +++ b/src/components/post-order-controls.js @@ -15,7 +15,7 @@ export const PostOrderControls = ( { attributes, setAttributes } ) => { return ( <> { label: __( 'Menu Order', 'advanced-query-loop' ), value: 'menu_order', }, + { + label: __( 'Post ID', 'advanced-query-loop' ), + value: 'id', + }, ] } onChange={ ( newOrderBy ) => { setAttributes( { From ff24edb9ddb0346caa5f3c2fbe588cac2180697f Mon Sep 17 00:00:00 2001 From: Ryan Welcher Date: Tue, 19 Dec 2023 15:41:03 -0500 Subject: [PATCH 05/36] Reset the meta_query array before processing new meta. See https://github.com/ryanwelcher/advanced-query-loop/issues/29 --- includes/query-loop.php | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/includes/query-loop.php b/includes/query-loop.php index 5f2eebf..f6b6102 100644 --- a/includes/query-loop.php +++ b/includes/query-loop.php @@ -106,6 +106,10 @@ function( $default_query ) use ( $parsed_block ) { // Generate a new custom query will all potential query vars. $query_args = array(); + if ( count( $query_args ) ) { + die( var_dump( $parsed_block['attrs']['query'] , $query_args) ); + } + // Post Related. if ( isset( $block_query['multiple_posts'] ) && ! empty( $block_query['multiple_posts'] ) ) { $query_args['post_type'] = array_merge( array( $default_query['post_type'] ), $block_query['multiple_posts'] ); @@ -118,6 +122,8 @@ function( $default_query ) use ( $parsed_block ) { } // Check for meta queries. + // Ensure any old meta is removed @see https://github.com/ryanwelcher/advanced-query-loop/issues/29 + $query_args['meta_query'] = array(); if ( isset( $block_query['meta_query'] ) && ! empty( $block_query['meta_query'] ) ) { $query_args['meta_query'] = parse_meta_query( $block_query['meta_query'] ); // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_query } From 546ddea5ddbd9214b834680771d95dc77b9b7887 Mon Sep 17 00:00:00 2001 From: Ryan Welcher Date: Fri, 29 Dec 2023 15:04:14 -0500 Subject: [PATCH 06/36] Update readmes and version bumps for release. --- index.php | 2 +- readme.md | 1 + readme.txt | 9 ++++++++- 3 files changed, 10 insertions(+), 2 deletions(-) diff --git a/index.php b/index.php index f4be303..cf99cd5 100644 --- a/index.php +++ b/index.php @@ -3,7 +3,7 @@ * Plugin Name: Advanced Query Loop * Description: Query loop block variations to create custom queries. * Plugin URI: https://github.com/ryanwelcher/advanced-query-loop/ - * Version: 2.0.0 + * Version: 2.1.0 * Requires at least: 6.1 * Requires PHP: 7.2 * Author: Ryan Welcher diff --git a/readme.md b/readme.md index f7fe1c4..b385fc8 100644 --- a/readme.md +++ b/readme.md @@ -46,6 +46,7 @@ Sort in ascending or descending order by: - Meta Value Num - Random - Menu Order ( props to @jvanja ) +- Post ID ( props to @markhowellsmead ) **Please note that this is a slight duplication of the existing sorting controls. They both work interchangeably but it just looks a bit odd in the UI** diff --git a/readme.txt b/readme.txt index 5cb68c8..946b529 100644 --- a/readme.txt +++ b/readme.txt @@ -3,7 +3,7 @@ Contributors: welcher Tags: Query Loop, Custom Queries Requires at least: 6.2 Tested up to: 6.4 -Stable tag: 2.0.0 +Stable tag: 2.1.0 Requires PHP: 7.2 License: GPL v2 or later License URI: https://www.gnu.org/licenses/gpl-2.0.html @@ -44,6 +44,7 @@ Sort in ascending or descending order by: - Meta Value Num - Random - Menu Order ( props to @jvanja ) +- Post ID ( props to @markhowellsmead ) **Please note that this is a slight duplication of the existing sorting controls. They both work interchangeably but it just looks a bit odd in the UI** @@ -54,6 +55,12 @@ Sort in ascending or descending order by: 3. Query posts before a date, after a date or between two dates. == Changelog == += 2.0.0 = +* ACF custom fields now show in the auto-complete dropdown list for Post Meta Queries ( props to @jvanja ) +* Adds sort by Post ID ( props to @markhowellsmead ) +* Fixes a typo in the Order By label. +* Fixes a bug where a second AQL instances was getting post meta query values from the first. + = 2.0.0 = * Due to a change in core, Post Count can no longer be overridden when the block is set to inherit the query. * Adds Exclude current post option. Props to @Pulsar-X From 2a921c7f26784cdfbde7c87993effb94931ba8aa Mon Sep 17 00:00:00 2001 From: Ryan Welcher Date: Fri, 29 Dec 2023 15:04:18 -0500 Subject: [PATCH 07/36] 2.1.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index e0251f3..7e7cf9f 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "advanced-query-loop", - "version": "2.0.0", + "version": "2.1.0", "description": "", "main": "index.js", "scripts": { From 0c61633bfc00a1d8f980eb0d00e74648a242d005 Mon Sep 17 00:00:00 2001 From: Ryan Welcher Date: Fri, 29 Dec 2023 15:51:05 -0500 Subject: [PATCH 08/36] Update readme. --- readme.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/readme.txt b/readme.txt index 946b529..361a3fa 100644 --- a/readme.txt +++ b/readme.txt @@ -55,7 +55,7 @@ Sort in ascending or descending order by: 3. Query posts before a date, after a date or between two dates. == Changelog == -= 2.0.0 = += 2.1.0 = * ACF custom fields now show in the auto-complete dropdown list for Post Meta Queries ( props to @jvanja ) * Adds sort by Post ID ( props to @markhowellsmead ) * Fixes a typo in the Order By label. From 99cc3ee3beb0958d8394f4b02f403fc4abb029ba Mon Sep 17 00:00:00 2001 From: Ryan Welcher Date: Tue, 20 Feb 2024 10:08:46 -0500 Subject: [PATCH 09/36] Gitignore test artifacts --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 5d35add..82dc413 100644 --- a/.gitignore +++ b/.gitignore @@ -8,3 +8,4 @@ DNU /vendor/ composer.lock .phpunit.* +artifacts From 59c6c7159074b28cdbef1a4d44d19e13415cfee8 Mon Sep 17 00:00:00 2001 From: Ryan Welcher Date: Wed, 13 Mar 2024 15:26:17 -0400 Subject: [PATCH 10/36] Retrieve the query from the passed block via the filter. --- includes/query-loop.php | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/includes/query-loop.php b/includes/query-loop.php index f6b6102..1d88196 100644 --- a/includes/query-loop.php +++ b/includes/query-loop.php @@ -49,7 +49,7 @@ function get_exclude_ids( $attributes ) { // Exclude Current Post. if ( isset( $attributes['exclude_current'] ) && boolval( $attributes['exclude_current'] ) ) { - array_push( $exclude_ids, $attributes['exclude_current']); + array_push( $exclude_ids, $attributes['exclude_current'] ); } return $exclude_ids; @@ -101,15 +101,13 @@ function( $pre_render, $parsed_block ) { } else { \add_filter( 'query_loop_block_query_vars', - function( $default_query ) use ( $parsed_block ) { - $block_query = $parsed_block['attrs']['query']; + function( $default_query, $block ) { + // Retrieve the query from the passed block context. + $block_query = $block->context['query']; + // Generate a new custom query will all potential query vars. $query_args = array(); - if ( count( $query_args ) ) { - die( var_dump( $parsed_block['attrs']['query'] , $query_args) ); - } - // Post Related. if ( isset( $block_query['multiple_posts'] ) && ! empty( $block_query['multiple_posts'] ) ) { $query_args['post_type'] = array_merge( array( $default_query['post_type'] ), $block_query['multiple_posts'] ); @@ -117,7 +115,7 @@ function( $default_query ) use ( $parsed_block ) { // Exclude Posts. $exclude_ids = get_exclude_ids( $block_query ); - if ( ! empty( $exclude_ids ) ) { + if ( ! empty( $exclude_ids ) ) { $query_args['post__not_in'] = $exclude_ids; } From afc1bf20ad6558e5e17433c063cf676278e7efca Mon Sep 17 00:00:00 2001 From: Ryan Welcher Date: Wed, 13 Mar 2024 15:31:29 -0400 Subject: [PATCH 11/36] Bump to 2.1.1 --- index.php | 2 +- package.json | 2 +- readme.txt | 5 ++++- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/index.php b/index.php index cf99cd5..f5e24c9 100644 --- a/index.php +++ b/index.php @@ -3,7 +3,7 @@ * Plugin Name: Advanced Query Loop * Description: Query loop block variations to create custom queries. * Plugin URI: https://github.com/ryanwelcher/advanced-query-loop/ - * Version: 2.1.0 + * Version: 2.1.1 * Requires at least: 6.1 * Requires PHP: 7.2 * Author: Ryan Welcher diff --git a/package.json b/package.json index 7e7cf9f..c5f7682 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "advanced-query-loop", - "version": "2.1.0", + "version": "2.1.1", "description": "", "main": "index.js", "scripts": { diff --git a/readme.txt b/readme.txt index 361a3fa..8d5e2e2 100644 --- a/readme.txt +++ b/readme.txt @@ -3,7 +3,7 @@ Contributors: welcher Tags: Query Loop, Custom Queries Requires at least: 6.2 Tested up to: 6.4 -Stable tag: 2.1.0 +Stable tag: 2.1.1 Requires PHP: 7.2 License: GPL v2 or later License URI: https://www.gnu.org/licenses/gpl-2.0.html @@ -55,6 +55,9 @@ Sort in ascending or descending order by: 3. Query posts before a date, after a date or between two dates. == Changelog == += 2.1.1 = +* Fixes issue with multiple AQL instances having settings leaked to each other. + = 2.1.0 = * ACF custom fields now show in the auto-complete dropdown list for Post Meta Queries ( props to @jvanja ) * Adds sort by Post ID ( props to @markhowellsmead ) From 4c14dc7eba953f3a584ae16dcb397f90321bc897 Mon Sep 17 00:00:00 2001 From: Ryan Welcher Date: Thu, 14 Mar 2024 13:37:19 -0400 Subject: [PATCH 12/36] Add env config. --- .wp-env.json | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 .wp-env.json diff --git a/.wp-env.json b/.wp-env.json new file mode 100644 index 0000000..9fc27dd --- /dev/null +++ b/.wp-env.json @@ -0,0 +1,9 @@ +{ + "core": "WordPress/WordPress", + "plugins": [ "." ], + "env": { + "tests": { + "phpVersion": "8.1" + } + } +} From 123f9a813acff9aa6107832805bb74c8bdd12f81 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Viktor=20Sz=C3=A9pe?= Date: Fri, 13 Jan 2023 01:12:27 +0000 Subject: [PATCH 13/36] Put global constants in namespace --- index.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/index.php b/index.php index f5e24c9..fb42fc3 100644 --- a/index.php +++ b/index.php @@ -19,8 +19,8 @@ namespace AdvancedQueryLoop; // Some helpful constants. -define( 'BUILD_DIR_PATH', plugin_dir_path( __FILE__ ) . 'build/' ); -define( 'BUILD_DIR_URL', plugin_dir_url( __FILE__ ) . 'build/' ); +const BUILD_DIR_PATH = plugin_dir_path( __FILE__ ) . 'build/'; +const BUILD_DIR_URL = plugin_dir_url( __FILE__ ) . 'build/'; // Require some files. require_once __DIR__ . '/includes/enqueues.php'; From afc623813f355dcdba797c7a2a5464fdc815a33f Mon Sep 17 00:00:00 2001 From: Ryan Welcher Date: Thu, 14 Mar 2024 15:09:39 -0400 Subject: [PATCH 14/36] Revert "Put global constants in namespace" --- index.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/index.php b/index.php index fb42fc3..f5e24c9 100644 --- a/index.php +++ b/index.php @@ -19,8 +19,8 @@ namespace AdvancedQueryLoop; // Some helpful constants. -const BUILD_DIR_PATH = plugin_dir_path( __FILE__ ) . 'build/'; -const BUILD_DIR_URL = plugin_dir_url( __FILE__ ) . 'build/'; +define( 'BUILD_DIR_PATH', plugin_dir_path( __FILE__ ) . 'build/' ); +define( 'BUILD_DIR_URL', plugin_dir_url( __FILE__ ) . 'build/' ); // Require some files. require_once __DIR__ . '/includes/enqueues.php'; From 21e40234dd8096e7acc080d2a5c8aedbbf36fb44 Mon Sep 17 00:00:00 2001 From: Ryan Welcher Date: Thu, 16 Nov 2023 18:38:55 -0500 Subject: [PATCH 15/36] Basic taxonomy controls Updating the query for the block editor. --- includes/query-loop.php | 8 +- includes/taxonomy.php | 30 ++++++ src/components/taxonomy-select.js | 166 ++++++++++++++++++++++++++++++ src/variations/controls.js | 2 + 4 files changed, 204 insertions(+), 2 deletions(-) create mode 100644 includes/taxonomy.php create mode 100644 src/components/taxonomy-select.js diff --git a/includes/query-loop.php b/includes/query-loop.php index 547c4fb..c246df6 100644 --- a/includes/query-loop.php +++ b/includes/query-loop.php @@ -128,6 +128,7 @@ function add_more_sort_by( $query_params ) { $query_params['orderby']['enum'][] = 'post__in'; $query_params['orderby']['enum'][] = 'comment_count'; $query_params['orderby']['enum'][] = 'name'; + // die( '
' .print_r( $query_params , 1 ) .'
' ); return $query_params; } @@ -151,10 +152,13 @@ function add_custom_query_params( $args, $request ) { $request->get_params(), false, ); - // Merge all queries. - return array_merge( + $merged = array_merge( $args, array_filter( $filtered_query_args ) ); + + // die( var_dump( $request->get_params() ) ); + + return $merged; } diff --git a/includes/taxonomy.php b/includes/taxonomy.php new file mode 100644 index 0000000..2a358e6 --- /dev/null +++ b/includes/taxonomy.php @@ -0,0 +1,30 @@ +term_id; + } + } + return $rtn; +} + +function parse_taxonomy_query( $tax_query_data ) { + return [ + [ + 'taxonomy' => $tax_query_data['taxonomy'], + 'terms' => convert_names_to_ids( $tax_query_data['terms'], $tax_query_data['taxonomy'] ), + 'include_children' => ( ! isset( $tax_query_data['include_children'] ) || 'true' === $tax_query_data['include_children'] ) ? true : false, + 'operator' => $tax_query_data['operator'], + ], + ]; +} diff --git a/src/components/taxonomy-select.js b/src/components/taxonomy-select.js new file mode 100644 index 0000000..0a0d6cf --- /dev/null +++ b/src/components/taxonomy-select.js @@ -0,0 +1,166 @@ +/** + * WordPress dependencies + */ +import { + FormTokenField, + SelectControl, + ToggleControl, +} from '@wordpress/components'; +import { __ } from '@wordpress/i18n'; +import { useSelect } from '@wordpress/data'; +import { store as coreStore, useEntityRecords } from '@wordpress/core-data'; +import { useState, useMemo, useEffect } from '@wordpress/element'; +import { useDebounce } from '@wordpress/compose'; + +const operatorOptions = [ 'IN', 'NOT IN', 'EXISTS', 'NOT EXISTS', 'AND' ]; + +export const TaxonomySelect = ( { attributes, setAttributes } ) => { + const { query: { postType, tax_query: taxQuery = {} } = {} } = attributes; + const { + taxonomy = '', + terms = [], + operator, + include_children: includeChildren = true, + } = taxQuery; + + const [ searchTerm, setSearchTerm ] = useState( '' ); + const [ isHierarchical, setIsHierarchical ] = useState( false ); + const debouncedSetSearchTerm = useDebounce( setSearchTerm, 500 ); + + // When there is only 1 term, we need to use the IN operator. + useEffect( () => { + if ( taxonomy && terms.length < 2 && operator !== 'IN' ) { + setAttributes( { + query: { + ...attributes.query, + tax_query: { + ...attributes.query.tax_query, + operator: 'IN', + }, + }, + } ); + } + }, [ attributes, terms, setAttributes, operator, taxonomy ] ); + + useEffect( () => { + if ( ! taxonomy ) { + setAttributes( { + query: { + ...attributes.query, + tax_query: {}, + }, + } ); + } + }, [ taxonomy, setAttributes ] ); + + const taxonomies = useSelect( ( select ) => + select( coreStore ) + .getTaxonomies() + .filter( ( { types } ) => types.includes( postType ) ) + ); + + const { records } = useEntityRecords( 'taxonomy', taxonomy, { + per_page: 10, + search: searchTerm, + _fields: 'id,name', + context: 'view', + } ); + + const suggestions = useMemo( () => { + return ( records ?? [] ).map( ( term ) => term.name ); + }, [ records ] ); + + return ( + <> +

{ __( 'Taxonomy Query', 'advanced-query-loop' ) }

+ { + return { label: name, value: slug }; + } ), + ] } + onChange={ ( newTaxonomy ) => { + setAttributes( { + query: { + ...attributes.query, + tax_query: { + ...attributes.query.taxQuery, + taxonomy: newTaxonomy, + }, + }, + } ); + } } + /> + { taxonomy.length > 1 && ( + <> + { + debouncedSetSearchTerm( newInput ); + } } + onChange={ ( newTerms ) => { + setAttributes( { + query: { + ...attributes.query, + tax_query: { + ...attributes.query.tax_query, + terms: newTerms, + }, + }, + } ); + } } + /> + { + setAttributes( { + query: { + ...attributes.query, + tax_query: { + ...attributes.query.tax_query, + include_children: ! includeChildren, + }, + }, + } ); + } } + help={ __( + 'For hierarchical taxonomies only', + 'advanced-query-loop' + ) } + disabled={ ! isHierarchical } + /> + { + return { label: value, value }; + } ), + ] } + disabled={ terms.length < 2 } + onChange={ ( newOperator ) => { + setAttributes( { + query: { + ...attributes.query, + tax_query: { + ...attributes.query.tax_query, + operator: newOperator, + }, + }, + } ); + } } + /> + + ) } + + ); +}; diff --git a/src/variations/controls.js b/src/variations/controls.js index 32ac2de..7249ac2 100644 --- a/src/variations/controls.js +++ b/src/variations/controls.js @@ -21,6 +21,7 @@ import { PostExcludeControls } from '../components/post-exclude-controls'; import { PostIncludeControls } from '../components/post-include-controls'; import { ExcludeTaxonomies } from '../components/exclude-taxonomies'; import { PaginationToggle } from '../components/pagination-toggle'; +import { TaxonomySelect } from '../components/taxonomy-select'; /** * Determines if the active variation is this one @@ -61,6 +62,7 @@ const withAdvancedQueryControls = ( BlockEdit ) => ( props ) => { fillProps={ { ...props } } /> + From 5118bbd69f1434bdf1f62bac2cbac2684819848c Mon Sep 17 00:00:00 2001 From: Ryan Welcher Date: Fri, 29 Dec 2023 15:04:14 -0500 Subject: [PATCH 16/36] Update readmes and version bumps for release. --- readme.txt | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/readme.txt b/readme.txt index 27ea209..08d3780 100644 --- a/readme.txt +++ b/readme.txt @@ -121,6 +121,12 @@ Sort in ascending or descending order by: * Fixes a typo in the Order By label. * Fixes a bug where a second AQL instances was getting post meta query values from the first. += 2.0.0 = +* ACF custom fields now show in the auto-complete dropdown list for Post Meta Queries ( props to @jvanja ) +* Adds sort by Post ID ( props to @markhowellsmead ) +* Fixes a typo in the Order By label. +* Fixes a bug where a second AQL instances was getting post meta query values from the first. + = 2.0.0 = * Due to a change in core, Post Count can no longer be overridden when the block is set to inherit the query. * Adds Exclude current post option. Props to @Pulsar-X From dc83058b9e1711e21e22a5bab933641feaa4cb2c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Viktor=20Sz=C3=A9pe?= Date: Fri, 13 Jan 2023 01:12:27 +0000 Subject: [PATCH 17/36] Put global constants in namespace --- index.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/index.php b/index.php index b03f8d3..4e33ff6 100644 --- a/index.php +++ b/index.php @@ -19,8 +19,8 @@ namespace AdvancedQueryLoop; // Some helpful constants. -define( 'BUILD_DIR_PATH', plugin_dir_path( __FILE__ ) . 'build/' ); -define( 'BUILD_DIR_URL', plugin_dir_url( __FILE__ ) . 'build/' ); +const BUILD_DIR_PATH = plugin_dir_path( __FILE__ ) . 'build/'; +const BUILD_DIR_URL = plugin_dir_url( __FILE__ ) . 'build/'; // Prevent direct access. defined( 'ABSPATH' ) || exit; From 7dc89347bd129124a4de89183f039956b741fd66 Mon Sep 17 00:00:00 2001 From: Ryan Welcher Date: Thu, 14 Mar 2024 15:09:39 -0400 Subject: [PATCH 18/36] Revert "Put global constants in namespace" --- index.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/index.php b/index.php index 4e33ff6..b03f8d3 100644 --- a/index.php +++ b/index.php @@ -19,8 +19,8 @@ namespace AdvancedQueryLoop; // Some helpful constants. -const BUILD_DIR_PATH = plugin_dir_path( __FILE__ ) . 'build/'; -const BUILD_DIR_URL = plugin_dir_url( __FILE__ ) . 'build/'; +define( 'BUILD_DIR_PATH', plugin_dir_path( __FILE__ ) . 'build/' ); +define( 'BUILD_DIR_URL', plugin_dir_url( __FILE__ ) . 'build/' ); // Prevent direct access. defined( 'ABSPATH' ) || exit; From c57f072fd5555d907b57cb2307deb1ed2b6d3fc0 Mon Sep 17 00:00:00 2001 From: Ryan Welcher Date: Thu, 21 Nov 2024 12:01:06 -0500 Subject: [PATCH 19/36] Add controls in a modal for now --- src/components/single-taxonomy-control.js | 179 ++++++++++++++++ src/components/taxonomy-select.js | 241 +++++++++------------- src/hooks/useDebouncedInputValue.js | 16 ++ src/variations/controls.js | 3 +- 4 files changed, 294 insertions(+), 145 deletions(-) create mode 100644 src/components/single-taxonomy-control.js create mode 100644 src/hooks/useDebouncedInputValue.js diff --git a/src/components/single-taxonomy-control.js b/src/components/single-taxonomy-control.js new file mode 100644 index 0000000..3e42c00 --- /dev/null +++ b/src/components/single-taxonomy-control.js @@ -0,0 +1,179 @@ +/** + * WordPress dependencies + */ +import { + FormTokenField, + SelectControl, + ToggleControl, +} from '@wordpress/components'; +import { __ } from '@wordpress/i18n'; +import { useSelect } from '@wordpress/data'; +import { store as coreStore, useEntityRecords } from '@wordpress/core-data'; +import { useMemo } from '@wordpress/element'; + +/** + * Internal dependencies + */ +import useDebouncedInputValue from '../hooks/useDebouncedInputValue'; +const operatorOptions = [ 'IN', 'NOT IN', 'EXISTS', 'NOT EXISTS', 'AND' ]; + +const updateTaxonomyQuery = ( queries, queryId, item, value ) => { + return queries.map( ( query ) => { + if ( query.id === queryId ) { + return { + ...query, + [ item ]: value, + }; + } + return query; + } ); +}; + +const SingleTaxonomyControl = ( { + taxonomy, + terms = [], + availableTaxonomies, + includeChildren, + setAttributes, + attributes, + id, + operator, +} ) => { + const [ searchTerm, setSearchTerm ] = useDebouncedInputValue( '', 500 ); + const taxInfo = useSelect( ( select ) => + select( coreStore ).getTaxonomy( taxonomy ) + ); + + const isHierarchical = taxInfo?.hierarchical ?? false; + + const { records } = useEntityRecords( 'taxonomy', taxonomy, { + per_page: 10, + search: searchTerm, + _fields: 'id,name', + context: 'view', + } ); + + const suggestions = useMemo( () => { + return ( records ?? [] ).map( ( term ) => term.name ); + }, [ records ] ); + + return ( + <> + { + return { + label: name, + value: slug, + }; + } ), + ] } + onChange={ ( newTaxonomy ) => { + setAttributes( { + query: { + ...attributes.query, + tax_query: { + ...attributes.query.tax_query, + queries: updateTaxonomyQuery( + attributes.query.tax_query.queries, + id, + 'taxonomy', + newTaxonomy + ), + }, + }, + } ); + } } + /> + { taxonomy.length > 1 && ( + <> + { + setSearchTerm( newInput ); + } } + onChange={ ( newTerms ) => { + setAttributes( { + query: { + ...attributes.query, + tax_query: { + ...attributes.query.tax_query, + queries: updateTaxonomyQuery( + attributes.query.tax_query.queries, + id, + 'terms', + newTerms + ), + }, + }, + } ); + } } + /> + { + return { label: value, value }; + } ), + ] } + onChange={ ( newOperator ) => { + setAttributes( { + query: { + ...attributes.query, + tax_query: { + ...attributes.query.tax_query, + queries: updateTaxonomyQuery( + attributes.query.tax_query.queries, + id, + 'operator', + newOperator + ), + }, + }, + } ); + } } + /> + { isHierarchical && ( + { + setAttributes( { + query: { + ...attributes.query, + tax_query: { + ...attributes.query.tax_query, + queries: updateTaxonomyQuery( + attributes.query.tax_query + .queries, + id, + 'include_children', + ! includeChildren + ), + }, + }, + } ); + } } + help={ __( + 'For hierarchical taxonomies only', + 'advanced-query-loop' + ) } + /> + ) } + + ) } + + ); +}; + +export default SingleTaxonomyControl; diff --git a/src/components/taxonomy-select.js b/src/components/taxonomy-select.js index 0a0d6cf..7c338ed 100644 --- a/src/components/taxonomy-select.js +++ b/src/components/taxonomy-select.js @@ -1,165 +1,120 @@ +/** + * External dependencies + */ +import { v4 as uuidv4 } from 'uuid'; + /** * WordPress dependencies */ -import { - FormTokenField, - SelectControl, - ToggleControl, -} from '@wordpress/components'; +import { Modal, Button, ButtonGroup } from '@wordpress/components'; import { __ } from '@wordpress/i18n'; import { useSelect } from '@wordpress/data'; -import { store as coreStore, useEntityRecords } from '@wordpress/core-data'; -import { useState, useMemo, useEffect } from '@wordpress/element'; -import { useDebounce } from '@wordpress/compose'; +import { store as coreStore } from '@wordpress/core-data'; +import { useState } from '@wordpress/element'; + +/** + * Internal dependencies + */ -const operatorOptions = [ 'IN', 'NOT IN', 'EXISTS', 'NOT EXISTS', 'AND' ]; +import SingleTaxonomyControl from './single-taxonomy-control'; export const TaxonomySelect = ( { attributes, setAttributes } ) => { - const { query: { postType, tax_query: taxQuery = {} } = {} } = attributes; const { - taxonomy = '', - terms = [], - operator, - include_children: includeChildren = true, - } = taxQuery; + query: { + postType, + tax_query: { relation = '', queries = [] } = {}, + } = {}, + } = attributes; - const [ searchTerm, setSearchTerm ] = useState( '' ); - const [ isHierarchical, setIsHierarchical ] = useState( false ); - const debouncedSetSearchTerm = useDebounce( setSearchTerm, 500 ); + const [ isOpen, setOpen ] = useState( false ); + const openModal = () => setOpen( true ); + const closeModal = () => setOpen( false ); - // When there is only 1 term, we need to use the IN operator. - useEffect( () => { - if ( taxonomy && terms.length < 2 && operator !== 'IN' ) { - setAttributes( { - query: { - ...attributes.query, - tax_query: { - ...attributes.query.tax_query, - operator: 'IN', - }, - }, - } ); - } - }, [ attributes, terms, setAttributes, operator, taxonomy ] ); - - useEffect( () => { - if ( ! taxonomy ) { - setAttributes( { - query: { - ...attributes.query, - tax_query: {}, - }, - } ); - } - }, [ taxonomy, setAttributes ] ); - - const taxonomies = useSelect( ( select ) => + const availableTaxonomies = useSelect( ( select ) => select( coreStore ) .getTaxonomies() - .filter( ( { types } ) => types.includes( postType ) ) + ?.filter( ( { types } ) => types.includes( postType ) ) ); - const { records } = useEntityRecords( 'taxonomy', taxonomy, { - per_page: 10, - search: searchTerm, - _fields: 'id,name', - context: 'view', - } ); - - const suggestions = useMemo( () => { - return ( records ?? [] ).map( ( term ) => term.name ); - }, [ records ] ); - return ( <> -

{ __( 'Taxonomy Query', 'advanced-query-loop' ) }

- { - return { label: name, value: slug }; - } ), - ] } - onChange={ ( newTaxonomy ) => { - setAttributes( { - query: { - ...attributes.query, - tax_query: { - ...attributes.query.taxQuery, - taxonomy: newTaxonomy, - }, - }, - } ); - } } - /> - { taxonomy.length > 1 && ( - <> - { - debouncedSetSearchTerm( newInput ); - } } - onChange={ ( newTerms ) => { - setAttributes( { - query: { - ...attributes.query, - tax_query: { - ...attributes.query.tax_query, - terms: newTerms, - }, - }, - } ); - } } - /> - { - setAttributes( { - query: { - ...attributes.query, - tax_query: { - ...attributes.query.tax_query, - include_children: ! includeChildren, + +
+ { isOpen && ( + + { queries.map( + ( { + id, + taxonomy, + terms, + include_children: includeChildren, + operator, + } ) => { + return ( + + ); + } + ) } + + + + + ) } ); diff --git a/src/hooks/useDebouncedInputValue.js b/src/hooks/useDebouncedInputValue.js new file mode 100644 index 0000000..6667cf1 --- /dev/null +++ b/src/hooks/useDebouncedInputValue.js @@ -0,0 +1,16 @@ +/** + * WordPress Dependencies + */ +import { useState } from '@wordpress/element'; +import { useDebounce } from '@wordpress/compose'; + +const useDebouncedInputValue = ( defaultVal, debounceTimeout ) => { + const [ searchTerm, setSearchTerm ] = useState( defaultVal ); + const debouncedSetSearchTerm = useDebounce( + setSearchTerm, + debounceTimeout + ); + return [ searchTerm, debouncedSetSearchTerm ]; +}; + +export default useDebouncedInputValue; diff --git a/src/variations/controls.js b/src/variations/controls.js index 966c434..8c43b75 100644 --- a/src/variations/controls.js +++ b/src/variations/controls.js @@ -22,7 +22,6 @@ import { TaxonomySelect } from '../components/taxonomy-select'; import { PostIncludeControls } from '../components/post-include-controls'; import { ExcludeTaxonomies } from '../components/exclude-taxonomies'; import { PaginationToggle } from '../components/pagination-toggle'; -import { TaxonomySelect } from '../components/taxonomy-select'; /** * Determines if the active variation is this one @@ -63,11 +62,11 @@ const withAdvancedQueryControls = ( BlockEdit ) => ( props ) => { fillProps={ { ...props } } /> - + From 6bc3cfc52af0a36ed9c237e15d69a999fa46c394 Mon Sep 17 00:00:00 2001 From: Ryan Welcher Date: Thu, 28 Nov 2024 15:47:39 -0500 Subject: [PATCH 20/36] Add the __nextHasNoMarginBottom to the console will stop yelling at me. --- src/components/exclude-taxonomies.js | 2 ++ src/components/multiple-post-select.js | 2 ++ src/components/pagination-toggle.js | 1 + src/components/post-date-query-controls.js | 2 ++ src/components/post-exclude-controls.js | 1 + src/components/post-include-controls.js | 2 ++ src/components/post-meta-control.js | 5 ++++- src/components/post-meta-query-controls.js | 1 + src/components/post-order-controls.js | 2 ++ 9 files changed, 17 insertions(+), 1 deletion(-) diff --git a/src/components/exclude-taxonomies.js b/src/components/exclude-taxonomies.js index 1ee3bfb..7fc8ef0 100644 --- a/src/components/exclude-taxonomies.js +++ b/src/components/exclude-taxonomies.js @@ -59,6 +59,7 @@ export const ExcludeTaxonomies = ( { attributes, setAttributes } ) => { 'Choose taxonomies to exclude from the query.', 'advanced-query-loop' ) } + __nextHasNoMarginBottom > { } } __experimentalExpandOnFocus __experimentalShowHowTo={ false } + __nextHasNoMarginBottom /> ); diff --git a/src/components/multiple-post-select.js b/src/components/multiple-post-select.js index 3dbc4b7..31906a0 100644 --- a/src/components/multiple-post-select.js +++ b/src/components/multiple-post-select.js @@ -26,6 +26,7 @@ export const MultiplePostSelect = ( { attributes, setAttributes } ) => { 'These post types will be queried in addition to the main post type.', 'advanced-query-loop' ) } + __nextHasNoMarginBottom > { } } __experimentalExpandOnFocus __experimentalShowHowTo={ false } + __nextHasNoMarginBottom /> ); diff --git a/src/components/pagination-toggle.js b/src/components/pagination-toggle.js index d654527..054151c 100644 --- a/src/components/pagination-toggle.js +++ b/src/components/pagination-toggle.js @@ -24,6 +24,7 @@ export const PaginationToggle = ( { attributes, setAttributes } ) => { }, } ); } } + __nextHasNoMarginBottom /> ); }; diff --git a/src/components/post-date-query-controls.js b/src/components/post-date-query-controls.js index 12c5316..a30d8df 100644 --- a/src/components/post-date-query-controls.js +++ b/src/components/post-date-query-controls.js @@ -66,6 +66,7 @@ export const PostDateQueryControls = ( { attributes, setAttributes } ) => { }, } ); } } + __nextHasNoMarginBottom /> { range !== '' && ( { }, } ); } } + __nextHasNoMarginBottom /> { relationFromQuery !== '' && ( <> diff --git a/src/components/post-exclude-controls.js b/src/components/post-exclude-controls.js index 7fc3949..4296f80 100644 --- a/src/components/post-exclude-controls.js +++ b/src/components/post-exclude-controls.js @@ -70,6 +70,7 @@ export const PostExcludeControls = ( { attributes, setAttributes } ) => { 'advanced-query-loop' ) } + __nextHasNoMarginBottom /> ); diff --git a/src/components/post-include-controls.js b/src/components/post-include-controls.js index 7b44e43..f4c3b25 100644 --- a/src/components/post-include-controls.js +++ b/src/components/post-include-controls.js @@ -96,6 +96,7 @@ export const PostIncludeControls = ( { attributes, setAttributes } ) => { 'Start typing to search for a post title or manually enter one.', 'advanced-query-loop' ) } + __nextHasNoMarginBottom > { } } __experimentalExpandOnFocus __experimentalShowHowTo={ false } + __nextHasNoMarginBottom /> diff --git a/src/components/post-meta-control.js b/src/components/post-meta-control.js index c390122..89b34b6 100644 --- a/src/components/post-meta-control.js +++ b/src/components/post-meta-control.js @@ -67,6 +67,7 @@ export const PostMetaControl = ( { 'Start typing to search for a meta key or manually enter one.', 'advanced-query-loop' ) } + __nextHasNoMarginBottom > -
- { isOpen && ( - - { queries.map( - ( { - id, - taxonomy, - terms, - include_children: includeChildren, - operator, - } ) => { - return ( - - ); - } - ) } - + ( + <> - - - - ) } + + { queries.map( + ( { id, taxonomy, terms, operator } ) => { + return ( + + ); + } + ) } + + setToggled( ! toggled ) } + __nextHasNoMarginBottom={ false } + /> + + + + { + switch ( tab.name ) { + case 'simple': { + return ( + + { queries.map( + ( { + id, + taxonomy, + terms, + operator, + } ) => { + return ( + + ); + } + ) } + + + + + + + + ); + } + case 'advanced': { + return null; + return ( + + { queries.map( + ( { + id, + taxonomy, + terms, + include_children: + includeChildren, + operator, + } ) => { + return ( + + ); + } + ) } + + + + + + ); + } + } + } } + /> + + ) } + /> ); }; From 4210dd9f78e16ed0937d1ecb748b3404668e75f7 Mon Sep 17 00:00:00 2001 From: Ryan Welcher Date: Fri, 29 Nov 2024 11:26:53 -0500 Subject: [PATCH 23/36] Add the trait and process for meta_query. --- includes/Query_Params_Generator.php | 4 +++- includes/Traits/Tax_Query.php | 33 +++++++++++++++++++++++++++++ 2 files changed, 36 insertions(+), 1 deletion(-) create mode 100644 includes/Traits/Tax_Query.php diff --git a/includes/Query_Params_Generator.php b/includes/Query_Params_Generator.php index 5f30139..5c90c0d 100644 --- a/includes/Query_Params_Generator.php +++ b/includes/Query_Params_Generator.php @@ -19,6 +19,7 @@ class Query_Params_Generator { use Traits\Date_Query; use Traits\Exclude_Taxonomies; use Traits\Disable_Pagination; + use Traits\Tax_Query; /** @@ -32,6 +33,7 @@ class Query_Params_Generator { 'date_query', 'exclude_taxonomies', 'disable_pagination', + 'tax_query', ); /** @@ -71,7 +73,7 @@ public function __construct( $default_params, $custom_params ) { * * @param string $param_name The param to look for. */ - public function has_custom_param( string $param_name ): bool { + public function has_custom_param( string $param_name): bool { return array_key_exists( $param_name, $this->custom_params ) && ! empty( $this->custom_params[ $param_name ] ); } diff --git a/includes/Traits/Tax_Query.php b/includes/Traits/Tax_Query.php new file mode 100644 index 0000000..e8c7559 --- /dev/null +++ b/includes/Traits/Tax_Query.php @@ -0,0 +1,33 @@ +custom_args['tax_query'] = $this->parse_tax_query( $this->custom_params['tax_query'] ); + } + + public function parse_tax_query( $queries ) { + $tax_query = []; + // Handle the relation parameter. + if ( isset( $queries['relation'] ) && count( $queries['queries'] ) > 1 ) { + $tax_query['relation'] = $queries['relation']; + } + + // Create the array for the queries + // Loop the queries + foreach ( $queries['queries'] as $query ) { + if ( isset( $query['taxonomy'] ) && isset( $query['terms'] ) && count( $query['terms'] ) > 0 ) { + $new_item = array_filter( $query, fn( $key ) => 'id' !== $key, ARRAY_FILTER_USE_KEY ); + $new_item['terms'] = [ ...array_map( fn( $term ) => get_term_by( 'name', $term, $query['taxonomy'] )->term_id, $query['terms'] ) ]; + $tax_query[] = $new_item; + } + } + // Let's not return empty arrays. + return array_filter( $tax_query ); + } +} From 855c69da4d6e70cf7dbaa53d93a1e5daa3706962 Mon Sep 17 00:00:00 2001 From: Ryan Welcher Date: Fri, 29 Nov 2024 11:27:14 -0500 Subject: [PATCH 24/36] Simplify the interface. We don't really need the tabs. --- src/components/taxonomy-select.js | 191 ------------------------------ 1 file changed, 191 deletions(-) diff --git a/src/components/taxonomy-select.js b/src/components/taxonomy-select.js index 641485f..f6b958e 100644 --- a/src/components/taxonomy-select.js +++ b/src/components/taxonomy-select.js @@ -115,197 +115,6 @@ export const TaxonomySelect = ( { attributes, setAttributes } ) => { /> - - { - switch ( tab.name ) { - case 'simple': { - return ( - - { queries.map( - ( { - id, - taxonomy, - terms, - operator, - } ) => { - return ( - - ); - } - ) } - - - - - - - - ); - } - case 'advanced': { - return null; - return ( - - { queries.map( - ( { - id, - taxonomy, - terms, - include_children: - includeChildren, - operator, - } ) => { - return ( - - ); - } - ) } - - - - - - ); - } - } - } } - /> ) } /> From b58da73b0cbc26c14dba3761290bdce9c0bdfa53 Mon Sep 17 00:00:00 2001 From: Ryan Welcher Date: Fri, 29 Nov 2024 13:42:12 -0500 Subject: [PATCH 25/36] =?UTF-8?q?Process=20booleans=20correctly=20and=20ha?= =?UTF-8?q?rden=20up=20the=20code.=20=F0=9F=92=AA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- includes/Traits/Tax_Query.php | 59 ++++++++++++++++++++++++++--------- 1 file changed, 45 insertions(+), 14 deletions(-) diff --git a/includes/Traits/Tax_Query.php b/includes/Traits/Tax_Query.php index e8c7559..e32231c 100644 --- a/includes/Traits/Tax_Query.php +++ b/includes/Traits/Tax_Query.php @@ -13,21 +13,52 @@ public function process_tax_query() { public function parse_tax_query( $queries ) { $tax_query = []; - // Handle the relation parameter. - if ( isset( $queries['relation'] ) && count( $queries['queries'] ) > 1 ) { - $tax_query['relation'] = $queries['relation']; - } - - // Create the array for the queries - // Loop the queries - foreach ( $queries['queries'] as $query ) { - if ( isset( $query['taxonomy'] ) && isset( $query['terms'] ) && count( $query['terms'] ) > 0 ) { - $new_item = array_filter( $query, fn( $key ) => 'id' !== $key, ARRAY_FILTER_USE_KEY ); - $new_item['terms'] = [ ...array_map( fn( $term ) => get_term_by( 'name', $term, $query['taxonomy'] )->term_id, $query['terms'] ) ]; - $tax_query[] = $new_item; + // Don't process empty array of queries. + if ( count( $queries['queries'] ) > 0 ) { + // Handle the relation parameter. + if ( isset( $queries['relation'] ) && count( $queries['queries'] ) > 1 ) { + $tax_query['relation'] = $queries['relation']; + } + // Loop the queries + foreach ( $queries['queries'] as $query ) { + if ( isset( $query['taxonomy'] ) && isset( $query['terms'] ) && count( $query['terms'] ) > 0 ) { + $processed_query = array_filter( $query, fn( $key ) => 'id' !== $key, ARRAY_FILTER_USE_KEY ); + $processed_query['include_children'] = filter_var( $query['include_children'], FILTER_VALIDATE_BOOLEAN ); + $processed_query['terms'] = [ ...array_map( fn( $term ) => get_term_by( 'name', $term, $query['taxonomy'] )->term_id, $query['terms'] ) ]; + $tax_query[] = $processed_query; + } } } - // Let's not return empty arrays. - return array_filter( $tax_query ); + return $tax_query; } } + +/** + * Example complex query: + * $tax_query = array( + * 'relation' => 'OR', + * array( + * 'taxonomy' => 'category', + * 'field' => 'slug', + * 'terms' => array( 'quotes' ), + * ), + * array( + * 'taxonomy' => 'tag', + * 'field' => 'slug', + * 'terms' => array( 2 ), + * ), + * array( + * 'relation' => 'AND', + * array( + * 'taxonomy' => 'post_format', + * 'field' => 'slug', + * 'terms' => array( 'post-format-quote' ), + * ), + * array( + * 'taxonomy' => 'category', + * 'field' => 'slug', + * 'terms' => array( 'wisdom' ), + * ), + * ), + * ); + */ From f0778417c93b119402bbb0ab7d69210c13dbf5a6 Mon Sep 17 00:00:00 2001 From: Ryan Welcher Date: Fri, 29 Nov 2024 14:07:24 -0500 Subject: [PATCH 26/36] Fix fatal when queries are not set. --- includes/Traits/Tax_Query.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/includes/Traits/Tax_Query.php b/includes/Traits/Tax_Query.php index e32231c..aa42c16 100644 --- a/includes/Traits/Tax_Query.php +++ b/includes/Traits/Tax_Query.php @@ -14,7 +14,7 @@ public function process_tax_query() { public function parse_tax_query( $queries ) { $tax_query = []; // Don't process empty array of queries. - if ( count( $queries['queries'] ) > 0 ) { + if ( isset( $queries['queries'] ) && count( $queries['queries'] ) > 0 ) { // Handle the relation parameter. if ( isset( $queries['relation'] ) && count( $queries['queries'] ) > 1 ) { $tax_query['relation'] = $queries['relation']; From 578b99d2541548a132a0ceb20bc5739a05c306cd Mon Sep 17 00:00:00 2001 From: Ryan Welcher Date: Fri, 29 Nov 2024 14:08:16 -0500 Subject: [PATCH 27/36] Rename controls and start refining the interface. --- src/components/single-taxonomy-control.js | 207 +++++++++++++++------- src/components/taxonomy-query-control.js | 193 ++++++++++++++++++++ src/components/taxonomy-select.js | 123 ------------- src/variations/controls.js | 4 +- 4 files changed, 341 insertions(+), 186 deletions(-) create mode 100644 src/components/taxonomy-query-control.js delete mode 100644 src/components/taxonomy-select.js diff --git a/src/components/single-taxonomy-control.js b/src/components/single-taxonomy-control.js index 3e42c00..97a9625 100644 --- a/src/components/single-taxonomy-control.js +++ b/src/components/single-taxonomy-control.js @@ -4,47 +4,54 @@ import { FormTokenField, SelectControl, + Button, ToggleControl, + __experimentalHStack as HStack, } from '@wordpress/components'; import { __ } from '@wordpress/i18n'; -import { useSelect } from '@wordpress/data'; -import { store as coreStore, useEntityRecords } from '@wordpress/core-data'; -import { useMemo } from '@wordpress/element'; +import { useEntityRecords } from '@wordpress/core-data'; +import { useMemo, useEffect } from '@wordpress/element'; /** * Internal dependencies */ import useDebouncedInputValue from '../hooks/useDebouncedInputValue'; +import { updateTaxonomyQuery } from '../utils'; + const operatorOptions = [ 'IN', 'NOT IN', 'EXISTS', 'NOT EXISTS', 'AND' ]; -const updateTaxonomyQuery = ( queries, queryId, item, value ) => { - return queries.map( ( query ) => { - if ( query.id === queryId ) { - return { - ...query, - [ item ]: value, - }; - } - return query; - } ); -}; +/* +tax_query: { + relation: 'AND', + queries: [ + { + taxonomy: 'category', + terms: [ 'current events' ], + operator: 'IN', + }, + { + taxonomy: 'category', + terms: [ 'politics' ], + operator: 'NOT_IN', + }, + ], +}, +*/ const SingleTaxonomyControl = ( { + id, taxonomy, - terms = [], - availableTaxonomies, + terms, + operator, includeChildren, - setAttributes, + availableTaxonomies, attributes, - id, - operator, + setAttributes, + advancedMode, + setAdvancedMode, + setDisabled, } ) => { const [ searchTerm, setSearchTerm ] = useDebouncedInputValue( '', 500 ); - const taxInfo = useSelect( ( select ) => - select( coreStore ).getTaxonomy( taxonomy ) - ); - - const isHierarchical = taxInfo?.hierarchical ?? false; const { records } = useEntityRecords( 'taxonomy', taxonomy, { per_page: 10, @@ -57,10 +64,21 @@ const SingleTaxonomyControl = ( { return ( records ?? [] ).map( ( term ) => term.name ); }, [ records ] ); + useEffect( () => { + if ( + ( operator !== 'IN' && operator !== 'NOT IN' ) || + includeChildren === false + ) { + setAdvancedMode( true ); + setDisabled( true ); + } else { + setDisabled( false ); + } + }, [ operator, includeChildren ] ); + return ( <> { taxonomy.length > 1 && ( <> { @@ -108,46 +127,86 @@ const SingleTaxonomyControl = ( { attributes.query.tax_query.queries, id, 'terms', - newTerms - ), - }, - }, - } ); - } } - /> - { - return { label: value, value }; - } ), - ] } - onChange={ ( newOperator ) => { - setAttributes( { - query: { - ...attributes.query, - tax_query: { - ...attributes.query.tax_query, - queries: updateTaxonomyQuery( - attributes.query.tax_query.queries, - id, - 'operator', - newOperator + newTerms, + 'include' ), }, }, } ); } } + __nextHasNoMarginBottom={ false } /> - { isHierarchical && ( + { advancedMode ? ( + <> + { + return { label: value, value }; + } ), + ] } + onChange={ ( newOperator ) => { + setAttributes( { + query: { + ...attributes.query, + tax_query: { + ...attributes.query.tax_query, + queries: updateTaxonomyQuery( + attributes.query.tax_query + .queries, + id, + 'operator', + newOperator + ), + }, + }, + } ); + } } + __nextHasNoMarginBottom={ false } + /> + { + setAttributes( { + query: { + ...attributes.query, + tax_query: { + ...attributes.query.tax_query, + queries: updateTaxonomyQuery( + attributes.query.tax_query + .queries, + id, + 'include_children', + include + ), + }, + }, + } ); + } } + __nextHasNoMarginBottom={ false } + /> + + ) : ( { + const currentQuery = + attributes.query.tax_query.queries.find( + ( query ) => query.id === id + ); + setAttributes( { query: { ...attributes.query, @@ -157,21 +216,47 @@ const SingleTaxonomyControl = ( { attributes.query.tax_query .queries, id, - 'include_children', - ! includeChildren + 'operator', + currentQuery.operator === 'IN' + ? 'NOT IN' + : 'IN' ), }, }, } ); } } - help={ __( - 'For hierarchical taxonomies only', - 'advanced-query-loop' - ) } + __nextHasNoMarginBottom={ false } /> ) } ) } + + + +
+
); }; diff --git a/src/components/taxonomy-query-control.js b/src/components/taxonomy-query-control.js new file mode 100644 index 0000000..d4890e7 --- /dev/null +++ b/src/components/taxonomy-query-control.js @@ -0,0 +1,193 @@ +/* eslint-disable @wordpress/no-unsafe-wp-apis */ + +/** + * External dependencies + */ +import { v4 as uuidv4 } from 'uuid'; + +/** + * WordPress dependencies + */ +import { + Button, + Dropdown, + __experimentalDropdownContentWrapper as DropdownContentWrapper, + PanelBody, + ToggleControl, + Panel, + __experimentalHStack as HStack, +} from '@wordpress/components'; +import { __ } from '@wordpress/i18n'; +import { useSelect } from '@wordpress/data'; +import { store as coreStore } from '@wordpress/core-data'; +import { useState } from '@wordpress/element'; + +/** + * Internal dependencies + */ +import SingleTaxonomyControl from './single-taxonomy-control'; + +export const TaxonomyQueryControl = ( { attributes, setAttributes } ) => { + const { + query: { + postType, + tax_query: { relation = '', queries = [] } = {}, + } = {}, + } = attributes; + + const availableTaxonomies = useSelect( ( select ) => + select( coreStore ) + .getTaxonomies() + ?.filter( ( { types } ) => types.includes( postType ) ) + ); + + const [ advancedMode, setAdvancedMode ] = useState( false ); + const [ disabled, setDisabled ] = useState( false ); + + return ( + <> + ( + <> + + + ) } + renderContent={ () => ( + + + + { queries.map( + ( { + id, + taxonomy, + terms, + operator, + include_children: includeChildren, + } ) => { + return ( + + ); + } + ) } + + + + { queries.length > 0 && ( + <> + + setAdvancedMode( + ! advancedMode + ) + } + disabled={ disabled } + __nextHasNoMarginBottom + /> + + + ) } + + + + + ) } + /> + + ); +}; diff --git a/src/components/taxonomy-select.js b/src/components/taxonomy-select.js deleted file mode 100644 index f6b958e..0000000 --- a/src/components/taxonomy-select.js +++ /dev/null @@ -1,123 +0,0 @@ -/* eslint-disable @wordpress/no-unsafe-wp-apis */ - -/** - * External dependencies - */ -import { v4 as uuidv4 } from 'uuid'; - -/** - * WordPress dependencies - */ -import { - ButtonGroup, - Button, - Dropdown, - __experimentalDropdownContentWrapper as DropdownContentWrapper, - TabPanel, - PanelBody, - ToggleControl, - Panel, - PanelRow, -} from '@wordpress/components'; -import { __ } from '@wordpress/i18n'; -import { useSelect } from '@wordpress/data'; -import { store as coreStore } from '@wordpress/core-data'; -import { useState } from '@wordpress/element'; - -/** - * Internal dependencies - */ -import SingleTaxonomyControl from './single-taxonomy-control'; -import SimpleTaxonomyControl from './simple-taxonomy-control'; - -export const TaxonomySelect = ( { attributes, setAttributes } ) => { - const { - query: { - postType, - tax_query: { relation = '', queries = [] } = {}, - } = {}, - } = attributes; - - const availableTaxonomies = useSelect( ( select ) => - select( coreStore ) - .getTaxonomies() - ?.filter( ( { types } ) => types.includes( postType ) ) - ); - - const [ toggled, setToggled ] = useState( false ); - - return ( - <> - ( - <> - - - ) } - renderContent={ () => ( - - - - { queries.map( - ( { id, taxonomy, terms, operator } ) => { - return ( - - ); - } - ) } - - setToggled( ! toggled ) } - __nextHasNoMarginBottom={ false } - /> - - - - ) } - /> - - ); -}; diff --git a/src/variations/controls.js b/src/variations/controls.js index 8c43b75..67cb301 100644 --- a/src/variations/controls.js +++ b/src/variations/controls.js @@ -18,7 +18,7 @@ import { PostDateQueryControls } from '../components/post-date-query-controls'; import { MultiplePostSelect } from '../components/multiple-post-select'; import { PostOrderControls } from '../components/post-order-controls'; import { PostExcludeControls } from '../components/post-exclude-controls'; -import { TaxonomySelect } from '../components/taxonomy-select'; +import { TaxonomyQueryControl } from '../components/taxonomy-query-control'; import { PostIncludeControls } from '../components/post-include-controls'; import { ExcludeTaxonomies } from '../components/exclude-taxonomies'; import { PaginationToggle } from '../components/pagination-toggle'; @@ -66,7 +66,7 @@ const withAdvancedQueryControls = ( BlockEdit ) => ( props ) => { - + From 572b1fc56230d9e27da53d7e6d3f6f04fdaef28c Mon Sep 17 00:00:00 2001 From: Ryan Welcher Date: Fri, 29 Nov 2024 14:21:18 -0500 Subject: [PATCH 28/36] Name things a little better. --- src/components/single-taxonomy-control.js | 6 +++--- src/components/taxonomy-query-control.js | 8 +++++--- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/src/components/single-taxonomy-control.js b/src/components/single-taxonomy-control.js index 97a9625..f9ad72c 100644 --- a/src/components/single-taxonomy-control.js +++ b/src/components/single-taxonomy-control.js @@ -49,7 +49,7 @@ const SingleTaxonomyControl = ( { setAttributes, advancedMode, setAdvancedMode, - setDisabled, + setAdvancedToggleDisabled, } ) => { const [ searchTerm, setSearchTerm ] = useDebouncedInputValue( '', 500 ); @@ -70,9 +70,9 @@ const SingleTaxonomyControl = ( { includeChildren === false ) { setAdvancedMode( true ); - setDisabled( true ); + setAdvancedToggleDisabled( true ); } else { - setDisabled( false ); + setAdvancedToggleDisabled( false ); } }, [ operator, includeChildren ] ); diff --git a/src/components/taxonomy-query-control.js b/src/components/taxonomy-query-control.js index d4890e7..5365885 100644 --- a/src/components/taxonomy-query-control.js +++ b/src/components/taxonomy-query-control.js @@ -61,11 +61,11 @@ export const TaxonomyQueryControl = ( { attributes, setAttributes } ) => { > { isOpen ? __( - 'Close Taxonomy Query', + 'Close Taxonomy Query Builder', 'advanced-query-loop' ) : __( - 'Taxonomy Query', + 'Taxonomy Query Builder', 'advanced-query-loop' ) } @@ -110,7 +110,9 @@ export const TaxonomyQueryControl = ( { attributes, setAttributes } ) => { setAdvancedMode={ setAdvancedMode } - setDisabled={ setDisabled } + setAdvancedToggleDisabled={ + setDisabled + } /> ); } From 8c3989489ec4ad5b736b62cdcbb6b11a969f6959 Mon Sep 17 00:00:00 2001 From: Ryan Welcher Date: Fri, 29 Nov 2024 14:34:11 -0500 Subject: [PATCH 29/36] Disable the button if there are no taxonomies associated with the selected post types. --- src/components/taxonomy-query-control.js | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/components/taxonomy-query-control.js b/src/components/taxonomy-query-control.js index 5365885..1932987 100644 --- a/src/components/taxonomy-query-control.js +++ b/src/components/taxonomy-query-control.js @@ -31,6 +31,7 @@ export const TaxonomyQueryControl = ( { attributes, setAttributes } ) => { const { query: { postType, + multiple_posts: multiplePosts = [], tax_query: { relation = '', queries = [] } = {}, } = {}, } = attributes; @@ -38,7 +39,11 @@ export const TaxonomyQueryControl = ( { attributes, setAttributes } ) => { const availableTaxonomies = useSelect( ( select ) => select( coreStore ) .getTaxonomies() - ?.filter( ( { types } ) => types.includes( postType ) ) + ?.filter( ( { types } ) => + types.some( ( type ) => + [ postType, ...multiplePosts ].includes( type ) + ) + ) ); const [ advancedMode, setAdvancedMode ] = useState( false ); @@ -58,6 +63,7 @@ export const TaxonomyQueryControl = ( { attributes, setAttributes } ) => { onClick={ onToggle } aria-haspopup="true" aria-expanded={ isOpen } + disabled={ availableTaxonomies.length === 0 } > { isOpen ? __( From 8d813c0edbf5d6a0bc14eb304e47cbebe4e39aba Mon Sep 17 00:00:00 2001 From: Ryan Welcher Date: Fri, 29 Nov 2024 14:48:48 -0500 Subject: [PATCH 30/36] Adding relation control to advanced mode. --- src/components/single-taxonomy-control.js | 6 ++- src/components/taxonomy-query-control.js | 49 +++++++++++++++++++++-- 2 files changed, 50 insertions(+), 5 deletions(-) diff --git a/src/components/single-taxonomy-control.js b/src/components/single-taxonomy-control.js index f9ad72c..617f0dc 100644 --- a/src/components/single-taxonomy-control.js +++ b/src/components/single-taxonomy-control.js @@ -43,6 +43,7 @@ const SingleTaxonomyControl = ( { taxonomy, terms, operator, + relation, includeChildren, availableTaxonomies, attributes, @@ -67,14 +68,15 @@ const SingleTaxonomyControl = ( { useEffect( () => { if ( ( operator !== 'IN' && operator !== 'NOT IN' ) || - includeChildren === false + includeChildren === false || + relation !== 'AND' ) { setAdvancedMode( true ); setAdvancedToggleDisabled( true ); } else { setAdvancedToggleDisabled( false ); } - }, [ operator, includeChildren ] ); + }, [ operator, includeChildren, relation ] ); return ( <> diff --git a/src/components/taxonomy-query-control.js b/src/components/taxonomy-query-control.js index 1932987..78734b0 100644 --- a/src/components/taxonomy-query-control.js +++ b/src/components/taxonomy-query-control.js @@ -16,6 +16,7 @@ import { ToggleControl, Panel, __experimentalHStack as HStack, + SelectControl, } from '@wordpress/components'; import { __ } from '@wordpress/i18n'; import { useSelect } from '@wordpress/data'; @@ -26,6 +27,9 @@ import { useState } from '@wordpress/element'; * Internal dependencies */ import SingleTaxonomyControl from './single-taxonomy-control'; +import { updateTaxonomyQuery } from '../utils'; + +const relationOptions = [ 'AND', 'OR' ]; export const TaxonomyQueryControl = ( { attributes, setAttributes } ) => { const { @@ -89,6 +93,43 @@ export const TaxonomyQueryControl = ( { attributes, setAttributes } ) => { ) } > + { advancedMode && ( + <> + { + return { + label: value, + value, + }; + } + ), + ] } + onChange={ ( newRelation ) => { + setAttributes( { + query: { + ...attributes.query, + tax_query: { + ...attributes.query + .tax_query, + relation: + newRelation, + }, + }, + } ); + } } + __nextHasNoMarginBottom={ false } + /> +
+ + ) } + { queries.map( ( { id, @@ -104,6 +145,7 @@ export const TaxonomyQueryControl = ( { attributes, setAttributes } ) => { operator={ operator } terms={ terms } id={ id } + relation={ relation } includeChildren={ includeChildren } @@ -174,14 +216,15 @@ export const TaxonomyQueryControl = ( { attributes, setAttributes } ) => { - + ) } renderContent={ () => ( ( props ) => { - From 76b192682effeda3043008210fb326ae90b56eab Mon Sep 17 00:00:00 2001 From: Ryan Welcher Date: Fri, 29 Nov 2024 15:16:07 -0500 Subject: [PATCH 32/36] Fix bad merge conflict fix. --- readme.txt | 6 ------ 1 file changed, 6 deletions(-) diff --git a/readme.txt b/readme.txt index 08d3780..27ea209 100644 --- a/readme.txt +++ b/readme.txt @@ -121,12 +121,6 @@ Sort in ascending or descending order by: * Fixes a typo in the Order By label. * Fixes a bug where a second AQL instances was getting post meta query values from the first. -= 2.0.0 = -* ACF custom fields now show in the auto-complete dropdown list for Post Meta Queries ( props to @jvanja ) -* Adds sort by Post ID ( props to @markhowellsmead ) -* Fixes a typo in the Order By label. -* Fixes a bug where a second AQL instances was getting post meta query values from the first. - = 2.0.0 = * Due to a change in core, Post Count can no longer be overridden when the block is set to inherit the query. * Adds Exclude current post option. Props to @Pulsar-X From 98ec88ca434f1d7d19ae2744af7b76519f457fe9 Mon Sep 17 00:00:00 2001 From: Ryan Welcher Date: Sun, 1 Dec 2024 20:08:55 -0500 Subject: [PATCH 33/36] Remove processing the exclude_taxonomies field. --- includes/Query_Params_Generator.php | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/includes/Query_Params_Generator.php b/includes/Query_Params_Generator.php index 5c90c0d..287adc6 100644 --- a/includes/Query_Params_Generator.php +++ b/includes/Query_Params_Generator.php @@ -17,7 +17,6 @@ class Query_Params_Generator { use Traits\Include_Posts; use Traits\Meta_Query; use Traits\Date_Query; - use Traits\Exclude_Taxonomies; use Traits\Disable_Pagination; use Traits\Tax_Query; @@ -31,7 +30,6 @@ class Query_Params_Generator { 'include_posts', 'meta_query', 'date_query', - 'exclude_taxonomies', 'disable_pagination', 'tax_query', ); @@ -73,7 +71,7 @@ public function __construct( $default_params, $custom_params ) { * * @param string $param_name The param to look for. */ - public function has_custom_param( string $param_name): bool { + public function has_custom_param( string $param_name ): bool { return array_key_exists( $param_name, $this->custom_params ) && ! empty( $this->custom_params[ $param_name ] ); } From c8c4a0488edad56abe4222f646ec0c31e5e3bea3 Mon Sep 17 00:00:00 2001 From: Ryan Welcher Date: Thu, 5 Dec 2024 09:14:19 -0500 Subject: [PATCH 34/36] WIP moving advanced into each item --- src/components/single-taxonomy-control.js | 20 +++-- src/components/taxonomy-query-control.js | 89 ++++++++--------------- 2 files changed, 42 insertions(+), 67 deletions(-) diff --git a/src/components/single-taxonomy-control.js b/src/components/single-taxonomy-control.js index 4bb73b1..3fdca35 100644 --- a/src/components/single-taxonomy-control.js +++ b/src/components/single-taxonomy-control.js @@ -11,7 +11,7 @@ import { } from '@wordpress/components'; import { __ } from '@wordpress/i18n'; import { useEntityRecords } from '@wordpress/core-data'; -import { useMemo, useEffect } from '@wordpress/element'; +import { useMemo, useEffect, useState } from '@wordpress/element'; /** * Internal dependencies @@ -49,12 +49,10 @@ const SingleTaxonomyControl = ( { availableTaxonomies, attributes, setAttributes, - advancedMode, - setAdvancedMode, - setAdvancedToggleDisabled, } ) => { const [ searchTerm, setSearchTerm ] = useDebouncedInputValue( '', 500 ); + const [ advancedMode, setAdvancedMode ] = useState( false ); const { records } = useEntityRecords( 'taxonomy', taxonomy, { per_page: 10, search: searchTerm, @@ -73,9 +71,6 @@ const SingleTaxonomyControl = ( { relation !== 'AND' ) { setAdvancedMode( true ); - setAdvancedToggleDisabled( true ); - } else { - setAdvancedToggleDisabled( false ); } }, [ operator, includeChildren, relation ] ); @@ -233,7 +228,16 @@ const SingleTaxonomyControl = ( { ) } ) } - +
+ + { taxonomy && ( + setAdvancedMode( ! advancedMode ) } + __nextHasNoMarginBottom + /> + ) } { queries.length > 0 && ( - <> - - setAdvancedMode( - ! advancedMode - ) - } - disabled={ disabled } - __nextHasNoMarginBottom - /> - - + ) }
From aaaaa87a6c6c5c2d90f8039b9594c25938fb1633 Mon Sep 17 00:00:00 2001 From: Ryan Welcher Date: Thu, 5 Dec 2024 10:36:39 -0500 Subject: [PATCH 35/36] Fast refresh is to hot right now. --- package.json | 1 + webpack.config.js | 9 +++++---- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/package.json b/package.json index 9ba8d41..14642f2 100644 --- a/package.json +++ b/package.json @@ -6,6 +6,7 @@ "scripts": { "setup": "composer run dev", "start": "wp-scripts start", + "start:hot": "wp-scripts start --hot", "build": "wp-scripts build", "plugin-zip": "wp-scripts plugin-zip", "format": "wp-scripts format", diff --git a/webpack.config.js b/webpack.config.js index c3dcf7b..0999455 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -1,14 +1,11 @@ // Import the original config from the @wordpress/scripts package. const defaultConfig = require( '@wordpress/scripts/config/webpack.config' ); -// Import the helper to find and generate the entry points in the src directory -const { getWebpackEntryPoints } = require( '@wordpress/scripts/utils/config' ); - // Add any a new entry point by extending the webpack config. module.exports = { ...defaultConfig, entry: { - ...getWebpackEntryPoints(), + ...defaultConfig.entry(), variations: './src/variations/index.js', 'legacy-pre-gb-19': './src/legacy-controls/pre-gb-19.js', }, @@ -16,4 +13,8 @@ module.exports = { ...defaultConfig.output, library: [ 'aql' ], }, + devServer: { + ...defaultConfig.devServer, + allowedHosts: 'all', // Allow Fast Refresh access from any host. This is useful for testing in different environments. + }, }; From e821cb1590edf1379eed39a14738b0685bfd4724 Mon Sep 17 00:00:00 2001 From: Ryan Welcher Date: Thu, 5 Dec 2024 11:28:01 -0500 Subject: [PATCH 36/36] Clean up the UI. Make the relation toggle better. Ignore Kevin and his requests for tests. --- src/components/single-taxonomy-control.js | 89 ++++++++++++++--------- src/components/taxonomy-query-control.js | 17 ++--- 2 files changed, 60 insertions(+), 46 deletions(-) diff --git a/src/components/single-taxonomy-control.js b/src/components/single-taxonomy-control.js index 3fdca35..5258d6d 100644 --- a/src/components/single-taxonomy-control.js +++ b/src/components/single-taxonomy-control.js @@ -18,8 +18,13 @@ import { useMemo, useEffect, useState } from '@wordpress/element'; */ import useDebouncedInputValue from '../hooks/useDebouncedInputValue'; import { updateTaxonomyQuery } from '../utils'; +const advancedOperators = [ 'EXISTS', 'NOT EXISTS', 'AND' ]; +const operatorOptions = [ 'IN', 'NOT IN', ...advancedOperators ]; -const operatorOptions = [ 'IN', 'NOT IN', 'EXISTS', 'NOT EXISTS', 'AND' ]; +const toggleMargin = { + marginTop: '1.5em', + marginBottom: '0.75em', +}; /* tax_query: { @@ -38,13 +43,11 @@ tax_query: { ], }, */ - const SingleTaxonomyControl = ( { id, taxonomy, terms, operator, - relation, includeChildren, availableTaxonomies, attributes, @@ -53,6 +56,8 @@ const SingleTaxonomyControl = ( { const [ searchTerm, setSearchTerm ] = useDebouncedInputValue( '', 500 ); const [ advancedMode, setAdvancedMode ] = useState( false ); + const [ disableAdvancedToggle, setDisableAdvancedToggle ] = + useState( false ); const { records } = useEntityRecords( 'taxonomy', taxonomy, { per_page: 10, search: searchTerm, @@ -66,13 +71,15 @@ const SingleTaxonomyControl = ( { useEffect( () => { if ( - ( operator !== 'IN' && operator !== 'NOT IN' ) || - includeChildren === false || - relation !== 'AND' + advancedOperators.includes( operator ) || + includeChildren === false ) { setAdvancedMode( true ); + setDisableAdvancedToggle( true ); + } else { + setDisableAdvancedToggle( false ); } - }, [ operator, includeChildren, relation ] ); + }, [ operator, includeChildren ] ); return ( <> @@ -104,7 +111,7 @@ const SingleTaxonomyControl = ( { }, } ); } } - __nextHasNoMarginBottom={ false } + __next40pxDefaultSize /> { taxonomy.length > 1 && ( <> @@ -132,7 +139,7 @@ const SingleTaxonomyControl = ( { }, } ); } } - __nextHasNoMarginBottom={ false } + __next40pxDefaultSize /> { advancedMode ? ( <> @@ -164,33 +171,39 @@ const SingleTaxonomyControl = ( { }, } ); } } - __nextHasNoMarginBottom={ false } + __next40pxDefaultSize /> - { - setAttributes( { - query: { - ...attributes.query, - tax_query: { - ...attributes.query.tax_query, - queries: updateTaxonomyQuery( - attributes.query.tax_query - .queries, - id, - 'include_children', - include - ), +
+ { + setAttributes( { + query: { + ...attributes.query, + tax_query: { + ...attributes.query + .tax_query, + queries: + updateTaxonomyQuery( + attributes.query + .tax_query + .queries, + id, + 'include_children', + include + ), + }, }, - }, - } ); - } } - __nextHasNoMarginBottom={ false } - /> + } ); + } } + __next40pxDefaultSize + /> +
) : ( ) } ) }
- + { taxonomy && ( setAdvancedMode( ! advancedMode ) } + disabled={ disableAdvancedToggle } __nextHasNoMarginBottom /> ) } diff --git a/src/components/taxonomy-query-control.js b/src/components/taxonomy-query-control.js index 895189f..8172d0d 100644 --- a/src/components/taxonomy-query-control.js +++ b/src/components/taxonomy-query-control.js @@ -16,20 +16,16 @@ import { ToggleControl, Panel, __experimentalHStack as HStack, - SelectControl, } from '@wordpress/components'; import { __ } from '@wordpress/i18n'; import { useSelect } from '@wordpress/data'; import { store as coreStore } from '@wordpress/core-data'; -import { useState } from '@wordpress/element'; /** * Internal dependencies */ import SingleTaxonomyControl from './single-taxonomy-control'; -const relationOptions = [ 'AND', 'OR' ]; - export const TaxonomyQueryControl = ( { attributes, setAttributes } ) => { const { query: { @@ -49,8 +45,6 @@ export const TaxonomyQueryControl = ( { attributes, setAttributes } ) => { ) ); - const advancedMode = false; - return ( <> { <> { setAttributes( { query: { @@ -159,7 +157,7 @@ export const TaxonomyQueryControl = ( { attributes, setAttributes } ) => { ...attributes.query, tax_query: { relation: - relation || 'AND', + relation || 'OR', queries: [ ...queries, @@ -192,7 +190,6 @@ export const TaxonomyQueryControl = ( { attributes, setAttributes } ) => { tax_query: [], }, } ); - setAdvancedMode( false ); } } > { __(