diff options
Diffstat (limited to 'wp-includes/style-engine/class-wp-style-engine-processor.php')
-rw-r--r-- | wp-includes/style-engine/class-wp-style-engine-processor.php | 162 |
1 files changed, 162 insertions, 0 deletions
diff --git a/wp-includes/style-engine/class-wp-style-engine-processor.php b/wp-includes/style-engine/class-wp-style-engine-processor.php new file mode 100644 index 0000000..0778748 --- /dev/null +++ b/wp-includes/style-engine/class-wp-style-engine-processor.php @@ -0,0 +1,162 @@ +<?php +/** + * Style Engine: WP_Style_Engine_Processor class + * + * @package WordPress + * @subpackage StyleEngine + * @since 6.1.0 + */ + +/** + * Core class used to compile styles from stores or collection of CSS rules. + * + * @since 6.1.0 + */ +#[AllowDynamicProperties] +class WP_Style_Engine_Processor { + + /** + * A collection of Style Engine Store objects. + * + * @since 6.1.0 + * @var WP_Style_Engine_CSS_Rules_Store[] + */ + protected $stores = array(); + + /** + * The set of CSS rules that this processor will work on. + * + * @since 6.1.0 + * @var WP_Style_Engine_CSS_Rule[] + */ + protected $css_rules = array(); + + /** + * Adds a store to the processor. + * + * @since 6.1.0 + * + * @param WP_Style_Engine_CSS_Rules_Store $store The store to add. + * @return WP_Style_Engine_Processor Returns the object to allow chaining methods. + */ + public function add_store( $store ) { + if ( ! $store instanceof WP_Style_Engine_CSS_Rules_Store ) { + _doing_it_wrong( + __METHOD__, + __( '$store must be an instance of WP_Style_Engine_CSS_Rules_Store' ), + '6.1.0' + ); + return $this; + } + + $this->stores[ $store->get_name() ] = $store; + + return $this; + } + + /** + * Adds rules to be processed. + * + * @since 6.1.0 + * + * @param WP_Style_Engine_CSS_Rule|WP_Style_Engine_CSS_Rule[] $css_rules A single, or an array of, + * WP_Style_Engine_CSS_Rule objects + * from a store or otherwise. + * @return WP_Style_Engine_Processor Returns the object to allow chaining methods. + */ + public function add_rules( $css_rules ) { + if ( ! is_array( $css_rules ) ) { + $css_rules = array( $css_rules ); + } + + foreach ( $css_rules as $rule ) { + $selector = $rule->get_selector(); + if ( isset( $this->css_rules[ $selector ] ) ) { + $this->css_rules[ $selector ]->add_declarations( $rule->get_declarations() ); + continue; + } + $this->css_rules[ $rule->get_selector() ] = $rule; + } + + return $this; + } + + /** + * Gets the CSS rules as a string. + * + * @since 6.1.0 + * @since 6.4.0 The Optimization is no longer the default. + * + * @param array $options { + * Optional. An array of options. Default empty array. + * + * @type bool $optimize Whether to optimize the CSS output, e.g. combine rules. + * Default false. + * @type bool $prettify Whether to add new lines and indents to output. + * Defaults to whether the `SCRIPT_DEBUG` constant is defined. + * } + * @return string The computed CSS. + */ + public function get_css( $options = array() ) { + $defaults = array( + 'optimize' => false, + 'prettify' => defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG, + ); + $options = wp_parse_args( $options, $defaults ); + + // If we have stores, get the rules from them. + foreach ( $this->stores as $store ) { + $this->add_rules( $store->get_all_rules() ); + } + + // Combine CSS selectors that have identical declarations. + if ( true === $options['optimize'] ) { + $this->combine_rules_selectors(); + } + + // Build the CSS. + $css = ''; + foreach ( $this->css_rules as $rule ) { + $css .= $rule->get_css( $options['prettify'] ); + $css .= $options['prettify'] ? "\n" : ''; + } + return $css; + } + + /** + * Combines selectors from the rules store when they have the same styles. + * + * @since 6.1.0 + */ + private function combine_rules_selectors() { + // Build an array of selectors along with the JSON-ified styles to make comparisons easier. + $selectors_json = array(); + foreach ( $this->css_rules as $rule ) { + $declarations = $rule->get_declarations()->get_declarations(); + ksort( $declarations ); + $selectors_json[ $rule->get_selector() ] = wp_json_encode( $declarations ); + } + + // Combine selectors that have the same styles. + foreach ( $selectors_json as $selector => $json ) { + // Get selectors that use the same styles. + $duplicates = array_keys( $selectors_json, $json, true ); + // Skip if there are no duplicates. + if ( 1 >= count( $duplicates ) ) { + continue; + } + + $declarations = $this->css_rules[ $selector ]->get_declarations(); + + foreach ( $duplicates as $key ) { + // Unset the duplicates from the $selectors_json array to avoid looping through them as well. + unset( $selectors_json[ $key ] ); + // Remove the rules from the rules collection. + unset( $this->css_rules[ $key ] ); + } + // Create a new rule with the combined selectors. + $duplicate_selectors = implode( ',', $duplicates ); + $this->css_rules[ $duplicate_selectors ] = new WP_Style_Engine_CSS_Rule( $duplicate_selectors, $declarations ); + } + } +} |