diff --git a/packages/block-editor/src/components/block-edit/edit.js b/packages/block-editor/src/components/block-edit/edit.js index 6b1ddd86f4c76e..83d0e3f406f829 100644 --- a/packages/block-editor/src/components/block-edit/edit.js +++ b/packages/block-editor/src/components/block-edit/edit.js @@ -18,8 +18,6 @@ import { useContext, useMemo } from '@wordpress/element'; * Internal dependencies */ import BlockContext from '../block-context'; -import { withBlockBindingsSupport } from './with-block-bindings-support'; -import { canBindBlock } from '../../utils/block-bindings'; /** * Default value used for blocks which do not define their own context needs, @@ -49,8 +47,6 @@ const Edit = ( props ) => { const EditWithFilters = withFilters( 'editor.BlockEdit' )( Edit ); -const EditWithFiltersAndBindings = withBlockBindingsSupport( EditWithFilters ); - const EditWithGeneratedProps = ( props ) => { const { attributes = {}, name } = props; const blockType = getBlockType( name ); @@ -71,12 +67,8 @@ const EditWithGeneratedProps = ( props ) => { return null; } - const EditComponent = canBindBlock( name ) - ? EditWithFiltersAndBindings - : EditWithFilters; - if ( blockType.apiVersion > 1 ) { - return ; + return ; } // Generate a class name for the block's editable form. @@ -90,7 +82,7 @@ const EditWithGeneratedProps = ( props ) => { ); return ( - ( props ) => { const registry = useRegistry(); const blockContext = useContext( BlockContext ); @@ -72,9 +108,9 @@ export const withBlockBindingsSupport = createHigherOrderComponent( () => replacePatternOverrideDefaultBindings( name, - props.attributes?.metadata?.bindings + props.attributes.metadata?.bindings ), - [ props.attributes?.metadata?.bindings, name ] + [ props.attributes.metadata?.bindings, name ] ); // While this hook doesn't directly call any selectors, `useSelect` is @@ -160,7 +196,7 @@ export const withBlockBindingsSupport = createHigherOrderComponent( const hasParentPattern = !! updatedContext[ 'pattern/overrides' ]; const hasPatternOverridesDefaultBinding = - props.attributes?.metadata?.bindings?.[ DEFAULT_ATTRIBUTE ] + props.attributes.metadata?.bindings?.[ DEFAULT_ATTRIBUTE ] ?.source === 'core/pattern-overrides'; const _setAttributes = useCallback( @@ -247,13 +283,40 @@ export const withBlockBindingsSupport = createHigherOrderComponent( ); return ( - + <> + + ); }, 'withBlockBindingSupport' ); + +/** + * Filters a registered block's settings to enhance a block's `edit` component + * to upgrade bound attributes. + * + * @param {WPBlockSettings} settings - Registered block settings. + * @param {string} name - Block name. + * @return {WPBlockSettings} Filtered block settings. + */ +function shimAttributeSource( settings, name ) { + if ( ! canBindBlock( name ) ) { + return settings; + } + + return { + ...settings, + edit: withBlockBindingSupport( settings.edit ), + }; +} + +addFilter( + 'blocks.registerBlockType', + 'core/editor/custom-sources-backwards-compatibility/shim-attribute-source', + shimAttributeSource +); diff --git a/packages/block-editor/src/utils/block-bindings.js b/packages/block-editor/src/utils/block-bindings.js index 82f0dff53531a4..dcf80d985473b2 100644 --- a/packages/block-editor/src/utils/block-bindings.js +++ b/packages/block-editor/src/utils/block-bindings.js @@ -13,43 +13,6 @@ function isObjectEmpty( object ) { return ! object || Object.keys( object ).length === 0; } -export const BLOCK_BINDINGS_ALLOWED_BLOCKS = { - 'core/paragraph': [ 'content' ], - 'core/heading': [ 'content' ], - 'core/image': [ 'id', 'url', 'title', 'alt' ], - 'core/button': [ 'url', 'text', 'linkTarget', 'rel' ], -}; - -/** - * Based on the given block name, - * check if it is possible to bind the block. - * - * @param {string} blockName - The block name. - * @return {boolean} Whether it is possible to bind the block to sources. - */ -export function canBindBlock( blockName ) { - return blockName in BLOCK_BINDINGS_ALLOWED_BLOCKS; -} - -/** - * Based on the given block name and attribute name, - * check if it is possible to bind the block attribute. - * - * @param {string} blockName - The block name. - * @param {string} attributeName - The attribute name. - * @return {boolean} Whether it is possible to bind the block attribute. - */ -export function canBindAttribute( blockName, attributeName ) { - return ( - canBindBlock( blockName ) && - BLOCK_BINDINGS_ALLOWED_BLOCKS[ blockName ].includes( attributeName ) - ); -} - -export function getBindableAttributes( blockName ) { - return BLOCK_BINDINGS_ALLOWED_BLOCKS[ blockName ]; -} - /** * Contains utils to update the block `bindings` metadata. * diff --git a/packages/e2e-tests/plugins/block-bindings.php b/packages/e2e-tests/plugins/block-bindings.php index 1fd6d8468c77db..b86673c2c523d0 100644 --- a/packages/e2e-tests/plugins/block-bindings.php +++ b/packages/e2e-tests/plugins/block-bindings.php @@ -41,11 +41,7 @@ function gutenberg_test_block_bindings_registration() { plugins_url( 'block-bindings/index.js', __FILE__ ), array( 'wp-blocks', - 'wp-block-editor', - 'wp-components', - 'wp-compose', - 'wp-element', - 'wp-hooks', + 'wp-private-apis', ), filemtime( plugin_dir_path( __FILE__ ) . 'block-bindings/index.js' ), true diff --git a/packages/e2e-tests/plugins/block-bindings/index.js b/packages/e2e-tests/plugins/block-bindings/index.js index 63c463e197fa8a..5c364257caed19 100644 --- a/packages/e2e-tests/plugins/block-bindings/index.js +++ b/packages/e2e-tests/plugins/block-bindings/index.js @@ -1,9 +1,4 @@ const { registerBlockBindingsSource } = wp.blocks; -const { InspectorControls } = wp.blockEditor; -const { PanelBody, TextControl } = wp.components; -const { createHigherOrderComponent } = wp.compose; -const { createElement: el, Fragment } = wp.element; -const { addFilter } = wp.hooks; const { fieldsList } = window.testingBindings || {}; const getValues = ( { bindings } ) => { @@ -51,43 +46,3 @@ registerBlockBindingsSource( { getValues, canUserEditValue: () => true, } ); - -const withBlockBindingsInspectorControl = createHigherOrderComponent( - ( BlockEdit ) => { - return ( props ) => { - if ( ! props.attributes?.metadata?.bindings?.content ) { - return el( BlockEdit, props ); - } - - return el( - Fragment, - {}, - el( BlockEdit, props ), - el( - InspectorControls, - {}, - el( - PanelBody, - { title: 'Bindings' }, - el( TextControl, { - __next40pxDefaultSize: true, - __nextHasNoMarginBottom: true, - label: 'Content', - value: props.attributes.content, - onChange: ( content ) => - props.setAttributes( { - content, - } ), - } ) - ) - ) - ); - }; - } -); - -addFilter( - 'editor.BlockEdit', - 'testing/bindings-inspector-control', - withBlockBindingsInspectorControl -); diff --git a/test/e2e/specs/editor/various/block-bindings/post-meta.spec.js b/test/e2e/specs/editor/various/block-bindings/post-meta.spec.js index 318707e22f098d..32334bfc777f2a 100644 --- a/test/e2e/specs/editor/various/block-bindings/post-meta.spec.js +++ b/test/e2e/specs/editor/various/block-bindings/post-meta.spec.js @@ -524,47 +524,6 @@ test.describe( 'Post Meta source', () => { previewPage.locator( '#connected-paragraph' ) ).toHaveText( 'new value' ); } ); - - test( 'should be possible to edit the value of the connected custom fields in the inspector control registered by the plugin', async ( { - editor, - page, - } ) => { - await editor.insertBlock( { - name: 'core/paragraph', - attributes: { - anchor: 'connected-paragraph', - content: 'fallback content', - metadata: { - bindings: { - content: { - source: 'core/post-meta', - args: { - key: 'movie_field', - }, - }, - }, - }, - }, - } ); - const contentInput = page.getByRole( 'textbox', { - name: 'Content', - } ); - await expect( contentInput ).toHaveValue( - 'Movie field default value' - ); - await contentInput.fill( 'new value' ); - // Check that the paragraph content attribute didn't change. - const [ paragraphBlockObject ] = await editor.getBlocks(); - expect( paragraphBlockObject.attributes.content ).toBe( - 'fallback content' - ); - // Check the value of the custom field is being updated by visiting the frontend. - const previewPage = await editor.openPreviewPage(); - await expect( - previewPage.locator( '#connected-paragraph' ) - ).toHaveText( 'new value' ); - } ); - test( 'should be possible to connect movie fields through the attributes panel', async ( { editor, page,