Skip to content

Commit

Permalink
Merge pull request #84 from alleyinteractive/feature/issue-73/add-and…
Browse files Browse the repository at this point in the history
…-or-option-multiple-terms

Issue-73: In Query block add AND/OR option for multiple terms
  • Loading branch information
mogmarsh authored Oct 26, 2023
2 parents 6358743 + 3fe4fe9 commit 4a5901e
Show file tree
Hide file tree
Showing 8 changed files with 140 additions and 17 deletions.
10 changes: 9 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,14 @@

All notable changes to `WP Curate` will be documented in this file.

## 0.1.0 - 202X-XX-XX
## 1.2.0 - 2023-10-26

- Adds support for AND/OR operators in the Query Parameters, giving more control over what posts to show.

## 1.1.0 - 2023-09-21

- Bug fix: prevents error if post type does not support meta.

## 1.0.0 - 2023-09-19

- Initial release
20 changes: 20 additions & 0 deletions blocks/query/block.json
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,26 @@
"type": "array"
},
"type": "object"
},
"termRelations": {
"default": {},
"items": {
"default": "AND",
"enum": [
"AND",
"OR"
],
"type": "string"
},
"type": "object"
},
"taxRelation": {
"default": "AND",
"enum": [
"AND",
"OR"
],
"type": "string"
}
}
}
68 changes: 56 additions & 12 deletions blocks/query/edit.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import {
PanelRow,
RadioControl,
RangeControl,
SelectControl,
TextControl,
} from '@wordpress/components';
import { useSelect } from '@wordpress/data';
Expand All @@ -30,6 +31,8 @@ import {
mainDedupe,
} from '../../services/deduplicate';

import buildTermQueryArgs from '../../services/buildTermQueryArgs';

import './index.scss';

interface Window {
Expand Down Expand Up @@ -59,6 +62,8 @@ export default function Edit({
postTypes = ['post'],
searchTerm = '',
terms = {},
termRelations = {},
taxRelation = 'AND',
},
setAttributes,
}: EditProps) {
Expand All @@ -69,6 +74,17 @@ export default function Edit({
} = {},
} = (window as any as Window);

const andOrOptions = [
{
label: __('AND', 'wp-curate'),
value: 'AND',
},
{
label: __('OR', 'wp-curate'),
value: 'OR',
},
];

// @ts-ignore
const [isPostDeduplicating, postTypeObject] = useSelect(
(select) => {
Expand All @@ -93,17 +109,15 @@ export default function Edit({
const [availableTaxonomies, setAvailableTaxonomies] = useState<Taxonomies>({});
const [availableTypes, setAvailableTypes] = useState<Types>({});

let termQueryArgs = '';
if (Object.keys(availableTaxonomies).length > 0) {
allowedTaxonomies.forEach((taxonomy) => {
if (terms[taxonomy]?.length > 0) {
const restBase = availableTaxonomies[taxonomy].rest_base;
if (restBase) {
termQueryArgs += `&${restBase}=${terms[taxonomy].map((term) => term.id).join(',')}`;
}
}
});
}
const taxCount = allowedTaxonomies.filter((taxonomy: string) => terms[taxonomy]?.length > 0).length; // eslint-disable-line max-len

const termQueryArgs = buildTermQueryArgs(
allowedTaxonomies,
terms,
availableTaxonomies,
termRelations,
taxRelation,
);

const manualPostIds = manualPosts.map((post) => (post ?? null)).join(',');
const postTypeString = postTypes.join(',');
Expand Down Expand Up @@ -143,7 +157,7 @@ export default function Edit({
per_page: 20,
},
);
path += termQueryArgs;
path += `&${termQueryArgs}`;

apiFetch({
path,
Expand Down Expand Up @@ -200,6 +214,14 @@ export default function Edit({
setAttributes({ terms: newTermAttrs });
});

const setTermRelation = ((type: string, relation: string) => {
const newTermRelationAttrs = {
...termRelations,
[type]: relation,
};
setAttributes({ termRelations: newTermRelationAttrs });
});

const setNumberOfPosts = (newValue?: number) => {
setAttributes({
numberOfPosts: newValue,
Expand Down Expand Up @@ -319,9 +341,31 @@ export default function Edit({
onSelect={(newCategories: Term[]) => setTerms(taxonomy, newCategories)}
multiple
/>
{terms[taxonomy]?.length > 1 ? (
<SelectControl
label={sprintf(
__('%s Relation', 'wp-curate'),
availableTaxonomies[taxonomy].name || taxonomy,
)}
help={__('AND: Posts must have all selected terms. OR: Posts may have one or more selected terms.', 'wp-curate')}
options={andOrOptions}
onChange={(newValue) => setTermRelation(taxonomy, newValue)}
value={termRelations[taxonomy] ?? 'OR'}
/>
) : null}
<hr />
</>
))
) : null}
{taxCount > 1 ? (
<SelectControl
label={__('Taxonomy Relation', 'wp-curate')}
help={__('AND: Posts must meet all selected taxonomy requirements. OR: Posts may have meet one or more selected taxonomy requirements.', 'wp-curate')}
options={andOrOptions}
onChange={(newValue) => setAttributes({ taxRelation: newValue })}
value={taxRelation}
/>
) : null }
<TextControl
label={__('Search Term', 'wp-curate')}
onChange={(next) => setAttributes({ searchTerm: next })}
Expand Down
4 changes: 4 additions & 0 deletions blocks/query/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,10 @@ interface EditProps {
terms?: {
[key: string]: any[];
};
termRelations?: {
[key: string]: string;
};
taxRelation?: string;
};
setAttributes: (attributes: any) => void;
}
Expand Down
46 changes: 46 additions & 0 deletions services/buildTermQueryArgs/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
interface Types {
[key: string]: {
name: string;
slug: string;
rest_base: string;
};
}

/**
* Builds the term query args for the WP REST API.
*
* @param string[] allowedTaxonomies The list of allowed taxonomies.
* @param { [key: string]: any[] } terms The selected terms.
* @param { [key: string]: any[] } availableTaxonomies The available taxonomies.
* @param { [key: string]: string } termRelations The AND/OR relation used for each taxonomy.
* @param string taxRelation The AND/OR relation used for all the terms.
* @returns string The term query args.
*/
export default function buildTermQueryArgs(
allowedTaxonomies: string[],
terms: { [key: string]: any[] },
availableTaxonomies: Types,
termRelations: { [key: string]: string },
taxRelation: string,
): string {
const taxCount = allowedTaxonomies.filter((taxonomy: string) => terms[taxonomy]?.length > 0).length; // eslint-disable-line max-len

const termQueryArgs: string[] = [];
if (Object.keys(availableTaxonomies).length > 0) {
allowedTaxonomies.forEach((taxonomy) => {
if (terms[taxonomy]?.length > 0) {
const restBase = availableTaxonomies[taxonomy].rest_base;
if (restBase) {
termQueryArgs.push(`${restBase}[terms]=${terms[taxonomy].map((term) => term.id).join(',')}`);
if (termRelations[taxonomy] !== '' && typeof termRelations[taxonomy] !== 'undefined') {
termQueryArgs.push(`${restBase}[operator]=${termRelations[taxonomy]}`);
}
}
}
});
if (taxCount > 1) {
termQueryArgs.push(`tax_relation=${taxRelation}`);
}
}
return termQueryArgs.join('&');
}
4 changes: 2 additions & 2 deletions services/deduplicate/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -121,13 +121,13 @@ export function mainDedupe() {
queryBlocks.forEach((queryBlock) => {
const { attributes } = queryBlock;
const {
backfillPosts = [],
backfillPosts = null,
deduplication = 'inherit',
posts = [],
numberOfPosts = 5,
postTypes = ['post'],
} = attributes;
if (!backfillPosts.length) {
if (!backfillPosts) {
return;
}
const postTypeString = postTypes.join(',');
Expand Down
3 changes: 2 additions & 1 deletion src/class-plugin-curated-posts.php
Original file line number Diff line number Diff line change
Expand Up @@ -51,14 +51,15 @@ public function with_query_context( array $context, array $attributes, WP_Block_

if ( isset( $attributes['terms'] ) && is_array( $attributes['terms'] ) && count( $attributes['terms'] ) > 0 ) {
$args['tax_query'] = [ // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_tax_query
'relation' => 'AND',
'relation' => $attributes['taxRelation'] ?? 'AND',
];

foreach ( $attributes['terms'] as $taxonomy => $terms ) {
if ( taxonomy_exists( $taxonomy ) && is_array( $terms ) && count( $terms ) > 0 ) {
$args['tax_query'][] = [
'taxonomy' => $taxonomy,
'terms' => array_column( $terms, 'id' ),
'operator' => is_array( $attributes['termRelations'] ) ? $attributes['termRelations'][ $taxonomy ] ?? 'AND' : 'AND',
];
}
}
Expand Down
2 changes: 1 addition & 1 deletion wp-curate.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
* Plugin Name: WP Curate
* Plugin URI: https://github.com/alleyinteractive/wp-curate
* Description: Plugin to curate homepages and other landing pages
* Version: 1.1.0
* Version: 1.2.0
* Author: Alley Interactive
* Author URI: https://github.com/alleyinteractive/wp-curate
* Requires at least: 6.3
Expand Down

0 comments on commit 4a5901e

Please sign in to comment.