diff --git a/packages/block-library/src/block/edit.js b/packages/block-library/src/block/edit.js index 6e6379571cc9e3..799df20a6ace56 100644 --- a/packages/block-library/src/block/edit.js +++ b/packages/block-library/src/block/edit.js @@ -94,11 +94,7 @@ function hasOverridableAttributes( block ) { return ( Object.keys( PARTIAL_SYNCING_SUPPORTED_BLOCKS ).includes( block.name - ) && - !! block.attributes.metadata?.bindings && - Object.values( block.attributes.metadata.bindings ).some( - ( binding ) => binding.source === 'core/pattern-overrides' - ) + ) && !! block.attributes.metadata?.name ); } @@ -110,11 +106,7 @@ function hasOverridableBlocks( blocks ) { } function getOverridableAttributes( block ) { - return Object.entries( block.attributes.metadata.bindings ) - .filter( - ( [ , binding ] ) => binding.source === 'core/pattern-overrides' - ) - .map( ( [ attributeKey ] ) => attributeKey ); + return PARTIAL_SYNCING_SUPPORTED_BLOCKS[ block.name ]; } function applyInitialContentValuesToInnerBlocks( diff --git a/packages/block-library/src/block/index.php b/packages/block-library/src/block/index.php index 9403205c186596..6f0c3465687c02 100644 --- a/packages/block-library/src/block/index.php +++ b/packages/block-library/src/block/index.php @@ -78,13 +78,42 @@ function render_block_core_block( $attributes ) { * filter so that it is available when a pattern's inner blocks are * rendering via do_blocks given it only receives the inner content. */ - $has_pattern_overrides = isset( $attributes['content'] ); + $has_pattern_overrides = isset( $attributes['content'] ) && null !== get_block_bindings_source( 'core/pattern-overrides' ); if ( $has_pattern_overrides ) { $filter_block_context = static function ( $context ) use ( $attributes ) { $context['pattern/overrides'] = $attributes['content']; return $context; }; add_filter( 'render_block_context', $filter_block_context, 1 ); + + $filter_pattern_overrides_bindings = static function ( $parsed_block ) { + $supported_block_attrs = array( + 'core/paragraph' => array( 'content' ), + 'core/heading' => array( 'content' ), + 'core/image' => array( 'id', 'url', 'title', 'alt' ), + 'core/button' => array( 'url', 'text', 'linkTarget', 'rel' ), + ); + + if ( + // Return early if the block isn't one of the supported block types, + ! isset( $supported_block_attrs[ $parsed_block['blockName'] ] ) || + // or doesn't have a name, + empty( $parsed_block['attrs']['metadata']['name'] ) || + // or already has bindings. + ! empty( $parsed_block['attrs']['metadata']['bindings'] ) + ) { + return $parsed_block; + } + + $bindings = array(); + foreach ( $supported_block_attrs[ $parsed_block['blockName'] ] as $attribute_name ) { + $bindings[ $attribute_name ] = array( 'source' => 'core/pattern-overrides' ); + } + $parsed_block['attrs']['metadata']['bindings'] = $bindings; + + return $parsed_block; + }; + add_filter( 'render_block_data', $filter_pattern_overrides_bindings, 10, 1 ); } $content = do_blocks( $content ); @@ -92,6 +121,7 @@ function render_block_core_block( $attributes ) { if ( $has_pattern_overrides ) { remove_filter( 'render_block_context', $filter_block_context, 1 ); + remove_filter( 'render_block_data', $filter_pattern_overrides_bindings, 10 ); } return $content; diff --git a/packages/editor/src/hooks/pattern-overrides.js b/packages/editor/src/hooks/pattern-overrides.js index 442ce70a2bf71c..ecbbcce56d9477 100644 --- a/packages/editor/src/hooks/pattern-overrides.js +++ b/packages/editor/src/hooks/pattern-overrides.js @@ -14,7 +14,6 @@ import { store as editorStore } from '../store'; import { unlock } from '../lock-unlock'; const { - useSetPatternBindings, ResetOverridesControl, PATTERN_TYPES, PARTIAL_SYNCING_SUPPORTED_BLOCKS, @@ -38,7 +37,6 @@ const withPatternOverrideControls = createHigherOrderComponent( return ( <> - { isSupportedBlock && } { props.isSelected && isSupportedBlock && ( ) } @@ -47,15 +45,6 @@ const withPatternOverrideControls = createHigherOrderComponent( } ); -function BindingUpdater( props ) { - const postType = useSelect( - ( select ) => select( editorStore ).getCurrentPostType(), - [] - ); - useSetPatternBindings( props, postType ); - return null; -} - // Split into a separate component to avoid a store subscription // on every block. function ControlsWithStoreSubscription( props ) { @@ -66,18 +55,10 @@ function ControlsWithStoreSubscription( props ) { [] ); - const bindings = props.attributes.metadata?.bindings; - const hasPatternBindings = - !! bindings && - Object.values( bindings ).some( - ( binding ) => binding.source === 'core/pattern-overrides' - ); - const shouldShowResetOverridesControl = ! isEditingPattern && !! props.attributes.metadata?.name && - blockEditingMode !== 'disabled' && - hasPatternBindings; + blockEditingMode !== 'disabled'; return ( <> diff --git a/packages/patterns/src/components/use-set-pattern-bindings.js b/packages/patterns/src/components/use-set-pattern-bindings.js deleted file mode 100644 index 261187a91088c1..00000000000000 --- a/packages/patterns/src/components/use-set-pattern-bindings.js +++ /dev/null @@ -1,120 +0,0 @@ -/** - * WordPress dependencies - */ -import { usePrevious } from '@wordpress/compose'; -import { store as blocksStore } from '@wordpress/blocks'; -import { useEffect } from '@wordpress/element'; -import { useSelect } from '@wordpress/data'; - -/** - * Internal dependencies - */ -import { PARTIAL_SYNCING_SUPPORTED_BLOCKS } from '../constants'; - -import { unlock } from '../lock-unlock'; - -function removeBindings( bindings, syncedAttributes ) { - let updatedBindings = {}; - for ( const attributeName of syncedAttributes ) { - // Omit any pattern override bindings from the `updatedBindings` object. - if ( - bindings?.[ attributeName ]?.source !== 'core/pattern-overrides' && - bindings?.[ attributeName ]?.source !== undefined - ) { - updatedBindings[ attributeName ] = bindings[ attributeName ]; - } - } - if ( ! Object.keys( updatedBindings ).length ) { - updatedBindings = undefined; - } - return updatedBindings; -} - -function addBindings( bindings, syncedAttributes ) { - const updatedBindings = { ...bindings }; - for ( const attributeName of syncedAttributes ) { - if ( ! bindings?.[ attributeName ] ) { - updatedBindings[ attributeName ] = { - source: 'core/pattern-overrides', - }; - } - } - return updatedBindings; -} - -export default function useSetPatternBindings( - { name, attributes, setAttributes }, - currentPostType -) { - const hasPatternOverridesSource = useSelect( ( select ) => { - const { getBlockBindingsSource } = unlock( select( blocksStore ) ); - - // For editing link to the site editor if the theme and user permissions support it. - return !! getBlockBindingsSource( 'core/pattern-overrides' ); - }, [] ); - - const metadataName = attributes?.metadata?.name ?? ''; - const prevMetadataName = usePrevious( metadataName ) ?? ''; - const bindings = attributes?.metadata?.bindings; - - useEffect( () => { - // Bindings should only be created when editing a wp_block post type, - // and also when there's a change to the user-given name for the block. - // Also check that the pattern overrides source is registered. - if ( - ! hasPatternOverridesSource || - currentPostType !== 'wp_block' || - metadataName === prevMetadataName - ) { - return; - } - - const syncedAttributes = PARTIAL_SYNCING_SUPPORTED_BLOCKS[ name ]; - const attributeSources = syncedAttributes.map( - ( attributeName ) => - attributes.metadata?.bindings?.[ attributeName ]?.source - ); - const isConnectedToOtherSources = attributeSources.every( - ( source ) => source && source !== 'core/pattern-overrides' - ); - - // Avoid overwriting other (e.g. meta) bindings. - if ( isConnectedToOtherSources ) { - return; - } - - // The user-given name for the block was deleted, remove the bindings. - if ( ! metadataName?.length && prevMetadataName?.length ) { - const updatedBindings = removeBindings( - bindings, - syncedAttributes - ); - setAttributes( { - metadata: { - ...attributes.metadata, - bindings: updatedBindings, - }, - } ); - } - - // The user-given name for the block was set, set the bindings. - if ( ! prevMetadataName?.length && metadataName.length ) { - const updatedBindings = addBindings( bindings, syncedAttributes ); - setAttributes( { - metadata: { - ...attributes.metadata, - bindings: updatedBindings, - }, - } ); - } - }, [ - hasPatternOverridesSource, - bindings, - prevMetadataName, - metadataName, - currentPostType, - name, - attributes.metadata, - setAttributes, - ] ); -} diff --git a/packages/patterns/src/private-apis.js b/packages/patterns/src/private-apis.js index 54ad5a4aa47d1b..164e644b70f56f 100644 --- a/packages/patterns/src/private-apis.js +++ b/packages/patterns/src/private-apis.js @@ -13,7 +13,6 @@ import { import RenamePatternModal from './components/rename-pattern-modal'; import PatternsMenuItems from './components'; import RenamePatternCategoryModal from './components/rename-pattern-category-modal'; -import useSetPatternBindings from './components/use-set-pattern-bindings'; import ResetOverridesControl from './components/reset-overrides-control'; import { useAddPatternCategory } from './private-hooks'; import { @@ -34,7 +33,6 @@ lock( privateApis, { RenamePatternModal, PatternsMenuItems, RenamePatternCategoryModal, - useSetPatternBindings, ResetOverridesControl, useAddPatternCategory, PATTERN_TYPES, diff --git a/test/e2e/specs/editor/various/pattern-overrides.spec.js b/test/e2e/specs/editor/various/pattern-overrides.spec.js index b4f32e26df87af..63859a2392e17e 100644 --- a/test/e2e/specs/editor/various/pattern-overrides.spec.js +++ b/test/e2e/specs/editor/various/pattern-overrides.spec.js @@ -93,14 +93,7 @@ test.describe( 'Pattern Overrides', () => { name: 'core/paragraph', attributes: { content: 'This paragraph can be edited', - metadata: { - name: editableParagraphName, - bindings: { - content: { - source: 'core/pattern-overrides', - }, - }, - }, + metadata: { name: editableParagraphName }, }, }, { @@ -225,7 +218,7 @@ test.describe( 'Pattern Overrides', () => { const paragraphId = 'paragraph-id'; const { id } = await requestUtils.createBlock( { title: 'Pattern', - content: ` + content: `

Editable

`, status: 'publish', @@ -257,7 +250,7 @@ test.describe( 'Pattern Overrides', () => { name: 'core/paragraph', attributes: { content: 'edited Editable', - metadata: undefined, + metadata: { name: paragraphId }, }, }, ] ); @@ -274,7 +267,7 @@ test.describe( 'Pattern Overrides', () => { const { id } = await requestUtils.createBlock( { title: 'Button with target', content: ` -
+ `, @@ -384,14 +377,14 @@ test.describe( 'Pattern Overrides', () => { const headingName = 'Editable heading'; const innerPattern = await requestUtils.createBlock( { title: 'Inner Pattern', - content: ` + content: `

Inner paragraph

`, status: 'publish', } ); const outerPattern = await requestUtils.createBlock( { title: 'Outer Pattern', - content: ` + content: `

Outer heading

`, @@ -501,10 +494,10 @@ test.describe( 'Pattern Overrides', () => { const paragraphName = 'Editable paragraph'; const { id } = await requestUtils.createBlock( { title: 'Pattern', - content: ` + content: `

Heading

- +

Paragraph

`, status: 'publish', @@ -596,7 +589,7 @@ test.describe( 'Pattern Overrides', () => { ); const { id } = await requestUtils.createBlock( { title: 'Pattern', - content: ` + content: `
`, status: 'publish',