Skip to content

Commit

Permalink
Try using the block connections api
Browse files Browse the repository at this point in the history
  • Loading branch information
aaronrobertshaw authored and kevin940726 committed Oct 20, 2023
1 parent c1a3d5a commit 5e02b61
Show file tree
Hide file tree
Showing 10 changed files with 311 additions and 53 deletions.
2 changes: 1 addition & 1 deletion docs/reference-guides/core-blocks.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ Create and save content to reuse across your site. Update the pattern, and the c
- **Name:** core/block
- **Category:** reusable
- **Supports:** ~~customClassName~~, ~~html~~, ~~inserter~~, ~~renaming~~
- **Attributes:** ref
- **Attributes:** dynamicContent, ref

## Button

Expand Down
31 changes: 31 additions & 0 deletions lib/block-supports/pattern.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
<?php
/**
* Pattern block support flag.
*
* @package gutenberg
*/

$gutenberg_experiments = get_option( 'gutenberg-experiments' );
if ( $gutenberg_experiments && array_key_exists( 'gutenberg-connections', $gutenberg_experiments ) ) {
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( 'dynamicContent', $block_type->uses_context, true ) ) {
$block_type->uses_context[] = 'dynamicContent';
}
}
}

// Register the block support.
WP_Block_Supports::get_instance()->register(
'pattern',
array(
'register_attribute' => 'gutenberg_register_pattern_support',
)
);
}
11 changes: 8 additions & 3 deletions lib/experimental/blocks.php
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,7 @@ function gutenberg_render_block_connections( $block_content, $block, $block_inst
$blocks_attributes_allowlist = array(
'core/paragraph' => array( 'content' ),
'core/image' => array( 'url' ),
'core/heading' => array( 'content' ),
);

// Whitelist of the block types that support block connections.
Expand Down Expand Up @@ -132,9 +133,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 @@ -154,6 +154,10 @@ function gutenberg_render_block_connections( $block_content, $block, $block_inst
$attribute_value['value']
);

if ( false === $custom_value ) {
continue;
}

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

return $block_content;
}

add_filter( 'render_block', 'gutenberg_render_block_connections', 10, 3 );
}
3 changes: 3 additions & 0 deletions lib/experimental/connection-sources/index.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,7 @@
// 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, $meta_field ) {
return _wp_array_get( $block_instance->context, array( 'dynamicContent', $meta_field ), false );
}
);
1 change: 1 addition & 0 deletions lib/load.php
Original file line number Diff line number Diff line change
Expand Up @@ -256,6 +256,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';
133 changes: 100 additions & 33 deletions packages/block-editor/src/hooks/custom-fields.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
/**
* WordPress dependencies
*/
import { useRegistry } from '@wordpress/data';
import { addFilter } from '@wordpress/hooks';
import { PanelBody, TextControl } from '@wordpress/components';
import { PanelBody, TextControl, SelectControl } from '@wordpress/components';
import { __, sprintf } from '@wordpress/i18n';
import { hasBlockSupport } from '@wordpress/blocks';
import { createHigherOrderComponent } from '@wordpress/compose';
Expand Down Expand Up @@ -55,7 +56,11 @@ const withInspectorControl = createHigherOrderComponent( ( BlockEdit ) => {

// Check if the current block is a paragraph or image block.
// Currently, only these two blocks are supported.
if ( ! [ 'core/paragraph', 'core/image' ].includes( props.name ) ) {
if (
! [ 'core/paragraph', 'core/image', 'core/heading' ].includes(
props.name
)
) {
return <BlockEdit { ...props } />;
}

Expand All @@ -65,6 +70,41 @@ const withInspectorControl = createHigherOrderComponent( ( BlockEdit ) => {
let attributeName;
if ( props.name === 'core/paragraph' ) attributeName = 'content';
if ( props.name === 'core/image' ) attributeName = 'url';
if ( props.name === 'core/heading' ) attributeName = 'content';

const connectionSource =
props.attributes?.connections?.attributes?.[ attributeName ]
?.source || '';
const connectionValue =
props.attributes?.connections?.attributes?.[ attributeName ]
?.value || '';

function updateConnections( source, value ) {
if ( value === '' ) {
props.setAttributes( {
connections: undefined,
placeholder: undefined,
} );
} else {
props.setAttributes( {
connections: {
attributes: {
// The attributeName will be either `content` or `url`.
[ attributeName ]: {
// Source will be variable, could be post_meta, user_meta, term_meta, etc.
// Could even be a custom source like a social media attribute.
source,
value,
},
},
},
placeholder: sprintf(
'This content will be replaced on the frontend by the value of "%s" custom field.',
value
),
} );
}
}

if ( hasCustomFieldsSupport && props.isSelected ) {
return (
Expand All @@ -76,42 +116,40 @@ const withInspectorControl = createHigherOrderComponent( ( BlockEdit ) => {
title={ __( 'Connections' ) }
initialOpen={ true }
>
<SelectControl
label={ __( 'Source' ) }
value={ connectionSource }
options={ [
{
label: __( 'None' ),
value: '',
},
{
label: __( 'Meta fields' ),
value: 'meta_fields',
},
{
label: __( 'Pattern attributes' ),
value: 'pattern_attributes',
},
] }
onChange={ ( nextSource ) => {
updateConnections(
nextSource,
connectionValue
);
} }
/>
<TextControl
__nextHasNoMarginBottom
autoComplete="off"
label={ __( 'Custom field meta_key' ) }
value={
props.attributes?.connections
?.attributes?.[ attributeName ]
?.value || ''
}
value={ connectionValue }
onChange={ ( nextValue ) => {
if ( nextValue === '' ) {
props.setAttributes( {
connections: undefined,
[ attributeName ]: undefined,
placeholder: undefined,
} );
} else {
props.setAttributes( {
connections: {
attributes: {
// The attributeName will be either `content` or `url`.
[ attributeName ]: {
// Source will be variable, could be post_meta, user_meta, term_meta, etc.
// Could even be a custom source like a social media attribute.
source: 'meta_fields',
value: nextValue,
},
},
},
[ attributeName ]: undefined,
placeholder: sprintf(
'This content will be replaced on the frontend by the value of "%s" custom field.',
nextValue
),
} );
}
updateConnections(
connectionSource,
nextValue
);
} }
/>
</PanelBody>
Expand All @@ -125,6 +163,30 @@ const withInspectorControl = createHigherOrderComponent( ( BlockEdit ) => {
};
}, 'withInspectorControl' );

const createEditFunctionWithPatternSource = () =>
createHigherOrderComponent(
( BlockEdit ) =>
( { attributes, ...props } ) => {
const registry = useRegistry();
const sourceAttributes =
registry._selectAttributes?.( {
clientId: props.clientId,
name: props.name,
attributes,
} ) ?? attributes;

return (
<BlockEdit { ...props } attributes={ sourceAttributes } />
);
}
);

function shimAttributeSource( settings ) {
settings.edit = createEditFunctionWithPatternSource()( settings.edit );

return settings;
}

if ( window.__experimentalConnections ) {
addFilter(
'blocks.registerBlockType',
Expand All @@ -136,4 +198,9 @@ if ( window.__experimentalConnections ) {
'core/connections/with-inspector-control',
withInspectorControl
);
addFilter(
'blocks.registerBlockType',
'core/pattern/shimAttributeSource',
shimAttributeSource
);
}
3 changes: 3 additions & 0 deletions packages/block-library/src/block/block.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@
"keywords": [ "reusable" ],
"textdomain": "default",
"attributes": {
"dynamicContent": {
"type": "object"
},
"ref": {
"type": "number"
}
Expand Down
Loading

0 comments on commit 5e02b61

Please sign in to comment.