From 6816262919fb22f7a3c695a44fcd6564d913bc1c Mon Sep 17 00:00:00 2001 From: Bernie Reiter Date: Mon, 22 Sep 2025 15:52:04 +0200 Subject: [PATCH 01/12] Block Bindings: Introduce gutenberg_get_block_bindings_supported_attributes --- lib/compat/wordpress-6.9/block-bindings.php | 85 +++++++++++++-------- 1 file changed, 54 insertions(+), 31 deletions(-) diff --git a/lib/compat/wordpress-6.9/block-bindings.php b/lib/compat/wordpress-6.9/block-bindings.php index f46a2dce398ce6..b5cd3ea53dd479 100644 --- a/lib/compat/wordpress-6.9/block-bindings.php +++ b/lib/compat/wordpress-6.9/block-bindings.php @@ -86,6 +86,59 @@ function gutenberg_block_bindings_render_block( $block_content, $block, $instanc } add_filter( 'render_block', 'gutenberg_block_bindings_render_block', 10, 3 ); +/** + * Retrieves the list of block attributes supported by block bindings. + * + * @since 6.9.0 + * + * @param string $block_type The block type whose supported attributes are being retrieved. + * @return array The list of block attributes that are supported by block bindings. + */ +function gutenberg_get_block_bindings_supported_attributes( $block_type ) { + // List of block attributes supported by Block Bindings in WP 6.8. + $block_bindings_supported_attributes_6_8 = array( + 'core/paragraph' => array( 'content' ), + 'core/heading' => array( 'content' ), + 'core/image' => array( 'id', 'url', 'title', 'alt' ), + 'core/button' => array( 'url', 'text', 'linkTarget', 'rel' ), + ); + + $supported_block_attributes = + $block_bindings_supported_attributes_6_8[ $block_type ] ?? + array(); + + /** + * Filters the supported block attributes for block bindings. + * + * @since 6.9.0 + * + * @param string[] $supported_block_attributes The block's attributes that are supported by block bindings. + * @param string $block_type The block type whose attributes are being filtered. + */ + $supported_block_attributes = apply_filters( + 'block_bindings_supported_attributes', + $supported_block_attributes, + $block_type + ); + + /** + * Filters the supported block attributes for block bindings. + * + * The dynamic portion of the hook name, `$block_type`, refers to the block type + * whose attributes are being filtered. + * + * @since 6.9.0 + * + * @param string[] $supported_block_attributes The block's attributes that are supported by block bindings. + */ + $supported_block_attributes = apply_filters( + "block_bindings_supported_attributes_{$block_type}", + $supported_block_attributes + ); + + return $supported_block_attributes; +} + /** * Processes the block bindings and updates the block attributes with the values from the sources. * @@ -138,38 +191,8 @@ function gutenberg_process_block_bindings( $instance ) { 'core/image' => array( 'id', 'url', 'title', 'alt' ), 'core/button' => array( 'url', 'text', 'linkTarget', 'rel' ), ); - $supported_block_attributes = - $block_bindings_supported_attributes_6_8[ $block_type ] ?? - array(); - - /** - * Filters the supported block attributes for block bindings. - * - * @since 6.9.0 - * - * @param string[] $supported_block_attributes The block's attributes that are supported by block bindings. - * @param string $block_type The block type whose attributes are being filtered. - */ - $supported_block_attributes = apply_filters( - 'block_bindings_supported_attributes', - $supported_block_attributes, - $block_type - ); - /** - * Filters the supported block attributes for block bindings. - * - * The dynamic portion of the hook name, `$block_type`, refers to the block type - * whose attributes are being filtered. - * - * @since 6.9.0 - * - * @param string[] $supported_block_attributes The block's attributes that are supported by block bindings. - */ - $supported_block_attributes = apply_filters( - "block_bindings_supported_attributes_{$block_type}", - $supported_block_attributes - ); + $supported_block_attributes = gutenberg_get_block_bindings_supported_attributes( $block_type ); /* * Remove attributes that we know are processed by WP 6.8 from the list, From 76053ff8671921536bbe9254b317763fe742d1bf Mon Sep 17 00:00:00 2001 From: Bernie Reiter Date: Mon, 22 Sep 2025 15:56:01 +0200 Subject: [PATCH 02/12] Block Bindings: Add blockBindingsSupportedAttributes to editor settings --- lib/compat/wordpress-6.9/block-bindings.php | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/lib/compat/wordpress-6.9/block-bindings.php b/lib/compat/wordpress-6.9/block-bindings.php index b5cd3ea53dd479..c9f1ac451cb847 100644 --- a/lib/compat/wordpress-6.9/block-bindings.php +++ b/lib/compat/wordpress-6.9/block-bindings.php @@ -24,6 +24,21 @@ function ( $attributes, $block_type ) { 2 ); +// The following filter can be removed once the minimum required WordPress version is 6.9 or newer. +add_filter( + 'block_editor_settings_all', + function ( $editor_settings ) { + $editor_settings['blockBindingsSupportedAttributes'] = array(); + foreach ( array_keys( WP_Block_Type_Registry::get_instance()->get_all_registered() ) as $block_type ) { + $supported_block_attributes = gutenberg_get_block_bindings_supported_attributes( $block_type ); + if ( ! empty( $supported_block_attributes ) ) { + $editor_settings['blockBindingsSupportedAttributes'][ $block_type ] = $supported_block_attributes; + } + } + return $editor_settings; + } +); + /** * Callback function for the render_block filter. * From 6b9045d629033e2618c703b9215a95b3cfae1b40 Mon Sep 17 00:00:00 2001 From: Bernie Reiter Date: Mon, 22 Sep 2025 16:35:04 +0200 Subject: [PATCH 03/12] Add backport changelog --- backport-changelog/6.9/9992.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 backport-changelog/6.9/9992.md diff --git a/backport-changelog/6.9/9992.md b/backport-changelog/6.9/9992.md new file mode 100644 index 00000000000000..9ca717940358c0 --- /dev/null +++ b/backport-changelog/6.9/9992.md @@ -0,0 +1,3 @@ +https://github.com/WordPress/wordpress-develop/pull/9992 + +* https://github.com/WordPress/gutenberg/pull/71820 \ No newline at end of file From 0a527a6f181afaae637f2fbced9736713bf364c9 Mon Sep 17 00:00:00 2001 From: Bernie Reiter Date: Tue, 23 Sep 2025 11:01:53 +0200 Subject: [PATCH 04/12] Replace getBindableAttributes --- .../block-editor/src/hooks/block-bindings.js | 83 ++++++++++--------- .../block-editor/src/utils/block-bindings.js | 11 --- 2 files changed, 45 insertions(+), 49 deletions(-) diff --git a/packages/block-editor/src/hooks/block-bindings.js b/packages/block-editor/src/hooks/block-bindings.js index 11e17aba3b30da..75efc0d5049913 100644 --- a/packages/block-editor/src/hooks/block-bindings.js +++ b/packages/block-editor/src/hooks/block-bindings.js @@ -25,7 +25,6 @@ import { useViewportMatch } from '@wordpress/compose'; */ import { canBindAttribute, - getBindableAttributes, useBlockBindingsUtils, } from '../utils/block-bindings'; import { unlock } from '../lock-unlock'; @@ -205,52 +204,60 @@ function EditableBlockBindingsPanelItems( { export const BlockBindingsPanel = ( { name: blockName, metadata } ) => { const blockContext = useContext( BlockContext ); const { removeAllBlockBindings } = useBlockBindingsUtils(); - const bindableAttributes = getBindableAttributes( blockName ); const dropdownMenuProps = useToolsPanelDropdownMenuProps(); // `useSelect` is used purposely here to ensure `getFieldsList` // is updated whenever there are updates in block context. // `source.getFieldsList` may also call a selector via `select`. const _fieldsList = {}; - const { fieldsList, canUpdateBlockBindings } = useSelect( - ( select ) => { - if ( ! bindableAttributes || bindableAttributes.length === 0 ) { - return EMPTY_OBJECT; - } - const registeredSources = getBlockBindingsSources(); - Object.entries( registeredSources ).forEach( - ( [ sourceName, { getFieldsList, usesContext } ] ) => { - if ( getFieldsList ) { - // Populate context. - const context = {}; - if ( usesContext?.length ) { - for ( const key of usesContext ) { - context[ key ] = blockContext[ key ]; + const { bindableAttributes, fieldsList, canUpdateBlockBindings } = + useSelect( + ( select ) => { + const { blockBindingsSupportedAttributes } = + select( blockEditorStore ).getSettings(); + const _bindableAttributes = + blockBindingsSupportedAttributes?.[ blockName ]; + if ( + ! _bindableAttributes || + _bindableAttributes.length === 0 + ) { + return EMPTY_OBJECT; + } + const registeredSources = getBlockBindingsSources(); + Object.entries( registeredSources ).forEach( + ( [ sourceName, { getFieldsList, usesContext } ] ) => { + if ( getFieldsList ) { + // Populate context. + const context = {}; + if ( usesContext?.length ) { + for ( const key of usesContext ) { + context[ key ] = blockContext[ key ]; + } + } + const sourceList = getFieldsList( { + select, + context, + } ); + // Only add source if the list is not empty. + if ( Object.keys( sourceList || {} ).length ) { + _fieldsList[ sourceName ] = { ...sourceList }; } - } - const sourceList = getFieldsList( { - select, - context, - } ); - // Only add source if the list is not empty. - if ( Object.keys( sourceList || {} ).length ) { - _fieldsList[ sourceName ] = { ...sourceList }; } } - } - ); - return { - fieldsList: - Object.values( _fieldsList ).length > 0 - ? _fieldsList - : EMPTY_OBJECT, - canUpdateBlockBindings: - select( blockEditorStore ).getSettings() - .canUpdateBlockBindings, - }; - }, - [ blockContext, bindableAttributes ] - ); + ); + return { + bindableAttributes: _bindableAttributes, + fieldsList: + Object.values( _fieldsList ).length > 0 + ? _fieldsList + : EMPTY_OBJECT, + canUpdateBlockBindings: + select( blockEditorStore ).getSettings() + .canUpdateBlockBindings, + }; + }, + [ blockContext ] + ); // Return early if there are no bindable attributes. if ( ! bindableAttributes || bindableAttributes.length === 0 ) { return null; diff --git a/packages/block-editor/src/utils/block-bindings.js b/packages/block-editor/src/utils/block-bindings.js index f7f44e2f599430..4e93a3e323c9b3 100644 --- a/packages/block-editor/src/utils/block-bindings.js +++ b/packages/block-editor/src/utils/block-bindings.js @@ -56,17 +56,6 @@ export function canBindAttribute( blockName, attributeName ) { ); } -/** - * Gets the bindable attributes for a given block. - * - * @param {string} blockName The name of the block. - * - * @return {string[]} The bindable attributes for the block. - */ -export function getBindableAttributes( blockName ) { - return BLOCK_BINDINGS_ALLOWED_BLOCKS[ blockName ]; -} - /** * Checks if the block has the `__default` binding for pattern overrides. * From 77daf10b903bc402f88f5936279eb3317a7e0e24 Mon Sep 17 00:00:00 2001 From: Bernie Reiter Date: Tue, 23 Sep 2025 12:22:20 +0200 Subject: [PATCH 05/12] Actually expose blockBindingsSupportedAttributes on the client side --- .../editor/src/components/provider/use-block-editor-settings.js | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/editor/src/components/provider/use-block-editor-settings.js b/packages/editor/src/components/provider/use-block-editor-settings.js index 6d1fbfde945176..3e8ddb61fdb387 100644 --- a/packages/editor/src/components/provider/use-block-editor-settings.js +++ b/packages/editor/src/components/provider/use-block-editor-settings.js @@ -45,6 +45,7 @@ const BLOCK_EDITOR_SETTINGS = [ '__experimentalFeatures', '__experimentalGlobalStylesBaseStyles', 'alignWide', + 'blockBindingsSupportedAttributes', 'blockInspectorTabs', 'maxUploadFileSize', 'allowedMimeTypes', From 6a9b106b75bdc2f6d859391aea96bd0b90a0023e Mon Sep 17 00:00:00 2001 From: Bernie Reiter Date: Tue, 23 Sep 2025 12:24:36 +0200 Subject: [PATCH 06/12] Replace canBindAttribute --- .../src/components/block-edit/edit.js | 19 ++++++++++++++++--- .../block-editor/src/hooks/block-bindings.js | 7 ++----- .../block-editor/src/utils/block-bindings.js | 15 --------------- 3 files changed, 18 insertions(+), 23 deletions(-) diff --git a/packages/block-editor/src/components/block-edit/edit.js b/packages/block-editor/src/components/block-edit/edit.js index 27d3650f3a0902..a02cf68bd07290 100644 --- a/packages/block-editor/src/components/block-edit/edit.js +++ b/packages/block-editor/src/components/block-edit/edit.js @@ -22,10 +22,10 @@ import { useCallback, useContext, useMemo } from '@wordpress/element'; import BlockContext from '../block-context'; import isURLLike from '../link-control/is-url-like'; import { - canBindAttribute, hasPatternOverridesDefaultBinding, replacePatternOverridesDefaultBinding, } from '../../utils/block-bindings'; +import { store as blockEditorStore } from '../../store'; import { unlock } from '../../lock-unlock'; /** @@ -66,6 +66,14 @@ const EditWithGeneratedProps = ( props ) => { unlock( select( blocksStore ) ).getAllBlockBindingsSources(), [] ); + const bindableAttributes = useSelect( + ( select ) => { + const { blockBindingsSupportedAttributes } = + select( blockEditorStore ).getSettings(); + return blockBindingsSupportedAttributes?.[ name ] || []; + }, + [ name ] + ); const { blockBindings, context, hasPatternOverrides } = useMemo( () => { // Assign context values using the block type's declared context needs. @@ -120,7 +128,10 @@ const EditWithGeneratedProps = ( props ) => { ) ) { const { source: sourceName, args: sourceArgs } = binding; const source = registeredSources[ sourceName ]; - if ( ! source || ! canBindAttribute( name, attributeName ) ) { + if ( + ! source || + ! bindableAttributes.includes( attributeName ) + ) { continue; } @@ -172,6 +183,7 @@ const EditWithGeneratedProps = ( props ) => { }, [ attributes, + bindableAttributes, blockBindings, clientId, context, @@ -197,7 +209,7 @@ const EditWithGeneratedProps = ( props ) => { ) ) { if ( ! blockBindings[ attributeName ] || - ! canBindAttribute( name, attributeName ) + ! bindableAttributes.includes( attributeName ) ) { continue; } @@ -250,6 +262,7 @@ const EditWithGeneratedProps = ( props ) => { } ); }, [ + bindableAttributes, blockBindings, clientId, context, diff --git a/packages/block-editor/src/hooks/block-bindings.js b/packages/block-editor/src/hooks/block-bindings.js index 75efc0d5049913..4f3ebf60a67029 100644 --- a/packages/block-editor/src/hooks/block-bindings.js +++ b/packages/block-editor/src/hooks/block-bindings.js @@ -23,10 +23,7 @@ import { useViewportMatch } from '@wordpress/compose'; /** * Internal dependencies */ -import { - canBindAttribute, - useBlockBindingsUtils, -} from '../utils/block-bindings'; +import { useBlockBindingsUtils } from '../utils/block-bindings'; import { unlock } from '../lock-unlock'; import InspectorControls from '../components/inspector-controls'; import BlockContext from '../components/block-context'; @@ -267,7 +264,7 @@ export const BlockBindingsPanel = ( { name: blockName, metadata } ) => { const filteredBindings = { ...bindings }; Object.keys( filteredBindings ).forEach( ( key ) => { if ( - ! canBindAttribute( blockName, key ) || + ! bindableAttributes.includes( key ) && filteredBindings[ key ].source === 'core/pattern-overrides' ) { delete filteredBindings[ key ]; diff --git a/packages/block-editor/src/utils/block-bindings.js b/packages/block-editor/src/utils/block-bindings.js index 4e93a3e323c9b3..5efe36e3ea31f6 100644 --- a/packages/block-editor/src/utils/block-bindings.js +++ b/packages/block-editor/src/utils/block-bindings.js @@ -41,21 +41,6 @@ export function canBindBlock( blockName ) { return blockName in BLOCK_BINDINGS_ALLOWED_BLOCKS; } -/** - * Based on the given block name and attribute name, checks if it is possible to bind the block attribute. - * - * @param {string} blockName The name of the block. - * @param {string} attributeName The name of attribute. - * - * @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 ) - ); -} - /** * Checks if the block has the `__default` binding for pattern overrides. * From 26e7dffcd4044bc554322ac24de62e2f353a393c Mon Sep 17 00:00:00 2001 From: Bernie Reiter Date: Tue, 23 Sep 2025 13:40:25 +0200 Subject: [PATCH 07/12] Replace canBindBlock --- .../block-list/use-block-props/index.js | 16 +++++++--------- .../src/components/rich-text/index.js | 6 ++++-- .../block-editor/src/utils/block-bindings.js | 11 ----------- 3 files changed, 11 insertions(+), 22 deletions(-) diff --git a/packages/block-editor/src/components/block-list/use-block-props/index.js b/packages/block-editor/src/components/block-list/use-block-props/index.js index 8d9e952c5929b5..d9eb1658e5c455 100644 --- a/packages/block-editor/src/components/block-list/use-block-props/index.js +++ b/packages/block-editor/src/components/block-list/use-block-props/index.js @@ -29,7 +29,6 @@ import { useBlockRefProvider } from './use-block-refs'; import { useIntersectionObserver } from './use-intersection-observer'; import { useScrollIntoView } from './use-scroll-into-view'; import { useFlashEditableBlocks } from '../../use-flash-editable-blocks'; -import { canBindBlock } from '../../../utils/block-bindings'; import { useFirefoxDraggableCompatibility } from './use-firefox-draggable-compatibility'; /** @@ -128,14 +127,13 @@ export function useBlockProps( props = {}, { __unstableIsHtml } = {} ) { const blockEditContext = useBlockEditContext(); const hasBlockBindings = !! blockEditContext[ blockBindingsKey ]; - const bindingsStyle = - hasBlockBindings && canBindBlock( name ) - ? { - '--wp-admin-theme-color': 'var(--wp-block-synced-color)', - '--wp-admin-theme-color--rgb': - 'var(--wp-block-synced-color--rgb)', - } - : {}; + const bindingsStyle = hasBlockBindings + ? { + '--wp-admin-theme-color': 'var(--wp-block-synced-color)', + '--wp-admin-theme-color--rgb': + 'var(--wp-block-synced-color--rgb)', + } + : {}; // Ensures it warns only inside the `edit` implementation for the block. if ( blockApiVersion < 2 && clientId === blockEditContext.clientId ) { diff --git a/packages/block-editor/src/components/rich-text/index.js b/packages/block-editor/src/components/rich-text/index.js index ac33f7f98d2968..e933a7ebbe6fcd 100644 --- a/packages/block-editor/src/components/rich-text/index.js +++ b/packages/block-editor/src/components/rich-text/index.js @@ -39,7 +39,6 @@ import FormatEdit from './format-edit'; import { getAllowedFormats } from './utils'; import { Content, valueToHTMLString } from './content'; import { withDeprecations } from './with-deprecations'; -import { canBindBlock } from '../../utils/block-bindings'; import BlockContext from '../block-context'; export const keyboardShortcutContext = createContext(); @@ -177,9 +176,12 @@ export function RichTextWrapper( const { disableBoundBlock, bindingsPlaceholder, bindingsLabel } = useSelect( ( select ) => { + const { blockBindingsSupportedAttributes } = + select( blockEditorStore ).getSettings(); + if ( ! blockBindings?.[ identifier ] || - ! canBindBlock( blockName ) + ! ( blockName in blockBindingsSupportedAttributes ) ) { return {}; } diff --git a/packages/block-editor/src/utils/block-bindings.js b/packages/block-editor/src/utils/block-bindings.js index 5efe36e3ea31f6..fa696d2f24e13c 100644 --- a/packages/block-editor/src/utils/block-bindings.js +++ b/packages/block-editor/src/utils/block-bindings.js @@ -30,17 +30,6 @@ function isObjectEmpty( object ) { return ! object || Object.keys( object ).length === 0; } -/** - * Based on the given block name, checks if it is possible to bind the block. - * - * @param {string} blockName The name of the block. - * - * @return {boolean} Whether it is possible to bind the block to sources. - */ -export function canBindBlock( blockName ) { - return blockName in BLOCK_BINDINGS_ALLOWED_BLOCKS; -} - /** * Checks if the block has the `__default` binding for pattern overrides. * From 42d5154f91177f87ccc48f9ff8c046a3006b1b91 Mon Sep 17 00:00:00 2001 From: Bernie Reiter Date: Tue, 23 Sep 2025 14:56:11 +0200 Subject: [PATCH 08/12] Change replacePatternOverridesDefaultBinding so it no longer relies on BLOCK_BINDINGS_ALLOWED_BLOCKS --- .../src/components/block-edit/edit.js | 2 +- .../block-editor/src/utils/block-bindings.js | 17 ++++++----------- 2 files changed, 7 insertions(+), 12 deletions(-) diff --git a/packages/block-editor/src/components/block-edit/edit.js b/packages/block-editor/src/components/block-edit/edit.js index a02cf68bd07290..e56b435c7ba2b8 100644 --- a/packages/block-editor/src/components/block-edit/edit.js +++ b/packages/block-editor/src/components/block-edit/edit.js @@ -98,7 +98,7 @@ const EditWithGeneratedProps = ( props ) => { } return { blockBindings: replacePatternOverridesDefaultBinding( - name, + bindableAttributes, attributes?.metadata?.bindings ), context: computedContext, diff --git a/packages/block-editor/src/utils/block-bindings.js b/packages/block-editor/src/utils/block-bindings.js index fa696d2f24e13c..dfc2047fc5089b 100644 --- a/packages/block-editor/src/utils/block-bindings.js +++ b/packages/block-editor/src/utils/block-bindings.js @@ -11,13 +11,6 @@ import { useBlockEditContext } from '../components/block-edit'; const DEFAULT_ATTRIBUTE = '__default'; const PATTERN_OVERRIDES_SOURCE = 'core/pattern-overrides'; -const BLOCK_BINDINGS_ALLOWED_BLOCKS = { - 'core/paragraph': [ 'content' ], - 'core/heading': [ 'content' ], - 'core/image': [ 'id', 'url', 'title', 'alt', 'caption' ], - 'core/button': [ 'url', 'text', 'linkTarget', 'rel' ], - 'core/post-date': [ 'datetime' ], -}; /** * Checks if the given object is empty. @@ -48,15 +41,17 @@ export function hasPatternOverridesDefaultBinding( bindings ) { * - bindings passed in: `{ __default: { source: 'core/pattern-overrides' } }` * - bindings returned: `{ content: { source: 'core/pattern-overrides' } }` * - * @param {string} blockName The block name (e.g. 'core/paragraph'). - * @param {?Record} bindings A block's bindings from the metadata attribute. + * @param {string[]} supportedAttributes The block's attributes which are supported by block bindings. + * @param {?Record} bindings A block's bindings from the metadata attribute. * * @return {Object} The bindings with default replaced for pattern overrides. */ -export function replacePatternOverridesDefaultBinding( blockName, bindings ) { +export function replacePatternOverridesDefaultBinding( + supportedAttributes, + bindings +) { // The `__default` binding currently only works for pattern overrides. if ( hasPatternOverridesDefaultBinding( bindings ) ) { - const supportedAttributes = BLOCK_BINDINGS_ALLOWED_BLOCKS[ blockName ]; const bindingsWithDefaults = {}; for ( const attributeName of supportedAttributes ) { // If the block has mixed binding sources, retain any non pattern override bindings. From e7d278d1fa62f63389ac904ccf75ff46c5aa6ce1 Mon Sep 17 00:00:00 2001 From: Bernie Reiter Date: Tue, 23 Sep 2025 14:57:58 +0200 Subject: [PATCH 09/12] Change param order --- packages/block-editor/src/components/block-edit/edit.js | 4 ++-- packages/block-editor/src/utils/block-bindings.js | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/packages/block-editor/src/components/block-edit/edit.js b/packages/block-editor/src/components/block-edit/edit.js index e56b435c7ba2b8..b520eaa4579dab 100644 --- a/packages/block-editor/src/components/block-edit/edit.js +++ b/packages/block-editor/src/components/block-edit/edit.js @@ -98,8 +98,8 @@ const EditWithGeneratedProps = ( props ) => { } return { blockBindings: replacePatternOverridesDefaultBinding( - bindableAttributes, - attributes?.metadata?.bindings + attributes?.metadata?.bindings, + bindableAttributes ), context: computedContext, hasPatternOverrides: hasPatternOverridesDefaultBinding( diff --git a/packages/block-editor/src/utils/block-bindings.js b/packages/block-editor/src/utils/block-bindings.js index dfc2047fc5089b..57c58560021293 100644 --- a/packages/block-editor/src/utils/block-bindings.js +++ b/packages/block-editor/src/utils/block-bindings.js @@ -41,14 +41,14 @@ export function hasPatternOverridesDefaultBinding( bindings ) { * - bindings passed in: `{ __default: { source: 'core/pattern-overrides' } }` * - bindings returned: `{ content: { source: 'core/pattern-overrides' } }` * - * @param {string[]} supportedAttributes The block's attributes which are supported by block bindings. * @param {?Record} bindings A block's bindings from the metadata attribute. + * @param {string[]} supportedAttributes The block's attributes which are supported by block bindings. * * @return {Object} The bindings with default replaced for pattern overrides. */ export function replacePatternOverridesDefaultBinding( - supportedAttributes, - bindings + bindings, + supportedAttributes ) { // The `__default` binding currently only works for pattern overrides. if ( hasPatternOverridesDefaultBinding( bindings ) ) { From 0c41d6cce2d07c2e65d179ce933fe45a7ddc3500 Mon Sep 17 00:00:00 2001 From: Bernie Reiter Date: Wed, 24 Sep 2025 13:27:47 +0200 Subject: [PATCH 10/12] Prefix var with __experimental --- lib/compat/wordpress-6.9/block-bindings.php | 4 ++-- packages/block-editor/src/components/block-edit/edit.js | 6 ++++-- packages/block-editor/src/components/rich-text/index.js | 6 ++++-- packages/block-editor/src/hooks/block-bindings.js | 6 ++++-- .../src/components/provider/use-block-editor-settings.js | 2 +- 5 files changed, 15 insertions(+), 9 deletions(-) diff --git a/lib/compat/wordpress-6.9/block-bindings.php b/lib/compat/wordpress-6.9/block-bindings.php index c9f1ac451cb847..ff78a2cac40bc8 100644 --- a/lib/compat/wordpress-6.9/block-bindings.php +++ b/lib/compat/wordpress-6.9/block-bindings.php @@ -28,11 +28,11 @@ function ( $attributes, $block_type ) { add_filter( 'block_editor_settings_all', function ( $editor_settings ) { - $editor_settings['blockBindingsSupportedAttributes'] = array(); + $editor_settings['__experimentalBlockBindingsSupportedAttributes'] = array(); foreach ( array_keys( WP_Block_Type_Registry::get_instance()->get_all_registered() ) as $block_type ) { $supported_block_attributes = gutenberg_get_block_bindings_supported_attributes( $block_type ); if ( ! empty( $supported_block_attributes ) ) { - $editor_settings['blockBindingsSupportedAttributes'][ $block_type ] = $supported_block_attributes; + $editor_settings['__experimentalBlockBindingsSupportedAttributes'][ $block_type ] = $supported_block_attributes; } } return $editor_settings; diff --git a/packages/block-editor/src/components/block-edit/edit.js b/packages/block-editor/src/components/block-edit/edit.js index b520eaa4579dab..90e9ae8502c575 100644 --- a/packages/block-editor/src/components/block-edit/edit.js +++ b/packages/block-editor/src/components/block-edit/edit.js @@ -68,9 +68,11 @@ const EditWithGeneratedProps = ( props ) => { ); const bindableAttributes = useSelect( ( select ) => { - const { blockBindingsSupportedAttributes } = + const { __experimentalBlockBindingsSupportedAttributes } = select( blockEditorStore ).getSettings(); - return blockBindingsSupportedAttributes?.[ name ] || []; + return ( + __experimentalBlockBindingsSupportedAttributes?.[ name ] || [] + ); }, [ name ] ); diff --git a/packages/block-editor/src/components/rich-text/index.js b/packages/block-editor/src/components/rich-text/index.js index e933a7ebbe6fcd..062e5749756d9a 100644 --- a/packages/block-editor/src/components/rich-text/index.js +++ b/packages/block-editor/src/components/rich-text/index.js @@ -176,12 +176,14 @@ export function RichTextWrapper( const { disableBoundBlock, bindingsPlaceholder, bindingsLabel } = useSelect( ( select ) => { - const { blockBindingsSupportedAttributes } = + const { __experimentalBlockBindingsSupportedAttributes } = select( blockEditorStore ).getSettings(); if ( ! blockBindings?.[ identifier ] || - ! ( blockName in blockBindingsSupportedAttributes ) + ! ( + blockName in __experimentalBlockBindingsSupportedAttributes + ) ) { return {}; } diff --git a/packages/block-editor/src/hooks/block-bindings.js b/packages/block-editor/src/hooks/block-bindings.js index 4f3ebf60a67029..2911aac1b256c1 100644 --- a/packages/block-editor/src/hooks/block-bindings.js +++ b/packages/block-editor/src/hooks/block-bindings.js @@ -210,10 +210,12 @@ export const BlockBindingsPanel = ( { name: blockName, metadata } ) => { const { bindableAttributes, fieldsList, canUpdateBlockBindings } = useSelect( ( select ) => { - const { blockBindingsSupportedAttributes } = + const { __experimentalBlockBindingsSupportedAttributes } = select( blockEditorStore ).getSettings(); const _bindableAttributes = - blockBindingsSupportedAttributes?.[ blockName ]; + __experimentalBlockBindingsSupportedAttributes?.[ + blockName + ]; if ( ! _bindableAttributes || _bindableAttributes.length === 0 diff --git a/packages/editor/src/components/provider/use-block-editor-settings.js b/packages/editor/src/components/provider/use-block-editor-settings.js index 3e8ddb61fdb387..1f84e4b3938cbd 100644 --- a/packages/editor/src/components/provider/use-block-editor-settings.js +++ b/packages/editor/src/components/provider/use-block-editor-settings.js @@ -44,8 +44,8 @@ const BLOCK_EDITOR_SETTINGS = [ '__experimentalDiscussionSettings', '__experimentalFeatures', '__experimentalGlobalStylesBaseStyles', + '__experimentalBlockBindingsSupportedAttributes', 'alignWide', - 'blockBindingsSupportedAttributes', 'blockInspectorTabs', 'maxUploadFileSize', 'allowedMimeTypes', From 7abc40cb6121a6b847f05e107f45c454554e75db Mon Sep 17 00:00:00 2001 From: Bernie Reiter Date: Wed, 24 Sep 2025 13:33:22 +0200 Subject: [PATCH 11/12] :abc: --- .../editor/src/components/provider/use-block-editor-settings.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/editor/src/components/provider/use-block-editor-settings.js b/packages/editor/src/components/provider/use-block-editor-settings.js index 1f84e4b3938cbd..136bb88dd10fae 100644 --- a/packages/editor/src/components/provider/use-block-editor-settings.js +++ b/packages/editor/src/components/provider/use-block-editor-settings.js @@ -40,11 +40,11 @@ function __experimentalReusableBlocksSelect( select ) { } const BLOCK_EDITOR_SETTINGS = [ + '__experimentalBlockBindingsSupportedAttributes', '__experimentalBlockDirectory', '__experimentalDiscussionSettings', '__experimentalFeatures', '__experimentalGlobalStylesBaseStyles', - '__experimentalBlockBindingsSupportedAttributes', 'alignWide', 'blockInspectorTabs', 'maxUploadFileSize', From 1659414645b075130601def2597920edfab7a279 Mon Sep 17 00:00:00 2001 From: Bernie Reiter Date: Thu, 25 Sep 2025 15:38:57 +0200 Subject: [PATCH 12/12] Add EMPTY_ARRAY const and use to have a stable reference --- packages/block-editor/src/components/block-edit/edit.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/packages/block-editor/src/components/block-edit/edit.js b/packages/block-editor/src/components/block-edit/edit.js index 90e9ae8502c575..3d368786a595fa 100644 --- a/packages/block-editor/src/components/block-edit/edit.js +++ b/packages/block-editor/src/components/block-edit/edit.js @@ -56,6 +56,8 @@ const Edit = ( props ) => { const EditWithFilters = withFilters( 'editor.BlockEdit' )( Edit ); +const EMPTY_ARRAY = []; + const EditWithGeneratedProps = ( props ) => { const { name, clientId, attributes, setAttributes } = props; const registry = useRegistry(); @@ -71,7 +73,8 @@ const EditWithGeneratedProps = ( props ) => { const { __experimentalBlockBindingsSupportedAttributes } = select( blockEditorStore ).getSettings(); return ( - __experimentalBlockBindingsSupportedAttributes?.[ name ] || [] + __experimentalBlockBindingsSupportedAttributes?.[ name ] || + EMPTY_ARRAY ); }, [ name ]