woocommerce/plugins/woocommerce-blocks/assets/js/atomic/utils/register-block-single-produ...

115 lines
3.4 KiB
TypeScript

/**
* External dependencies
*/
import {
BlockAttributes,
BlockConfiguration,
BlockVariation,
getBlockType,
registerBlockType,
registerBlockVariation,
unregisterBlockType,
unregisterBlockVariation,
} from '@wordpress/blocks';
import { subscribe, select } from '@wordpress/data';
// Creating a local cache to prevent multiple registration tries.
const blocksRegistered = new Set();
function parseTemplateId( templateId: string | undefined ) {
return templateId?.split( '//' )[ 1 ];
}
export const registerBlockSingleProductTemplate = ( {
blockName,
blockMetadata,
blockSettings,
isVariationBlock = false,
variationName,
}: {
blockName: string;
blockMetadata: Partial< BlockConfiguration >;
blockSettings: Partial< BlockConfiguration >;
isVariationBlock?: boolean;
variationName?: string;
} ) => {
let currentTemplateId: string | undefined = '';
subscribe( () => {
const previousTemplateId = currentTemplateId;
const store = select( 'core/edit-site' );
currentTemplateId = parseTemplateId( store?.getEditedPostId() );
const hasChangedTemplate = previousTemplateId !== currentTemplateId;
const hasTemplateId = Boolean( currentTemplateId );
if ( ! hasChangedTemplate || ! hasTemplateId || ! blockName ) {
return;
}
let isBlockRegistered = Boolean( getBlockType( blockName ) );
/**
* We need to unregister the block each time the user visits or leaves the Single Product template.
*
* The Single Product template is the only template where the `ancestor` property is not needed because it provides the context
* for the product blocks. We need to unregister and re-register the block to remove or add the `ancestor` property depending on which
* location (template, post, page, etc.) the user is in.
*
*/
if (
isBlockRegistered &&
( currentTemplateId?.includes( 'single-product' ) ||
previousTemplateId?.includes( 'single-product' ) )
) {
if ( isVariationBlock && variationName ) {
unregisterBlockVariation( blockName, variationName );
} else {
unregisterBlockType( blockName );
}
isBlockRegistered = false;
}
if ( ! isBlockRegistered ) {
if ( isVariationBlock ) {
registerBlockVariation( blockName, {
...blockSettings,
// @ts-expect-error: `ancestor` key is typed in WordPress core
ancestor: ! currentTemplateId?.includes( 'single-product' )
? blockSettings?.ancestor
: undefined,
} );
} else {
// @ts-expect-error: `registerBlockType` is typed in WordPress core
registerBlockType( blockMetadata, {
...blockSettings,
ancestor: ! currentTemplateId?.includes( 'single-product' )
? blockSettings?.ancestor
: undefined,
} );
}
}
}, 'core/edit-site' );
subscribe( () => {
const isBlockRegistered = Boolean( variationName )
? blocksRegistered.has( variationName )
: blocksRegistered.has( blockName );
// This subscribe callback could be invoked with the core/blocks store
// which would cause infinite registration loops because of the `registerBlockType` call.
// This local cache helps prevent that.
if ( ! isBlockRegistered ) {
if ( isVariationBlock ) {
blocksRegistered.add( variationName );
registerBlockVariation(
blockName,
blockSettings as BlockVariation< BlockAttributes >
);
} else {
blocksRegistered.add( blockName );
// @ts-expect-error: `registerBlockType` is typed in WordPress core
registerBlockType( blockMetadata, blockSettings );
}
}
}, 'core/edit-post' );
};