Skip to content

Commit

Permalink
Block bindings: allow only string field types in bindings. (#66174)
Browse files Browse the repository at this point in the history
* Filter fields by type in post meta

* Add e2e test

* Allow only strings

* Update test to expect numbers and integers to be hidden

* Update tests to check for label instead of key

* Adapt object custom field

* Adapt e2e tests

* Add `type` prop to `getFieldsList`

* Adapt testing source

* Reduce diff

* Add `attribute` to dependencies



---------
Co-authored-by: SantosGuillamot <[email protected]>
Co-authored-by: cbravobernal <[email protected]>
Co-authored-by: artemiomorales <[email protected]>
Co-authored-by: gziolo <[email protected]>
  • Loading branch information
SantosGuillamot authored and priethor committed Oct 23, 2024
1 parent 8492898 commit da326f9
Show file tree
Hide file tree
Showing 4 changed files with 176 additions and 23 deletions.
63 changes: 40 additions & 23 deletions packages/block-editor/src/hooks/block-bindings.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { __ } from '@wordpress/i18n';
import {
getBlockBindingsSource,
getBlockBindingsSources,
getBlockType,
} from '@wordpress/blocks';
import {
__experimentalItemGroup as ItemGroup,
Expand All @@ -29,6 +30,7 @@ import {
import { unlock } from '../lock-unlock';
import InspectorControls from '../components/inspector-controls';
import BlockContext from '../components/block-context';
import { useBlockEditContext } from '../components/block-edit';
import { useBlockBindingsUtils } from '../utils/block-bindings';
import { store as blockEditorStore } from '../store';

Expand All @@ -50,9 +52,20 @@ const useToolsPanelDropdownMenuProps = () => {
};

function BlockBindingsPanelDropdown( { fieldsList, attribute, binding } ) {
const { clientId } = useBlockEditContext();
const registeredSources = getBlockBindingsSources();
const { updateBlockBindings } = useBlockBindingsUtils();
const currentKey = binding?.args?.key;
const attributeType = useSelect(
( select ) => {
const { name: blockName } =
select( blockEditorStore ).getBlock( clientId );
const _attributeType =
getBlockType( blockName ).attributes?.[ attribute ]?.type;
return _attributeType === 'rich-text' ? 'string' : _attributeType;
},
[ clientId, attribute ]
);
return (
<>
{ Object.entries( fieldsList ).map( ( [ name, fields ], i ) => (
Expand All @@ -63,29 +76,33 @@ function BlockBindingsPanelDropdown( { fieldsList, attribute, binding } ) {
{ registeredSources[ name ].label }
</DropdownMenuV2.GroupLabel>
) }
{ Object.entries( fields ).map( ( [ key, args ] ) => (
<DropdownMenuV2.RadioItem
key={ key }
onChange={ () =>
updateBlockBindings( {
[ attribute ]: {
source: name,
args: { key },
},
} )
}
name={ attribute + '-binding' }
value={ key }
checked={ key === currentKey }
>
<DropdownMenuV2.ItemLabel>
{ args?.label }
</DropdownMenuV2.ItemLabel>
<DropdownMenuV2.ItemHelpText>
{ args?.value }
</DropdownMenuV2.ItemHelpText>
</DropdownMenuV2.RadioItem>
) ) }
{ Object.entries( fields )
.filter(
( [ , args ] ) => args?.type === attributeType
)
.map( ( [ key, args ] ) => (
<DropdownMenuV2.RadioItem
key={ key }
onChange={ () =>
updateBlockBindings( {
[ attribute ]: {
source: name,
args: { key },
},
} )
}
name={ attribute + '-binding' }
value={ key }
checked={ key === currentKey }
>
<DropdownMenuV2.ItemLabel>
{ args?.label }
</DropdownMenuV2.ItemLabel>
<DropdownMenuV2.ItemHelpText>
{ args?.value }
</DropdownMenuV2.ItemHelpText>
</DropdownMenuV2.RadioItem>
) ) }
</DropdownMenuV2.Group>
{ i !== Object.keys( fieldsList ).length - 1 && (
<DropdownMenuV2.Separator />
Expand Down
86 changes: 86 additions & 0 deletions packages/e2e-tests/plugins/block-bindings.php
Original file line number Diff line number Diff line change
Expand Up @@ -21,14 +21,17 @@ function gutenberg_test_block_bindings_registration() {
'text_field' => array(
'label' => 'Text Field Label',
'value' => 'Text Field Value',
'type' => 'string',
),
'url_field' => array(
'label' => 'URL Field Label',
'value' => $testing_url,
'type' => 'string',
),
'empty_field' => array(
'label' => 'Empty Field Label',
'value' => '',
'type' => 'string',
),
);

Expand Down Expand Up @@ -106,6 +109,89 @@ function gutenberg_test_block_bindings_registration() {
'type' => 'string',
)
);
// Register different types of custom fields for testing.
register_meta(
'post',
'string_custom_field',
array(
'label' => 'String custom field',
'default' => '',
'show_in_rest' => true,
'single' => true,
'type' => 'string',
)
);
register_meta(
'post',
'object_custom_field',
array(
'label' => 'Object custom field',
'show_in_rest' => array(
'schema' => array(
'type' => 'object',
'properties' => array(
'foo' => array(
'type' => 'string',
),
),
),
),
'single' => true,
'type' => 'object',
)
);
register_meta(
'post',
'array_custom_field',
array(
'label' => 'Array custom field',
'show_in_rest' => array(
'schema' => array(
'type' => 'array',
'items' => array(
'type' => 'string',
),
),
),
'single' => true,
'type' => 'array',
'default' => array(),
)
);
register_meta(
'post',
'number',
array(
'label' => 'Number custom field',
'type' => 'number',
'show_in_rest' => true,
'single' => true,
'default' => 5.5,
)
);
register_meta(
'post',
'integer',
array(
'label' => 'Integer custom field',
'type' => 'integer',
'show_in_rest' => true,
'single' => true,
'default' => 5,
)
);
register_meta(
'post',
'boolean',
array(
'label' => 'Boolean custom field',
'type' => 'boolean',
'show_in_rest' => true,
'single' => true,
'default' => true,
)
);

// Register CPT custom fields.
register_meta(
'post',
Expand Down
1 change: 1 addition & 0 deletions packages/editor/src/bindings/post-meta.js
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ function getPostMetaFields( select, context ) {
entityMetaValues?.[ key ] ??
// When using the default, an empty string IS NOT a valid value.
( props.default || undefined ),
type: props.type,
};
}
} );
Expand Down
49 changes: 49 additions & 0 deletions test/e2e/specs/editor/various/block-bindings/post-meta.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -547,5 +547,54 @@ test.describe( 'Post Meta source', () => {
.filter( { hasText: 'Movie field label' } );
await expect( movieField ).toBeVisible();
} );
test( 'should not be possible to connect non-supported fields through the attributes panel', async ( {
editor,
page,
} ) => {
await editor.insertBlock( {
name: 'core/paragraph',
} );
await page.getByLabel( 'Attributes options' ).click();
await page
.getByRole( 'menuitemcheckbox', {
name: 'Show content',
} )
.click();
await page
.getByRole( 'button', {
name: 'content',
} )
.click();
await expect(
page.getByRole( 'menuitemradio', {
name: 'String custom field',
} )
).toBeVisible();
await expect(
page.getByRole( 'menuitemradio', {
name: 'Number custom field',
} )
).toBeHidden();
await expect(
page.getByRole( 'menuitemradio', {
name: 'Integer custom field',
} )
).toBeHidden();
await expect(
page.getByRole( 'menuitemradio', {
name: 'Boolean custom field',
} )
).toBeHidden();
await expect(
page.getByRole( 'menuitemradio', {
name: 'Object custom field',
} )
).toBeHidden();
await expect(
page.getByRole( 'menuitemradio', {
name: 'Array custom field',
} )
).toBeHidden();
} );
} );
} );

0 comments on commit da326f9

Please sign in to comment.