From 5c816621d1bfdc04bf92631c98e1f6f8ecbe204d Mon Sep 17 00:00:00 2001 From: Jake Foster Date: Wed, 24 Apr 2024 16:38:16 -0400 Subject: [PATCH 01/15] WIP: TECH-84 From 9e8ad3d2b55f3e2df03ce939f310f75f54c6e5bd Mon Sep 17 00:00:00 2001 From: Jake Foster Date: Wed, 1 May 2024 14:30:46 -0400 Subject: [PATCH 02/15] add condition attribute and remove unused attributes --- blocks/condition/block.json | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/blocks/condition/block.json b/blocks/condition/block.json index de1bf2c..75c950a 100644 --- a/blocks/condition/block.json +++ b/blocks/condition/block.json @@ -14,19 +14,6 @@ "attributes": { "condition": { "type": "string" - }, - "custom": { - "type": "string" - }, - "post": { - "type": "string" - }, - "query": { - "type": "string" - }, - "index": { - "type": "object", - "default": { "": "" } } } } From c609b9987f06fda03d468992e68423dd0f59800b Mon Sep 17 00:00:00 2001 From: Jake Foster Date: Wed, 1 May 2024 14:31:19 -0400 Subject: [PATCH 03/15] add apifetch to get conditions from rest api, set attributes --- blocks/condition/edit.tsx | 121 ++++++++++---------------------------- 1 file changed, 32 insertions(+), 89 deletions(-) diff --git a/blocks/condition/edit.tsx b/blocks/condition/edit.tsx index e6e51a9..7d084d2 100644 --- a/blocks/condition/edit.tsx +++ b/blocks/condition/edit.tsx @@ -1,21 +1,21 @@ import { __ } from '@wordpress/i18n'; +import apiFetch from '@wordpress/api-fetch'; +import { useEffect, useState } from '@wordpress/element'; import { InnerBlocks, InspectorControls, useBlockProps } from '@wordpress/block-editor'; import { - PanelBody, PanelRow, SelectControl, TextControl, + PanelBody, PanelRow, SelectControl, } from '@wordpress/components'; -import { useParentBlock } from '@alleyinteractive/block-editor-tools'; - interface EditProps { attributes: { condition?: string; - custom?: string; - post?: string; - query?: string; - index?: object; }; setAttributes: (attributes: any) => void; - clientId: string; +} + +interface Conditions { + value: string; + label: string; } /** @@ -26,16 +26,27 @@ interface EditProps { export default function Edit({ attributes: { condition = '', - custom = '', - post = '', - query = '', - index = { '': '' }, }, setAttributes, - clientId, }: EditProps) { - const { name: parentBlock } = useParentBlock(clientId) as { name?: string } || {}; - const [operator, compared] = Object.entries(index)[0]; + const [conditions, setConditions] = useState([]); + + // Fetch and set the Conditions data. + useEffect(() => { + apiFetch({ path: '/conditional-blocks/v1/get-conditions/' }) + .then((response) => { + if (response.message.length > 0) { + const nextConditions = response.message.map((condition) => ({ + value: condition.slug ?? '', + label: condition.name ?? '', + })); + setConditions(nextConditions); + } else { + console.error('[wp-block-conditions] Failed to retrieve conditions.'); + } + } + ); + }, []); return ( <> @@ -48,90 +59,22 @@ export default function Edit({ {/* @ts-ignore-next-line */} {/* @ts-ignore-next-line */} {/* @ts-ignore-next-line */} - setAttributes({ query: next })} - value={query} - /> - - {/* @ts-ignore-next-line */} - - {/* @ts-ignore-next-line */} - setAttributes({ post: next })} - value={post} - /> - - - {/* @ts-ignore-next-line */} - - {/* @ts-ignore-next-line */} - setAttributes({ custom: next })} - value={custom} - /> - - - {/* @ts-ignore-next-line */} - - {/* @ts-ignore-next-line */} - setAttributes({ condition: next })} + multiple={false} value={condition} + options={conditions} /> - - { parentBlock === 'wp-conditional-blocks/query' ? ( - /* @ts-ignore-next-line */ - -

{__('Checks the index of how many times the parent condition block has been rendered, ie "Equal to 0", "Greater than 5"', 'wp-conditional-blocks')}

- - {/* @ts-ignore-next-line */} - - ', label: __('Greater than', 'wp-conditional-blocks') }, - { value: '<', label: __('Less than', 'wp-conditional-blocks') }, - { value: '>=', label: __('Greater than or equal to', 'wp-conditional-blocks') }, - { value: '<=', label: __('Less than or equal to', 'wp-conditional-blocks') }, - ]} - onChange={(next: string) => setAttributes({ index: { [next]: compared } })} - /> - - - {/* @ts-ignore-next-line */} - - {/* @ts-ignore-next-line */} - setAttributes({ index: { [operator]: next } })} - type="number" - value={compared} - /> - -
- ) : null}
); From 2eb01428bdc2f9a6a36624173bd306abbe304a6a Mon Sep 17 00:00:00 2001 From: Jake Foster Date: Wed, 1 May 2024 14:58:27 -0400 Subject: [PATCH 04/15] update condition evaluation function --- blocks/condition/index.php | 168 +++++-------------------------------- 1 file changed, 21 insertions(+), 147 deletions(-) diff --git a/blocks/condition/index.php b/blocks/condition/index.php index 7c95fb0..71d35eb 100644 --- a/blocks/condition/index.php +++ b/blocks/condition/index.php @@ -10,6 +10,7 @@ use Alley\WP\WP_Conditional_Blocks\Global_Post_Query; use Alley\WP\WP_Conditional_Blocks\Validator\Slug_Is_In_Category; +use \Alley\WP\WP_Conditional_Blocks\Conditions; /** * Registers the block using the metadata loaded from the `block.json` file. @@ -34,11 +35,7 @@ function wp_conditional_blocks_condition_block_init(): void { * * @param array{ * attrs?: array{ - * query?: string|array, - * post?: mixed[], - * custom?: mixed[], - * condition?: string[], - * index?: array + * condition?: string, * } * } $parsed_block Parsed condition block. * @param array{'postId'?: int} $context Available context. @@ -47,154 +44,31 @@ function wp_conditional_blocks_condition_block_init(): void { function wp_conditional_blocks_condition_block_result( array $parsed_block, array $context ): bool { global $wp_query; - $num_conditions = 0; - $num_true = 0; + $condition_slug = ''; - $conditions = []; - - if ( isset( $parsed_block['attrs'] ) ) { - $conditions = $parsed_block['attrs']; - } - - if ( isset( $conditions['query'] ) && $wp_query instanceof WP_Query ) { - // Map `{"query": "is_home"} to {"query": {"is_home": true}}`. - if ( is_string( $conditions['query'] ) ) { - $conditions['query'] = array_fill_keys( (array) $conditions['query'], true ); - } - - foreach ( $conditions['query'] as $condition => $expect ) { - $num_conditions++; - - switch ( true ) { - case 'is_singular' === $condition && ( is_string( $expect ) || is_array( $expect ) ): - $result = $wp_query->is_singular( $expect ); - break; - - case 'is_page' === $condition && ( is_string( $expect ) || is_array( $expect ) ): - $result = $wp_query->is_page( $expect ); - break; - - case 'is_tax' === $condition && ( is_string( $expect ) || is_array( $expect ) ): - $result = $wp_query->is_tax( $expect ); - break; - - case method_exists( $wp_query, $condition ) && is_callable( [ $wp_query, $condition ] ): - $result = call_user_func( [ $wp_query, $condition ] ) === $expect; // @phpstan-ignore-line - break; - - default: - $result = false; - break; - } - - if ( false === $result ) { - break; - } - - $num_true++; - } - } - - /* - * Checks the index of how many times the parent condition block has been rendered, like: - * - * {"index": {"===": 0}} - * {"index": {">": 2}} - * {"index": {">": 2, "<": 4}} - * - * @see \Alley\Validator\Comparison for the available operators. - * - * Note that this approach means that two identical conditions with two identical set of - * child blocks will use the same counter. - */ - if ( isset( $conditions['index'] ) ) { - $num_conditions++; - - $validator = new \Laminas\Validator\ValidatorChain(); - - foreach ( $conditions['index'] as $operator => $compared ) { - try { - $validator->attach( - validator: new \Alley\Validator\Comparison( - [ - 'operator' => $operator, - 'compared' => $compared, - ], - ), - breakChainOnFailure: true, - ); - } catch ( Exception $exception ) { - // Nothing yet. - unset( $exception ); - } - } - - if ( count( $validator ) > 0 ) { - if ( $validator->isValid( wp_conditional_blocks_current_counter_block() ) ) { - $num_true++; - } - } + if ( isset( $parsed_block['attrs']['condition'] ) ) { + $condition_slug = $parsed_block['attrs']['condition']; } + $wp_block_condition = Conditions::get_instance()->get_condition( $condition_slug ); + // Validate callable function. if ( - isset( $conditions['post'] ) - && isset( $context['postId'] ) - && $context['postId'] > 0 + empty( $wp_block_condition['callable'] ) + || ! is_callable( $wp_block_condition['callable'] ) + || ! $wp_query instanceof WP_Query ) { - $conditions['post'] = (array) $conditions['post']; - - foreach ( $conditions['post'] as $condition ) { - $num_conditions++; - - if ( 'has_content' === $condition ) { - if ( '' !== get_the_content( null, false, $context['postId'] ) ) { - $num_true++; - } - - continue; - } - - /** - * Filters the condition block's result for the given post condition. - * - * @param bool $result Condition result. - * @param mixed $condition Condition name. - * @param int $post_id Post ID. - */ - if ( true === apply_filters( 'wp_conditional_blocks_condition_block_post_condition', false, $condition, $context['postId'] ) ) { - $num_true++; - } - } - } - - if ( isset( $conditions['custom'] ) ) { - $conditions['custom'] = (array) $conditions['custom']; - - foreach ( $conditions['custom'] as $condition ) { - $num_conditions++; - } + return false; } - if ( isset( $conditions['condition'] ) ) { - $conditions['condition'] = (array) $conditions['condition']; - - foreach ( $conditions['condition'] as $name ) { - $num_conditions++; - - /** - * Filters the condition block's result for the given condition. - * - * @param bool $result Condition result. - * @param array $context Available context. - * @param WP_Query $wp_query Global query object. - */ - $result = apply_filters( "wp_conditional_blocks_condition_block_{$name}_condition", false, $context, $wp_query ); + // Execute conditional's callable. + $callable_result = call_user_func( $wp_block_condition['callable'] ); - if ( true === $result ) { - $num_true++; - } - } - } - - return $num_conditions > 0 && $num_conditions === $num_true; + /** + * Filters the condition block's result for the given condition. + * + * @param bool $result Condition result. + * @param array $context Available context. + * @param WP_Query $wp_query Global query object. + */ + return apply_filters( "wp_conditional_blocks_condition_block_{$wp_block_condition['slug']}_condition", $callable_result, $context, $wp_query ); } From e3a3e731d50cf0b423137855ba4a9f182d11264f Mon Sep 17 00:00:00 2001 From: Jake Foster Date: Wed, 1 May 2024 14:58:47 -0400 Subject: [PATCH 05/15] add default conditions --- src/class-conditions.php | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/src/class-conditions.php b/src/class-conditions.php index 678e1ea..68882ef 100644 --- a/src/class-conditions.php +++ b/src/class-conditions.php @@ -129,6 +129,15 @@ function ( $condition ) use ( $slug ) { ); } + /** + * Initializes the conditions. + * + * @return void + */ + public function init(): void { + add_action( 'init', [ $this, 'add_default_conditions' ] ); + } + /** * Resets the conditions for testing purposes. * @@ -140,4 +149,16 @@ function ( $condition ) use ( $slug ) { public function reset_conditions_for_testing(): void { $this->conditions = []; } + + /** + * Crates and adds default conditions. + * + * @return void + */ + public function add_default_conditions(): void { + $this->add_condition( 'Is Archive Page', 'is_archive', fn() => is_archive() ); + $this->add_condition( 'Is Home Page', 'is_home_page', fn() => is_home() || is_front_page() ); + $this->add_condition( 'Is Search Page', 'is_search', fn() => is_search() ); + $this->add_condition( 'Is Single', 'is_single', fn() => is_single() ); + } } From fe01f694e71a116b106f178aa5b41ea162cd934d Mon Sep 17 00:00:00 2001 From: Jake Foster Date: Wed, 1 May 2024 15:22:57 -0400 Subject: [PATCH 06/15] phpcs and npm lint fixes --- blocks/condition/edit.tsx | 24 ++++++++++++------------ blocks/condition/index.php | 6 +++--- 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/blocks/condition/edit.tsx b/blocks/condition/edit.tsx index 7d084d2..e17871e 100644 --- a/blocks/condition/edit.tsx +++ b/blocks/condition/edit.tsx @@ -33,19 +33,19 @@ export default function Edit({ // Fetch and set the Conditions data. useEffect(() => { - apiFetch({ path: '/conditional-blocks/v1/get-conditions/' }) + apiFetch({path: '/conditional-blocks/v1/get-conditions/'}) .then((response) => { - if (response.message.length > 0) { - const nextConditions = response.message.map((condition) => ({ - value: condition.slug ?? '', - label: condition.name ?? '', - })); - setConditions(nextConditions); - } else { - console.error('[wp-block-conditions] Failed to retrieve conditions.'); - } - } - ); + // @ts-ignore + if (Array.isArray(response.message) && response.message.length > 0) { + const nextConditions = response.message.map((condition) => ({ + value: condition.slug ?? '', + label: condition.name ?? '', + })); + setConditions(nextConditions); + } else { + console.error('[wp-block-conditions] Failed to retrieve conditions.'); + } + }); }, []); return ( diff --git a/blocks/condition/index.php b/blocks/condition/index.php index 71d35eb..5a4b546 100644 --- a/blocks/condition/index.php +++ b/blocks/condition/index.php @@ -10,7 +10,7 @@ use Alley\WP\WP_Conditional_Blocks\Global_Post_Query; use Alley\WP\WP_Conditional_Blocks\Validator\Slug_Is_In_Category; -use \Alley\WP\WP_Conditional_Blocks\Conditions; +use Alley\WP\WP_Conditional_Blocks\Conditions; /** * Registers the block using the metadata loaded from the `block.json` file. @@ -54,7 +54,7 @@ function wp_conditional_blocks_condition_block_result( array $parsed_block, arra // Validate callable function. if ( empty( $wp_block_condition['callable'] ) - || ! is_callable( $wp_block_condition['callable'] ) + || false === is_callable( $wp_block_condition['callable'] ) || ! $wp_query instanceof WP_Query ) { return false; @@ -63,7 +63,7 @@ function wp_conditional_blocks_condition_block_result( array $parsed_block, arra // Execute conditional's callable. $callable_result = call_user_func( $wp_block_condition['callable'] ); - /** + /** * Filters the condition block's result for the given condition. * * @param bool $result Condition result. From f393b3e1bc62a2869c03cb5ab9d5f3530774941b Mon Sep 17 00:00:00 2001 From: Jake Foster Date: Wed, 1 May 2024 15:26:39 -0400 Subject: [PATCH 07/15] add type interface for condition --- blocks/condition/edit.tsx | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/blocks/condition/edit.tsx b/blocks/condition/edit.tsx index e17871e..a965b40 100644 --- a/blocks/condition/edit.tsx +++ b/blocks/condition/edit.tsx @@ -13,11 +13,18 @@ interface EditProps { setAttributes: (attributes: any) => void; } +// Structure for the SelectControl options. interface Conditions { value: string; label: string; } +// Structure coming from Conditions API. +interface Condition { + slug: string; + name: string; +} + /** * The wp-conditional-blocks/condition block edit function. * @@ -37,7 +44,7 @@ export default function Edit({ .then((response) => { // @ts-ignore if (Array.isArray(response.message) && response.message.length > 0) { - const nextConditions = response.message.map((condition) => ({ + const nextConditions = response.message.map((condition: Condition) => ({ value: condition.slug ?? '', label: condition.name ?? '', })); From bb07c856457f7565eb16b6ae4b245e595fa66cf6 Mon Sep 17 00:00:00 2001 From: Jake Foster Date: Wed, 1 May 2024 15:29:35 -0400 Subject: [PATCH 08/15] remove redundant check --- blocks/condition/index.php | 1 - 1 file changed, 1 deletion(-) diff --git a/blocks/condition/index.php b/blocks/condition/index.php index 5a4b546..2d25cc6 100644 --- a/blocks/condition/index.php +++ b/blocks/condition/index.php @@ -54,7 +54,6 @@ function wp_conditional_blocks_condition_block_result( array $parsed_block, arra // Validate callable function. if ( empty( $wp_block_condition['callable'] ) - || false === is_callable( $wp_block_condition['callable'] ) || ! $wp_query instanceof WP_Query ) { return false; From ba15d0ecd3826f029662842a0cd5b5607aa7796e Mon Sep 17 00:00:00 2001 From: Jake Foster Date: Wed, 1 May 2024 15:31:12 -0400 Subject: [PATCH 09/15] add type t response --- blocks/condition/edit.tsx | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/blocks/condition/edit.tsx b/blocks/condition/edit.tsx index a965b40..6898fad 100644 --- a/blocks/condition/edit.tsx +++ b/blocks/condition/edit.tsx @@ -41,8 +41,7 @@ export default function Edit({ // Fetch and set the Conditions data. useEffect(() => { apiFetch({path: '/conditional-blocks/v1/get-conditions/'}) - .then((response) => { - // @ts-ignore + .then((response: any) => { if (Array.isArray(response.message) && response.message.length > 0) { const nextConditions = response.message.map((condition: Condition) => ({ value: condition.slug ?? '', From 9d739892255c50bc3dc04ccb0477a650b3a51257 Mon Sep 17 00:00:00 2001 From: Jake Foster Date: Wed, 1 May 2024 15:41:42 -0400 Subject: [PATCH 10/15] more linting fixes --- blocks/condition/edit.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/blocks/condition/edit.tsx b/blocks/condition/edit.tsx index 6898fad..4e68737 100644 --- a/blocks/condition/edit.tsx +++ b/blocks/condition/edit.tsx @@ -40,10 +40,10 @@ export default function Edit({ // Fetch and set the Conditions data. useEffect(() => { - apiFetch({path: '/conditional-blocks/v1/get-conditions/'}) + apiFetch({ path: '/conditional-blocks/v1/get-conditions/' }) .then((response: any) => { if (Array.isArray(response.message) && response.message.length > 0) { - const nextConditions = response.message.map((condition: Condition) => ({ + const nextConditions = response.message.map((condition) => ({ value: condition.slug ?? '', label: condition.name ?? '', })); From 592d8c9d9991d318e09c24e89770fdf9ceec98c0 Mon Sep 17 00:00:00 2001 From: Jake Foster Date: Wed, 1 May 2024 15:49:58 -0400 Subject: [PATCH 11/15] ignore impossible desires from linter --- blocks/condition/edit.tsx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/blocks/condition/edit.tsx b/blocks/condition/edit.tsx index 4e68737..74ad67b 100644 --- a/blocks/condition/edit.tsx +++ b/blocks/condition/edit.tsx @@ -43,7 +43,8 @@ export default function Edit({ apiFetch({ path: '/conditional-blocks/v1/get-conditions/' }) .then((response: any) => { if (Array.isArray(response.message) && response.message.length > 0) { - const nextConditions = response.message.map((condition) => ({ + /* @ts-ignore-next-line */ + const nextConditions = response.message.map((condition: Condition) => ({ value: condition.slug ?? '', label: condition.name ?? '', })); From 41559ea4700bf430d9dac55d2f42d4e9ca85ca45 Mon Sep 17 00:00:00 2001 From: Jake Foster Date: Wed, 1 May 2024 16:18:26 -0400 Subject: [PATCH 12/15] change var name to avoid linter confusion --- blocks/condition/edit.tsx | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/blocks/condition/edit.tsx b/blocks/condition/edit.tsx index 74ad67b..8f02e79 100644 --- a/blocks/condition/edit.tsx +++ b/blocks/condition/edit.tsx @@ -43,10 +43,9 @@ export default function Edit({ apiFetch({ path: '/conditional-blocks/v1/get-conditions/' }) .then((response: any) => { if (Array.isArray(response.message) && response.message.length > 0) { - /* @ts-ignore-next-line */ - const nextConditions = response.message.map((condition: Condition) => ({ - value: condition.slug ?? '', - label: condition.name ?? '', + const nextConditions = response.message.map((blockCondition: Condition) => ({ + value: blockCondition.slug ?? '', + label: blockCondition.name ?? '', })); setConditions(nextConditions); } else { From 127b1a63932103c30e1b48b03641e7534c7614b5 Mon Sep 17 00:00:00 2001 From: Jake Date: Wed, 1 May 2024 16:31:23 -0400 Subject: [PATCH 13/15] Update src/class-conditions.php Co-authored-by: Scott Nelle --- src/class-conditions.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/class-conditions.php b/src/class-conditions.php index 68882ef..9ebd86a 100644 --- a/src/class-conditions.php +++ b/src/class-conditions.php @@ -151,7 +151,7 @@ public function reset_conditions_for_testing(): void { } /** - * Crates and adds default conditions. + * Creates and adds default conditions. * * @return void */ From 7b2b1674484e1216559777730d9ca84095fe502b Mon Sep 17 00:00:00 2001 From: Jake Foster Date: Wed, 1 May 2024 16:32:45 -0400 Subject: [PATCH 14/15] use consistent language --- blocks/condition/edit.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/blocks/condition/edit.tsx b/blocks/condition/edit.tsx index 8f02e79..96936cc 100644 --- a/blocks/condition/edit.tsx +++ b/blocks/condition/edit.tsx @@ -72,7 +72,7 @@ export default function Edit({ {/* @ts-ignore-next-line */} setAttributes({ condition: next })} multiple={false} From 29907f7cef2ec47dc66470abf24a9e41f5a5e35d Mon Sep 17 00:00:00 2001 From: Jake Foster Date: Wed, 1 May 2024 16:38:50 -0400 Subject: [PATCH 15/15] update naming for clarity --- blocks/condition/edit.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/blocks/condition/edit.tsx b/blocks/condition/edit.tsx index 96936cc..a3f8df7 100644 --- a/blocks/condition/edit.tsx +++ b/blocks/condition/edit.tsx @@ -20,7 +20,7 @@ interface Conditions { } // Structure coming from Conditions API. -interface Condition { +interface BlockCondition { slug: string; name: string; } @@ -43,7 +43,7 @@ export default function Edit({ apiFetch({ path: '/conditional-blocks/v1/get-conditions/' }) .then((response: any) => { if (Array.isArray(response.message) && response.message.length > 0) { - const nextConditions = response.message.map((blockCondition: Condition) => ({ + const nextConditions = response.message.map((blockCondition: BlockCondition) => ({ value: blockCondition.slug ?? '', label: blockCondition.name ?? '', }));