import shorthash from 'shorthash'; import { createHigherOrderComponent } from '@wordpress/compose'; import { withSelect } from '@wordpress/data'; import { Component } from '@wordpress/element'; import { addFilter } from '@wordpress/hooks'; // List of used IDs to prevent duplicates. const usedIds = {}; /** * Override the default edit UI to include a new block inspector control for * assigning the custom styles if needed. * * @param {Function | Component} BlockEdit Original component. * * @return {string} Wrapped component. */ const withUniqueBlockId = createHigherOrderComponent((BlockEdit) => { class newEdit extends Component { constructor(...args) { super(...args); const { attributes, clientId } = this.props; // fix duplicated classes after block clone. if ( clientId && attributes.block_id && typeof usedIds[attributes.block_id] === 'undefined' ) { usedIds[attributes.block_id] = clientId; } this.maybeCreateBlockId = this.maybeCreateBlockId.bind(this); } componentDidMount() { this.maybeCreateBlockId(); } componentDidUpdate() { this.maybeCreateBlockId(); } maybeCreateBlockId() { if (this.props.blockName !== 'visual-portfolio/block') { return; } const { setAttributes, attributes, clientId } = this.props; const { block_id: blockId } = attributes; if (!blockId || usedIds[blockId] !== clientId) { let newBlockId = ''; // check if ID already exist. let tryCount = 10; while ( !newBlockId || (typeof usedIds[newBlockId] !== 'undefined' && usedIds[newBlockId] !== clientId && tryCount > 0) ) { newBlockId = shorthash.unique(clientId); tryCount -= 1; } if (newBlockId && typeof usedIds[newBlockId] === 'undefined') { usedIds[newBlockId] = clientId; } if (newBlockId !== blockId) { setAttributes({ block_id: newBlockId, }); } } } render() { return ; } } return withSelect((select, ownProps) => ({ blockName: ownProps.name, }))(newEdit); }, 'withUniqueBlockId'); addFilter('editor.BlockEdit', 'vpf/editor/unique-block-id', withUniqueBlockId);