Files
CHIEFSOFT\ameye e9e5c0546c first commit
2023-11-30 13:20:54 -05:00

359 lines
8.3 KiB
React

/**
* Internal dependencies
*/
import './style.scss';
import QueryControl from '../../components/query-control';
import getParentBlock from '../../../gutenberg/utils/get-parent-block';
import './posts-block';
/**
* WordPress dependencies
*/
const { __ } = wp.i18n;
const {
addFilter,
} = wp.hooks;
const {
Component,
Fragment,
} = wp.element;
const { InspectorControls } = wp.blockEditor;
const {
PanelBody,
ToggleControl,
} = wp.components;
const {
createHigherOrderComponent,
compose,
} = wp.compose;
const {
withSelect,
withDispatch,
} = wp.data;
/**
* Extend block attributes with posts block query attributes.
*
* @param {Object} blockSettings Original block settings.
* @param {String} name Original block name.
*
* @return {Object} Filtered block settings.
*/
function addAttribute( blockSettings, name ) {
// add support to core blocks
if ( 'core/group' === name ) {
if ( ! blockSettings.attributes ) {
blockSettings.attributes = {};
}
if ( ! blockSettings.attributes.canvasPostsQuery ) {
blockSettings.attributes.canvasPostsQuery = {
type: 'boolean',
};
}
}
return blockSettings;
}
/**
* Get all posts blocks inside Posts Group block.
*
* @param {Object} block - block data.
*
* @returns {Array} - list of collected blocks.
*/
function getAllPostsBlocks( block ) {
let result = [];
if ( ! block ) {
return result;
}
// Collect posts block data.
if ( block.name && 'canvas/posts' === block.name ) {
result.push( block );
}
// Check inner blocks.
if ( block.innerBlocks && block.innerBlocks.length ) {
block.innerBlocks.forEach( ( innerBlock ) => {
result = [
...result,
...getAllPostsBlocks( innerBlock ),
];
} );
}
return result;
}
/**
* Override the default edit UI to include a new block inspector control for
* assigning the Query settings to Group block.
*
* @param {function|Component} BlockEdit Original component.
*
* @return {string} Wrapped component.
*/
const withInspectorControl = createHigherOrderComponent( ( OriginalComponent ) => {
class CanvasGroupPostsQueryWrapper extends Component {
constructor() {
super( ...arguments );
this.update = this.update.bind( this );
this.getQueryAttrs = this.getQueryAttrs.bind( this );
this.updateQueryAttrs = this.updateQueryAttrs.bind( this );
this.maybeUpdatePostsBlockAttrs = this.maybeUpdatePostsBlockAttrs.bind( this );
}
componentDidMount() {
this.update();
}
componentDidUpdate() {
this.update();
}
update() {
const {
attributes,
canvasPostsBlocks,
allowCanvasPostsQuery,
} = this.props;
if ( ! allowCanvasPostsQuery || ! attributes.canvasPostsQuery ) {
return;
}
// Update inner Posts blocks attributes.
this.maybeUpdatePostsBlockAttrs( canvasPostsBlocks );
}
/**
* Get group query attrs.
* On first run get attrs from the first found Posts block.
*
* @returns {Object} - grouped posts attrs.
*/
getQueryAttrs() {
const {
canvasPostsBlocks,
} = this.props;
if ( ! this.canvasPostsGroupAttrs ) {
// default attributes.
this.canvasPostsGroupAttrs = {
avoidDuplicatePosts: false,
query: {
posts_type: 'post',
categories: '',
tags: '',
exclude_categories: '',
exclude_tags: '',
formats: '',
posts: '',
offset: '',
orderby: 'date',
order: 'DESC',
time_frame: '',
},
};
// attributes from the first inner Posts block.
if ( canvasPostsBlocks && canvasPostsBlocks.length ) {
if ( canvasPostsBlocks[ 0 ].attributes && canvasPostsBlocks[ 0 ].attributes.query ) {
this.canvasPostsGroupAttrs.query = {
...this.canvasPostsGroupAttrs.query,
...canvasPostsBlocks[ 0 ].attributes.query,
};
}
if ( canvasPostsBlocks[ 0 ].attributes && canvasPostsBlocks[ 0 ].attributes.avoidDuplicatePosts ) {
this.canvasPostsGroupAttrs.avoidDuplicatePosts = true;
}
}
}
return this.canvasPostsGroupAttrs;
}
/**
* Update query attrs.
*/
updateQueryAttrs( newAttrs ) {
const currentAttrs = this.getQueryAttrs();
this.canvasPostsGroupAttrs = {
...currentAttrs,
...newAttrs,
query: {
...currentAttrs.query,
...newAttrs.query || {},
},
};
this.update();
}
/**
* Update posts blocks Query attributes to work properly inside Posts Group block.
*
* @param {Array} blocks block list.
*/
maybeUpdatePostsBlockAttrs( blocks ) {
if ( this.groupBlockAttrsBusy ) {
return;
}
this.groupBlockAttrsBusy = true;
const {
updateBlockAttributes,
} = this.props;
const newAttrs = this.getQueryAttrs();
const queryString = JSON.stringify( newAttrs );
blocks.forEach( ( { clientId, attributes } ) => {
const postsQueryString = JSON.stringify( {
avoidDuplicatePosts: attributes.avoidDuplicatePosts,
query: attributes.query,
} );
if (
attributes.relatedPosts ||
postsQueryString !== queryString
) {
updateBlockAttributes( clientId, {
relatedPosts: false,
avoidDuplicatePosts: newAttrs.avoidDuplicatePosts,
query: {
...newAttrs.query,
},
} );
}
} );
setTimeout( () => {
this.groupBlockAttrsBusy = false;
}, 100 );
}
render() {
const {
setAttributes,
attributes,
allowCanvasPostsQuery,
} = this.props;
if ( ! attributes.canvasPostsQuery && ! allowCanvasPostsQuery ) {
return <OriginalComponent { ...this.props } />;
}
const postsGroupAttrs = attributes.canvasPostsQuery ? this.getQueryAttrs() : {};
// add new spacings controls.
return (
<Fragment>
<OriginalComponent { ...this.props } />
<InspectorControls>
<PanelBody
title={ __( 'Query Settings', 'canvas' ) }
initialOpen={ false }
>
<ToggleControl
label={ __( 'Enable global Query settings for child Posts blocks', 'canvas' ) }
checked={ attributes.canvasPostsQuery }
onChange={ () => {
setAttributes( {
canvasPostsQuery: ! attributes.canvasPostsQuery,
} );
} }
/>
{ attributes.canvasPostsQuery ? (
<Fragment>
<QueryControl
value={ postsGroupAttrs.query }
onChange={ ( val ) => {
this.updateQueryAttrs( {
query: val,
} );
} }
/>
<ToggleControl
label={ __( 'Avoid Duplicate Posts', 'canvas' ) }
help={ __( 'Changes will be visible on frontend only.', 'canvas' ) }
checked={ postsGroupAttrs.avoidDuplicatePosts }
onChange={ ( val ) => {
this.updateQueryAttrs( {
avoidDuplicatePosts: val,
} );
} }
/>
</Fragment>
) : '' }
</PanelBody>
</InspectorControls>
</Fragment>
);
}
}
return compose(
withSelect((select, ownProps) => {
if ( 'core/group' !== ownProps.name ) {
return {};
}
const {
getBlockHierarchyRootClientId,
getBlockParents,
getBlock,
} = select('core/block-editor');
const currentBlock = getBlock( ownProps.clientId );
const rootBlock = getBlock( getBlockHierarchyRootClientId( ownProps.clientId ) );
const parentBlocks = getBlockParents(ownProps.clientId);
const canvasPostsBlocks = getAllPostsBlocks( currentBlock );
let isInsideAnotherGroupQuery = false;
// Trying to find parent Posts Group block.
if ( rootBlock && (undefined === typeof rootBlock.attributes.ref || ! rootBlock.attributes.ref) && parentBlocks ) {
parentBlocks.forEach((parentID) => {
let parentBlock = getBlock( parentID );
if ( ! isInsideAnotherGroupQuery ) {
isInsideAnotherGroupQuery = 'core/group' === parentBlock.name && parentBlock.attributes.canvasPostsQuery ? parentBlock : false;
}
});
}
return {
allowCanvasPostsQuery: canvasPostsBlocks.length && ! isInsideAnotherGroupQuery,
canvasPostsBlocks,
};
}),
withDispatch((dispatch) => {
const {
updateBlockAttributes,
} = dispatch('core/block-editor');
return {
updateBlockAttributes,
};
})
)(CanvasGroupPostsQueryWrapper);
}, 'withInspectorControl' );
// Init filters.
addFilter( 'blocks.registerBlockType', 'canvas/group-block-posts-query/additional-attributes', addAttribute );
addFilter( 'editor.BlockEdit', 'canvas/group-block-posts-query/additional-attributes', withInspectorControl );