diff --git a/docs/designers-developers/developers/data/data-core-block-editor.md b/docs/designers-developers/developers/data/data-core-block-editor.md index 8a146dcb49b26e..f05788dcf52818 100644 --- a/docs/designers-developers/developers/data/data-core-block-editor.md +++ b/docs/designers-developers/developers/data/data-core-block-editor.md @@ -94,15 +94,10 @@ then the nested template part's child blocks will not be returned. This way, the template block itself is considered part of the parent, but the children are not. -You can override this behavior with the includeControlledInnerBlocks setting. -So if you call `getBlock( TP, { WPGetBlockSettings: true } )`, it will return -all nested blocks, including all child inner block controllers and their children. - _Parameters_ - _state_ `Object`: Editor state. - _clientId_ `string`: Block client ID. -- _settings_ `?WPGetBlockSettings`: A settings object. _Returns_ @@ -282,8 +277,7 @@ _Returns_ Returns all block objects for the current post being edited as an array in the order they appear in the post. Note that this will exclude child blocks -of nested inner block controllers unless the `includeControlledInnerBlocks` -setting is set to true. +of nested inner block controllers. Note: It's important to memoize this selector to avoid return a new instance on each call. We use the block cache state for each top-level block of the @@ -295,7 +289,6 @@ _Parameters_ - _state_ `Object`: Editor state. - _rootClientId_ `?string`: Optional root client ID of block list. -- _settings_ `?WPGetBlockSettings`: A settings object. _Returns_ diff --git a/packages/block-editor/src/components/block-navigation/index.js b/packages/block-editor/src/components/block-navigation/index.js index f704338e52824e..4e18231de1d663 100644 --- a/packages/block-editor/src/components/block-navigation/index.js +++ b/packages/block-editor/src/components/block-navigation/index.js @@ -62,16 +62,15 @@ export default compose( const { getSelectedBlockClientId, getBlockHierarchyRootClientId, - getBlock, - getBlocks, + __unstableGetBlockWithBlockTree, + __unstableGetBlockTree, } = select( 'core/block-editor' ); const selectedBlockClientId = getSelectedBlockClientId(); return { - rootBlocks: getBlocks( '', { includeControlledInnerBlocks: true } ), + rootBlocks: __unstableGetBlockTree(), rootBlock: selectedBlockClientId - ? getBlock( - getBlockHierarchyRootClientId( selectedBlockClientId ), - { includeControlledInnerBlocks: true } + ? __unstableGetBlockWithBlockTree( + getBlockHierarchyRootClientId( selectedBlockClientId ) ) : null, selectedBlockClientId, diff --git a/packages/block-editor/src/store/selectors.js b/packages/block-editor/src/store/selectors.js index 9d4bff675432ac..4fe021a9cc0966 100644 --- a/packages/block-editor/src/store/selectors.js +++ b/packages/block-editor/src/store/selectors.js @@ -40,16 +40,6 @@ import { Platform } from '@wordpress/element'; * text value. See `wp.richText.create`. */ -/** - * Settings which can be passed to the getBlock or getBlocks selectors. - * - * @typedef {Object} WPGetBlockSettings - * @property {boolean} includeControlledInnerBlocks If true, include nested child - * blocks of inner block controllers. - * The default of false excludes - * nested blocks of inner block controllers. - */ - // Module constants const MILLISECONDS_PER_HOUR = 3600 * 1000; const MILLISECONDS_PER_DAY = 24 * 3600 * 1000; @@ -143,18 +133,13 @@ export function getBlockAttributes( state, clientId ) { * the template block itself is considered part of the parent, but the children * are not. * - * You can override this behavior with the includeControlledInnerBlocks setting. - * So if you call `getBlock( TP, { WPGetBlockSettings: true } )`, it will return - * all nested blocks, including all child inner block controllers and their children. - * - * @param {Object} state Editor state. - * @param {string} clientId Block client ID. - * @param {?WPGetBlockSettings} settings A settings object. + * @param {Object} state Editor state. + * @param {string} clientId Block client ID. * * @return {Object} Parsed block object. */ export const getBlock = createSelector( - ( state, clientId, { includeControlledInnerBlocks = false } = {} ) => { + ( state, clientId ) => { const block = state.blocks.byClientId[ clientId ]; if ( ! block ) { return null; @@ -163,13 +148,9 @@ export const getBlock = createSelector( return { ...block, attributes: getBlockAttributes( state, clientId ), - innerBlocks: - ! includeControlledInnerBlocks && - areInnerBlocksControlled( state, clientId ) - ? EMPTY_ARRAY - : getBlocks( state, clientId, { - includeControlledInnerBlocks, - } ), + innerBlocks: areInnerBlocksControlled( state, clientId ) + ? EMPTY_ARRAY + : getBlocks( state, clientId ), }; }, ( state, clientId ) => [ @@ -203,8 +184,7 @@ export const __unstableGetBlockWithoutInnerBlocks = createSelector( /** * Returns all block objects for the current post being edited as an array in * the order they appear in the post. Note that this will exclude child blocks - * of nested inner block controllers unless the `includeControlledInnerBlocks` - * setting is set to true. + * of nested inner block controllers. * * Note: It's important to memoize this selector to avoid return a new instance * on each call. We use the block cache state for each top-level block of the @@ -212,16 +192,15 @@ export const __unstableGetBlockWithoutInnerBlocks = createSelector( * associated with the given entity, and does not refresh when changes are made * to blocks which are part of different inner block controllers. * - * @param {Object} state Editor state. - * @param {?string} rootClientId Optional root client ID of block list. - * @param {?WPGetBlockSettings} settings A settings object. + * @param {Object} state Editor state. + * @param {?string} rootClientId Optional root client ID of block list. * * @return {Object[]} Post blocks. */ export const getBlocks = createSelector( - ( state, rootClientId, { includeControlledInnerBlocks = false } = {} ) => { + ( state, rootClientId ) => { return map( getBlockOrder( state, rootClientId ), ( clientId ) => - getBlock( state, clientId, { includeControlledInnerBlocks } ) + getBlock( state, clientId ) ); }, ( state, rootClientId ) => @@ -231,6 +210,58 @@ export const getBlocks = createSelector( ) ); +/** + * Similar to getBlock, except it will include the entire nested block tree as + * inner blocks. The normal getBlock selector will exclude sections of the block + * tree which belong to different entities. + * + * @param {Object} state Editor state. + * @param {string} clientId Client ID of the block to get. + * + * @return {Object} The block with all + */ +export const __unstableGetBlockWithBlockTree = createSelector( + ( state, clientId ) => { + const block = state.blocks.byClientId[ clientId ]; + if ( ! block ) { + return null; + } + + return { + ...block, + attributes: getBlockAttributes( state, clientId ), + innerBlocks: __unstableGetBlockTree( state, clientId ), + }; + }, + ( state ) => [ + state.blocks.byClientId, + state.blocks.order, + state.blocks.attributes, + ] +); + +/** + * Similar to getBlocks, except this selector returns the entire block tree + * represented in the block-editor store from the given root regardless of any + * inner block controllers. + * + * @param {Object} state Editor state. + * @param {?string} rootClientId Optional root client ID of block list. + * + * @return {Object[]} Post blocks. + */ +export const __unstableGetBlockTree = createSelector( + ( state, rootClientId = '' ) => + map( getBlockOrder( state, rootClientId ), ( clientId ) => + __unstableGetBlockWithBlockTree( state, clientId ) + ), + ( state ) => [ + state.blocks.byClientId, + state.blocks.order, + state.blocks.attributes, + ] +); + /** * Returns an array containing the clientIds of all descendants * of the blocks given.