Skip to content

Commit 6bdb9b4

Browse files
SantosGuillamotcbravobernal
authored andcommitted
Block Bindings: Remove getPlaceholder API and rely on key argument or source label (WordPress#64910)
* Remove `getPlaceholder` API * Skip unregistered sources * Add e2e tests * Accept undefined as a valid value * Properly check if value is a URL Co-authored-by: SantosGuillamot <santosguillamot@git.wordpress.org> Co-authored-by: cbravobernal <cbravobernal@git.wordpress.org>
1 parent 84baf0e commit 6bdb9b4

File tree

7 files changed

+75
-57
lines changed

7 files changed

+75
-57
lines changed

packages/block-editor/src/hooks/use-bindings-attributes.js

+23-24
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import { addFilter } from '@wordpress/hooks';
1010
/**
1111
* Internal dependencies
1212
*/
13+
import isURLLike from '../components/link-control/is-url-like';
1314
import { unlock } from '../lock-unlock';
1415
import BlockContext from '../components/block-context';
1516

@@ -134,10 +135,7 @@ export const withBlockBindingSupport = createHigherOrderComponent(
134135
) ) {
135136
const { source: sourceName, args: sourceArgs } = binding;
136137
const source = sources[ sourceName ];
137-
if (
138-
! source?.getValues ||
139-
! canBindAttribute( name, attributeName )
140-
) {
138+
if ( ! source || ! canBindAttribute( name, attributeName ) ) {
141139
continue;
142140
}
143141

@@ -161,29 +159,30 @@ export const withBlockBindingSupport = createHigherOrderComponent(
161159
}
162160

163161
// Get values in batch if the source supports it.
164-
const values = source.getValues( {
165-
registry,
166-
context,
167-
clientId,
168-
bindings,
169-
} );
162+
let values = {};
163+
if ( ! source.getValues ) {
164+
Object.keys( bindings ).forEach( ( attr ) => {
165+
// Default to the `key` or the source label when `getValues` doesn't exist
166+
values[ attr ] =
167+
bindings[ attr ].args?.key || source.label;
168+
} );
169+
} else {
170+
values = source.getValues( {
171+
registry,
172+
context,
173+
clientId,
174+
bindings,
175+
} );
176+
}
170177
for ( const [ attributeName, value ] of Object.entries(
171178
values
172179
) ) {
173-
// Use placeholder when value is undefined.
174-
if ( value === undefined ) {
175-
if ( attributeName === 'url' ) {
176-
attributes[ attributeName ] = null;
177-
} else {
178-
attributes[ attributeName ] =
179-
source.getPlaceholder?.( {
180-
registry,
181-
context,
182-
clientId,
183-
attributeName,
184-
args: bindings[ attributeName ].args,
185-
} );
186-
}
180+
if (
181+
attributeName === 'url' &&
182+
( ! value || ! isURLLike( value ) )
183+
) {
184+
// Return null if value is not a valid URL.
185+
attributes[ attributeName ] = null;
187186
} else {
188187
attributes[ attributeName ] = value;
189188
}

packages/blocks/src/api/registration.js

+1-10
Original file line numberDiff line numberDiff line change
@@ -773,7 +773,6 @@ export const unregisterBlockVariation = ( blockName, variationName ) => {
773773
* @param {Array} [source.usesContext] Array of context needed by the source only in the editor.
774774
* @param {Function} [source.getValues] Function to get the values from the source.
775775
* @param {Function} [source.setValues] Function to update multiple values connected to the source.
776-
* @param {Function} [source.getPlaceholder] Function to get the placeholder when the value is undefined.
777776
* @param {Function} [source.canUserEditValue] Function to determine if the user can edit the value.
778777
* @param {Function} [source.getFieldsList] Function to get the lists of fields to expose in the connections panel.
779778
*
@@ -787,7 +786,6 @@ export const unregisterBlockVariation = ( blockName, variationName ) => {
787786
* label: _x( 'My Custom Source', 'block bindings source' ),
788787
* getValues: () => getSourceValues(),
789788
* setValues: () => updateMyCustomValuesInBatch(),
790-
* getPlaceholder: () => 'Placeholder text when the value is undefined',
791789
* canUserEditValue: () => true,
792790
* } );
793791
* ```
@@ -799,7 +797,6 @@ export const registerBlockBindingsSource = ( source ) => {
799797
usesContext,
800798
getValues,
801799
setValues,
802-
getPlaceholder,
803800
canUserEditValue,
804801
getFieldsList,
805802
} = source;
@@ -889,13 +886,7 @@ export const registerBlockBindingsSource = ( source ) => {
889886
return;
890887
}
891888

892-
// Check the `getPlaceholder` property is correct.
893-
if ( getPlaceholder && typeof getPlaceholder !== 'function' ) {
894-
warning( 'Block bindings source getPlaceholder must be a function.' );
895-
return;
896-
}
897-
898-
// Check the `getPlaceholder` property is correct.
889+
// Check the `canUserEditValue` property is correct.
899890
if ( canUserEditValue && typeof canUserEditValue !== 'function' ) {
900891
warning( 'Block bindings source canUserEditValue must be a function.' );
901892
return;

packages/blocks/src/api/test/registration.js

-16
Original file line numberDiff line numberDiff line change
@@ -1630,19 +1630,6 @@ describe( 'blocks', () => {
16301630
expect( getBlockBindingsSource( 'core/testing' ) ).toBeUndefined();
16311631
} );
16321632

1633-
// Check the `getPlaceholder` callback is correct.
1634-
it( 'should reject invalid getPlaceholder callback', () => {
1635-
registerBlockBindingsSource( {
1636-
name: 'core/testing',
1637-
label: 'testing',
1638-
getPlaceholder: 'should be a function',
1639-
} );
1640-
expect( console ).toHaveWarnedWith(
1641-
'Block bindings source getPlaceholder must be a function.'
1642-
);
1643-
expect( getBlockBindingsSource( 'core/testing' ) ).toBeUndefined();
1644-
} );
1645-
16461633
// Check the `canUserEditValue` callback is correct.
16471634
it( 'should reject invalid canUserEditValue callback', () => {
16481635
registerBlockBindingsSource( {
@@ -1676,7 +1663,6 @@ describe( 'blocks', () => {
16761663
usesContext: [ 'postId' ],
16771664
getValues: () => 'value',
16781665
setValues: () => 'new values',
1679-
getPlaceholder: () => 'placeholder',
16801666
canUserEditValue: () => true,
16811667
getFieldsList: () => {
16821668
return { field: 'value' };
@@ -1701,7 +1687,6 @@ describe( 'blocks', () => {
17011687
expect( source.usesContext ).toBeUndefined();
17021688
expect( source.getValues ).toBeUndefined();
17031689
expect( source.setValues ).toBeUndefined();
1704-
expect( source.getPlaceholder ).toBeUndefined();
17051690
expect( source.canUserEditValue ).toBeUndefined();
17061691
expect( source.getFieldsList ).toBeUndefined();
17071692
unregisterBlockBindingsSource( 'core/valid-source' );
@@ -1726,7 +1711,6 @@ describe( 'blocks', () => {
17261711
const clientOnlyProperties = {
17271712
getValues: () => 'values',
17281713
setValues: () => 'new values',
1729-
getPlaceholder: () => 'placeholder',
17301714
canUserEditValue: () => true,
17311715
};
17321716
registerBlockBindingsSource( {

packages/blocks/src/store/private-actions.js

-1
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,6 @@ export function addBlockBindingsSource( source ) {
5454
usesContext: source.usesContext,
5555
getValues: source.getValues,
5656
setValues: source.setValues,
57-
getPlaceholder: source.getPlaceholder,
5857
canUserEditValue: source.canUserEditValue,
5958
getFieldsList: source.getFieldsList,
6059
};

packages/blocks/src/store/reducer.js

-1
Original file line numberDiff line numberDiff line change
@@ -404,7 +404,6 @@ export function blockBindingsSources( state = {}, action ) {
404404
),
405405
getValues: action.getValues,
406406
setValues: action.setValues,
407-
getPlaceholder: action.getPlaceholder,
408407
canUserEditValue: action.canUserEditValue,
409408
getFieldsList: action.getFieldsList,
410409
},

packages/editor/src/bindings/post-meta.js

+3-4
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,6 @@ import { store as editorStore } from '../store';
1010

1111
export default {
1212
name: 'core/post-meta',
13-
getPlaceholder( { args } ) {
14-
return args.key;
15-
},
1613
getValues( { registry, context, bindings } ) {
1714
const meta = registry
1815
.select( coreDataStore )
@@ -23,7 +20,9 @@ export default {
2320
)?.meta;
2421
const newValues = {};
2522
for ( const [ attributeName, source ] of Object.entries( bindings ) ) {
26-
newValues[ attributeName ] = meta?.[ source.args.key ];
23+
// Use the key if the value is not set.
24+
newValues[ attributeName ] =
25+
meta?.[ source.args.key ] || source.args.key;
2726
}
2827
return newValues;
2928
},

test/e2e/specs/editor/various/block-bindings.spec.js

+48-1
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ test.describe( 'Block bindings', () => {
4141
} );
4242

4343
test.describe( 'Paragraph', () => {
44-
test( 'should show the value of the custom field', async ( {
44+
test( 'should show the key of the custom field in post meta', async ( {
4545
editor,
4646
} ) => {
4747
await editor.insertBlock( {
@@ -66,6 +66,53 @@ test.describe( 'Block bindings', () => {
6666
);
6767
} );
6868

69+
test( 'should show the key of the custom field in server sources with key', async ( {
70+
editor,
71+
} ) => {
72+
await editor.insertBlock( {
73+
name: 'core/paragraph',
74+
attributes: {
75+
content: 'paragraph default content',
76+
metadata: {
77+
bindings: {
78+
content: {
79+
source: 'core/server-source',
80+
args: { key: 'text_custom_field' },
81+
},
82+
},
83+
},
84+
},
85+
} );
86+
const paragraphBlock = editor.canvas.getByRole( 'document', {
87+
name: 'Block: Paragraph',
88+
} );
89+
await expect( paragraphBlock ).toHaveText(
90+
'text_custom_field'
91+
);
92+
} );
93+
94+
test( 'should show the source label in server sources without key', async ( {
95+
editor,
96+
} ) => {
97+
await editor.insertBlock( {
98+
name: 'core/paragraph',
99+
attributes: {
100+
content: 'paragraph default content',
101+
metadata: {
102+
bindings: {
103+
content: {
104+
source: 'core/server-source',
105+
},
106+
},
107+
},
108+
},
109+
} );
110+
const paragraphBlock = editor.canvas.getByRole( 'document', {
111+
name: 'Block: Paragraph',
112+
} );
113+
await expect( paragraphBlock ).toHaveText( 'Server Source' );
114+
} );
115+
69116
test( 'should lock the appropriate controls with a registered source', async ( {
70117
editor,
71118
page,

0 commit comments

Comments
 (0)