wp/wp-includes/style-engine/class-wp-style-engine-css-rule.php
changeset 21 48c4eec2b7e6
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/wp/wp-includes/style-engine/class-wp-style-engine-css-rule.php	Fri Sep 05 18:40:08 2025 +0200
@@ -0,0 +1,189 @@
+<?php
+/**
+ * Style Engine: WP_Style_Engine_CSS_Rule class
+ *
+ * @package WordPress
+ * @subpackage StyleEngine
+ * @since 6.1.0
+ */
+
+/**
+ * Core class used for style engine CSS rules.
+ *
+ * Holds, sanitizes, processes, and prints CSS declarations for the style engine.
+ *
+ * @since 6.1.0
+ */
+#[AllowDynamicProperties]
+class WP_Style_Engine_CSS_Rule {
+
+	/**
+	 * The selector.
+	 *
+	 * @since 6.1.0
+	 * @var string
+	 */
+	protected $selector;
+
+	/**
+	 * The selector declarations.
+	 *
+	 * Contains a WP_Style_Engine_CSS_Declarations object.
+	 *
+	 * @since 6.1.0
+	 * @var WP_Style_Engine_CSS_Declarations
+	 */
+	protected $declarations;
+
+	/**
+	 * A parent CSS selector in the case of nested CSS, or a CSS nested @rule,
+	 * such as `@media (min-width: 80rem)` or `@layer module`.
+	 *
+	 * @since 6.6.0
+	 * @var string
+	 */
+	protected $rules_group;
+
+	/**
+	 * Constructor.
+	 *
+	 * @since 6.1.0
+	 * @since 6.6.0 Added the `$rules_group` parameter.
+	 *
+	 * @param string                                    $selector     Optional. The CSS selector. Default empty string.
+	 * @param string[]|WP_Style_Engine_CSS_Declarations $declarations Optional. An associative array of CSS definitions,
+	 *                                                                e.g. `array( "$property" => "$value", "$property" => "$value" )`,
+	 *                                                                or a WP_Style_Engine_CSS_Declarations object.
+	 *                                                                Default empty array.
+	 * @param string                                    $rules_group  A parent CSS selector in the case of nested CSS, or a CSS nested @rule,
+	 *                                                                such as `@media (min-width: 80rem)` or `@layer module`.
+	 */
+	public function __construct( $selector = '', $declarations = array(), $rules_group = '' ) {
+		$this->set_selector( $selector );
+		$this->add_declarations( $declarations );
+		$this->set_rules_group( $rules_group );
+	}
+
+	/**
+	 * Sets the selector.
+	 *
+	 * @since 6.1.0
+	 *
+	 * @param string $selector The CSS selector.
+	 * @return WP_Style_Engine_CSS_Rule Returns the object to allow chaining of methods.
+	 */
+	public function set_selector( $selector ) {
+		$this->selector = $selector;
+		return $this;
+	}
+
+	/**
+	 * Sets the declarations.
+	 *
+	 * @since 6.1.0
+	 *
+	 * @param string[]|WP_Style_Engine_CSS_Declarations $declarations An array of declarations (property => value pairs),
+	 *                                                                or a WP_Style_Engine_CSS_Declarations object.
+	 * @return WP_Style_Engine_CSS_Rule Returns the object to allow chaining of methods.
+	 */
+	public function add_declarations( $declarations ) {
+		$is_declarations_object = ! is_array( $declarations );
+		$declarations_array     = $is_declarations_object ? $declarations->get_declarations() : $declarations;
+
+		if ( null === $this->declarations ) {
+			if ( $is_declarations_object ) {
+				$this->declarations = $declarations;
+				return $this;
+			}
+			$this->declarations = new WP_Style_Engine_CSS_Declarations( $declarations_array );
+		}
+		$this->declarations->add_declarations( $declarations_array );
+
+		return $this;
+	}
+
+	/**
+	 * Sets the rules group.
+	 *
+	 * @since 6.6.0
+	 *
+	 * @param string $rules_group A parent CSS selector in the case of nested CSS, or a CSS nested @rule,
+	 *                            such as `@media (min-width: 80rem)` or `@layer module`.
+	 * @return WP_Style_Engine_CSS_Rule Returns the object to allow chaining of methods.
+	 */
+	public function set_rules_group( $rules_group ) {
+		$this->rules_group = $rules_group;
+		return $this;
+	}
+
+	/**
+	 * Gets the rules group.
+	 *
+	 * @since 6.6.0
+	 *
+	 * @return string
+	 */
+	public function get_rules_group() {
+		return $this->rules_group;
+	}
+
+	/**
+	 * Gets the declarations object.
+	 *
+	 * @since 6.1.0
+	 *
+	 * @return WP_Style_Engine_CSS_Declarations The declarations object.
+	 */
+	public function get_declarations() {
+		return $this->declarations;
+	}
+
+	/**
+	 * Gets the full selector.
+	 *
+	 * @since 6.1.0
+	 *
+	 * @return string
+	 */
+	public function get_selector() {
+		return $this->selector;
+	}
+
+	/**
+	 * Gets the CSS.
+	 *
+	 * @since 6.1.0
+	 * @since 6.6.0 Added support for nested CSS with rules groups.
+	 *
+	 * @param bool $should_prettify Optional. Whether to add spacing, new lines and indents.
+	 *                              Default false.
+	 * @param int  $indent_count    Optional. The number of tab indents to apply to the rule.
+	 *                              Applies if `prettify` is `true`. Default 0.
+	 * @return string
+	 */
+	public function get_css( $should_prettify = false, $indent_count = 0 ) {
+		$rule_indent                = $should_prettify ? str_repeat( "\t", $indent_count ) : '';
+		$nested_rule_indent         = $should_prettify ? str_repeat( "\t", $indent_count + 1 ) : '';
+		$declarations_indent        = $should_prettify ? $indent_count + 1 : 0;
+		$nested_declarations_indent = $should_prettify ? $indent_count + 2 : 0;
+		$suffix                     = $should_prettify ? "\n" : '';
+		$spacer                     = $should_prettify ? ' ' : '';
+		// Trims any multiple selectors strings.
+		$selector         = $should_prettify ? implode( ',', array_map( 'trim', explode( ',', $this->get_selector() ) ) ) : $this->get_selector();
+		$selector         = $should_prettify ? str_replace( array( ',' ), ",\n", $selector ) : $selector;
+		$rules_group      = $this->get_rules_group();
+		$has_rules_group  = ! empty( $rules_group );
+		$css_declarations = $this->declarations->get_declarations_string( $should_prettify, $has_rules_group ? $nested_declarations_indent : $declarations_indent );
+
+		if ( empty( $css_declarations ) ) {
+			return '';
+		}
+
+		if ( $has_rules_group ) {
+			$selector = "{$rule_indent}{$rules_group}{$spacer}{{$suffix}{$nested_rule_indent}{$selector}{$spacer}{{$suffix}{$css_declarations}{$suffix}{$nested_rule_indent}}{$suffix}{$rule_indent}}";
+			return $selector;
+		}
+
+		return "{$rule_indent}{$selector}{$spacer}{{$suffix}{$css_declarations}{$suffix}{$rule_indent}}";
+	}
+}