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

Make global styles data filterable #44015

Merged
merged 10 commits into from
Sep 13, 2022
60 changes: 60 additions & 0 deletions lib/compat/wordpress-6.1/class-wp-theme-json-data.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
<?php
/**
* API to update a theme.json structure.
*
* @package gutenberg
*/

/**
* Class to update with a theme.json structure.
*/
class WP_Theme_JSON_Data {
Copy link
Contributor

Choose a reason for hiding this comment

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

Apologies for commenting just after this PR merged, but should this line have a Gutenberg suffix, or have a class_exists check before defining it, so that we don't run into any issues when this is backported to core?

Copy link
Member

@gziolo gziolo Sep 13, 2022

Choose a reason for hiding this comment

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

Yes, it'd be best to call class_exists before requiring this file.

Copy link
Member

Choose a reason for hiding this comment

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

+1


/**
* Container of the data to update.
*
* @var WP_Theme_JSON
*/
private $theme_json = null;

/**
* The origin of the data: default, theme, user, etc.
*
* @var string
*/
private $origin = null;
Copy link
Contributor

Choose a reason for hiding this comment

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

This should probably default to '' (empty string) if the type is explicitly set as string.


/**
* Constructor.
*
* @param array $data Array following the theme.json specification.
* @param string $origin The origin of the data: default, theme, user.
*/
public function __construct( $data = array(), $origin = 'theme' ) {
$this->origin = $origin;
$this->theme_json = new WP_Theme_JSON_Gutenberg( $data, $this->origin );
}

/**
* Updates the theme.json with the the given data.
*
* @param array $new_data Array following the theme.json specification.
*
* @return WP_Theme_JSON_Data the modified data.
*/
public function update_with( $new_data ) {
$this->theme_json->merge( new WP_Theme_JSON_Gutenberg( $new_data, $this->origin ) );

Copy link
Contributor

Choose a reason for hiding this comment

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

Unnecessary line break here?

return $this;
}

/**
* Returns the underlying data.
*
* @return array
*/
public function get_data() {
return $this->theme_json->get_raw_data();
}

}
44 changes: 43 additions & 1 deletion lib/compat/wordpress-6.1/class-wp-theme-json-resolver-6-1.php
Original file line number Diff line number Diff line change
Expand Up @@ -56,8 +56,50 @@ public static function get_core_data() {

$config = static::read_json_file( __DIR__ . '/theme.json' );
$config = static::translate( $config );
static::$core = new WP_Theme_JSON_Gutenberg( $config, 'default' );
$config = apply_filters( 'global_styles_default', new WP_Theme_JSON_Data( $config, 'default' ) );
static::$core = new WP_Theme_JSON_Gutenberg( $config->get_data(), 'default' );
Comment on lines +59 to +60
Copy link
Member

@gziolo gziolo Sep 13, 2022

Choose a reason for hiding this comment

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

With WP filters we need to return the same data type as in the input, so that should be $data instead of config, so maybe the following would be more accurate:

$data = apply_filters( 'global_styles_default', new WP_Theme_JSON_Data( $config, 'default' ) );
static::$core = new WP_Theme_JSON_Gutenberg( $data->get_config(), 'default' );

I see the same pattern in other places. WP_Theme_JSON lists $theme_json in the constructor:

https://github.com/WordPress/wordpress-develop/blob/1746a68584dbadb8807a1520546725f8a1e572df/src/wp-includes/class-wp-theme-json.php#L431-L440

Maybe, we could rename that to $theme_config in WP core and here it would be $data->get_theme_config()?


return static::$core;
}

/**
* Returns the user's origin config.
*
* @return WP_Theme_JSON_Gutenberg Entity that holds styles for user data.
*/
public static function get_user_data() {
if ( null !== static::$user ) {
return static::$user;
}

$config = array();
$user_cpt = static::get_user_data_from_wp_global_styles( wp_get_theme() );

if ( array_key_exists( 'post_content', $user_cpt ) ) {
$decoded_data = json_decode( $user_cpt['post_content'], true );

$json_decoding_error = json_last_error();
if ( JSON_ERROR_NONE !== $json_decoding_error ) {
trigger_error( 'Error when decoding a theme.json schema for user data. ' . json_last_error_msg() );
$config = apply_filters( 'global_styles_user', new WP_Theme_JSON_Data( $config, 'custom' ) );
return new WP_Theme_JSON_Gutenberg( $config->get_data(), 'custom' );
}

// Very important to verify if the flag isGlobalStylesUserThemeJSON is true.
// If is not true the content was not escaped and is not safe.
if (
is_array( $decoded_data ) &&
isset( $decoded_data['isGlobalStylesUserThemeJSON'] ) &&
$decoded_data['isGlobalStylesUserThemeJSON']
) {
unset( $decoded_data['isGlobalStylesUserThemeJSON'] );
$config = $decoded_data;
}
}

$config = apply_filters( 'global_styles_user', new WP_Theme_JSON_Data( $config, 'custom' ) );
static::$user = new WP_Theme_JSON_Gutenberg( $config->get_data(), 'custom' );

return static::$user;
}
}
8 changes: 6 additions & 2 deletions lib/experimental/class-wp-theme-json-resolver-gutenberg.php
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,9 @@ public static function get_theme_data( $deprecated = array(), $settings = array(
$theme_json_data = static::read_json_file( static::get_file_path_from_theme( 'theme.json' ) );
$theme_json_data = static::translate( $theme_json_data, wp_get_theme()->get( 'TextDomain' ) );
$theme_json_data = gutenberg_add_registered_webfonts_to_theme_json( $theme_json_data );
static::$theme = new WP_Theme_JSON_Gutenberg( $theme_json_data );

$theme_json_data = apply_filters( 'global_styles_theme', new WP_Theme_JSON_Data( $theme_json_data, 'theme' ) );
static::$theme = new WP_Theme_JSON_Gutenberg( $theme_json_data->get_data() );

if ( wp_get_theme()->parent() ) {
// Get parent theme.json.
Expand Down Expand Up @@ -128,9 +130,11 @@ public static function get_block_data() {
}
}

$config = apply_filters( 'global_styles_blocks', new WP_Theme_JSON_Data( $config, 'core' ) );

// Core here means it's the lower level part of the styles chain.
// It can be a core or a third-party block.
return new WP_Theme_JSON_Gutenberg( $config, 'core' );
return new WP_Theme_JSON_Gutenberg( $config->get_data(), 'core' );
}

/**
Expand Down
1 change: 1 addition & 0 deletions lib/load.php
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ function gutenberg_is_experiment_enabled( $name ) {
require __DIR__ . '/compat/wordpress-6.1/block-editor-settings.php';
require __DIR__ . '/compat/wordpress-6.1/persisted-preferences.php';
require __DIR__ . '/compat/wordpress-6.1/get-global-styles-and-settings.php';
require __DIR__ . '/compat/wordpress-6.1/class-wp-theme-json-data.php';
require __DIR__ . '/compat/wordpress-6.1/class-wp-theme-json-6-1.php';
require __DIR__ . '/compat/wordpress-6.1/class-wp-theme-json-resolver-6-1.php';
require __DIR__ . '/compat/wordpress-6.1/block-template-utils.php';
Expand Down