Skip to content

Commit

Permalink
Blocks: Merge variations bootstrapped from a server with the client d…
Browse files Browse the repository at this point in the history
…efinitions (#60832)


Co-authored-by: Mamaduka <[email protected]>
Co-authored-by: jsnajdr <[email protected]>
Co-authored-by: tyxla <[email protected]>
Co-authored-by: t-hamano <[email protected]>
Co-authored-by: joemcgill <[email protected]>
  • Loading branch information
6 people authored Apr 22, 2024
1 parent 72c1291 commit ad31355
Show file tree
Hide file tree
Showing 2 changed files with 83 additions and 2 deletions.
45 changes: 45 additions & 0 deletions packages/blocks/src/api/test/registration.js
Original file line number Diff line number Diff line change
Expand Up @@ -398,6 +398,51 @@ describe( 'blocks', () => {
} );
} );

it( 'should merge settings provided by server and client', () => {
const blockName = 'core/test-block-with-merged-settings';
unstable__bootstrapServerSideBlockDefinitions( {
[ blockName ]: {
variations: [
{ name: 'foo', label: 'Foo' },
{ name: 'baz', label: 'Baz', description: 'Testing' },
],
},
} );

const blockType = {
title: 'block settings merge',
variations: [
{ name: 'bar', label: 'Bar' },
{ name: 'baz', label: 'Baz', icon: 'layout' },
],
};
registerBlockType( blockName, blockType );
expect( getBlockType( blockName ) ).toEqual( {
name: blockName,
save: expect.any( Function ),
title: 'block settings merge',
icon: { src: BLOCK_ICON_DEFAULT },
attributes: {},
providesContext: {},
usesContext: [],
keywords: [],
selectors: {},
supports: {},
styles: [],
variations: [
{ name: 'foo', label: 'Foo' },
{
description: 'Testing',
name: 'baz',
label: 'Baz',
icon: 'layout',
},
{ name: 'bar', label: 'Bar' },
],
blockHooks: {},
} );
} );

// This test can be removed once the polyfill for blockHooks gets removed.
it( 'should polyfill blockHooks using metadata on the client when not set on the server', () => {
const blockName = 'tests/hooked-block';
Expand Down
40 changes: 38 additions & 2 deletions packages/blocks/src/store/process-block-type.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,37 @@ const LEGACY_CATEGORY_MAPPING = {
layout: 'design',
};

/**
* Merge block variations bootstrapped from the server and client.
*
* When a variation is registered in both places, its properties are merged.
*
* @param {Array} bootstrappedVariations - A block type variations from the server.
* @param {Array} clientVariations - A block type variations from the client.
* @return {Array} The merged array of block variations.
*/
function mergeBlockVariations(
bootstrappedVariations = [],
clientVariations = []
) {
const result = [ ...bootstrappedVariations ];

clientVariations.forEach( ( clientVariation ) => {
const index = result.findIndex(
( bootstrappedVariation ) =>
bootstrappedVariation.name === clientVariation.name
);

if ( index !== -1 ) {
result[ index ] = { ...result[ index ], ...clientVariation };
} else {
result.push( clientVariation );
}
} );

return result;
}

/**
* Takes the unprocessed block type settings, merges them with block type metadata
* and applies all the existing filters for the registered block type.
Expand All @@ -46,6 +77,8 @@ const LEGACY_CATEGORY_MAPPING = {
export const processBlockType =
( name, blockSettings ) =>
( { select } ) => {
const bootstrappedBlockType = select.getBootstrappedBlockType( name );

const blockType = {
name,
icon: BLOCK_ICON_DEFAULT,
Expand All @@ -56,11 +89,14 @@ export const processBlockType =
selectors: {},
supports: {},
styles: [],
variations: [],
blockHooks: {},
save: () => null,
...select.getBootstrappedBlockType( name ),
...bootstrappedBlockType,
...blockSettings,
variations: mergeBlockVariations(
bootstrappedBlockType?.variations,
blockSettings?.variations
),
};

const settings = applyFilters(
Expand Down

0 comments on commit ad31355

Please sign in to comment.