diff --git a/src/wp-includes/class-wp-theme-json-resolver.php b/src/wp-includes/class-wp-theme-json-resolver.php index 38df6cebf1e82..56d398aacbfe1 100644 --- a/src/wp-includes/class-wp-theme-json-resolver.php +++ b/src/wp-includes/class-wp-theme-json-resolver.php @@ -25,7 +25,7 @@ class WP_Theme_JSON_Resolver { * @since 5.8.0 * @var WP_Theme_JSON */ - private static $core = null; + protected static $core = null; /** * Container for data coming from the theme. @@ -33,7 +33,7 @@ class WP_Theme_JSON_Resolver { * @since 5.8.0 * @var WP_Theme_JSON */ - private static $theme = null; + protected static $theme = null; /** * Whether or not the theme supports theme.json. @@ -41,7 +41,7 @@ class WP_Theme_JSON_Resolver { * @since 5.8.0 * @var bool */ - private static $theme_has_support = null; + protected static $theme_has_support = null; /** * Container for data coming from the user. @@ -49,7 +49,7 @@ class WP_Theme_JSON_Resolver { * @since 5.9.0 * @var WP_Theme_JSON */ - private static $user = null; + protected static $user = null; /** * Stores the ID of the custom post type @@ -58,7 +58,7 @@ class WP_Theme_JSON_Resolver { * @since 5.9.0 * @var int */ - private static $user_custom_post_type_id = null; + protected static $user_custom_post_type_id = null; /** * Container to keep loaded i18n schema for `theme.json`. @@ -67,7 +67,7 @@ class WP_Theme_JSON_Resolver { * @since 5.9.0 Renamed from `$theme_json_i18n` to `$i18n_schema`. * @var array */ - private static $i18n_schema = null; + protected static $i18n_schema = null; /** * Processes a file that adheres to the theme.json schema @@ -78,7 +78,7 @@ class WP_Theme_JSON_Resolver { * @param string $file_path Path to file. Empty if no file. * @return array Contents that adhere to the theme.json schema. */ - private static function read_json_file( $file_path ) { + protected static function read_json_file( $file_path ) { $config = array(); if ( $file_path ) { $decoded_file = wp_json_file_decode( $file_path, array( 'associative' => true ) ); @@ -113,13 +113,13 @@ public static function get_fields_to_translate() { * Default 'default'. * @return array Returns the modified $theme_json_structure. */ - private static function translate( $theme_json, $domain = 'default' ) { - if ( null === self::$i18n_schema ) { - $i18n_schema = wp_json_file_decode( __DIR__ . '/theme-i18n.json' ); - self::$i18n_schema = null === $i18n_schema ? array() : $i18n_schema; + protected static function translate( $theme_json, $domain = 'default' ) { + if ( null === static::$i18n_schema ) { + $i18n_schema = wp_json_file_decode( __DIR__ . '/theme-i18n.json' ); + static::$i18n_schema = null === $i18n_schema ? array() : $i18n_schema; } - return translate_settings_using_i18n_schema( self::$i18n_schema, $theme_json, $domain ); + return translate_settings_using_i18n_schema( static::$i18n_schema, $theme_json, $domain ); } /** @@ -130,15 +130,15 @@ private static function translate( $theme_json, $domain = 'default' ) { * @return WP_Theme_JSON Entity that holds core data. */ public static function get_core_data() { - if ( null !== self::$core ) { - return self::$core; + if ( null !== static::$core ) { + return static::$core; } - $config = self::read_json_file( __DIR__ . '/theme.json' ); - $config = self::translate( $config ); - self::$core = new WP_Theme_JSON( $config, 'default' ); + $config = static::read_json_file( __DIR__ . '/theme.json' ); + $config = static::translate( $config ); + static::$core = new WP_Theme_JSON( $config, 'default' ); - return self::$core; + return static::$core; } /** @@ -159,21 +159,21 @@ public static function get_theme_data( $deprecated = array() ) { if ( ! empty( $deprecated ) ) { _deprecated_argument( __METHOD__, '5.9.0' ); } - if ( null === self::$theme ) { - $theme_json_data = self::read_json_file( self::get_file_path_from_theme( 'theme.json' ) ); - $theme_json_data = self::translate( $theme_json_data, wp_get_theme()->get( 'TextDomain' ) ); - self::$theme = new WP_Theme_JSON( $theme_json_data ); + if ( null === static::$theme ) { + $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' ) ); + static::$theme = new WP_Theme_JSON( $theme_json_data ); if ( wp_get_theme()->parent() ) { // Get parent theme.json. - $parent_theme_json_data = self::read_json_file( self::get_file_path_from_theme( 'theme.json', true ) ); - $parent_theme_json_data = self::translate( $parent_theme_json_data, wp_get_theme()->parent()->get( 'TextDomain' ) ); + $parent_theme_json_data = static::read_json_file( static::get_file_path_from_theme( 'theme.json', true ) ); + $parent_theme_json_data = static::translate( $parent_theme_json_data, wp_get_theme()->parent()->get( 'TextDomain' ) ); $parent_theme = new WP_Theme_JSON( $parent_theme_json_data ); // Merge the child theme.json into the parent theme.json. // The child theme takes precedence over the parent. - $parent_theme->merge( self::$theme ); - self::$theme = $parent_theme; + $parent_theme->merge( static::$theme ); + static::$theme = $parent_theme; } } @@ -181,10 +181,10 @@ public static function get_theme_data( $deprecated = array() ) { * We want the presets and settings declared in theme.json * to override the ones declared via theme supports. * So we take theme supports, transform it to theme.json shape - * and merge the self::$theme upon that. + * and merge the static::$theme upon that. */ $theme_support_data = WP_Theme_JSON::get_from_editor_settings( get_default_block_editor_settings() ); - if ( ! self::theme_has_support() ) { + if ( ! static::theme_has_support() ) { if ( ! isset( $theme_support_data['settings']['color'] ) ) { $theme_support_data['settings']['color'] = array(); } @@ -210,7 +210,7 @@ public static function get_theme_data( $deprecated = array() ) { $theme_support_data['settings']['color']['defaultGradients'] = $default_gradients; } $with_theme_supports = new WP_Theme_JSON( $theme_support_data ); - $with_theme_supports->merge( self::$theme ); + $with_theme_supports->merge( static::$theme ); return $with_theme_supports; } @@ -299,12 +299,12 @@ public static function get_user_data_from_wp_global_styles( $theme, $create_post * @return WP_Theme_JSON Entity that holds styles for user data. */ public static function get_user_data() { - if ( null !== self::$user ) { - return self::$user; + if ( null !== static::$user ) { + return static::$user; } $config = array(); - $user_cpt = self::get_user_data_from_wp_global_styles( wp_get_theme() ); + $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 ); @@ -326,9 +326,9 @@ public static function get_user_data() { $config = $decoded_data; } } - self::$user = new WP_Theme_JSON( $config, 'custom' ); + static::$user = new WP_Theme_JSON( $config, 'custom' ); - return self::$user; + return static::$user; } /** @@ -363,11 +363,11 @@ public static function get_merged_data( $origin = 'custom' ) { } $result = new WP_Theme_JSON(); - $result->merge( self::get_core_data() ); - $result->merge( self::get_theme_data() ); + $result->merge( static::get_core_data() ); + $result->merge( static::get_theme_data() ); if ( 'custom' === $origin ) { - $result->merge( self::get_user_data() ); + $result->merge( static::get_user_data() ); } return $result; @@ -382,17 +382,17 @@ public static function get_merged_data( $origin = 'custom' ) { * @return integer|null */ public static function get_user_global_styles_post_id() { - if ( null !== self::$user_custom_post_type_id ) { - return self::$user_custom_post_type_id; + if ( null !== static::$user_custom_post_type_id ) { + return static::$user_custom_post_type_id; } - $user_cpt = self::get_user_data_from_wp_global_styles( wp_get_theme(), true ); + $user_cpt = static::get_user_data_from_wp_global_styles( wp_get_theme(), true ); if ( array_key_exists( 'ID', $user_cpt ) ) { - self::$user_custom_post_type_id = $user_cpt['ID']; + static::$user_custom_post_type_id = $user_cpt['ID']; } - return self::$user_custom_post_type_id; + return static::$user_custom_post_type_id; } /** @@ -404,14 +404,14 @@ public static function get_user_global_styles_post_id() { * @return bool */ public static function theme_has_support() { - if ( ! isset( self::$theme_has_support ) ) { - self::$theme_has_support = ( - is_readable( self::get_file_path_from_theme( 'theme.json' ) ) || - is_readable( self::get_file_path_from_theme( 'theme.json', true ) ) + if ( ! isset( static::$theme_has_support ) ) { + static::$theme_has_support = ( + is_readable( static::get_file_path_from_theme( 'theme.json' ) ) || + is_readable( static::get_file_path_from_theme( 'theme.json', true ) ) ); } - return self::$theme_has_support; + return static::$theme_has_support; } /** @@ -426,7 +426,7 @@ public static function theme_has_support() { * @param bool $template Optional. Use template theme directory. Default false. * @return string The whole file path or empty if the file doesn't exist. */ - private static function get_file_path_from_theme( $file_name, $template = false ) { + protected static function get_file_path_from_theme( $file_name, $template = false ) { $path = $template ? get_template_directory() : get_stylesheet_directory(); $candidate = $path . '/' . $file_name; @@ -441,12 +441,12 @@ private static function get_file_path_from_theme( $file_name, $template = false * and `$i18n_schema` variables to reset. */ public static function clean_cached_data() { - self::$core = null; - self::$theme = null; - self::$user = null; - self::$user_custom_post_type_id = null; - self::$theme_has_support = null; - self::$i18n_schema = null; + static::$core = null; + static::$theme = null; + static::$user = null; + static::$user_custom_post_type_id = null; + static::$theme_has_support = null; + static::$i18n_schema = null; } } diff --git a/src/wp-includes/class-wp-theme-json.php b/src/wp-includes/class-wp-theme-json.php index 5c643cf138a67..7aa653948fa98 100644 --- a/src/wp-includes/class-wp-theme-json.php +++ b/src/wp-includes/class-wp-theme-json.php @@ -24,7 +24,7 @@ class WP_Theme_JSON { * @since 5.8.0 * @var array */ - private $theme_json = null; + protected $theme_json = null; /** * Holds block metadata extracted from block.json @@ -34,7 +34,7 @@ class WP_Theme_JSON { * @since 5.8.0 * @var array */ - private static $blocks_metadata = null; + protected static $blocks_metadata = null; /** * The CSS selector for the top-level styles. @@ -366,20 +366,20 @@ class WP_Theme_JSON { * One of 'default', 'theme', or 'custom'. Default 'theme'. */ public function __construct( $theme_json = array(), $origin = 'theme' ) { - if ( ! in_array( $origin, self::VALID_ORIGINS, true ) ) { + if ( ! in_array( $origin, static::VALID_ORIGINS, true ) ) { $origin = 'theme'; } $this->theme_json = WP_Theme_JSON_Schema::migrate( $theme_json ); - $valid_block_names = array_keys( self::get_blocks_metadata() ); - $valid_element_names = array_keys( self::ELEMENTS ); - $theme_json = self::sanitize( $this->theme_json, $valid_block_names, $valid_element_names ); - $this->theme_json = self::maybe_opt_in_into_settings( $theme_json ); + $valid_block_names = array_keys( static::get_blocks_metadata() ); + $valid_element_names = array_keys( static::ELEMENTS ); + $theme_json = static::sanitize( $this->theme_json, $valid_block_names, $valid_element_names ); + $this->theme_json = static::maybe_opt_in_into_settings( $theme_json ); // Internally, presets are keyed by origin. - $nodes = self::get_setting_nodes( $this->theme_json ); + $nodes = static::get_setting_nodes( $this->theme_json ); foreach ( $nodes as $node ) { - foreach ( self::PRESETS_METADATA as $preset_metadata ) { + foreach ( static::PRESETS_METADATA as $preset_metadata ) { $path = array_merge( $node['path'], $preset_metadata['path'] ); $preset = _wp_array_get( $this->theme_json, $path, null ); if ( null !== $preset ) { @@ -400,20 +400,20 @@ public function __construct( $theme_json = array(), $origin = 'theme' ) { * @param array $theme_json A theme.json structure to modify. * @return array The modified theme.json structure. */ - private static function maybe_opt_in_into_settings( $theme_json ) { + protected static function maybe_opt_in_into_settings( $theme_json ) { $new_theme_json = $theme_json; if ( isset( $new_theme_json['settings']['appearanceTools'] ) && true === $new_theme_json['settings']['appearanceTools'] ) { - self::do_opt_in_into_settings( $new_theme_json['settings'] ); + static::do_opt_in_into_settings( $new_theme_json['settings'] ); } if ( isset( $new_theme_json['settings']['blocks'] ) && is_array( $new_theme_json['settings']['blocks'] ) ) { foreach ( $new_theme_json['settings']['blocks'] as &$block ) { if ( isset( $block['appearanceTools'] ) && ( true === $block['appearanceTools'] ) ) { - self::do_opt_in_into_settings( $block ); + static::do_opt_in_into_settings( $block ); } } } @@ -428,7 +428,7 @@ private static function maybe_opt_in_into_settings( $theme_json ) { * * @param array $context The context to which the settings belong. */ - private static function do_opt_in_into_settings( &$context ) { + protected static function do_opt_in_into_settings( &$context ) { $to_opt_in = array( array( 'border', 'color' ), array( 'border', 'radius' ), @@ -463,18 +463,18 @@ private static function do_opt_in_into_settings( &$context ) { * @param array $valid_element_names List of valid element names. * @return array The sanitized output. */ - private static function sanitize( $input, $valid_block_names, $valid_element_names ) { + protected static function sanitize( $input, $valid_block_names, $valid_element_names ) { $output = array(); if ( ! is_array( $input ) ) { return $output; } - $output = array_intersect_key( $input, array_flip( self::VALID_TOP_LEVEL_KEYS ) ); + $output = array_intersect_key( $input, array_flip( static::VALID_TOP_LEVEL_KEYS ) ); // Some styles are only meant to be available at the top-level (e.g.: blockGap), // hence, the schema for blocks & elements should not have them. - $styles_non_top_level = self::VALID_STYLES; + $styles_non_top_level = static::VALID_STYLES; foreach ( array_keys( $styles_non_top_level ) as $section ) { foreach ( array_keys( $styles_non_top_level[ $section ] ) as $prop ) { if ( 'top' === $styles_non_top_level[ $section ][ $prop ] ) { @@ -492,14 +492,14 @@ private static function sanitize( $input, $valid_block_names, $valid_element_nam $schema_styles_blocks = array(); $schema_settings_blocks = array(); foreach ( $valid_block_names as $block ) { - $schema_settings_blocks[ $block ] = self::VALID_SETTINGS; + $schema_settings_blocks[ $block ] = static::VALID_SETTINGS; $schema_styles_blocks[ $block ] = $styles_non_top_level; $schema_styles_blocks[ $block ]['elements'] = $schema_styles_elements; } - $schema['styles'] = self::VALID_STYLES; + $schema['styles'] = static::VALID_STYLES; $schema['styles']['blocks'] = $schema_styles_blocks; $schema['styles']['elements'] = $schema_styles_elements; - $schema['settings'] = self::VALID_SETTINGS; + $schema['settings'] = static::VALID_SETTINGS; $schema['settings']['blocks'] = $schema_settings_blocks; // Remove anything that's not present in the schema. @@ -513,7 +513,7 @@ private static function sanitize( $input, $valid_block_names, $valid_element_nam continue; } - $result = self::remove_keys_not_in_schema( $input[ $subtree ], $schema[ $subtree ] ); + $result = static::remove_keys_not_in_schema( $input[ $subtree ], $schema[ $subtree ] ); if ( empty( $result ) ) { unset( $output[ $subtree ] ); @@ -554,12 +554,12 @@ private static function sanitize( $input, $valid_block_names, $valid_element_nam * * @return array Block metadata. */ - private static function get_blocks_metadata() { - if ( null !== self::$blocks_metadata ) { - return self::$blocks_metadata; + protected static function get_blocks_metadata() { + if ( null !== static::$blocks_metadata ) { + return static::$blocks_metadata; } - self::$blocks_metadata = array(); + static::$blocks_metadata = array(); $registry = WP_Block_Type_Registry::get_instance(); $blocks = $registry->get_all_registered(); @@ -568,32 +568,32 @@ private static function get_blocks_metadata() { isset( $block_type->supports['__experimentalSelector'] ) && is_string( $block_type->supports['__experimentalSelector'] ) ) { - self::$blocks_metadata[ $block_name ]['selector'] = $block_type->supports['__experimentalSelector']; + static::$blocks_metadata[ $block_name ]['selector'] = $block_type->supports['__experimentalSelector']; } else { - self::$blocks_metadata[ $block_name ]['selector'] = '.wp-block-' . str_replace( '/', '-', str_replace( 'core/', '', $block_name ) ); + static::$blocks_metadata[ $block_name ]['selector'] = '.wp-block-' . str_replace( '/', '-', str_replace( 'core/', '', $block_name ) ); } if ( isset( $block_type->supports['color']['__experimentalDuotone'] ) && is_string( $block_type->supports['color']['__experimentalDuotone'] ) ) { - self::$blocks_metadata[ $block_name ]['duotone'] = $block_type->supports['color']['__experimentalDuotone']; + static::$blocks_metadata[ $block_name ]['duotone'] = $block_type->supports['color']['__experimentalDuotone']; } // Assign defaults, then overwrite those that the block sets by itself. // If the block selector is compounded, will append the element to each // individual block selector. - $block_selectors = explode( ',', self::$blocks_metadata[ $block_name ]['selector'] ); - foreach ( self::ELEMENTS as $el_name => $el_selector ) { + $block_selectors = explode( ',', static::$blocks_metadata[ $block_name ]['selector'] ); + foreach ( static::ELEMENTS as $el_name => $el_selector ) { $element_selector = array(); foreach ( $block_selectors as $selector ) { $element_selector[] = $selector . ' ' . $el_selector; } - self::$blocks_metadata[ $block_name ]['elements'][ $el_name ] = implode( ',', $element_selector ); + static::$blocks_metadata[ $block_name ]['elements'][ $el_name ] = implode( ',', $element_selector ); } } - return self::$blocks_metadata; + return static::$blocks_metadata; } /** @@ -607,7 +607,7 @@ private static function get_blocks_metadata() { * @param array $schema Schema to adhere to. * @return array Returns the modified $tree. */ - private static function remove_keys_not_in_schema( $tree, $schema ) { + protected static function remove_keys_not_in_schema( $tree, $schema ) { $tree = array_intersect_key( $tree, $schema ); foreach ( $schema as $key => $data ) { @@ -616,7 +616,7 @@ private static function remove_keys_not_in_schema( $tree, $schema ) { } if ( is_array( $schema[ $key ] ) && is_array( $tree[ $key ] ) ) { - $tree[ $key ] = self::remove_keys_not_in_schema( $tree[ $key ], $schema[ $key ] ); + $tree[ $key ] = static::remove_keys_not_in_schema( $tree[ $key ], $schema[ $key ] ); if ( empty( $tree[ $key ] ) ) { unset( $tree[ $key ] ); @@ -670,10 +670,14 @@ public function get_settings() { * - `variables`: only the CSS Custom Properties for presets & custom ones. * - `styles`: only the styles section in theme.json. * - `presets`: only the classes for the presets. - * @param array $origins A list of origins to include. By default it includes `self::VALID_ORIGINS`. + * @param array $origins A list of origins to include. By default it includes VALID_ORIGINS. * @return string Stylesheet. */ - public function get_stylesheet( $types = array( 'variables', 'styles', 'presets' ), $origins = self::VALID_ORIGINS ) { + public function get_stylesheet( $types = array( 'variables', 'styles', 'presets' ), $origins = null ) { + if ( null === $origins ) { + $origins = static::VALID_ORIGINS; + } + if ( is_string( $types ) ) { // Dispatch error and map old arguments to new ones. _deprecated_argument( __FUNCTION__, '5.9.0' ); @@ -686,9 +690,9 @@ public function get_stylesheet( $types = array( 'variables', 'styles', 'presets' } } - $blocks_metadata = self::get_blocks_metadata(); - $style_nodes = self::get_style_nodes( $this->theme_json, $blocks_metadata ); - $setting_nodes = self::get_setting_nodes( $this->theme_json, $blocks_metadata ); + $blocks_metadata = static::get_blocks_metadata(); + $style_nodes = static::get_style_nodes( $this->theme_json, $blocks_metadata ); + $setting_nodes = static::get_setting_nodes( $this->theme_json, $blocks_metadata ); $stylesheet = ''; @@ -775,7 +779,7 @@ public function get_template_parts() { * @param array $style_nodes Nodes with styles. * @return string The new stylesheet. */ - private function get_block_classes( $style_nodes ) { + protected function get_block_classes( $style_nodes ) { $block_rules = ''; foreach ( $style_nodes as $metadata ) { @@ -786,7 +790,7 @@ private function get_block_classes( $style_nodes ) { $node = _wp_array_get( $this->theme_json, $metadata['path'], array() ); $selector = $metadata['selector']; $settings = _wp_array_get( $this->theme_json, array( 'settings' ) ); - $declarations = self::compute_style_properties( $node, $settings ); + $declarations = static::compute_style_properties( $node, $settings ); // 1. Separate the ones who use the general selector // and the ones who use the duotone selector. @@ -806,20 +810,20 @@ private function get_block_classes( $style_nodes ) { * user-generated values take precedence in the CSS cascade. * @link https://github.com/WordPress/gutenberg/issues/36147. */ - if ( self::ROOT_BLOCK_SELECTOR === $selector ) { + if ( static::ROOT_BLOCK_SELECTOR === $selector ) { $block_rules .= 'body { margin: 0; }'; } // 2. Generate the rules that use the general selector. - $block_rules .= self::to_ruleset( $selector, $declarations ); + $block_rules .= static::to_ruleset( $selector, $declarations ); // 3. Generate the rules that use the duotone selector. if ( isset( $metadata['duotone'] ) && ! empty( $declarations_duotone ) ) { - $selector_duotone = self::scope_selector( $metadata['selector'], $metadata['duotone'] ); - $block_rules .= self::to_ruleset( $selector_duotone, $declarations_duotone ); + $selector_duotone = static::scope_selector( $metadata['selector'], $metadata['duotone'] ); + $block_rules .= static::to_ruleset( $selector_duotone, $declarations_duotone ); } - if ( self::ROOT_BLOCK_SELECTOR === $selector ) { + if ( static::ROOT_BLOCK_SELECTOR === $selector ) { $block_rules .= '.wp-site-blocks > .alignleft { float: left; margin-right: 2em; }'; $block_rules .= '.wp-site-blocks > .alignright { float: right; margin-left: 2em; }'; $block_rules .= '.wp-site-blocks > .aligncenter { justify-content: center; margin-left: auto; margin-right: auto; }'; @@ -864,7 +868,7 @@ private function get_block_classes( $style_nodes ) { * @param array $origins List of origins to process presets from. * @return string The new stylesheet. */ - private function get_preset_classes( $setting_nodes, $origins ) { + protected function get_preset_classes( $setting_nodes, $origins ) { $preset_rules = ''; foreach ( $setting_nodes as $metadata ) { @@ -874,7 +878,7 @@ private function get_preset_classes( $setting_nodes, $origins ) { $selector = $metadata['selector']; $node = _wp_array_get( $this->theme_json, $metadata['path'], array() ); - $preset_rules .= self::compute_preset_classes( $node, $selector, $origins ); + $preset_rules .= static::compute_preset_classes( $node, $selector, $origins ); } return $preset_rules; @@ -901,7 +905,7 @@ private function get_preset_classes( $setting_nodes, $origins ) { * @param array $origins List of origins to process. * @return string The new stylesheet. */ - private function get_css_variables( $nodes, $origins ) { + protected function get_css_variables( $nodes, $origins ) { $stylesheet = ''; foreach ( $nodes as $metadata ) { if ( null === $metadata['selector'] ) { @@ -911,9 +915,9 @@ private function get_css_variables( $nodes, $origins ) { $selector = $metadata['selector']; $node = _wp_array_get( $this->theme_json, $metadata['path'], array() ); - $declarations = array_merge( self::compute_preset_vars( $node, $origins ), self::compute_theme_vars( $node ) ); + $declarations = array_merge( static::compute_preset_vars( $node, $origins ), static::compute_theme_vars( $node ) ); - $stylesheet .= self::to_ruleset( $selector, $declarations ); + $stylesheet .= static::to_ruleset( $selector, $declarations ); } return $stylesheet; @@ -929,7 +933,7 @@ private function get_css_variables( $nodes, $origins ) { * @param array $declarations List of declarations. * @return string CSS ruleset. */ - private static function to_ruleset( $selector, $declarations ) { + protected static function to_ruleset( $selector, $declarations ) { if ( empty( $declarations ) ) { return ''; } @@ -957,7 +961,7 @@ static function ( $carry, $element ) { * @param string $to_append Selector to append. * @return string */ - private static function append_to_selector( $selector, $to_append ) { + protected static function append_to_selector( $selector, $to_append ) { $new_selectors = array(); $selectors = explode( ',', $selector ); foreach ( $selectors as $sel ) { @@ -979,22 +983,22 @@ private static function append_to_selector( $selector, $to_append ) { * @param array $origins List of origins to process. * @return string The result of processing the presets. */ - private static function compute_preset_classes( $settings, $selector, $origins ) { - if ( self::ROOT_BLOCK_SELECTOR === $selector ) { + protected static function compute_preset_classes( $settings, $selector, $origins ) { + if ( static::ROOT_BLOCK_SELECTOR === $selector ) { // Classes at the global level do not need any CSS prefixed, // and we don't want to increase its specificity. $selector = ''; } $stylesheet = ''; - foreach ( self::PRESETS_METADATA as $preset_metadata ) { - $slugs = self::get_settings_slugs( $settings, $preset_metadata, $origins ); + foreach ( static::PRESETS_METADATA as $preset_metadata ) { + $slugs = static::get_settings_slugs( $settings, $preset_metadata, $origins ); foreach ( $preset_metadata['classes'] as $class => $property ) { foreach ( $slugs as $slug ) { - $css_var = self::replace_slug_in_string( $preset_metadata['css_vars'], $slug ); - $class_name = self::replace_slug_in_string( $class, $slug ); - $stylesheet .= self::to_ruleset( - self::append_to_selector( $selector, $class_name ), + $css_var = static::replace_slug_in_string( $preset_metadata['css_vars'], $slug ); + $class_name = static::replace_slug_in_string( $class, $slug ); + $stylesheet .= static::to_ruleset( + static::append_to_selector( $selector, $class_name ), array( array( 'name' => $property, @@ -1026,7 +1030,7 @@ private static function compute_preset_classes( $settings, $selector, $origins ) * @param string $selector Original selector. * @return string Scoped selector. */ - private static function scope_selector( $scope, $selector ) { + protected static function scope_selector( $scope, $selector ) { $scopes = explode( ',', $scope ); $selectors = explode( ',', $selector ); @@ -1076,7 +1080,7 @@ private static function scope_selector( $scope, $selector ) { * @param array $origins List of origins to process. * @return array Array of presets where each key is a slug and each value is the preset value. */ - private static function get_settings_values_by_slug( $settings, $preset_metadata, $origins ) { + protected static function get_settings_values_by_slug( $settings, $preset_metadata, $origins ) { $preset_per_origin = _wp_array_get( $settings, $preset_metadata['path'], array() ); $result = array(); @@ -1118,7 +1122,11 @@ private static function get_settings_values_by_slug( $settings, $preset_metadata * @param array $origins List of origins to process. * @return array Array of presets where the key and value are both the slug. */ - private static function get_settings_slugs( $settings, $preset_metadata, $origins = self::VALID_ORIGINS ) { + protected static function get_settings_slugs( $settings, $preset_metadata, $origins = null ) { + if ( null === $origins ) { + $origins = static::VALID_ORIGINS; + } + $preset_per_origin = _wp_array_get( $settings, $preset_metadata['path'], array() ); $result = array(); @@ -1145,7 +1153,7 @@ private static function get_settings_slugs( $settings, $preset_metadata, $origin * @param string $slug The slug value to use to generate the custom property. * @return string The CSS Custom Property. Something along the lines of `--wp--preset--color--black`. */ - private static function replace_slug_in_string( $input, $slug ) { + protected static function replace_slug_in_string( $input, $slug ) { return strtr( $input, array( '$slug' => $slug ) ); } @@ -1166,13 +1174,13 @@ private static function replace_slug_in_string( $input, $slug ) { * @param array $origins List of origins to process. * @return array Returns the modified $declarations. */ - private static function compute_preset_vars( $settings, $origins ) { + protected static function compute_preset_vars( $settings, $origins ) { $declarations = array(); - foreach ( self::PRESETS_METADATA as $preset_metadata ) { - $values_by_slug = self::get_settings_values_by_slug( $settings, $preset_metadata, $origins ); + foreach ( static::PRESETS_METADATA as $preset_metadata ) { + $values_by_slug = static::get_settings_values_by_slug( $settings, $preset_metadata, $origins ); foreach ( $values_by_slug as $slug => $value ) { $declarations[] = array( - 'name' => self::replace_slug_in_string( $preset_metadata['css_vars'], $slug ), + 'name' => static::replace_slug_in_string( $preset_metadata['css_vars'], $slug ), 'value' => $value, ); } @@ -1196,10 +1204,10 @@ private static function compute_preset_vars( $settings, $origins ) { * @param array $settings Settings to process. * @return array Returns the modified $declarations. */ - private static function compute_theme_vars( $settings ) { + protected static function compute_theme_vars( $settings ) { $declarations = array(); $custom_values = _wp_array_get( $settings, array( 'custom' ), array() ); - $css_vars = self::flatten_tree( $custom_values ); + $css_vars = static::flatten_tree( $custom_values ); foreach ( $css_vars as $key => $value ) { $declarations[] = array( 'name' => '--wp--custom--' . $key, @@ -1247,7 +1255,7 @@ private static function compute_theme_vars( $settings ) { * @param string $token Optional. Token to use between levels. Default '--'. * @return array The flattened tree. */ - private static function flatten_tree( $tree, $prefix = '', $token = '--' ) { + protected static function flatten_tree( $tree, $prefix = '', $token = '--' ) { $result = array(); foreach ( $tree as $property => $value ) { $new_key = $prefix . str_replace( @@ -1260,7 +1268,7 @@ private static function flatten_tree( $tree, $prefix = '', $token = '--' ) { $new_prefix = $new_key . $token; $result = array_merge( $result, - self::flatten_tree( $value, $new_prefix, $token ) + static::flatten_tree( $value, $new_prefix, $token ) ); } else { $result[ $new_key ] = $value; @@ -1286,22 +1294,26 @@ private static function flatten_tree( $tree, $prefix = '', $token = '--' ) { * @param array $properties Properties metadata. * @return array Returns the modified $declarations. */ - private static function compute_style_properties( $styles, $settings = array(), $properties = self::PROPERTIES_METADATA ) { + protected static function compute_style_properties( $styles, $settings = array(), $properties = null ) { + if ( null === $properties ) { + $properties = static::PROPERTIES_METADATA; + } + $declarations = array(); if ( empty( $styles ) ) { return $declarations; } foreach ( $properties as $css_property => $value_path ) { - $value = self::get_property_value( $styles, $value_path ); + $value = static::get_property_value( $styles, $value_path ); // Look up protected properties, keyed by value path. // Skip protected properties that are explicitly set to `null`. if ( is_array( $value_path ) ) { $path_string = implode( '.', $value_path ); if ( - array_key_exists( $path_string, self::PROTECTED_PROPERTIES ) && - _wp_array_get( $settings, self::PROTECTED_PROPERTIES[ $path_string ], null ) === null + array_key_exists( $path_string, static::PROTECTED_PROPERTIES ) && + _wp_array_get( $settings, static::PROTECTED_PROPERTIES[ $path_string ], null ) === null ) { continue; } @@ -1336,7 +1348,7 @@ private static function compute_style_properties( $styles, $settings = array(), * @param array $path Which property to process. * @return string|array Style property value. */ - private static function get_property_value( $styles, $path ) { + protected static function get_property_value( $styles, $path ) { $value = _wp_array_get( $styles, $path, '' ); if ( '' === $value || is_array( $value ) ) { @@ -1379,7 +1391,7 @@ private static function get_property_value( $styles, $path ) { * @param array $selectors List of selectors per block. * @return array */ - private static function get_setting_nodes( $theme_json, $selectors = array() ) { + protected static function get_setting_nodes( $theme_json, $selectors = array() ) { $nodes = array(); if ( ! isset( $theme_json['settings'] ) ) { return $nodes; @@ -1388,7 +1400,7 @@ private static function get_setting_nodes( $theme_json, $selectors = array() ) { // Top-level. $nodes[] = array( 'path' => array( 'settings' ), - 'selector' => self::ROOT_BLOCK_SELECTOR, + 'selector' => static::ROOT_BLOCK_SELECTOR, ); // Calculate paths for blocks. @@ -1433,7 +1445,7 @@ private static function get_setting_nodes( $theme_json, $selectors = array() ) { * @param array $selectors List of selectors per block. * @return array */ - private static function get_style_nodes( $theme_json, $selectors = array() ) { + protected static function get_style_nodes( $theme_json, $selectors = array() ) { $nodes = array(); if ( ! isset( $theme_json['styles'] ) ) { return $nodes; @@ -1442,14 +1454,14 @@ private static function get_style_nodes( $theme_json, $selectors = array() ) { // Top-level. $nodes[] = array( 'path' => array( 'styles' ), - 'selector' => self::ROOT_BLOCK_SELECTOR, + 'selector' => static::ROOT_BLOCK_SELECTOR, ); if ( isset( $theme_json['styles']['elements'] ) ) { foreach ( $theme_json['styles']['elements'] as $element => $node ) { $nodes[] = array( 'path' => array( 'styles', 'elements', $element ), - 'selector' => self::ELEMENTS[ $element ], + 'selector' => static::ELEMENTS[ $element ], ); } } @@ -1523,10 +1535,10 @@ public function merge( $incoming ) { * with the equivalent dfefault presets: if a slug is present as a default * we remove it from the theme presets. */ - $nodes = self::get_setting_nodes( $incoming_data ); - $slugs_global = self::get_default_slugs( $this->theme_json, array( 'settings' ) ); + $nodes = static::get_setting_nodes( $incoming_data ); + $slugs_global = static::get_default_slugs( $this->theme_json, array( 'settings' ) ); foreach ( $nodes as $node ) { - $slugs_node = self::get_default_slugs( $this->theme_json, $node['path'] ); + $slugs_node = static::get_default_slugs( $this->theme_json, $node['path'] ); $slugs = array_merge_recursive( $slugs_global, $slugs_node ); // Replace the spacing.units. @@ -1537,10 +1549,10 @@ public function merge( $incoming ) { } // Replace the presets. - foreach ( self::PRESETS_METADATA as $preset ) { - $override_preset = self::should_override_preset( $this->theme_json, $node['path'], $preset['override'] ); + foreach ( static::PRESETS_METADATA as $preset ) { + $override_preset = static::should_override_preset( $this->theme_json, $node['path'], $preset['override'] ); - foreach ( self::VALID_ORIGINS as $origin ) { + foreach ( static::VALID_ORIGINS as $origin ) { $base_path = array_merge( $node['path'], $preset['path'] ); $path = array_merge( $base_path, array( $origin ) ); $content = _wp_array_get( $incoming_data, $path, null ); @@ -1551,7 +1563,7 @@ public function merge( $incoming ) { if ( 'theme' === $origin && $preset['use_default_names'] ) { foreach ( $content as &$item ) { if ( ! array_key_exists( 'name', $item ) ) { - $name = self::get_name_from_defaults( $item['slug'], $base_path ); + $name = static::get_name_from_defaults( $item['slug'], $base_path ); if ( null !== $name ) { $item['name'] = $name; } @@ -1566,7 +1578,7 @@ public function merge( $incoming ) { _wp_array_set( $this->theme_json, $path, $content ); } else { $slugs_for_preset = _wp_array_get( $slugs, $preset['path'], array() ); - $content = self::filter_slugs( $content, $slugs_for_preset ); + $content = static::filter_slugs( $content, $slugs_for_preset ); _wp_array_set( $this->theme_json, $path, $content ); } } @@ -1584,7 +1596,7 @@ public function merge( $incoming ) { * @param bool|array $override Data to compute whether to override the preset. * @return boolean */ - private static function should_override_preset( $theme_json, $path, $override ) { + protected static function should_override_preset( $theme_json, $path, $override ) { if ( is_bool( $override ) ) { return $override; } @@ -1636,10 +1648,10 @@ private static function should_override_preset( $theme_json, $path, $override ) * @param array $node_path The path to inspect. It's 'settings' by default. * @return array */ - private static function get_default_slugs( $data, $node_path ) { + protected static function get_default_slugs( $data, $node_path ) { $slugs = array(); - foreach ( self::PRESETS_METADATA as $metadata ) { + foreach ( static::PRESETS_METADATA as $metadata ) { $path = array_merge( $node_path, $metadata['path'], array( 'default' ) ); $preset = _wp_array_get( $data, $path, null ); if ( ! isset( $preset ) ) { @@ -1668,7 +1680,7 @@ static function( $value ) { * @param array $base_path The path to inspect. It's 'settings' by default. * @return string|null */ - private function get_name_from_defaults( $slug, $base_path ) { + protected function get_name_from_defaults( $slug, $base_path ) { $path = array_merge( $base_path, array( 'default' ) ); $default_content = _wp_array_get( $this->theme_json, $path, null ); if ( ! $default_content ) { @@ -1691,7 +1703,7 @@ private function get_name_from_defaults( $slug, $base_path ) { * @param array $slugs The slugs that should not be overriden. * @return array The new node. */ - private static function filter_slugs( $node, $slugs ) { + protected static function filter_slugs( $node, $slugs ) { if ( empty( $slugs ) ) { return $node; } @@ -1719,32 +1731,32 @@ public static function remove_insecure_properties( $theme_json ) { $theme_json = WP_Theme_JSON_Schema::migrate( $theme_json ); - $valid_block_names = array_keys( self::get_blocks_metadata() ); - $valid_element_names = array_keys( self::ELEMENTS ); - $theme_json = self::sanitize( $theme_json, $valid_block_names, $valid_element_names ); + $valid_block_names = array_keys( static::get_blocks_metadata() ); + $valid_element_names = array_keys( static::ELEMENTS ); + $theme_json = static::sanitize( $theme_json, $valid_block_names, $valid_element_names ); - $blocks_metadata = self::get_blocks_metadata(); - $style_nodes = self::get_style_nodes( $theme_json, $blocks_metadata ); + $blocks_metadata = static::get_blocks_metadata(); + $style_nodes = static::get_style_nodes( $theme_json, $blocks_metadata ); foreach ( $style_nodes as $metadata ) { $input = _wp_array_get( $theme_json, $metadata['path'], array() ); if ( empty( $input ) ) { continue; } - $output = self::remove_insecure_styles( $input ); + $output = static::remove_insecure_styles( $input ); if ( ! empty( $output ) ) { _wp_array_set( $sanitized, $metadata['path'], $output ); } } - $setting_nodes = self::get_setting_nodes( $theme_json ); + $setting_nodes = static::get_setting_nodes( $theme_json ); foreach ( $setting_nodes as $metadata ) { $input = _wp_array_get( $theme_json, $metadata['path'], array() ); if ( empty( $input ) ) { continue; } - $output = self::remove_insecure_settings( $input ); + $output = static::remove_insecure_settings( $input ); if ( ! empty( $output ) ) { _wp_array_set( $sanitized, $metadata['path'], $output ); } @@ -1774,10 +1786,10 @@ public static function remove_insecure_properties( $theme_json ) { * @param array $input Node to process. * @return array */ - private static function remove_insecure_settings( $input ) { + protected static function remove_insecure_settings( $input ) { $output = array(); - foreach ( self::PRESETS_METADATA as $preset_metadata ) { - foreach ( self::VALID_ORIGINS as $origin ) { + foreach ( static::PRESETS_METADATA as $preset_metadata ) { + foreach ( static::VALID_ORIGINS as $origin ) { $path_with_origin = array_merge( $preset_metadata['path'], array( $origin ) ); $presets = _wp_array_get( $input, $path_with_origin, null ); if ( null === $presets ) { @@ -1802,7 +1814,7 @@ private static function remove_insecure_settings( $input ) { $preset_is_valid = true; foreach ( $preset_metadata['properties'] as $property ) { - if ( ! self::is_safe_css_declaration( $property, $value ) ) { + if ( ! static::is_safe_css_declaration( $property, $value ) ) { $preset_is_valid = false; break; } @@ -1831,13 +1843,13 @@ private static function remove_insecure_settings( $input ) { * @param array $input Node to process. * @return array */ - private static function remove_insecure_styles( $input ) { + protected static function remove_insecure_styles( $input ) { $output = array(); - $declarations = self::compute_style_properties( $input ); + $declarations = static::compute_style_properties( $input ); foreach ( $declarations as $declaration ) { - if ( self::is_safe_css_declaration( $declaration['name'], $declaration['value'] ) ) { - $path = self::PROPERTIES_METADATA[ $declaration['name'] ]; + if ( static::is_safe_css_declaration( $declaration['name'], $declaration['value'] ) ) { + $path = static::PROPERTIES_METADATA[ $declaration['name'] ]; // Check the value isn't an array before adding so as to not // double up shorthand and longhand styles. @@ -1859,7 +1871,7 @@ private static function remove_insecure_styles( $input ) { * @param string $property_value Value in a CSS declaration, i.e. the `red` in `color: red`. * @return bool */ - private static function is_safe_css_declaration( $property_name, $property_value ) { + protected static function is_safe_css_declaration( $property_name, $property_value ) { $style_to_validate = $property_name . ': ' . $property_value; $filtered = esc_html( safecss_filter_attr( $style_to_validate ) ); return ! empty( trim( $filtered ) ); @@ -1887,7 +1899,7 @@ public function get_raw_data() { */ public static function get_from_editor_settings( $settings ) { $theme_settings = array( - 'version' => self::LATEST_SCHEMA, + 'version' => static::LATEST_SCHEMA, 'settings' => array(), );