diff --git a/includes/Query_Params_Generator.php b/includes/Query_Params_Generator.php index 298c226..36f700a 100644 --- a/includes/Query_Params_Generator.php +++ b/includes/Query_Params_Generator.php @@ -21,21 +21,23 @@ class Query_Params_Generator { use Traits\Tax_Query; use Traits\Post_Parent; - /** - * The list of all custom params + * The list of allowed controls and their associated params in the query. */ - const KNOWN_PARAMS = array( - 'multiple_posts', - 'exclude_current', - 'include_posts', - 'meta_query', - 'date_query', - 'disable_pagination', - 'tax_query', - 'post_parent', + const ALLOWED_CONTROLS = array( + 'additional_post_types' => 'multiple_posts', + 'taxonomy_query_builder' => 'tax_query', + 'post_meta_query' => 'meta_query', + 'post_order' => 'post_order', + 'exclude_current_post' => 'exclude_current', + 'include_posts' => 'include_posts', + 'child_items_only' => 'child_items_only', + 'date_query_dynamic_range' => 'date_query', + 'date_query_relationship' => 'date_query', + 'pagination' => 'disable_pagination', ); + /** * Default values from the default block. * @@ -68,7 +70,6 @@ public function __construct( $default_params, $custom_params ) { $this->custom_params = is_array( $custom_params ) ? $custom_params : array(); } - /** * Checks to see if the item that is passed is a post ID. * @@ -106,12 +107,30 @@ public function get_custom_param( string $name ) { } return false; } + /** + * Static function to return the list of allowed controls and their associated params in the query. + * + * @return array + */ + public static function get_allowed_controls() { + return \apply_filters( 'aql_allowed_controls', array_keys( self::ALLOWED_CONTROLS ) ); + } + + protected function get_params_to_process() { + $params = array(); + foreach ( self::get_allowed_controls() as $control ) { + $params[] = self::ALLOWED_CONTROLS[ $control ]; + } + return $params; + } /** * Process all params at once. */ public function process_all(): void { - foreach ( self::KNOWN_PARAMS as $param_name ) { + // Get the params from the allowed controls and remove any duplicates. + $params = array_unique( $this->get_params_to_process() ); + foreach ( $params as $param_name ) { if ( $this->has_custom_param( $param_name ) ) { call_user_func( array( $this, 'process_' . $param_name ) ); } @@ -124,5 +143,4 @@ public function process_all(): void { public function get_query_args(): array { return $this->custom_args; } - } diff --git a/includes/enqueues.php b/includes/enqueues.php index c5ebbcf..430e557 100644 --- a/includes/enqueues.php +++ b/includes/enqueues.php @@ -7,7 +7,7 @@ namespace AdvancedQueryLoop; -use function AdvancedQueryLoop\Utils\{ is_gutenberg_plugin_version_or_higher,is_core_version_or_higher }; +use function AdvancedQueryLoop\Utils\{ is_gutenberg_plugin_version_or_higher, is_core_version_or_higher }; // Bail on unit tests. @@ -35,9 +35,14 @@ function () { ); // Allow for translation. wp_set_script_translations( 'advanced-query-loop', 'advanced-query-loop' ); + // Add inline script. + wp_add_inline_script( + 'advanced-query-loop', + 'aql.allowedControls = "' . implode( ',', Query_Params_Generator::get_allowed_controls() ) . '";' + ); } - // Per Page, Offset, and Max count controls where merged into GB 19. + // Per Page, Offset, and Max count controls were merged into GB 19. if ( ! is_gutenberg_plugin_version_or_higher( '19' ) && ! is_core_version_or_higher( '6.7' ) ) { // Enqueue the legacy controls. $pre_gb_19_assets_file = BUILD_DIR_PATH . 'legacy-pre-gb-19.asset.php'; diff --git a/phpunit.xml b/phpunit.xml index 07ee568..6e07158 100644 --- a/phpunit.xml +++ b/phpunit.xml @@ -1,7 +1,7 @@ { +export const ChildItemsToggle = ( { + attributes, + setAttributes, + allowedControls, +} ) => { const { query: { post_parent: postParent } = {} } = attributes; const { isHierarchial, postTypeName, postID } = useSelect( ( select ) => { @@ -22,6 +26,11 @@ export const ChildItemsToggle = ( { attributes, setAttributes } ) => { }; }, [] ); + // If the control is not allowed, return null. + if ( ! allowedControls.includes( 'child_items_only' ) ) { + return null; + } + return ( { +export const MultiplePostSelect = ( { + attributes, + setAttributes, + allowedControls, +} ) => { const { query: { multiple_posts: multiplePosts = [], postType } = {} } = attributes; - const postTypes = useSelect( ( select ) => - select( coreStore ) - .getPostTypes( { per_page: 50 } ) - ?.filter( ( { viewable } ) => viewable ) - ?.map( ( { slug } ) => slug ) + const postTypes = useSelect( + ( select ) => + select( coreStore ) + .getPostTypes( { per_page: 50 } ) + ?.filter( ( { viewable } ) => viewable ) + ?.map( ( { slug } ) => slug ), + [] ); + // If the control is not allowed, return null. + if ( ! allowedControls.includes( 'additional_post_types' ) ) { + return null; + } + if ( ! postTypes ) { return
{ __( 'Loading…', 'advanced-query-loop' ) }
; } diff --git a/src/components/pagination-toggle.js b/src/components/pagination-toggle.js index 054151c..e6704f7 100644 --- a/src/components/pagination-toggle.js +++ b/src/components/pagination-toggle.js @@ -4,9 +4,17 @@ import { ToggleControl } from '@wordpress/components'; import { __ } from '@wordpress/i18n'; -export const PaginationToggle = ( { attributes, setAttributes } ) => { +export const PaginationToggle = ( { + attributes, + setAttributes, + allowedControls, +} ) => { const { query: { disable_pagination: disablePagination } = {} } = attributes; + // If the control is not allowed, return null. + if ( ! allowedControls.includes( 'pagination' ) ) { + return null; + } return ( { +export const PostDateQueryControls = ( { + attributes, + setAttributes, + allowedControls, +} ) => { const { query: { date_query: { @@ -24,143 +28,155 @@ export const PostDateQueryControls = ( { attributes, setAttributes } ) => { return ( <>

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

- { - setAttributes( { - query: { - ...attributes.query, - date_query: { - ...attributes.query.date_query, - range: newRange, - }, - }, - } ); - } } - __nextHasNoMarginBottom - /> - { range !== '' && ( - { + value={ range } + disabled={ relationFromQuery !== '' } + options={ [ + { + label: __( 'None', 'advanced-query-loop' ), + value: '', + }, + { + label: __( 'Last month', 'advanced-query-loop' ), + value: 'last-month', + }, + { + label: __( 'Last 3 months', 'advanced-query-loop' ), + value: 'three-months', + }, + { + label: __( 'Last 6 months', 'advanced-query-loop' ), + value: 'six-months', + }, + { + label: __( + 'Last 12 months', + 'advanced-query-loop' + ), + value: 'twelve-months', + }, + ] } + onChange={ ( newRange ) => { setAttributes( { query: { ...attributes.query, date_query: { ...attributes.query.date_query, - current_date_in_range: - newCurrentDateInRange, + range: newRange, }, }, } ); } } + __nextHasNoMarginBottom /> ) } - - { - setAttributes( { - query: { - ...attributes.query, - date_query: - relation !== '' - ? { - ...attributes.query.date_query, - relation, - } - : '', + ) } + disabled={ range === '' } + checked={ currentDateInRange } + onChange={ ( newCurrentDateInRange ) => { + setAttributes( { + query: { + ...attributes.query, + date_query: { + ...attributes.query.date_query, + current_date_in_range: + newCurrentDateInRange, + }, + }, + } ); + } } + /> + ) } + { allowedControls.includes( 'date_query_relationship' ) && ( + + { + label: __( + 'Between specific dates', + 'advanced-query-loop' + ), + value: 'between', + }, + ] } + onChange={ ( relation ) => { + setAttributes( { + query: { + ...attributes.query, + date_query: + relation !== '' + ? { + ...attributes.query.date_query, + relation, + } + : '', + }, + } ); + } } + __nextHasNoMarginBottom + /> + ) } { relationFromQuery !== '' && - ! relationFromQuery.includes( 'current' ) && ( + ! relationFromQuery.includes( 'current' ) && + allowedControls.includes( 'date_query_relationship' ) && ( <> { relationFromQuery === 'between' && (

diff --git a/src/components/post-exclude-controls.js b/src/components/post-exclude-controls.js index ff82341..f1db202 100644 --- a/src/components/post-exclude-controls.js +++ b/src/components/post-exclude-controls.js @@ -9,13 +9,18 @@ import { __ } from '@wordpress/i18n'; /** * A component that lets you pick posts to be excluded from the query * - * @param {Object} props Component props - * @param {Object} props.attributes Block attributes - * @param {Function} props.setAttributes Block attributes setter + * @param {Object} props Component props + * @param {Object} props.attributes Block attributes + * @param {Function} props.setAttributes Block attributes setter + * @param {Array} props.allowedControls Allowed controls * * @return {Element} PostExcludeControls */ -export const PostExcludeControls = ( { attributes, setAttributes } ) => { +export const PostExcludeControls = ( { + attributes, + setAttributes, + allowedControls, +} ) => { const { query: { exclude_current: excludeCurrent } = {} } = attributes; const { record: siteOptions } = useEntityRecord( 'root', 'site' ); const { currentPost, isAdmin } = useSelect( ( select ) => { @@ -28,6 +33,11 @@ export const PostExcludeControls = ( { attributes, setAttributes } ) => { }; }, [] ); + // If the control is not allowed, return null. + if ( ! allowedControls.includes( 'exclude_current_post' ) ) { + return null; + } + if ( ! currentPost ) { return
{ __( 'Loading…', 'advanced-query-loop' ) }
; } diff --git a/src/components/post-include-controls.js b/src/components/post-include-controls.js index 3a2a07a..2074523 100644 --- a/src/components/post-include-controls.js +++ b/src/components/post-include-controls.js @@ -13,7 +13,11 @@ import { __ } from '@wordpress/i18n'; *@return {Element} PostIncludeControls */ -export const PostIncludeControls = ( { attributes, setAttributes } ) => { +export const PostIncludeControls = ( { + attributes, + setAttributes, + allowedControls, +} ) => { const { query: { include_posts: includePosts = [], @@ -69,6 +73,11 @@ export const PostIncludeControls = ( { attributes, setAttributes } ) => { } }, [ multiplePosts ] ); + // If the control is not allowed, return null.`` + if ( ! allowedControls.includes( 'include_posts' ) ) { + return null; + } + /** * Retrieves the ID of a post based on its title. * diff --git a/src/components/post-meta-query-controls.js b/src/components/post-meta-query-controls.js index 6960303..06e2850 100644 --- a/src/components/post-meta-query-controls.js +++ b/src/components/post-meta-query-controls.js @@ -30,7 +30,11 @@ const combineMetaKeys = ( records ) => { }; // A component to render a select control for the post meta query. -export const PostMetaQueryControls = ( { attributes, setAttributes } ) => { +export const PostMetaQueryControls = ( { + attributes, + setAttributes, + allowedControls, +} ) => { const { query: { postType, @@ -44,8 +48,6 @@ export const PostMetaQueryControls = ( { attributes, setAttributes } ) => { const [ selectedPostType ] = useState( postType ); - const registeredMeta = combineMetaKeys( records ); - useEffect( () => { // If the post type changes, reset the meta query. if ( postType !== selectedPostType ) { @@ -59,6 +61,13 @@ export const PostMetaQueryControls = ( { attributes, setAttributes } ) => { } }, [ postType ] ); + // If the control is not allowed, return null. + if ( ! allowedControls.includes( 'post_meta_query' ) ) { + return null; + } + + const registeredMeta = combineMetaKeys( records ); + return ( <>

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

diff --git a/src/components/post-order-controls.js b/src/components/post-order-controls.js index f7eee69..c7e3b91 100644 --- a/src/components/post-order-controls.js +++ b/src/components/post-order-controls.js @@ -61,8 +61,18 @@ export const sortOptions = [ * @param {*} param0 * @return {Element} PostCountControls */ -export const PostOrderControls = ( { attributes, setAttributes } ) => { +export const PostOrderControls = ( { + attributes, + setAttributes, + allowedControls, +} ) => { const { query: { order, orderBy } = {} } = attributes; + + // If the control is not allowed, return null. + if ( ! allowedControls.includes( 'post_order' ) ) { + return null; + } + return ( <> { +export const TaxonomyQueryControl = ( { + attributes, + setAttributes, + allowedControls, +} ) => { const { query: { postType, @@ -45,6 +49,11 @@ export const TaxonomyQueryControl = ( { attributes, setAttributes } ) => { ) ); + // If the control is not allowed, return null. + if ( ! allowedControls.includes( 'taxonomy_query_builder' ) ) { + return null; + } + return ( <> { const withAdvancedQueryControls = ( BlockEdit ) => ( props ) => { // If the is the correct variation, add the custom controls. if ( isAdvancedQueryLoop( props ) ) { - // If the inherit prop is false or undefined, add all the controls. + const { allowedControls } = window?.aql; const { attributes } = props; + const allowedControlsArray = allowedControls.split( ',' ); + const propsWithControls = { + ...props, + allowedControls: allowedControlsArray, + }; + // If the inherit prop is false or undefined, add all the controls. if ( ! attributes.query.inherit ) { return ( <> @@ -60,18 +66,21 @@ const withAdvancedQueryControls = ( BlockEdit ) => ( props ) => { ) } > + + + + + + + + + + + - - - - - - - - - - @@ -88,9 +97,9 @@ const withAdvancedQueryControls = ( BlockEdit ) => ( props ) => { 'advanced-query-loop' ) } > - + diff --git a/tests/unit/bootstrap.php b/tests/unit/bootstrap.php new file mode 100644 index 0000000..0faef51 --- /dev/null +++ b/tests/unit/bootstrap.php @@ -0,0 +1,6 @@ +