Skip to content

Commit

Permalink
Implement partially synced patterns behind an experimental flag (#56235)
Browse files Browse the repository at this point in the history
* Try using the block connections api

* Fix native

* Rename dynamicContent to overrides

* Add new experiment flag for partial syncing

* Automatically assign block ids to pattern blocks for use in partial synching of pattern instances (#56495)

* Automatically assign block ids

* Downgrade package to fix tooling

* Move to the editor package and allow core/button

* Fix test resolver

* Fix the flag and remove support for core/button

* Address code reviews

* Rename to pattern/overrides

* Fix php lint error

---------

Co-authored-by: Aaron Robertshaw <60436221+aaronrobertshaw@users.noreply.github.com>
Co-authored-by: Glen Davies <glen.davies@automattic.com>
  • Loading branch information
3 people authored Dec 1, 2023
1 parent 7b1f24c commit 16eb009
Show file tree
Hide file tree
Showing 22 changed files with 661 additions and 39 deletions.
36 changes: 36 additions & 0 deletions lib/block-supports/pattern.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
<?php
/**
* Pattern block support flag.
*
* @package gutenberg
*/

$gutenberg_experiments = get_option( 'gutenberg-experiments' );
if ( $gutenberg_experiments && array_key_exists( 'gutenberg-pattern-partial-syncing', $gutenberg_experiments ) ) {
/**
* Registers the overrides context for block types that support it.
*
* @param WP_Block_Type $block_type Block Type.
*/
function gutenberg_register_pattern_support( $block_type ) {
$pattern_support = property_exists( $block_type, 'supports' ) ? _wp_array_get( $block_type->supports, array( '__experimentalConnections' ), false ) : false;

if ( $pattern_support ) {
if ( ! $block_type->uses_context ) {
$block_type->uses_context = array();
}

if ( ! in_array( 'pattern/overrides', $block_type->uses_context, true ) ) {
$block_type->uses_context[] = 'pattern/overrides';
}
}
}

// Register the block support.
WP_Block_Supports::get_instance()->register(
'pattern',
array(
'register_attribute' => 'gutenberg_register_pattern_support',
)
);
}
39 changes: 27 additions & 12 deletions lib/experimental/blocks.php
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,10 @@ function wp_enqueue_block_view_script( $block_name, $args ) {


$gutenberg_experiments = get_option( 'gutenberg-experiments' );
if ( $gutenberg_experiments && array_key_exists( 'gutenberg-connections', $gutenberg_experiments ) ) {
if ( $gutenberg_experiments && (
array_key_exists( 'gutenberg-connections', $gutenberg_experiments ) ||
array_key_exists( 'gutenberg-pattern-partial-syncing', $gutenberg_experiments )
) ) {
/**
* Renders the block meta attributes.
*
Expand Down Expand Up @@ -132,9 +135,8 @@ function gutenberg_render_block_connections( $block_content, $block, $block_inst
continue;
}

// If the source value is not "meta_fields", skip it because the only supported
// connection source is meta (custom fields) for now.
if ( 'meta_fields' !== $attribute_value['source'] ) {
// Skip if the source value is not "meta_fields" or "pattern_attributes".
if ( 'meta_fields' !== $attribute_value['source'] && 'pattern_attributes' !== $attribute_value['source'] ) {
continue;
}

Expand All @@ -143,16 +145,28 @@ function gutenberg_render_block_connections( $block_content, $block, $block_inst
continue;
}

// If the attribute does not specify the name of the custom field, skip it.
if ( ! isset( $attribute_value['value'] ) ) {
continue;
if ( 'pattern_attributes' === $attribute_value['source'] ) {
if ( ! _wp_array_get( $block_instance->attributes, array( 'metadata', 'id' ), false ) ) {
continue;
}

$custom_value = $connection_sources[ $attribute_value['source'] ]( $block_instance );
} else {
// If the attribute does not specify the name of the custom field, skip it.
if ( ! isset( $attribute_value['value'] ) ) {
continue;
}

// Get the content from the connection source.
$custom_value = $connection_sources[ $attribute_value['source'] ](
$block_instance,
$attribute_value['value']
);
}

// Get the content from the connection source.
$custom_value = $connection_sources[ $attribute_value['source'] ](
$block_instance,
$attribute_value['value']
);
if ( false === $custom_value ) {
continue;
}

$tags = new WP_HTML_Tag_Processor( $block_content );
$found = $tags->next_tag(
Expand Down Expand Up @@ -181,5 +195,6 @@ function gutenberg_render_block_connections( $block_content, $block, $block_inst

return $block_content;
}

add_filter( 'render_block', 'gutenberg_render_block_connections', 10, 3 );
}
8 changes: 6 additions & 2 deletions lib/experimental/connection-sources/index.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,14 @@
*/

return array(
'name' => 'meta',
'meta_fields' => function ( $block_instance, $meta_field ) {
'name' => 'meta',
'meta_fields' => function ( $block_instance, $meta_field ) {
// We should probably also check if the meta field exists but for now it's okay because
// if it doesn't, `get_post_meta()` will just return an empty string.
return get_post_meta( $block_instance->context['postId'], $meta_field, true );
},
'pattern_attributes' => function ( $block_instance ) {
$block_id = $block_instance->attributes['metadata']['id'];
return _wp_array_get( $block_instance->context, array( 'pattern/overrides', $block_id ), false );
},
);
4 changes: 4 additions & 0 deletions lib/experimental/editor-settings.php
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,10 @@ function gutenberg_enable_experiments() {
if ( gutenberg_is_experiment_enabled( 'gutenberg-no-tinymce' ) ) {
wp_add_inline_script( 'wp-block-library', 'window.__experimentalDisableTinymce = true', 'before' );
}

if ( $gutenberg_experiments && array_key_exists( 'gutenberg-pattern-partial-syncing', $gutenberg_experiments ) ) {
wp_add_inline_script( 'wp-block-editor', 'window.__experimentalPatternPartialSyncing = true', 'before' );
}
}

add_action( 'admin_init', 'gutenberg_enable_experiments' );
Expand Down
12 changes: 12 additions & 0 deletions lib/experiments-page.php
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,18 @@ function gutenberg_initialize_experiments_settings() {
)
);

add_settings_field(
'gutenberg-pattern-partial-syncing',
__( 'Synced patterns partial syncing', 'gutenberg' ),
'gutenberg_display_experiment_field',
'gutenberg-experiments',
'gutenberg_experiments_section',
array(
'label' => __( 'Test partial syncing of patterns', 'gutenberg' ),
'id' => 'gutenberg-pattern-partial-syncing',
)
);

register_setting(
'gutenberg-experiments',
'gutenberg-experiments'
Expand Down
1 change: 1 addition & 0 deletions lib/load.php
Original file line number Diff line number Diff line change
Expand Up @@ -248,6 +248,7 @@ function () {
require __DIR__ . '/block-supports/shadow.php';
require __DIR__ . '/block-supports/background.php';
require __DIR__ . '/block-supports/behaviors.php';
require __DIR__ . '/block-supports/pattern.php';

// Data views.
require_once __DIR__ . '/experimental/data-views.php';
6 changes: 4 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

7 changes: 6 additions & 1 deletion packages/block-editor/src/hooks/custom-fields.js
Original file line number Diff line number Diff line change
Expand Up @@ -128,12 +128,17 @@ const withCustomFieldsControls = createHigherOrderComponent( ( BlockEdit ) => {
};
}, 'withCustomFieldsControls' );

if ( window.__experimentalConnections ) {
if (
window.__experimentalConnections ||
window.__experimentalPatternPartialSyncing
) {
addFilter(
'blocks.registerBlockType',
'core/editor/connections/attribute',
addAttribute
);
}
if ( window.__experimentalConnections ) {
addFilter(
'editor.BlockEdit',
'core/editor/connections/with-inspector-controls',
Expand Down
8 changes: 8 additions & 0 deletions packages/block-editor/src/store/private-actions.js
Original file line number Diff line number Diff line change
Expand Up @@ -290,3 +290,11 @@ export function deleteStyleOverride( id ) {
id,
};
}

export function syncDerivedBlockAttributes( clientId, attributes ) {
return {
type: 'SYNC_DERIVED_BLOCK_ATTRIBUTES',
clientIds: [ clientId ],
attributes,
};
}
8 changes: 8 additions & 0 deletions packages/block-editor/src/store/reducer.js
Original file line number Diff line number Diff line change
Expand Up @@ -283,6 +283,7 @@ const withBlockTree =
false
);
break;
case 'SYNC_DERIVED_BLOCK_ATTRIBUTES':
case 'UPDATE_BLOCK_ATTRIBUTES': {
newState.tree = new Map( newState.tree );
action.clientIds.forEach( ( clientId ) => {
Expand Down Expand Up @@ -456,6 +457,12 @@ function withPersistentBlockChange( reducer ) {
return ( state, action ) => {
let nextState = reducer( state, action );

if ( action.type === 'SYNC_DERIVED_BLOCK_ATTRIBUTES' ) {
return nextState.isPersistentChange
? { ...nextState, isPersistentChange: false }
: nextState;
}

const isExplicitPersistentChange =
action.type === 'MARK_LAST_CHANGE_AS_PERSISTENT' ||
markNextChangeAsNotPersistent;
Expand Down Expand Up @@ -860,6 +867,7 @@ export const blocks = pipe(
return newState;
}

case 'SYNC_DERIVED_BLOCK_ATTRIBUTES':
case 'UPDATE_BLOCK_ATTRIBUTES': {
// Avoid a state change if none of the block IDs are known.
if ( action.clientIds.every( ( id ) => ! state.get( id ) ) ) {
Expand Down
Loading

0 comments on commit 16eb009

Please sign in to comment.