-
Notifications
You must be signed in to change notification settings - Fork 4.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Introduce block metadata files for dynamic blocks #14238
Changes from all commits
5c05cd8
7519ab6
33a6265
625c7e7
cff3053
981e136
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
<?php | ||
/** | ||
* Overrides all core blocks. | ||
* | ||
* @package gutenberg | ||
*/ | ||
|
||
/** | ||
* Registers block type from metadata file. | ||
* | ||
* @param string $file Path to the translation file to load. | ||
*/ | ||
function gutenberg_register_block_type_from_metadata( $file ) { | ||
$metadata = json_decode( file_get_contents( $file ), true ); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Technically this implementation seems to be fine for a file which doesn't exist ( There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes, it should use more checks with proper error messages. I will make those checks more granular 👍 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Also make sure to use There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Usages of There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm sure this part needs more work if we decide to introduce such API for reading JSON file. This PR is more exploratory. I expect it's going to be divided in more solid smaller PRs which will implement more granular features. If someone wants to work on this part, we can find ways to split this task :) |
||
if ( empty( $metadata['name'] ) || empty( $metadata['title'] ) || empty( $metadata['category'] ) ) { | ||
$message = __( 'Required block types must be provided.' ); | ||
_doing_it_wrong( __FUNCTION__, $message, '5.2.0' ); | ||
return; | ||
} | ||
$block_name = $metadata['name']; | ||
$settings = array( | ||
'title' => $metadata['title'], | ||
'category' => $metadata['category'], | ||
); | ||
foreach( array( 'description', 'keywords', 'attributes', 'supports' ) as $field_name ) { | ||
if ( ! empty( $metadata[ $field_name ] ) ) { | ||
$settings[ $field_name ] = $metadata[ $field_name ]; | ||
} | ||
} | ||
if ( ! empty( $metadata['renderCallback'] ) ) { | ||
$render_callback_file = dirname( $file ) . '/' . $metadata['renderCallback']; | ||
if ( file_exists( $render_callback_file ) ) { | ||
require $render_callback_file; | ||
$settings['render_callback'] = 'gutenberg_render_block_' . str_replace( array( '/', '-' ), '_', $block_name ); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think it requires anonymous functions (PHP 5.4.0+), but I wonder if rather than relying on a specific naming convention for functions, we use the file returns semantics: https://gist.github.com/aduth/ef27bfaae19a9959a263f1600b37c71d There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I didn't think too much about so far. I definitely would prefer to avoid using the specific conventions for naming functions. Another solution is to use a function which registers such callbacks as follows: register_block_render_callback( 'core/block', 'render_block_core_block' ); which would be placed inside a PHP file which would also contain the definition. We would also have to change the way such file is required. Maybe we load metadata definitions in one go. Then at the time, we are about to process There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The A yet-other idea is treating it more like a template file, expecting it to output HTML directly. I'm not sure this is a good way to go though, and it's not obvious how the template would read from attributes (unless they were just some There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Some of those existing render callbacks reference other custom functions so this might get tricky. I don't know, maybe this would work. I'd love to see some thoughts from developers better familiar with patterns used in other parts of WordPress core like @pento or @danielbachhuber. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm not 100% sure I follow. Why is Probably the best example of prior art to follow is |
||
} | ||
} | ||
$registry = WP_Block_Type_Registry::get_instance(); | ||
if ( $registry->is_registered( $block_name ) ) { | ||
$registry->unregister( $block_name ); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I guess this is part of it "overriding" ? Not something to be included with a final implementation. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Definitely, it was only added to make it work until it's fixed in |
||
} | ||
register_block_type( $block_name, $settings ); | ||
} | ||
|
||
function gutenberg_override_core_blocks() { | ||
$block_types = array( | ||
'archives', | ||
'block', | ||
'calendar', | ||
'categories', | ||
'latest-comments', | ||
'latest-posts', | ||
'rss', | ||
'search', | ||
'shortcode', | ||
'tag-cloud' | ||
); | ||
|
||
$file_format = dirname( dirname( __FILE__ ) ) . '/packages/block-library/src/%s/block.json'; | ||
foreach ( $block_types as $name ) { | ||
gutenberg_register_block_type_from_metadata( sprintf( $file_format, $name ) ); | ||
} | ||
} | ||
|
||
add_action( 'init', 'gutenberg_override_core_blocks' ); |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
{ | ||
"name": "core/archives", | ||
"title": "Archives", | ||
"category": "widgets", | ||
"icon": { | ||
"src": "icon.js" | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This one kind of sticks out as far as being inconsistent with other file references like in In all, I think it's okay, though I also wonder on a few variations:
Was looking at some similar specifications, where There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
It is reserved for the slug at the moment, which aligns with how you can register block's icon as of today. I would be happy to use the file name as a shortcut but then we need to figure out how to provide the slug differently. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Oh right. That makes sense. I guess the other option is to inspect the shape of the string to see if it "appears" as a file path (e.g. has file extension, or starts with |
||
}, | ||
"description": "Display a monthly archive of your posts.", | ||
"attributes": { | ||
"align": { | ||
"type": "string" | ||
}, | ||
"className": { | ||
"type": "string" | ||
}, | ||
"displayAsDropdown": { | ||
"type": "boolean", | ||
"default": false | ||
}, | ||
"showPostCounts": { | ||
"type": "boolean", | ||
"default": false | ||
} | ||
}, | ||
"edit": "edit.js", | ||
"supports": { | ||
"align": true, | ||
"alignWide": false, | ||
"html": false | ||
}, | ||
"renderCallback": "index.php" | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -14,13 +14,11 @@ import { __ } from '@wordpress/i18n'; | |
*/ | ||
import { | ||
InspectorControls, | ||
BlockAlignmentToolbar, | ||
BlockControls, | ||
ServerSideRender, | ||
} from '@wordpress/editor'; | ||
|
||
export default function ArchivesEdit( { attributes, setAttributes } ) { | ||
const { align, showPostCounts, displayAsDropdown } = attributes; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is this something we could extract separately? Can we not implement supports.align for server-registered blocks currently? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes, I will tackle it and some other preparatory tasks in their own PRs. I'm using this PR to identify all work that is required to get us closer to have the ability to register blocks with metadata. However, I'm discovering that we have some issues with the existing blocks. |
||
const { showPostCounts, displayAsDropdown } = attributes; | ||
|
||
return ( | ||
<Fragment> | ||
|
@@ -38,15 +36,6 @@ export default function ArchivesEdit( { attributes, setAttributes } ) { | |
/> | ||
</PanelBody> | ||
</InspectorControls> | ||
<BlockControls> | ||
<BlockAlignmentToolbar | ||
value={ align } | ||
onChange={ ( nextAlign ) => { | ||
setAttributes( { align: nextAlign } ); | ||
} } | ||
controls={ [ 'left', 'center', 'right' ] } | ||
/> | ||
</BlockControls> | ||
<Disabled> | ||
<ServerSideRender block="core/archives" attributes={ attributes } /> | ||
</Disabled> | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
/** | ||
* WordPress dependencies | ||
*/ | ||
import { G, Path, SVG } from '@wordpress/components'; | ||
|
||
export default ( | ||
<SVG viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><Path fill="none" d="M0 0h24v24H0V0z" /><G><Path d="M7 11h2v2H7v-2zm14-5v14c0 1.1-.9 2-2 2H5c-1.11 0-2-.9-2-2l.01-14c0-1.1.88-2 1.99-2h1V2h2v2h8V2h2v2h1c1.1 0 2 .9 2 2zM5 8h14V6H5v2zm14 12V10H5v10h14zm-4-7h2v-2h-2v2zm-4 0h2v-2h-2v2z" /></G></SVG> | ||
); |
This file was deleted.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
{ | ||
"name": "core/block", | ||
"title": "Reusable Block", | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Have you thought about how translation will work? From #13693:
A challenge here is in knowing the textdomain to use if we were to call There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think this is the biggest issue I identified so far. I still don't have a good idea of how this could work. I was also wondering if we can dynamically wrap with i18n functions when loading metadata. E.g.: $settings = array(
'title' => __( $metadata['title'], $metadata['textdomain'] ),
); /cc @swissspidy |
||
"category": "reusable", | ||
"description": "Create content, and save it for you and other contributors to reuse across your site. Update the block, and the changes apply everywhere it’s used.", | ||
"attributes": { | ||
"ref": { | ||
"type": "number" | ||
} | ||
}, | ||
"edit": "edit.js", | ||
"supports": { | ||
"customClassName": false, | ||
"html": false, | ||
"inserter": false | ||
}, | ||
"renderCallback": "index.php" | ||
} |
This file was deleted.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
{ | ||
"name": "core/calendar", | ||
"title": "Calendar", | ||
"category": "widgets", | ||
"icon": { | ||
"slug": "calendar" | ||
}, | ||
"description": "A calendar of your site’s posts.", | ||
"keywords": [ "posts", "archive" ], | ||
"attributes": { | ||
"align": { | ||
"type": "string" | ||
}, | ||
"className": { | ||
"type": "string" | ||
}, | ||
"month": { | ||
"type": "integer" | ||
}, | ||
"year": { | ||
"type": "integer" | ||
} | ||
}, | ||
"edit": "edit.js", | ||
"supports": { | ||
"align": true | ||
}, | ||
"renderCallback": "index.php" | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this something we see becoming a part of core implementation? I think for any new functions like this, I'm wondering if we should bother with the namespacing convention, since it was a pain point for deprecating Gutenberg-specific functions toward and after WordPress 5.0.
Wondering if instead it's enough to just
if ( ! function_exists( 'register_block_type_from_metadata' ) ) {
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I had it named this way initially. I wasn't sure what the process looks like so I opted for
gutenberg_
prefixed version. I'm fine with updating it as suggested as soon as we figure out how this definition should look and work like.