diff --git a/packages/e2e-tests/plugins/block-bindings.php b/packages/e2e-tests/plugins/block-bindings.php index b2eb9d797610d5..bd963ce76a5036 100644 --- a/packages/e2e-tests/plugins/block-bindings.php +++ b/packages/e2e-tests/plugins/block-bindings.php @@ -28,7 +28,7 @@ function gutenberg_test_block_bindings_registration() { 'show_in_rest' => true, 'type' => 'string', 'single' => true, - 'default' => 'Value of the text_custom_field', + 'default' => 'Value of the text custom field', ) ); register_meta( diff --git a/packages/editor/src/bindings/post-meta.js b/packages/editor/src/bindings/post-meta.js index d04b235ef5420a..87efbe1687cdaa 100644 --- a/packages/editor/src/bindings/post-meta.js +++ b/packages/editor/src/bindings/post-meta.js @@ -9,21 +9,75 @@ import { store as coreDataStore } from '@wordpress/core-data'; import { store as editorStore } from '../store'; import { unlock } from '../lock-unlock'; +function getMetadata( registry, context ) { + let metaFields = {}; + const { + type, + is_custom: isCustom, + slug, + } = registry.select( editorStore ).getCurrentPost(); + const { getPostTypes, getEditedEntityRecord } = + registry.select( coreDataStore ); + + const { getRegisteredPostMeta } = unlock( + registry.select( coreDataStore ) + ); + + // Inherit the postType from the slug if it is a template. + if ( ! context?.postType && type === 'wp_template' ) { + // Get the 'kind' from the start of the slug. + // Use 'post' as the default. + let postType = 'post'; + const isGlobalTemplate = isCustom || slug === 'index'; + if ( ! isGlobalTemplate ) { + const [ kind ] = slug.split( '-' ); + if ( kind === 'page' ) { + postType = 'page'; + } else if ( kind === 'single' ) { + const postTypes = + getPostTypes( { per_page: -1 } )?.map( + ( entity ) => entity.slug + ) || []; + + // Infer the post type from the slug. + // TODO: Review, as it may not have a post type. http://localhost:8888/wp-admin/site-editor.php?canvas=edit + const match = slug.match( + `^single-(${ postTypes.join( '|' ) })(?:-.+)?$` + ); + postType = match ? match[ 1 ] : 'post'; + } + } + const fields = getRegisteredPostMeta( postType ); + + // Populate the `metaFields` object with the default values. + Object.entries( fields || {} ).forEach( ( [ key, props ] ) => { + // If the template is global, skip the fields with a subtype. + if ( isGlobalTemplate && props.object_subtype ) { + return; + } + metaFields[ key ] = props.default; + } ); + } else { + metaFields = getEditedEntityRecord( + 'postType', + context?.postType, + context?.postId + ).meta; + } + + return metaFields; +} + export default { name: 'core/post-meta', getValues( { registry, context, bindings } ) { - const meta = registry - .select( coreDataStore ) - .getEditedEntityRecord( - 'postType', - context?.postType, - context?.postId - )?.meta; + const metaFields = getMetadata( registry, context ); + const newValues = {}; for ( const [ attributeName, source ] of Object.entries( bindings ) ) { // Use the key if the value is not set. newValues[ attributeName ] = - meta?.[ source.args.key ] || source.args.key; + metaFields?.[ source.args.key ] || source.args.key; } return newValues; }, @@ -83,61 +137,7 @@ export default { return true; }, getFieldsList( { registry, context } ) { - let metaFields = {}; - const { - type, - is_custom: isCustom, - slug, - } = registry.select( editorStore ).getCurrentPost(); - const { getPostTypes, getEditedEntityRecord } = - registry.select( coreDataStore ); - - const { getRegisteredPostMeta } = unlock( - registry.select( coreDataStore ) - ); - - // Inherit the postType from the slug if it is a template. - if ( ! context?.postType && type === 'wp_template' ) { - // Get the 'kind' from the start of the slug. - // Use 'post' as the default. - let postType = 'post'; - // A global template can be used with any post type. - const isGlobalTemplate = isCustom || slug === 'index'; - if ( ! isGlobalTemplate ) { - const [ kind ] = slug.split( '-' ); - if ( kind === 'page' ) { - postType = 'page'; - } else if ( kind === 'single' ) { - const postTypes = - getPostTypes( { per_page: -1 } )?.map( - ( entity ) => entity.slug - ) || []; - - // Infer the post type from the slug. - // TODO: Review, as it may not have a post type. http://localhost:8888/wp-admin/site-editor.php?canvas=edit - const match = slug.match( - `^single-(${ postTypes.join( '|' ) })(?:-.+)?$` - ); - postType = match ? match[ 1 ] : 'post'; - } - } - const fields = getRegisteredPostMeta( postType ); - - // Populate the `metaFields` object with the default values. - Object.entries( fields || {} ).forEach( ( [ key, props ] ) => { - // If the template is global, skip the fields with a subtype. - if ( isGlobalTemplate && props.object_subtype ) { - return; - } - metaFields[ key ] = props.default; - } ); - } else { - metaFields = getEditedEntityRecord( - 'postType', - context?.postType, - context?.postId - ).meta; - } + const metaFields = getMetadata( registry, context ); if ( ! metaFields || ! Object.keys( metaFields ).length ) { return null; diff --git a/test/e2e/specs/editor/various/block-bindings.spec.js b/test/e2e/specs/editor/various/block-bindings.spec.js index 2799315a10b220..84dbacc54fa56d 100644 --- a/test/e2e/specs/editor/various/block-bindings.spec.js +++ b/test/e2e/specs/editor/various/block-bindings.spec.js @@ -62,7 +62,7 @@ test.describe( 'Block bindings', () => { name: 'Block: Paragraph', } ); await expect( paragraphBlock ).toHaveText( - 'text_custom_field' + 'Value of the text custom field' ); } ); @@ -922,7 +922,7 @@ test.describe( 'Block bindings', () => { .getByRole( 'tabpanel', { name: 'Settings' } ) .getByLabel( 'Alternative text' ) .inputValue(); - expect( altValue ).toBe( 'text_custom_field' ); + expect( altValue ).toBe( 'Value of the text custom field' ); // Title input is enabled and with the original value. await page @@ -1064,7 +1064,7 @@ test.describe( 'Block bindings', () => { .getByRole( 'tabpanel', { name: 'Settings' } ) .getByLabel( 'Title attribute' ) .inputValue(); - expect( titleValue ).toBe( 'text_custom_field' ); + expect( titleValue ).toBe( 'Value of the text custom field' ); } ); test( 'should disable title input when title is bound to an undefined source', async ( { @@ -1183,7 +1183,7 @@ test.describe( 'Block bindings', () => { .getByRole( 'tabpanel', { name: 'Settings' } ) .getByLabel( 'Alternative text' ) .inputValue(); - expect( altValue ).toBe( 'text_custom_field' ); + expect( altValue ).toBe( 'Value of the text custom field' ); // Title input is enabled and with the original value. await page @@ -1231,14 +1231,14 @@ test.describe( 'Block bindings', () => { name: 'Block: Paragraph', } ); await expect( paragraphBlock ).toHaveText( - 'Value of the text_custom_field' + 'Value of the text custom field' ); // Check the frontend shows the value of the custom field. const previewPage = await editor.openPreviewPage(); await expect( previewPage.locator( '#paragraph-binding' ) - ).toHaveText( 'Value of the text_custom_field' ); + ).toHaveText( 'Value of the text custom field' ); } ); test( "should show the value of the key when custom field doesn't exist", async ( { @@ -1368,7 +1368,7 @@ test.describe( 'Block bindings', () => { .locator( '[data-type="core/paragraph"]' ) .all(); await expect( initialParagraph ).toHaveText( - 'Value of the text_custom_field' + 'Value of the text custom field' ); await expect( newEmptyParagraph ).toHaveText( '' ); await expect( newEmptyParagraph ).toBeEditable(); @@ -1478,7 +1478,7 @@ test.describe( 'Block bindings', () => { name: 'Block: Paragraph', } ); await expect( paragraphBlock ).toHaveText( - 'Value of the text_custom_field' + 'Value of the text custom field' ); } ); } ); @@ -1506,14 +1506,14 @@ test.describe( 'Block bindings', () => { name: 'Block: Heading', } ); await expect( headingBlock ).toHaveText( - 'Value of the text_custom_field' + 'Value of the text custom field' ); // Check the frontend shows the value of the custom field. const previewPage = await editor.openPreviewPage(); await expect( previewPage.locator( '#heading-binding' ) - ).toHaveText( 'Value of the text_custom_field' ); + ).toHaveText( 'Value of the text custom field' ); } ); test( 'should add empty paragraph block when pressing enter', async ( { @@ -1552,7 +1552,7 @@ test.describe( 'Block bindings', () => { 'core/heading' ); await expect( initialHeading ).toHaveText( - 'Value of the text_custom_field' + 'Value of the text custom field' ); // Second block should be an empty paragraph block. await expect( newEmptyParagraph ).toHaveAttribute( @@ -1610,7 +1610,7 @@ test.describe( 'Block bindings', () => { .getByRole( 'textbox' ); await buttonBlock.click(); await expect( buttonBlock ).toHaveText( - 'Value of the text_custom_field' + 'Value of the text custom field' ); // Check the frontend shows the value of the custom field. @@ -1619,7 +1619,7 @@ test.describe( 'Block bindings', () => { '#button-text-binding a' ); await expect( buttonDom ).toHaveText( - 'Value of the text_custom_field' + 'Value of the text custom field' ); await expect( buttonDom ).toHaveAttribute( 'href', @@ -1699,7 +1699,7 @@ test.describe( 'Block bindings', () => { '#button-multiple-bindings a' ); await expect( buttonDom ).toHaveText( - 'Value of the text_custom_field' + 'Value of the text custom field' ); await expect( buttonDom ).toHaveAttribute( 'href', @@ -1746,7 +1746,7 @@ test.describe( 'Block bindings', () => { .all(); // First block should be the original block. await expect( initialButton ).toHaveText( - 'Value of the text_custom_field' + 'Value of the text custom field' ); // Second block should be an empty paragraph block. await expect( newEmptyButton ).toHaveText( '' ); @@ -1911,7 +1911,7 @@ test.describe( 'Block bindings', () => { .getByRole( 'tabpanel', { name: 'Settings' } ) .getByLabel( 'Alternative text' ) .inputValue(); - expect( altValue ).toBe( 'Value of the text_custom_field' ); + expect( altValue ).toBe( 'Value of the text custom field' ); // Check the frontend uses the value of the custom field. const previewPage = await editor.openPreviewPage(); @@ -1924,7 +1924,7 @@ test.describe( 'Block bindings', () => { ); await expect( imageDom ).toHaveAttribute( 'alt', - 'Value of the text_custom_field' + 'Value of the text custom field' ); await expect( imageDom ).toHaveAttribute( 'title', @@ -1981,7 +1981,7 @@ test.describe( 'Block bindings', () => { .getByRole( 'tabpanel', { name: 'Settings' } ) .getByLabel( 'Title attribute' ) .inputValue(); - expect( titleValue ).toBe( 'Value of the text_custom_field' ); + expect( titleValue ).toBe( 'Value of the text custom field' ); // Check the frontend uses the value of the custom field. const previewPage = await editor.openPreviewPage(); @@ -1998,7 +1998,7 @@ test.describe( 'Block bindings', () => { ); await expect( imageDom ).toHaveAttribute( 'title', - 'Value of the text_custom_field' + 'Value of the text custom field' ); } ); @@ -2045,7 +2045,7 @@ test.describe( 'Block bindings', () => { .getByRole( 'tabpanel', { name: 'Settings' } ) .getByLabel( 'Alternative text' ) .inputValue(); - expect( altValue ).toBe( 'Value of the text_custom_field' ); + expect( altValue ).toBe( 'Value of the text custom field' ); // Title input should have the original value. const advancedButton = page @@ -2075,7 +2075,7 @@ test.describe( 'Block bindings', () => { ); await expect( imageDom ).toHaveAttribute( 'alt', - 'Value of the text_custom_field' + 'Value of the text custom field' ); await expect( imageDom ).toHaveAttribute( 'title',