w CSS. * @param string $device Optional. The device. Default is empty. * * @return Stylesheet The current stylesheet class instance. */ public function add_raw_css( $css, $device = '' ) { if ( ! isset( $this->raw[ $device ] ) ) { $this->raw[ $device ] = []; } $this->raw[ $device ][] = trim( $css ); return $this; } /** * Get CSS rules. * * Retrieve the CSS rules. * * @since 1.0.5 * @access public * * @param string $device Optional. The device. Default is empty. * @param string $selector Optional. CSS selector. Default is empty. * @param string $property Optional. CSS property. Default is empty. * * @return null|array CSS rules, or `null` if not rules found. */ public function get_rules( $device = null, $selector = null, $property = null ) { if ( ! $device ) { return $this->rules; } if ( $property ) { return isset( $this->rules[ $device ][ $selector ][ $property ] ) ? $this->rules[ $device ][ $selector ][ $property ] : null; } if ( $selector ) { return isset( $this->rules[ $device ][ $selector ] ) ? $this->rules[ $device ][ $selector ] : null; } return isset( $this->rules[ $device ] ) ? $this->rules[ $device ] : null; } /** * To string. * * This magic method responsible for parsing the rules into one CSS string. * * @since 1.0.0 * @access public * * @return string CSS style. */ public function __toString() { $style_text = ''; foreach ( $this->rules as $query_hash => $rule ) { $device_text = self::parse_rules( $rule ); if ( 'all' !== $query_hash ) { $device_text = $this->get_query_hash_style_format( $query_hash ) . '{' . $device_text . '}'; } $style_text .= $device_text; } foreach ( $this->raw as $device_name => $raw ) { $raw = implode( "\n", $raw ); if ( $raw && isset( $this->devices[ $device_name ] ) ) { $raw = '@media(max-width: ' . $this->devices[ $device_name ] . 'px){' . $raw . '}'; } $style_text .= $raw; } return $style_text; } /** * Query to hash. * * Turns the media query into a hashed string that represents the query * endpoint in the rules list. * * @since 1.2.0 * @access private * * @param array $query CSS media query. * * @return string Hashed string of the query. */ private function query_to_hash( array $query ) { $hash = []; foreach ( $query as $endpoint => $value ) { $hash[] = $endpoint . '_' . $value; } return implode( '-', $hash ); } /** * Hash to query. * * Turns the hashed string to an array that contains the data of the query * endpoint. * * @since 1.2.0 * @access private * * @param string $hash Hashed string of the query. * * @return array Media query data. */ private function hash_to_query( $hash ) { $query = []; $hash = array_filter( explode( '-', $hash ) ); foreach ( $hash as $single_query ) { preg_match( '/(min|max)_(.*)/', $single_query, $query_parts ); $end_point = $query_parts[1]; $device_name = $query_parts[2]; $query[ $end_point ] = 'max' === $end_point ? $this->devices[ $device_name ] : Plugin::$instance->breakpoints->get_device_min_breakpoint( $device_name ); } return $query; } /** * Add query hash. * * Register new endpoint query and sort the rules the way they should be * displayed in the final stylesheet based on the device and the viewport * width. * * @since 1.2.0 * @access private * * @param string $query_hash Hashed string of the query. */ private function add_query_hash( $query_hash ) { $this->rules[ $query_hash ] = []; uksort( $this->rules, function( $a, $b ) { if ( 'all' === $a ) { return -1; } if ( 'all' === $b ) { return 1; } $a_query = $this->hash_to_query( $a ); $b_query = $this->hash_to_query( $b ); if ( isset( $a_query['min'] ) xor isset( $b_query['min'] ) ) { return 1; } if ( isset( $a_query['min'] ) ) { $range = $a_query['min'] - $b_query['min']; if ( $range ) { return $range; } $a_has_max = isset( $a_query['max'] ); if ( $a_has_max xor isset( $b_query['max'] ) ) { return $a_has_max ? 1 : -1; } if ( ! $a_has_max ) { return 0; } } return $b_query['max'] - $a_query['max']; } ); } /** * Get query hash style format. * * Retrieve formated media query rule with the endpoint width settings. * * The method returns the CSS `@media` rule and supported viewport width in * pixels. It can also handel multiple width endpoints. * * @since 1.2.0 * @access private * * @param string $query_hash The hash of the query. * * @return string CSS media query. */ private function get_query_hash_style_format( $query_hash ) { $query = $this->hash_to_query( $query_hash ); $style_format = []; foreach ( $query as $end_point => $value ) { $style_format[] = '(' . $end_point . '-width:' . $value . 'px)'; } return '@media' . implode( ' and ', $style_format ); } }