Skip to content
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

Add hooks to modify theme.json structure #27722

Closed
wants to merge 5 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 37 additions & 12 deletions lib/class-wp-theme-json.php
Original file line number Diff line number Diff line change
Expand Up @@ -310,6 +310,7 @@ public function __construct( $contexts = array() ) {
return;
}

$schema = self::get_schema();
$metadata = $this->get_blocks_metadata();
foreach ( $contexts as $key => $context ) {
if ( ! isset( $metadata[ $key ] ) ) {
Expand All @@ -319,13 +320,14 @@ public function __construct( $contexts = array() ) {
}

// Filter out top-level keys that aren't valid according to the schema.
$context = array_intersect_key( $context, self::SCHEMA );
$context = array_intersect_key( $context, $schema );

// Process styles subtree.
$this->process_key( 'styles', $context, self::SCHEMA );
$this->process_key( 'styles', $context, $schema );
if ( isset( $context['styles'] ) ) {
$this->process_key( 'color', $context['styles'], self::SCHEMA['styles'] );
$this->process_key( 'typography', $context['styles'], self::SCHEMA['styles'] );
$this->process_key( 'color', $context['styles'], $schema['styles'] );
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @nosolosw,

With this PR we will be able to change the schema but this PR does not allow us to make the new properties output/do anything. When we add a new property to the schema, or a new preset how are we going to output the new styles?
E.g: after we move lib/class-wp-theme-json.php to the core if we want to add more functionalities to theme.json what is the strategy we should follow?
I guess a possibility would be to in plugin keeep lib/class-wp-theme-json.php and ignore/unregister the one shipped in the core?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey, while this is proof of concept it already works in the front-end and post editor. The remaining task would be to be able to make it work in the site editor, which seems a matter of being able to extend __EXPERIMENTAL_STYLE_PROPERTY client-side. What other blockers do you anticipate to make this work?

Also note that I don't think we should add hooks yet, as we're still consolidating the theme.json shape #27295 #28110

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm also happy to hear/discuss what use cases we anticipate to have to see if we may need a different approach. I've listed the ones I can think of at #27504

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

At first sight, it seems if we also add a filter to presets we cover the extensibility needs of class-wp-theme-json.php.
But to allow the Gutenberg plugin to continue to evolve and not need to standardize on an API/fitlers right after including theme.json into the core, we also have the opportunity of on the plugin simply unregistering what core is doing and making core class-wp-theme-json.php unused and simply use class-wp-theme-json.php from the plugin. Then updating core would be a matter of updating class-wp-theme-json.php to match the plugin. Similarly to what happens on server-side render blocks.

$this->process_key( 'spacing', $context['styles'], $schema['styles'] );
$this->process_key( 'typography', $context['styles'], $schema['styles'] );

if ( empty( $context['styles'] ) ) {
unset( $context['styles'] );
Expand All @@ -335,11 +337,11 @@ public function __construct( $contexts = array() ) {
}

// Process settings subtree.
$this->process_key( 'settings', $context, self::SCHEMA );
$this->process_key( 'settings', $context, $schema );
if ( isset( $context['settings'] ) ) {
$this->process_key( 'color', $context['settings'], self::SCHEMA['settings'] );
$this->process_key( 'spacing', $context['settings'], self::SCHEMA['settings'] );
$this->process_key( 'typography', $context['settings'], self::SCHEMA['settings'] );
$this->process_key( 'color', $context['settings'], $schema['settings'] );
$this->process_key( 'spacing', $context['settings'], $schema['settings'] );
$this->process_key( 'typography', $context['settings'], $schema['settings'] );

if ( empty( $context['settings'] ) ) {
unset( $context['settings'] );
Expand All @@ -350,6 +352,26 @@ public function __construct( $contexts = array() ) {
}
}

/**
* Returns the metadata for the properties that we support
* after having called the filter for 3rd party to hook into.
*
* @return array Properties metadata.
*/
private static function get_properties_metadata() {
return apply_filters( 'theme_json_properties_metadata', self::PROPERTIES_METADATA );
}

/**
* Returns the schema to be used to validate the contexts
* after having called the filter for 3rd party to hook into.
*
* @return array Schema.
*/
private static function get_schema() {
return apply_filters( 'theme_json_schema', self::SCHEMA );
}

/**
* Returns the metadata for each block.
*
Expand Down Expand Up @@ -398,8 +420,9 @@ private static function get_blocks_metadata() {
/*
* Extract block support keys that are related to the style properties.
*/
$block_supports = array();
foreach ( self::PROPERTIES_METADATA as $key => $metadata ) {
$block_supports = array();
$properties_metadata = self::get_properties_metadata();
foreach ( $properties_metadata as $key => $metadata ) {
if ( gutenberg_experimental_get( $block_type->supports, $metadata['support'] ) ) {
$block_supports[] = $key;
}
Expand Down Expand Up @@ -628,7 +651,8 @@ private static function compute_style_properties( &$declarations, $context, $con
return;
}

foreach ( self::PROPERTIES_METADATA as $name => $metadata ) {
$properties_metadata = self::get_properties_metadata();
foreach ( $properties_metadata as $name => $metadata ) {
if ( ! in_array( $name, $context_supports, true ) ) {
continue;
}
Expand Down Expand Up @@ -923,6 +947,7 @@ public function get_stylesheet( $type = 'all' ) {
*/
public function merge( $theme_json ) {
$incoming_data = $theme_json->get_raw_data();
$schema = self::get_schema();

foreach ( array_keys( $incoming_data ) as $context ) {
foreach ( array( 'settings', 'styles' ) as $subtree ) {
Expand All @@ -935,7 +960,7 @@ public function merge( $theme_json ) {
continue;
}

foreach ( array_keys( self::SCHEMA[ $subtree ] ) as $leaf ) {
foreach ( array_keys( $schema[ $subtree ] ) as $leaf ) {
if ( ! isset( $incoming_data[ $context ][ $subtree ][ $leaf ] ) ) {
continue;
}
Expand Down
7 changes: 7 additions & 0 deletions lib/experimental-default-theme.json
Original file line number Diff line number Diff line change
Expand Up @@ -174,5 +174,12 @@
"customRadius": true
}
}
},
"core/group": {
"styles": {
"box": {
"boxShadow": "10px 5px 5px red"
}
}
}
}
3 changes: 2 additions & 1 deletion packages/block-library/src/group/block.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,8 @@
},
"spacing": {
"padding": true
}
},
"__experimentalBoxShadow": true
},
"editorStyle": "wp-block-group-editor",
"style": "wp-block-group"
Expand Down