From 575370536b48d115ddd5306e5d9a428f73041877 Mon Sep 17 00:00:00 2001 From: Mario Santos Date: Fri, 19 Jul 2024 12:26:57 +0200 Subject: [PATCH 01/13] Rename to `setValuesInBatch` --- .../block-editor/src/hooks/use-bindings-attributes.js | 9 ++++++--- packages/blocks/src/store/private-actions.js | 2 +- packages/blocks/src/store/reducer.js | 2 +- packages/editor/src/bindings/pattern-overrides.js | 2 +- 4 files changed, 9 insertions(+), 6 deletions(-) diff --git a/packages/block-editor/src/hooks/use-bindings-attributes.js b/packages/block-editor/src/hooks/use-bindings-attributes.js index a63f59b69ca21c..e57c40f9c23b8f 100644 --- a/packages/block-editor/src/hooks/use-bindings-attributes.js +++ b/packages/block-editor/src/hooks/use-bindings-attributes.js @@ -181,7 +181,10 @@ export const withBlockBindingSupport = createHigherOrderComponent( const binding = bindings[ attributeName ]; const source = sources[ binding?.source ]; - if ( ! source?.setValue && ! source?.setValues ) { + if ( + ! source?.setValue && + ! source?.setValuesInBatch + ) { continue; } updatesBySource.set( source, { @@ -196,8 +199,8 @@ export const withBlockBindingSupport = createHigherOrderComponent( source, attributes, ] of updatesBySource ) { - if ( source.setValues ) { - source.setValues( { + if ( source.setValuesInBatch ) { + source.setValuesInBatch( { registry, context, clientId, diff --git a/packages/blocks/src/store/private-actions.js b/packages/blocks/src/store/private-actions.js index a59ed157e98693..b1ba5bf9154d14 100644 --- a/packages/blocks/src/store/private-actions.js +++ b/packages/blocks/src/store/private-actions.js @@ -53,7 +53,7 @@ export function addBlockBindingsSource( source ) { label: source.label, getValue: source.getValue, setValue: source.setValue, - setValues: source.setValues, + setValuesInBatch: source.setValuesInBatch, getPlaceholder: source.getPlaceholder, canUserEditValue: source.canUserEditValue, }; diff --git a/packages/blocks/src/store/reducer.js b/packages/blocks/src/store/reducer.js index 4237590f8887a4..e9308afb035dce 100644 --- a/packages/blocks/src/store/reducer.js +++ b/packages/blocks/src/store/reducer.js @@ -380,7 +380,7 @@ export function blockBindingsSources( state = {}, action ) { label: action.label, getValue: action.getValue, setValue: action.setValue, - setValues: action.setValues, + setValuesInBatch: action.setValuesInBatch, getPlaceholder: action.getPlaceholder, canUserEditValue: action.canUserEditValue, }, diff --git a/packages/editor/src/bindings/pattern-overrides.js b/packages/editor/src/bindings/pattern-overrides.js index 54ca77650a5fe9..4d3fe098d9340e 100644 --- a/packages/editor/src/bindings/pattern-overrides.js +++ b/packages/editor/src/bindings/pattern-overrides.js @@ -30,7 +30,7 @@ export default { return overridableValue === '' ? undefined : overridableValue; }, - setValues( { registry, clientId, attributes } ) { + setValuesInBatch( { registry, clientId, attributes } ) { const { getBlockAttributes, getBlockParentsByBlockName, getBlocks } = registry.select( blockEditorStore ); const currentBlockAttributes = getBlockAttributes( clientId ); From 181e58f23fea24dbaa150b1ca82df1454c4535b3 Mon Sep 17 00:00:00 2001 From: Mario Santos Date: Fri, 19 Jul 2024 12:26:57 +0200 Subject: [PATCH 02/13] Pass whole binding instead of just the new value --- .../src/hooks/use-bindings-attributes.js | 26 ++++++++++--------- .../editor/src/bindings/pattern-overrides.js | 11 +++++++- 2 files changed, 24 insertions(+), 13 deletions(-) diff --git a/packages/block-editor/src/hooks/use-bindings-attributes.js b/packages/block-editor/src/hooks/use-bindings-attributes.js index e57c40f9c23b8f..fe958ef50092d7 100644 --- a/packages/block-editor/src/hooks/use-bindings-attributes.js +++ b/packages/block-editor/src/hooks/use-bindings-attributes.js @@ -166,7 +166,7 @@ export const withBlockBindingSupport = createHigherOrderComponent( } const keptAttributes = { ...nextAttributes }; - const updatesBySource = new Map(); + const bindingsBySource = new Map(); // Loop only over the updated attributes to avoid modifying the bound ones that haven't changed. for ( const [ attributeName, newValue ] of Object.entries( @@ -187,37 +187,39 @@ export const withBlockBindingSupport = createHigherOrderComponent( ) { continue; } - updatesBySource.set( source, { - ...updatesBySource.get( source ), - [ attributeName ]: newValue, + bindingsBySource.set( source, { + ...bindingsBySource.get( source ), + [ attributeName ]: { + args: binding.args, + newValue, + }, } ); delete keptAttributes[ attributeName ]; } - if ( updatesBySource.size ) { + if ( bindingsBySource.size ) { for ( const [ source, - attributes, - ] of updatesBySource ) { + sourceBindings, + ] of bindingsBySource ) { if ( source.setValuesInBatch ) { source.setValuesInBatch( { registry, context, clientId, - attributes, + sourceBindings, } ); } else { for ( const [ attributeName, - value, - ] of Object.entries( attributes ) ) { - const binding = bindings[ attributeName ]; + { args, newValue: value }, + ] of Object.entries( sourceBindings ) ) { source.setValue( { registry, context, clientId, attributeName, - args: binding.args, + args, value, } ); } diff --git a/packages/editor/src/bindings/pattern-overrides.js b/packages/editor/src/bindings/pattern-overrides.js index 4d3fe098d9340e..4837c3d271dea3 100644 --- a/packages/editor/src/bindings/pattern-overrides.js +++ b/packages/editor/src/bindings/pattern-overrides.js @@ -30,7 +30,7 @@ export default { return overridableValue === '' ? undefined : overridableValue; }, - setValuesInBatch( { registry, clientId, attributes } ) { + setValuesInBatch( { registry, clientId, sourceBindings } ) { const { getBlockAttributes, getBlockParentsByBlockName, getBlocks } = registry.select( blockEditorStore ); const currentBlockAttributes = getBlockAttributes( clientId ); @@ -45,6 +45,15 @@ export default { true ); + // Extract the updated attributes from the source bindings. + const attributes = Object.entries( sourceBindings ).reduce( + ( attrs, [ key, { newValue } ] ) => { + attrs[ key ] = newValue; + return attrs; + }, + {} + ); + // If there is no pattern client ID, sync blocks with the same name and same attributes. if ( ! patternClientId ) { const syncBlocksWithSameName = ( blocks ) => { From e9cf3049dde4673e2213ca65caa51c169be0d2ff Mon Sep 17 00:00:00 2001 From: Mario Santos Date: Fri, 19 Jul 2024 12:26:57 +0200 Subject: [PATCH 03/13] Use `setValuesInBatch` in post meta --- packages/editor/src/bindings/post-meta.js | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/packages/editor/src/bindings/post-meta.js b/packages/editor/src/bindings/post-meta.js index a2fb5964663978..85762a4905ab06 100644 --- a/packages/editor/src/bindings/post-meta.js +++ b/packages/editor/src/bindings/post-meta.js @@ -24,6 +24,8 @@ export default { context?.postId ).meta?.[ args.key ]; }, + // When `setValuesInBatch` is defined, this is not running. + // Keeping it here to show the different possibilities. setValue( { registry, context, args, value } ) { registry .dispatch( coreDataStore ) @@ -33,6 +35,17 @@ export default { }, } ); }, + setValuesInBatch( { registry, context, sourceBindings } ) { + const newMeta = {}; + Object.values( sourceBindings ).forEach( ( { args, newValue } ) => { + newMeta[ args.key ] = newValue; + } ); + registry + .dispatch( coreDataStore ) + .editEntityRecord( 'postType', context?.postType, context?.postId, { + meta: newMeta, + } ); + }, canUserEditValue( { select, context, args } ) { // Lock editing in query loop. if ( context?.query || context?.queryId ) { From 0f19b1f1fe4122602bbb88a25abd88ac0f02c60a Mon Sep 17 00:00:00 2001 From: Mario Santos Date: Fri, 19 Jul 2024 12:26:57 +0200 Subject: [PATCH 04/13] Add support for `getValuesInBatch` --- .../src/hooks/use-bindings-attributes.js | 79 +++++++++++++++---- packages/blocks/src/store/private-actions.js | 1 + packages/blocks/src/store/reducer.js | 1 + 3 files changed, 64 insertions(+), 17 deletions(-) diff --git a/packages/block-editor/src/hooks/use-bindings-attributes.js b/packages/block-editor/src/hooks/use-bindings-attributes.js index fe958ef50092d7..273a42456dcb5c 100644 --- a/packages/block-editor/src/hooks/use-bindings-attributes.js +++ b/packages/block-editor/src/hooks/use-bindings-attributes.js @@ -121,33 +121,77 @@ export const withBlockBindingSupport = createHigherOrderComponent( const attributes = {}; - for ( const [ attributeName, boundAttribute ] of Object.entries( + const bindingsBySource = new Map(); + + for ( const [ attributeName, binding ] of Object.entries( bindings ) ) { - const source = sources[ boundAttribute.source ]; + const { source: sourceName, args: sourceArgs } = binding; + const source = sources[ sourceName ]; if ( - ! source?.getValue || + ( ! source?.getValue && ! source?.getValuesInBatch ) || ! canBindAttribute( name, attributeName ) ) { continue; } - const args = { - registry, - context, - clientId, - attributeName, - args: boundAttribute.args, - }; - - attributes[ attributeName ] = source.getValue( args ); + bindingsBySource.set( source, { + ...bindingsBySource.get( source ), + [ attributeName ]: { + args: sourceArgs, + }, + } ); + } - if ( attributes[ attributeName ] === undefined ) { - if ( attributeName === 'url' ) { - attributes[ attributeName ] = null; + if ( bindingsBySource.size ) { + for ( const [ source, sourceBindings ] of bindingsBySource ) { + // Get values in batch if the source supports it. + if ( source.getValuesInBatch ) { + const values = source.getValuesInBatch( { + registry, + context, + clientId, + sourceBindings, + } ); + for ( const [ attributeName, value ] of Object.entries( + values + ) ) { + attributes[ attributeName ] = value; + } } else { - attributes[ attributeName ] = - source.getPlaceholder?.( args ); + for ( const [ + attributeName, + { args }, + ] of Object.entries( sourceBindings ) ) { + attributes[ attributeName ] = source.getValue( { + registry, + context, + clientId, + attributeName, + args, + } ); + } + } + + // Add placeholders when value is undefined. + // TODO: Revisit this part. + for ( const [ attributeName, { args } ] of Object.entries( + sourceBindings + ) ) { + if ( attributes[ attributeName ] === undefined ) { + if ( attributeName === 'url' ) { + attributes[ attributeName ] = null; + } else { + attributes[ attributeName ] = + source.getPlaceholder?.( { + registry, + context, + clientId, + attributeName, + args, + } ); + } + } } } } @@ -202,6 +246,7 @@ export const withBlockBindingSupport = createHigherOrderComponent( source, sourceBindings, ] of bindingsBySource ) { + // Set values in batch if the source supports it. if ( source.setValuesInBatch ) { source.setValuesInBatch( { registry, diff --git a/packages/blocks/src/store/private-actions.js b/packages/blocks/src/store/private-actions.js index b1ba5bf9154d14..29d43b97255721 100644 --- a/packages/blocks/src/store/private-actions.js +++ b/packages/blocks/src/store/private-actions.js @@ -52,6 +52,7 @@ export function addBlockBindingsSource( source ) { name: source.name, label: source.label, getValue: source.getValue, + getValuesInBatch: source.getValuesInBatch, setValue: source.setValue, setValuesInBatch: source.setValuesInBatch, getPlaceholder: source.getPlaceholder, diff --git a/packages/blocks/src/store/reducer.js b/packages/blocks/src/store/reducer.js index e9308afb035dce..da9400db210bc0 100644 --- a/packages/blocks/src/store/reducer.js +++ b/packages/blocks/src/store/reducer.js @@ -379,6 +379,7 @@ export function blockBindingsSources( state = {}, action ) { [ action.name ]: { label: action.label, getValue: action.getValue, + getValuesInBatch: action.getValuesInBatch, setValue: action.setValue, setValuesInBatch: action.setValuesInBatch, getPlaceholder: action.getPlaceholder, From 6cbb14c88efa796572cd43dcd77da73291c9bc95 Mon Sep 17 00:00:00 2001 From: Mario Santos Date: Fri, 19 Jul 2024 12:26:57 +0200 Subject: [PATCH 05/13] Use `getValuesInBatch` in post meta --- packages/editor/src/bindings/post-meta.js | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/packages/editor/src/bindings/post-meta.js b/packages/editor/src/bindings/post-meta.js index 85762a4905ab06..f3cfd1c5c62640 100644 --- a/packages/editor/src/bindings/post-meta.js +++ b/packages/editor/src/bindings/post-meta.js @@ -15,6 +15,8 @@ export default { getPlaceholder( { args } ) { return args.key; }, + // When `getValuesInBatch` is defined, this is not running. + // Keeping it here to show the different possibilities. getValue( { registry, context, args } ) { return registry .select( coreDataStore ) @@ -24,6 +26,22 @@ export default { context?.postId ).meta?.[ args.key ]; }, + getValuesInBatch( { registry, context, sourceBindings } ) { + const meta = registry + .select( coreDataStore ) + .getEditedEntityRecord( + 'postType', + context?.postType, + context?.postId + )?.meta; + const newValues = {}; + for ( const [ attributeName, source ] of Object.entries( + sourceBindings + ) ) { + newValues[ attributeName ] = meta?.[ source.args.key ]; + } + return newValues; + }, // When `setValuesInBatch` is defined, this is not running. // Keeping it here to show the different possibilities. setValue( { registry, context, args, value } ) { From 81c81b1d2dd8ea8e159a5d7479d89494948d8e2e Mon Sep 17 00:00:00 2001 From: Mario Santos Date: Fri, 19 Jul 2024 12:26:57 +0200 Subject: [PATCH 06/13] Use `getValuesInBatch` in pattern overrides --- .../editor/src/bindings/pattern-overrides.js | 22 +++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/packages/editor/src/bindings/pattern-overrides.js b/packages/editor/src/bindings/pattern-overrides.js index 4837c3d271dea3..b3669ed5424cf5 100644 --- a/packages/editor/src/bindings/pattern-overrides.js +++ b/packages/editor/src/bindings/pattern-overrides.js @@ -30,6 +30,28 @@ export default { return overridableValue === '' ? undefined : overridableValue; }, + // When `getValuesInBatch` is defined, this is not running. + // Keeping it here to show the different possibilities. + getValuesInBatch( { registry, clientId, context, sourceBindings } ) { + const patternOverridesContent = context[ 'pattern/overrides' ]; + if ( ! patternOverridesContent ) { + return {}; + } + + const { getBlockAttributes } = registry.select( blockEditorStore ); + const currentBlockAttributes = getBlockAttributes( clientId ); + + const overridesValues = {}; + for ( const attributeName of Object.keys( sourceBindings ) ) { + const overridableValue = + patternOverridesContent?.[ + currentBlockAttributes?.metadata?.name + ]?.[ attributeName ]; + overridesValues[ attributeName ] = + overridableValue === '' ? undefined : overridableValue; + } + return overridesValues; + }, setValuesInBatch( { registry, clientId, sourceBindings } ) { const { getBlockAttributes, getBlockParentsByBlockName, getBlocks } = registry.select( blockEditorStore ); From 07d8463e64a45b77b999e2bf35ab71ef40135507 Mon Sep 17 00:00:00 2001 From: Mario Santos Date: Fri, 19 Jul 2024 12:26:57 +0200 Subject: [PATCH 07/13] Use only `getValues` and `setValues` --- .../src/hooks/use-bindings-attributes.js | 83 +++++-------------- packages/blocks/src/store/private-actions.js | 6 +- packages/blocks/src/store/reducer.js | 6 +- .../editor/src/bindings/pattern-overrides.js | 27 +----- packages/editor/src/bindings/post-meta.js | 26 +----- 5 files changed, 30 insertions(+), 118 deletions(-) diff --git a/packages/block-editor/src/hooks/use-bindings-attributes.js b/packages/block-editor/src/hooks/use-bindings-attributes.js index 273a42456dcb5c..cd85fa70adf5bf 100644 --- a/packages/block-editor/src/hooks/use-bindings-attributes.js +++ b/packages/block-editor/src/hooks/use-bindings-attributes.js @@ -129,7 +129,7 @@ export const withBlockBindingSupport = createHigherOrderComponent( const { source: sourceName, args: sourceArgs } = binding; const source = sources[ sourceName ]; if ( - ( ! source?.getValue && ! source?.getValuesInBatch ) || + ! source?.getValues || ! canBindAttribute( name, attributeName ) ) { continue; @@ -146,39 +146,17 @@ export const withBlockBindingSupport = createHigherOrderComponent( if ( bindingsBySource.size ) { for ( const [ source, sourceBindings ] of bindingsBySource ) { // Get values in batch if the source supports it. - if ( source.getValuesInBatch ) { - const values = source.getValuesInBatch( { - registry, - context, - clientId, - sourceBindings, - } ); - for ( const [ attributeName, value ] of Object.entries( - values - ) ) { - attributes[ attributeName ] = value; - } - } else { - for ( const [ - attributeName, - { args }, - ] of Object.entries( sourceBindings ) ) { - attributes[ attributeName ] = source.getValue( { - registry, - context, - clientId, - attributeName, - args, - } ); - } - } - - // Add placeholders when value is undefined. - // TODO: Revisit this part. - for ( const [ attributeName, { args } ] of Object.entries( - sourceBindings + const values = source.getValues( { + registry, + context, + clientId, + sourceBindings, + } ); + for ( const [ attributeName, value ] of Object.entries( + values ) ) { - if ( attributes[ attributeName ] === undefined ) { + // Use placeholder when value is undefined. + if ( value === undefined ) { if ( attributeName === 'url' ) { attributes[ attributeName ] = null; } else { @@ -188,9 +166,12 @@ export const withBlockBindingSupport = createHigherOrderComponent( context, clientId, attributeName, - args, + args: sourceBindings[ attributeName ] + .args, } ); } + } else { + attributes[ attributeName ] = value; } } } @@ -225,10 +206,7 @@ export const withBlockBindingSupport = createHigherOrderComponent( const binding = bindings[ attributeName ]; const source = sources[ binding?.source ]; - if ( - ! source?.setValue && - ! source?.setValuesInBatch - ) { + if ( ! source?.setValues ) { continue; } bindingsBySource.set( source, { @@ -246,29 +224,12 @@ export const withBlockBindingSupport = createHigherOrderComponent( source, sourceBindings, ] of bindingsBySource ) { - // Set values in batch if the source supports it. - if ( source.setValuesInBatch ) { - source.setValuesInBatch( { - registry, - context, - clientId, - sourceBindings, - } ); - } else { - for ( const [ - attributeName, - { args, newValue: value }, - ] of Object.entries( sourceBindings ) ) { - source.setValue( { - registry, - context, - clientId, - attributeName, - args, - value, - } ); - } - } + source.setValues( { + registry, + context, + clientId, + sourceBindings, + } ); } } diff --git a/packages/blocks/src/store/private-actions.js b/packages/blocks/src/store/private-actions.js index 29d43b97255721..55cdb2128895f5 100644 --- a/packages/blocks/src/store/private-actions.js +++ b/packages/blocks/src/store/private-actions.js @@ -51,10 +51,8 @@ export function addBlockBindingsSource( source ) { type: 'ADD_BLOCK_BINDINGS_SOURCE', name: source.name, label: source.label, - getValue: source.getValue, - getValuesInBatch: source.getValuesInBatch, - setValue: source.setValue, - setValuesInBatch: source.setValuesInBatch, + getValues: source.getValues, + setValues: source.setValues, getPlaceholder: source.getPlaceholder, canUserEditValue: source.canUserEditValue, }; diff --git a/packages/blocks/src/store/reducer.js b/packages/blocks/src/store/reducer.js index da9400db210bc0..b6b275bb91f6f3 100644 --- a/packages/blocks/src/store/reducer.js +++ b/packages/blocks/src/store/reducer.js @@ -378,10 +378,8 @@ export function blockBindingsSources( state = {}, action ) { ...state, [ action.name ]: { label: action.label, - getValue: action.getValue, - getValuesInBatch: action.getValuesInBatch, - setValue: action.setValue, - setValuesInBatch: action.setValuesInBatch, + getValues: action.getValuesInBatch, + setValues: action.setValuesInBatch, getPlaceholder: action.getPlaceholder, canUserEditValue: action.canUserEditValue, }, diff --git a/packages/editor/src/bindings/pattern-overrides.js b/packages/editor/src/bindings/pattern-overrides.js index b3669ed5424cf5..30ec1e0ad808b0 100644 --- a/packages/editor/src/bindings/pattern-overrides.js +++ b/packages/editor/src/bindings/pattern-overrides.js @@ -9,30 +9,7 @@ const CONTENT = 'content'; export default { name: 'core/pattern-overrides', label: _x( 'Pattern Overrides', 'block bindings source' ), - getValue( { registry, clientId, context, attributeName } ) { - const patternOverridesContent = context[ 'pattern/overrides' ]; - const { getBlockAttributes } = registry.select( blockEditorStore ); - const currentBlockAttributes = getBlockAttributes( clientId ); - - if ( ! patternOverridesContent ) { - return currentBlockAttributes[ attributeName ]; - } - - const overridableValue = - patternOverridesContent?.[ - currentBlockAttributes?.metadata?.name - ]?.[ attributeName ]; - - // If there is no pattern client ID, or it is not overwritten, return the default value. - if ( overridableValue === undefined ) { - return currentBlockAttributes[ attributeName ]; - } - - return overridableValue === '' ? undefined : overridableValue; - }, - // When `getValuesInBatch` is defined, this is not running. - // Keeping it here to show the different possibilities. - getValuesInBatch( { registry, clientId, context, sourceBindings } ) { + getValues( { registry, clientId, context, sourceBindings } ) { const patternOverridesContent = context[ 'pattern/overrides' ]; if ( ! patternOverridesContent ) { return {}; @@ -52,7 +29,7 @@ export default { } return overridesValues; }, - setValuesInBatch( { registry, clientId, sourceBindings } ) { + setValues( { registry, clientId, sourceBindings } ) { const { getBlockAttributes, getBlockParentsByBlockName, getBlocks } = registry.select( blockEditorStore ); const currentBlockAttributes = getBlockAttributes( clientId ); diff --git a/packages/editor/src/bindings/post-meta.js b/packages/editor/src/bindings/post-meta.js index f3cfd1c5c62640..fe56876b9f0a27 100644 --- a/packages/editor/src/bindings/post-meta.js +++ b/packages/editor/src/bindings/post-meta.js @@ -15,18 +15,7 @@ export default { getPlaceholder( { args } ) { return args.key; }, - // When `getValuesInBatch` is defined, this is not running. - // Keeping it here to show the different possibilities. - getValue( { registry, context, args } ) { - return registry - .select( coreDataStore ) - .getEditedEntityRecord( - 'postType', - context?.postType, - context?.postId - ).meta?.[ args.key ]; - }, - getValuesInBatch( { registry, context, sourceBindings } ) { + getValues( { registry, context, sourceBindings } ) { const meta = registry .select( coreDataStore ) .getEditedEntityRecord( @@ -42,18 +31,7 @@ export default { } return newValues; }, - // When `setValuesInBatch` is defined, this is not running. - // Keeping it here to show the different possibilities. - setValue( { registry, context, args, value } ) { - registry - .dispatch( coreDataStore ) - .editEntityRecord( 'postType', context?.postType, context?.postId, { - meta: { - [ args.key ]: value, - }, - } ); - }, - setValuesInBatch( { registry, context, sourceBindings } ) { + setValues( { registry, context, sourceBindings } ) { const newMeta = {}; Object.values( sourceBindings ).forEach( ( { args, newValue } ) => { newMeta[ args.key ] = newValue; From bd5b21cc209a334454d6b7427528bec86dd2f529 Mon Sep 17 00:00:00 2001 From: Mario Santos Date: Fri, 19 Jul 2024 12:26:57 +0200 Subject: [PATCH 08/13] Fix pattern overrides --- .../editor/src/bindings/pattern-overrides.js | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/packages/editor/src/bindings/pattern-overrides.js b/packages/editor/src/bindings/pattern-overrides.js index 30ec1e0ad808b0..cbb2b011a82bb5 100644 --- a/packages/editor/src/bindings/pattern-overrides.js +++ b/packages/editor/src/bindings/pattern-overrides.js @@ -11,10 +11,6 @@ export default { label: _x( 'Pattern Overrides', 'block bindings source' ), getValues( { registry, clientId, context, sourceBindings } ) { const patternOverridesContent = context[ 'pattern/overrides' ]; - if ( ! patternOverridesContent ) { - return {}; - } - const { getBlockAttributes } = registry.select( blockEditorStore ); const currentBlockAttributes = getBlockAttributes( clientId ); @@ -24,8 +20,16 @@ export default { patternOverridesContent?.[ currentBlockAttributes?.metadata?.name ]?.[ attributeName ]; - overridesValues[ attributeName ] = - overridableValue === '' ? undefined : overridableValue; + + // If it has not been overriden, return the original value. + if ( ! overridableValue ) { + overridesValues[ attributeName ] = + currentBlockAttributes[ attributeName ]; + continue; + } else { + overridesValues[ attributeName ] = + overridableValue === '' ? undefined : overridableValue; + } } return overridesValues; }, From 4c9ca73eb50174122e24d0b6d17e5f3808d95779 Mon Sep 17 00:00:00 2001 From: Mario Santos Date: Fri, 19 Jul 2024 12:26:57 +0200 Subject: [PATCH 09/13] Check undefined instead of ! --- packages/editor/src/bindings/pattern-overrides.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/editor/src/bindings/pattern-overrides.js b/packages/editor/src/bindings/pattern-overrides.js index cbb2b011a82bb5..5ab7a9b77ab414 100644 --- a/packages/editor/src/bindings/pattern-overrides.js +++ b/packages/editor/src/bindings/pattern-overrides.js @@ -22,7 +22,8 @@ export default { ]?.[ attributeName ]; // If it has not been overriden, return the original value. - if ( ! overridableValue ) { + // Check undefined because empty string is a valid value. + if ( overridableValue === undefined ) { overridesValues[ attributeName ] = currentBlockAttributes[ attributeName ]; continue; From b82792e9be965d8261aea35373a150f0f1a1ea91 Mon Sep 17 00:00:00 2001 From: Mario Santos Date: Fri, 19 Jul 2024 12:26:57 +0200 Subject: [PATCH 10/13] Fix error after rebasing --- packages/blocks/src/store/reducer.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/blocks/src/store/reducer.js b/packages/blocks/src/store/reducer.js index b6b275bb91f6f3..fc386e7ea9f557 100644 --- a/packages/blocks/src/store/reducer.js +++ b/packages/blocks/src/store/reducer.js @@ -378,8 +378,8 @@ export function blockBindingsSources( state = {}, action ) { ...state, [ action.name ]: { label: action.label, - getValues: action.getValuesInBatch, - setValues: action.setValuesInBatch, + getValues: action.getValues, + setValues: action.setValues, getPlaceholder: action.getPlaceholder, canUserEditValue: action.canUserEditValue, }, From 4c7db71a50ae872816e7a8ac3574e878600a41c9 Mon Sep 17 00:00:00 2001 From: Mario Santos Date: Fri, 19 Jul 2024 12:26:57 +0200 Subject: [PATCH 11/13] Change registration checks --- packages/blocks/src/api/registration.js | 21 +++++---------- packages/blocks/src/api/test/registration.js | 27 +++++--------------- 2 files changed, 12 insertions(+), 36 deletions(-) diff --git a/packages/blocks/src/api/registration.js b/packages/blocks/src/api/registration.js index 2dd433bca383e9..78aab99b11b617 100644 --- a/packages/blocks/src/api/registration.js +++ b/packages/blocks/src/api/registration.js @@ -770,8 +770,7 @@ export const unregisterBlockVariation = ( blockName, variationName ) => { * @param {Object} source Properties of the source to be registered. * @param {string} source.name The unique and machine-readable name. * @param {string} source.label Human-readable label. - * @param {Function} [source.getValue] Function to get the value of the source. - * @param {Function} [source.setValue] Function to update the value of the source. + * @param {Function} [source.getValues] Function to get the values from the source. * @param {Function} [source.setValues] Function to update multiple values connected to the source. * @param {Function} [source.getPlaceholder] Function to get the placeholder when the value is undefined. * @param {Function} [source.canUserEditValue] Function to determine if the user can edit the value. @@ -784,8 +783,7 @@ export const unregisterBlockVariation = ( blockName, variationName ) => { * registerBlockBindingsSource( { * name: 'plugin/my-custom-source', * label: _x( 'My Custom Source', 'block bindings source' ), - * getValue: () => 'Value to place in the block attribute', - * setValue: () => updateMyCustomValue(), + * getValues: () => getSourceValues(), * setValues: () => updateMyCustomValuesInBatch(), * getPlaceholder: () => 'Placeholder text when the value is undefined', * canUserEditValue: () => true, @@ -796,8 +794,7 @@ export const registerBlockBindingsSource = ( source ) => { const { name, label, - getValue, - setValue, + getValues, setValues, getPlaceholder, canUserEditValue, @@ -857,15 +854,9 @@ export const registerBlockBindingsSource = ( source ) => { return; } - // Check the `getValue` property is correct. - if ( getValue && typeof getValue !== 'function' ) { - warning( 'Block bindings source getValue must be a function.' ); - return; - } - - // Check the `setValue` property is correct. - if ( setValue && typeof setValue !== 'function' ) { - warning( 'Block bindings source setValue must be a function.' ); + // Check the `getValues` property is correct. + if ( getValues && typeof getValues !== 'function' ) { + warning( 'Block bindings source getValues must be a function.' ); return; } diff --git a/packages/blocks/src/api/test/registration.js b/packages/blocks/src/api/test/registration.js index 991b299c08abf6..bc1057597bcd7a 100644 --- a/packages/blocks/src/api/test/registration.js +++ b/packages/blocks/src/api/test/registration.js @@ -1512,28 +1512,15 @@ describe( 'blocks', () => { expect( getBlockBindingsSource( 'core/testing' ) ).toBeUndefined(); } ); - // Check the `getValue` callback is correct. - it( 'should reject invalid getValue callback', () => { + // Check the `getValues` callback is correct. + it( 'should reject invalid getValues callback', () => { registerBlockBindingsSource( { name: 'core/testing', label: 'testing', - getValue: 'should be a function', + getValues: 'should be a function', } ); expect( console ).toHaveWarnedWith( - 'Block bindings source getValue must be a function.' - ); - expect( getBlockBindingsSource( 'core/testing' ) ).toBeUndefined(); - } ); - - // Check the `setValue` callback is correct. - it( 'should reject invalid setValue callback', () => { - registerBlockBindingsSource( { - name: 'core/testing', - label: 'testing', - setValue: 'should be a function', - } ); - expect( console ).toHaveWarnedWith( - 'Block bindings source setValue must be a function.' + 'Block bindings source getValues must be a function.' ); expect( getBlockBindingsSource( 'core/testing' ) ).toBeUndefined(); } ); @@ -1581,8 +1568,7 @@ describe( 'blocks', () => { it( 'should register a valid source', () => { const sourceProperties = { label: 'Valid Source', - getValue: () => 'value', - setValue: () => 'new value', + getValues: () => 'value', setValues: () => 'new values', getPlaceholder: () => 'placeholder', canUserEditValue: () => true, @@ -1603,8 +1589,7 @@ describe( 'blocks', () => { label: 'Valid Source', } ); const source = getBlockBindingsSource( 'core/valid-source' ); - expect( source.getValue ).toBeUndefined(); - expect( source.setValue ).toBeUndefined(); + expect( source.getValues ).toBeUndefined(); expect( source.setValues ).toBeUndefined(); expect( source.getPlaceholder ).toBeUndefined(); expect( source.canUserEditValue ).toBeUndefined(); From c4bf3dd682c20229610db94adcba0a38d7b69095 Mon Sep 17 00:00:00 2001 From: Mario Santos Date: Fri, 19 Jul 2024 12:26:57 +0200 Subject: [PATCH 12/13] Use `bindings` param for the API --- .../src/hooks/use-bindings-attributes.js | 30 ++++++++----------- .../editor/src/bindings/pattern-overrides.js | 8 ++--- packages/editor/src/bindings/post-meta.js | 10 +++---- 3 files changed, 21 insertions(+), 27 deletions(-) diff --git a/packages/block-editor/src/hooks/use-bindings-attributes.js b/packages/block-editor/src/hooks/use-bindings-attributes.js index cd85fa70adf5bf..0c978d436e8d64 100644 --- a/packages/block-editor/src/hooks/use-bindings-attributes.js +++ b/packages/block-editor/src/hooks/use-bindings-attributes.js @@ -101,7 +101,7 @@ export const withBlockBindingSupport = createHigherOrderComponent( const hasPatternOverridesDefaultBinding = props.attributes.metadata?.bindings?.[ DEFAULT_ATTRIBUTE ] ?.source === 'core/pattern-overrides'; - const bindings = useMemo( + const blockBindings = useMemo( () => replacePatternOverrideDefaultBindings( name, @@ -115,7 +115,7 @@ export const withBlockBindingSupport = createHigherOrderComponent( // there are attribute updates. // `source.getValues` may also call a selector via `registry.select`. const boundAttributes = useSelect( () => { - if ( ! bindings ) { + if ( ! blockBindings ) { return; } @@ -124,7 +124,7 @@ export const withBlockBindingSupport = createHigherOrderComponent( const bindingsBySource = new Map(); for ( const [ attributeName, binding ] of Object.entries( - bindings + blockBindings ) ) { const { source: sourceName, args: sourceArgs } = binding; const source = sources[ sourceName ]; @@ -144,13 +144,13 @@ export const withBlockBindingSupport = createHigherOrderComponent( } if ( bindingsBySource.size ) { - for ( const [ source, sourceBindings ] of bindingsBySource ) { + for ( const [ source, bindings ] of bindingsBySource ) { // Get values in batch if the source supports it. const values = source.getValues( { registry, context, clientId, - sourceBindings, + bindings, } ); for ( const [ attributeName, value ] of Object.entries( values @@ -166,8 +166,7 @@ export const withBlockBindingSupport = createHigherOrderComponent( context, clientId, attributeName, - args: sourceBindings[ attributeName ] - .args, + args: bindings[ attributeName ].args, } ); } } else { @@ -178,14 +177,14 @@ export const withBlockBindingSupport = createHigherOrderComponent( } return attributes; - }, [ bindings, name, clientId, context, registry, sources ] ); + }, [ blockBindings, name, clientId, context, registry, sources ] ); const { setAttributes } = props; const _setAttributes = useCallback( ( nextAttributes ) => { registry.batch( () => { - if ( ! bindings ) { + if ( ! blockBindings ) { setAttributes( nextAttributes ); return; } @@ -198,13 +197,13 @@ export const withBlockBindingSupport = createHigherOrderComponent( keptAttributes ) ) { if ( - ! bindings[ attributeName ] || + ! blockBindings[ attributeName ] || ! canBindAttribute( name, attributeName ) ) { continue; } - const binding = bindings[ attributeName ]; + const binding = blockBindings[ attributeName ]; const source = sources[ binding?.source ]; if ( ! source?.setValues ) { continue; @@ -220,15 +219,12 @@ export const withBlockBindingSupport = createHigherOrderComponent( } if ( bindingsBySource.size ) { - for ( const [ - source, - sourceBindings, - ] of bindingsBySource ) { + for ( const [ source, bindings ] of bindingsBySource ) { source.setValues( { registry, context, clientId, - sourceBindings, + bindings, } ); } } @@ -253,7 +249,7 @@ export const withBlockBindingSupport = createHigherOrderComponent( }, [ registry, - bindings, + blockBindings, name, clientId, context, diff --git a/packages/editor/src/bindings/pattern-overrides.js b/packages/editor/src/bindings/pattern-overrides.js index 5ab7a9b77ab414..b299211900095d 100644 --- a/packages/editor/src/bindings/pattern-overrides.js +++ b/packages/editor/src/bindings/pattern-overrides.js @@ -9,13 +9,13 @@ const CONTENT = 'content'; export default { name: 'core/pattern-overrides', label: _x( 'Pattern Overrides', 'block bindings source' ), - getValues( { registry, clientId, context, sourceBindings } ) { + getValues( { registry, clientId, context, bindings } ) { const patternOverridesContent = context[ 'pattern/overrides' ]; const { getBlockAttributes } = registry.select( blockEditorStore ); const currentBlockAttributes = getBlockAttributes( clientId ); const overridesValues = {}; - for ( const attributeName of Object.keys( sourceBindings ) ) { + for ( const attributeName of Object.keys( bindings ) ) { const overridableValue = patternOverridesContent?.[ currentBlockAttributes?.metadata?.name @@ -34,7 +34,7 @@ export default { } return overridesValues; }, - setValues( { registry, clientId, sourceBindings } ) { + setValues( { registry, clientId, bindings } ) { const { getBlockAttributes, getBlockParentsByBlockName, getBlocks } = registry.select( blockEditorStore ); const currentBlockAttributes = getBlockAttributes( clientId ); @@ -50,7 +50,7 @@ export default { ); // Extract the updated attributes from the source bindings. - const attributes = Object.entries( sourceBindings ).reduce( + const attributes = Object.entries( bindings ).reduce( ( attrs, [ key, { newValue } ] ) => { attrs[ key ] = newValue; return attrs; diff --git a/packages/editor/src/bindings/post-meta.js b/packages/editor/src/bindings/post-meta.js index fe56876b9f0a27..f8161dd47b5c41 100644 --- a/packages/editor/src/bindings/post-meta.js +++ b/packages/editor/src/bindings/post-meta.js @@ -15,7 +15,7 @@ export default { getPlaceholder( { args } ) { return args.key; }, - getValues( { registry, context, sourceBindings } ) { + getValues( { registry, context, bindings } ) { const meta = registry .select( coreDataStore ) .getEditedEntityRecord( @@ -24,16 +24,14 @@ export default { context?.postId )?.meta; const newValues = {}; - for ( const [ attributeName, source ] of Object.entries( - sourceBindings - ) ) { + for ( const [ attributeName, source ] of Object.entries( bindings ) ) { newValues[ attributeName ] = meta?.[ source.args.key ]; } return newValues; }, - setValues( { registry, context, sourceBindings } ) { + setValues( { registry, context, bindings } ) { const newMeta = {}; - Object.values( sourceBindings ).forEach( ( { args, newValue } ) => { + Object.values( bindings ).forEach( ( { args, newValue } ) => { newMeta[ args.key ] = newValue; } ); registry From ce803308505987b62c5afd58c947f1671b8bd48b Mon Sep 17 00:00:00 2001 From: Mario Santos Date: Fri, 19 Jul 2024 12:26:57 +0200 Subject: [PATCH 13/13] Use `blockBindingsBySource` name --- .../src/hooks/use-bindings-attributes.js | 23 +++++++++++-------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/packages/block-editor/src/hooks/use-bindings-attributes.js b/packages/block-editor/src/hooks/use-bindings-attributes.js index 0c978d436e8d64..410ad93bd971a7 100644 --- a/packages/block-editor/src/hooks/use-bindings-attributes.js +++ b/packages/block-editor/src/hooks/use-bindings-attributes.js @@ -121,7 +121,7 @@ export const withBlockBindingSupport = createHigherOrderComponent( const attributes = {}; - const bindingsBySource = new Map(); + const blockBindingsBySource = new Map(); for ( const [ attributeName, binding ] of Object.entries( blockBindings @@ -135,16 +135,16 @@ export const withBlockBindingSupport = createHigherOrderComponent( continue; } - bindingsBySource.set( source, { - ...bindingsBySource.get( source ), + blockBindingsBySource.set( source, { + ...blockBindingsBySource.get( source ), [ attributeName ]: { args: sourceArgs, }, } ); } - if ( bindingsBySource.size ) { - for ( const [ source, bindings ] of bindingsBySource ) { + if ( blockBindingsBySource.size ) { + for ( const [ source, bindings ] of blockBindingsBySource ) { // Get values in batch if the source supports it. const values = source.getValues( { registry, @@ -190,7 +190,7 @@ export const withBlockBindingSupport = createHigherOrderComponent( } const keptAttributes = { ...nextAttributes }; - const bindingsBySource = new Map(); + const blockBindingsBySource = new Map(); // Loop only over the updated attributes to avoid modifying the bound ones that haven't changed. for ( const [ attributeName, newValue ] of Object.entries( @@ -208,8 +208,8 @@ export const withBlockBindingSupport = createHigherOrderComponent( if ( ! source?.setValues ) { continue; } - bindingsBySource.set( source, { - ...bindingsBySource.get( source ), + blockBindingsBySource.set( source, { + ...blockBindingsBySource.get( source ), [ attributeName ]: { args: binding.args, newValue, @@ -218,8 +218,11 @@ export const withBlockBindingSupport = createHigherOrderComponent( delete keptAttributes[ attributeName ]; } - if ( bindingsBySource.size ) { - for ( const [ source, bindings ] of bindingsBySource ) { + if ( blockBindingsBySource.size ) { + for ( const [ + source, + bindings, + ] of blockBindingsBySource ) { source.setValues( { registry, context,