diff --git a/backport-changelog/6.7/7552.md b/backport-changelog/6.7/7552.md new file mode 100644 index 0000000000000..d304162b3cae6 --- /dev/null +++ b/backport-changelog/6.7/7552.md @@ -0,0 +1,3 @@ +https://github.com/WordPress/wordpress-develop/pull/7552 + +* https://github.com/WordPress/gutenberg/pull/66058 diff --git a/lib/compat/wordpress-6.7/block-bindings.php b/lib/compat/wordpress-6.7/block-bindings.php index a8f68c0f0f04e..70ba523ac966e 100644 --- a/lib/compat/wordpress-6.7/block-bindings.php +++ b/lib/compat/wordpress-6.7/block-bindings.php @@ -6,38 +6,28 @@ */ /** - * Adds the block bindings sources registered in the server to the editor settings. - * - * This allows them to be bootstrapped in the editor. - * - * @param array $settings The block editor settings from the `block_editor_settings_all` filter. - * @return array The editor settings including the block bindings sources. + * Bootstrap the block bindings sources registered in the server. */ -function gutenberg_add_server_block_bindings_sources_to_editor_settings( $editor_settings ) { - // Check if the sources are already exposed in the editor settings. - if ( isset( $editor_settings['blockBindingsSources'] ) ) { - return $editor_settings; - } - - $registered_block_bindings_sources = get_all_registered_block_bindings_sources(); - if ( ! empty( $registered_block_bindings_sources ) ) { - // Initialize array. - $editor_settings['blockBindingsSources'] = array(); - foreach ( $registered_block_bindings_sources as $source_name => $source_properties ) { - // Add source with the label to editor settings. - $editor_settings['blockBindingsSources'][ $source_name ] = array( - 'label' => $source_properties->label, +function gutenberg_bootstrap_server_block_bindings_sources() { + $registered_sources = get_all_registered_block_bindings_sources(); + if ( ! empty( $registered_sources ) ) { + $filtered_sources = array(); + foreach ( $registered_sources as $source ) { + $filtered_sources[] = array( + 'name' => $source->name, + 'label' => $source->label, + 'usesContext' => $source->uses_context, ); - // Add `usesContext` property if exists. - if ( ! empty( $source_properties->uses_context ) ) { - $editor_settings['blockBindingsSources'][ $source_name ]['usesContext'] = $source_properties->uses_context; - } } + $script = sprintf( 'for ( const source of %s ) { ! wp.blocks.getBlockBindingsSource( source.name ) && wp.blocks.registerBlockBindingsSource( source ); }', wp_json_encode( $filtered_sources ) ); + wp_add_inline_script( + 'wp-blocks', + $script + ); } - return $editor_settings; } -add_filter( 'block_editor_settings_all', 'gutenberg_add_server_block_bindings_sources_to_editor_settings', 10 ); +add_action( 'enqueue_block_editor_assets', 'gutenberg_bootstrap_server_block_bindings_sources', 5 ); /** * Initialize `canUpdateBlockBindings` editor setting if it doesn't exist. By default, it is `true` only for admin users. diff --git a/packages/blocks/src/api/registration.js b/packages/blocks/src/api/registration.js index f7d85cd816c9d..73520b6f993d6 100644 --- a/packages/blocks/src/api/registration.js +++ b/packages/blocks/src/api/registration.js @@ -807,13 +807,16 @@ export const registerBlockBindingsSource = ( source ) => { /* * Check if the source has been already registered on the client. - * If the `getValues` property is defined, it could be assumed the source is already registered. + * If any property expected to be "client-only" is defined, return a warning. */ - if ( existingSource?.getValues ) { - warning( - 'Block bindings source "' + name + '" is already registered.' - ); - return; + const serverProps = [ 'label', 'usesContext' ]; + for ( const prop in existingSource ) { + if ( ! serverProps.includes( prop ) && existingSource[ prop ] ) { + warning( + 'Block bindings source "' + name + '" is already registered.' + ); + return; + } } // Check the `name` property is correct. diff --git a/packages/blocks/src/api/test/registration.js b/packages/blocks/src/api/test/registration.js index 483949af4fe5f..99ca6390d2d3b 100644 --- a/packages/blocks/src/api/test/registration.js +++ b/packages/blocks/src/api/test/registration.js @@ -1513,10 +1513,8 @@ describe( 'blocks', () => { } ); it( 'should not override label from the server', () => { - // Bootstrap source from the server. - unlock( - dispatch( blocksStore ) - ).addBootstrappedBlockBindingsSource( { + // Simulate bootstrap source from the server. + registerBlockBindingsSource( { name: 'core/server', label: 'Server label', } ); @@ -1543,10 +1541,8 @@ describe( 'blocks', () => { } ); it( 'should add usesContext when only defined in the server', () => { - // Bootstrap source from the server. - unlock( - dispatch( blocksStore ) - ).addBootstrappedBlockBindingsSource( { + // Simulate bootstrap source from the server. + registerBlockBindingsSource( { name: 'core/testing', label: 'testing', usesContext: [ 'postId', 'postType' ], @@ -1562,10 +1558,8 @@ describe( 'blocks', () => { } ); it( 'should add usesContext when only defined in the client', () => { - // Bootstrap source from the server. - unlock( - dispatch( blocksStore ) - ).addBootstrappedBlockBindingsSource( { + // Simulate bootstrap source from the server. + registerBlockBindingsSource( { name: 'core/testing', label: 'testing', } ); @@ -1581,10 +1575,8 @@ describe( 'blocks', () => { } ); it( 'should merge usesContext from server and client without duplicates', () => { - // Bootstrap source from the server. - unlock( - dispatch( blocksStore ) - ).addBootstrappedBlockBindingsSource( { + // Simulate bootstrap source from the server. + registerBlockBindingsSource( { name: 'core/testing', label: 'testing', usesContext: [ 'postId', 'postType' ], @@ -1705,42 +1697,6 @@ describe( 'blocks', () => { 'Block bindings source "core/test-source" is already registered.' ); } ); - - it( 'should correctly merge properties when bootstrap happens after registration', () => { - // Register source in the client. - const clientOnlyProperties = { - getValues: () => 'values', - setValues: () => 'new values', - canUserEditValue: () => true, - }; - registerBlockBindingsSource( { - name: 'core/custom-source', - label: 'Client Label', - usesContext: [ 'postId', 'postType' ], - ...clientOnlyProperties, - } ); - - // Bootstrap source from the server. - unlock( - dispatch( blocksStore ) - ).addBootstrappedBlockBindingsSource( { - name: 'core/custom-source', - label: 'Server Label', - usesContext: [ 'postId', 'serverContext' ], - } ); - - // Check that the bootstrap values prevail and the client properties are still there. - expect( getBlockBindingsSource( 'core/custom-source' ) ).toEqual( { - // Should use the server label. - label: 'Server Label', - // Should merge usesContext from server and client. - usesContext: [ 'postId', 'postType', 'serverContext' ], - // Should keep client properties. - ...clientOnlyProperties, - } ); - - unregisterBlockBindingsSource( 'core/custom-source' ); - } ); } ); describe( 'unregisterBlockBindingsSource', () => { diff --git a/packages/blocks/src/store/private-actions.js b/packages/blocks/src/store/private-actions.js index 02f8506b3c3bf..bfefe56773d77 100644 --- a/packages/blocks/src/store/private-actions.js +++ b/packages/blocks/src/store/private-actions.js @@ -70,17 +70,3 @@ export function removeBlockBindingsSource( name ) { name, }; } - -/** - * Add bootstrapped block bindings sources, usually initialized from the server. - * - * @param {string} source Name of the source to bootstrap. - */ -export function addBootstrappedBlockBindingsSource( source ) { - return { - type: 'ADD_BOOTSTRAPPED_BLOCK_BINDINGS_SOURCE', - name: source.name, - label: source.label, - usesContext: source.usesContext, - }; -} diff --git a/packages/blocks/src/store/reducer.js b/packages/blocks/src/store/reducer.js index 7c7fb4763a1cb..16594a79271e6 100644 --- a/packages/blocks/src/store/reducer.js +++ b/packages/blocks/src/store/reducer.js @@ -417,22 +417,6 @@ export function blockBindingsSources( state = {}, action ) { getFieldsList, }, }; - case 'ADD_BOOTSTRAPPED_BLOCK_BINDINGS_SOURCE': - return { - ...state, - [ action.name ]: { - /* - * Keep the exisitng properties in case the source has been registered - * in the client before bootstrapping. - */ - ...state[ action.name ], - label: action.label, - usesContext: getMergedUsesContext( - state[ action.name ]?.usesContext, - action.usesContext - ), - }, - }; case 'REMOVE_BLOCK_BINDINGS_SOURCE': return omit( state, action.name ); } diff --git a/packages/e2e-tests/plugins/block-bindings/index.js b/packages/e2e-tests/plugins/block-bindings/index.js index c31502631307d..5c364257caed1 100644 --- a/packages/e2e-tests/plugins/block-bindings/index.js +++ b/packages/e2e-tests/plugins/block-bindings/index.js @@ -19,7 +19,6 @@ const setValues = ( { dispatch, bindings } ) => { registerBlockBindingsSource( { name: 'testing/complete-source', - label: 'Complete Source', getValues, setValues, canUserEditValue: () => true, diff --git a/packages/edit-post/src/index.js b/packages/edit-post/src/index.js index daf789cb0a2ec..685ffc56f63a8 100644 --- a/packages/edit-post/src/index.js +++ b/packages/edit-post/src/index.js @@ -28,7 +28,6 @@ import { unlock } from './lock-unlock'; const { BackButton: __experimentalMainDashboardButton, registerCoreBlockBindingsSources, - bootstrapBlockBindingsSourcesFromServer, } = unlock( editorPrivateApis ); /** @@ -95,7 +94,6 @@ export function initializeEditor( } registerCoreBlocks(); - bootstrapBlockBindingsSourcesFromServer( settings?.blockBindingsSources ); registerCoreBlockBindingsSources(); registerLegacyWidgetBlock( { inserter: false } ); registerWidgetGroupBlock( { inserter: false } ); diff --git a/packages/edit-site/src/index.js b/packages/edit-site/src/index.js index 1aceecc4d8b1f..83d25bcd0c03a 100644 --- a/packages/edit-site/src/index.js +++ b/packages/edit-site/src/index.js @@ -28,10 +28,7 @@ import { store as editSiteStore } from './store'; import { unlock } from './lock-unlock'; import App from './components/app'; -const { - registerCoreBlockBindingsSources, - bootstrapBlockBindingsSourcesFromServer, -} = unlock( editorPrivateApis ); +const { registerCoreBlockBindingsSources } = unlock( editorPrivateApis ); /** * Initializes the site editor screen. @@ -48,7 +45,6 @@ export function initializeEditor( id, settings ) { ( { name } ) => name !== 'core/freeform' ); registerCoreBlocks( coreBlocks ); - bootstrapBlockBindingsSourcesFromServer( settings?.blockBindingsSources ); registerCoreBlockBindingsSources(); dispatch( blocksStore ).setFreeformFallbackBlockName( 'core/html' ); registerLegacyWidgetBlock( { inserter: false } ); diff --git a/packages/editor/src/bindings/api.js b/packages/editor/src/bindings/api.js index 84003fab7eaf7..2d32d76abbc3b 100644 --- a/packages/editor/src/bindings/api.js +++ b/packages/editor/src/bindings/api.js @@ -1,18 +1,13 @@ /** * WordPress dependencies */ -import { - store as blocksStore, - registerBlockBindingsSource, -} from '@wordpress/blocks'; -import { dispatch } from '@wordpress/data'; +import { registerBlockBindingsSource } from '@wordpress/blocks'; /** * Internal dependencies */ import patternOverrides from './pattern-overrides'; import postMeta from './post-meta'; -import { unlock } from '../lock-unlock'; /** * Function to register core block bindings sources provided by the editor. @@ -28,29 +23,3 @@ export function registerCoreBlockBindingsSources() { registerBlockBindingsSource( patternOverrides ); registerBlockBindingsSource( postMeta ); } - -/** - * Function to bootstrap core block bindings sources defined in the server. - * - * @param {Object} sources Object containing the sources to bootstrap. - * - * @example - * ```js - * import { bootstrapBlockBindingsSourcesFromServer } from '@wordpress/editor'; - * - * bootstrapBlockBindingsSourcesFromServer( sources ); - * ``` - */ -export function bootstrapBlockBindingsSourcesFromServer( sources ) { - if ( sources ) { - const { addBootstrappedBlockBindingsSource } = unlock( - dispatch( blocksStore ) - ); - for ( const [ name, args ] of Object.entries( sources ) ) { - addBootstrappedBlockBindingsSource( { - name, - ...args, - } ); - } - } -} diff --git a/packages/editor/src/private-apis.js b/packages/editor/src/private-apis.js index d4a5c3eebbb4c..f9a6d4d17904e 100644 --- a/packages/editor/src/private-apis.js +++ b/packages/editor/src/private-apis.js @@ -23,10 +23,7 @@ import { mergeBaseAndUserConfigs, GlobalStylesProvider, } from './components/global-styles-provider'; -import { - registerCoreBlockBindingsSources, - bootstrapBlockBindingsSourcesFromServer, -} from './bindings/api'; +import { registerCoreBlockBindingsSources } from './bindings/api'; const { store: interfaceStore, ...remainingInterfaceApis } = interfaceApis; @@ -47,7 +44,6 @@ lock( privateApis, { ViewMoreMenuGroup, ResizableEditor, registerCoreBlockBindingsSources, - bootstrapBlockBindingsSourcesFromServer, // This is a temporary private API while we're updating the site editor to use EditorProvider. interfaceStore,