Diff: STRATO-apps/wordpress_03/app/wp-content/plugins/elementor/includes/stylesheet.php

Keine Baseline-Datei – Diff nur gegen leer.
Zur Liste
1 -
1 + <?php
2 + namespace Elementor;
3 +
4 + if ( ! defined( 'ABSPATH' ) ) {
5 + exit; // Exit if accessed directly.
6 + }
7 +
8 + /**
9 + * Elementor stylesheet.
10 + *
11 + * Elementor stylesheet handler class responsible for setting up CSS rules and
12 + * properties, and all the CSS `@media` rule with supported viewport width.
13 + *
14 + * @since 1.0.0
15 + */
16 + class Stylesheet {
17 +
18 + /**
19 + * CSS Rules.
20 + *
21 + * Holds the list of CSS rules.
22 + *
23 + * @since 1.0.0
24 + * @access private
25 + *
26 + * @var array A list of CSS rules.
27 + */
28 + private $rules = [];
29 +
30 + /**
31 + * Devices.
32 + *
33 + * Holds the list of devices.
34 + *
35 + * @since 1.0.0
36 + * @access private
37 + *
38 + * @var array A list of devices.
39 + */
40 + private $devices = [];
41 +
42 + /**
43 + * Raw CSS.
44 + *
45 + * Holds the raw CSS.
46 + *
47 + * @since 1.0.0
48 + * @access private
49 + *
50 + * @var array The raw CSS.
51 + */
52 + private $raw = [];
53 +
54 + /**
55 + * Parse CSS rules.
56 + *
57 + * Goes over the list of CSS rules and generates the final CSS.
58 + *
59 + * @since 1.0.0
60 + * @access public
61 + * @static
62 + *
63 + * @param array $rules CSS rules.
64 + *
65 + * @return string Parsed rules.
66 + */
67 + public static function parse_rules( array $rules ) {
68 + $parsed_rules = '';
69 +
70 + foreach ( $rules as $selector => $properties ) {
71 + $selector_content = self::parse_properties( $properties );
72 +
73 + if ( $selector_content ) {
74 + $parsed_rules .= $selector . '{' . $selector_content . '}';
75 + }
76 + }
77 +
78 + return $parsed_rules;
79 + }
80 +
81 + /**
82 + * Parse CSS properties.
83 + *
84 + * Goes over the selector properties and generates the CSS of the selector.
85 + *
86 + * @since 1.0.0
87 + * @access public
88 + * @static
89 + *
90 + * @param array $properties CSS properties.
91 + *
92 + * @return string Parsed properties.
93 + */
94 + public static function parse_properties( array $properties ) {
95 + $parsed_properties = '';
96 +
97 + foreach ( $properties as $property_key => $property_value ) {
98 + if ( '' !== $property_value ) {
99 + $parsed_properties .= $property_key . ':' . $property_value . ';';
100 + }
101 + }
102 +
103 + return $parsed_properties;
104 + }
105 +
106 + /**
107 + * Add device.
108 + *
109 + * Add a new device to the devices list.
110 + *
111 + * @since 1.0.0
112 + * @access public
113 + *
114 + * @param string $device_name Device name.
115 + * @param string $device_max_point Device maximum point.
116 + *
117 + * @return Stylesheet The current stylesheet class instance.
118 + */
119 + public function add_device( $device_name, $device_max_point ) {
120 + $this->devices[ $device_name ] = $device_max_point;
121 +
122 + asort( $this->devices );
123 +
124 + return $this;
125 + }
126 +
127 + /**
128 + * Add rules.
129 + *
130 + * Add a new CSS rule to the rules list.
131 + *
132 + * @since 1.0.0
133 + * @access public
134 + *
135 + * @param string $selector CSS selector.
136 + * @param array|string $style_rules Optional. Style rules. Default is `null`.
137 + * @param array $query Optional. Media query. Default is `null`.
138 + *
139 + * @return Stylesheet The current stylesheet class instance.
140 + */
141 + public function add_rules( $selector, $style_rules = null, ?array $query = null ) {
142 + $query_hash = 'all';
143 +
144 + if ( $query ) {
145 + $query_hash = $this->query_to_hash( $query );
146 + }
147 +
148 + if ( ! isset( $this->rules[ $query_hash ] ) ) {
149 + $this->add_query_hash( $query_hash );
150 + }
151 +
152 + if ( null === $style_rules ) {
153 + preg_match_all( '/([^\s].+?(?=\{))\{((?s:.)+?(?=}))}/', $selector, $parsed_rules );
154 +
155 + foreach ( $parsed_rules[1] as $index => $selector ) {
156 + $this->add_rules( $selector, $parsed_rules[2][ $index ], $query );
157 + }
158 +
159 + return $this;
160 + }
161 +
162 + if ( ! isset( $this->rules[ $query_hash ][ $selector ] ) ) {
163 + $this->rules[ $query_hash ][ $selector ] = [];
164 + }
165 +
166 + if ( is_string( $style_rules ) ) {
167 + $style_rules = array_filter( explode( ';', trim( $style_rules ) ) );
168 +
169 + $ordered_rules = [];
170 +
171 + foreach ( $style_rules as $rule ) {
172 + $property = explode( ':', $rule, 2 );
173 +
174 + if ( count( $property ) < 2 ) {
175 + return $this;
176 + }
177 +
178 + $ordered_rules[ trim( $property[0] ) ] = trim( $property[1], ' ;' );
179 + }
180 +
181 + $style_rules = $ordered_rules;
182 + }
183 +
184 + $this->rules[ $query_hash ][ $selector ] = array_merge( $this->rules[ $query_hash ][ $selector ], $style_rules );
185 +
186 + return $this;
187 + }
188 +
189 + /**
190 + * Add raw CSS.
191 + *
192 + * Add a raw CSS rule.
193 + *
194 + * @since 1.0.8
195 + * @access public
196 + *
197 + * @param string $css The raw CSS.
198 + * @param string $device Optional. The device. Default is empty.
199 + *
200 + * @return Stylesheet The current stylesheet class instance.
201 + */
202 + public function add_raw_css( $css, $device = '' ) {
203 + if ( ! isset( $this->raw[ $device ] ) ) {
204 + $this->raw[ $device ] = [];
205 + }
206 +
207 + $this->raw[ $device ][] = trim( $css );
208 +
209 + return $this;
210 + }
211 +
212 + /**
213 + * Get CSS rules.
214 + *
215 + * Retrieve the CSS rules.
216 + *
217 + * @since 1.0.5
218 + * @access public
219 + *
220 + * @param string $device Optional. The device. Default is empty.
221 + * @param string $selector Optional. CSS selector. Default is empty.
222 + * @param string $property Optional. CSS property. Default is empty.
223 + *
224 + * @return null|array CSS rules, or `null` if not rules found.
225 + */
226 + public function get_rules( $device = null, $selector = null, $property = null ) {
227 + if ( ! $device ) {
228 + return $this->rules;
229 + }
230 +
231 + if ( $property ) {
232 + return isset( $this->rules[ $device ][ $selector ][ $property ] ) ? $this->rules[ $device ][ $selector ][ $property ] : null;
233 + }
234 +
235 + if ( $selector ) {
236 + return isset( $this->rules[ $device ][ $selector ] ) ? $this->rules[ $device ][ $selector ] : null;
237 + }
238 +
239 + return isset( $this->rules[ $device ] ) ? $this->rules[ $device ] : null;
240 + }
241 +
242 + /**
243 + * To string.
244 + *
245 + * This magic method responsible for parsing the rules into one CSS string.
246 + *
247 + * @since 1.0.0
248 + * @access public
249 + *
250 + * @return string CSS style.
251 + */
252 + public function __toString() {
253 + $style_text = '';
254 +
255 + foreach ( $this->rules as $query_hash => $rule ) {
256 + $device_text = self::parse_rules( $rule );
257 +
258 + if ( 'all' !== $query_hash ) {
259 + $device_text = $this->get_query_hash_style_format( $query_hash ) . '{' . $device_text . '}';
260 + }
261 +
262 + $style_text .= $device_text;
263 + }
264 +
265 + foreach ( $this->raw as $device_name => $raw ) {
266 + $raw = implode( "\n", $raw );
267 +
268 + if ( $raw && isset( $this->devices[ $device_name ] ) ) {
269 + $raw = '@media(max-width: ' . $this->devices[ $device_name ] . 'px){' . $raw . '}';
270 + }
271 +
272 + $style_text .= $raw;
273 + }
274 +
275 + return $style_text;
276 + }
277 +
278 + /**
279 + * Query to hash.
280 + *
281 + * Turns the media query into a hashed string that represents the query
282 + * endpoint in the rules list.
283 + *
284 + * @since 1.2.0
285 + * @access private
286 + *
287 + * @param array $query CSS media query.
288 + *
289 + * @return string Hashed string of the query.
290 + */
291 + private function query_to_hash( array $query ) {
292 + $hash = [];
293 +
294 + foreach ( $query as $endpoint => $value ) {
295 + $hash[] = $endpoint . '_' . $value;
296 + }
297 +
298 + return implode( '-', $hash );
299 + }
300 +
301 + /**
302 + * Hash to query.
303 + *
304 + * Turns the hashed string to an array that contains the data of the query
305 + * endpoint.
306 + *
307 + * @since 1.2.0
308 + * @access private
309 + *
310 + * @param string $hash Hashed string of the query.
311 + *
312 + * @return array Media query data.
313 + */
314 + private function hash_to_query( $hash ) {
315 + $query = [];
316 +
317 + $hash = array_filter( explode( '-', $hash ) );
318 +
319 + foreach ( $hash as $single_query ) {
320 + preg_match( '/(min|max)_(.*)/', $single_query, $query_parts );
321 +
322 + $end_point = $query_parts[1];
323 +
324 + $device_name = $query_parts[2];
325 +
326 + $query[ $end_point ] = 'max' === $end_point ? $this->devices[ $device_name ] : Plugin::$instance->breakpoints->get_device_min_breakpoint( $device_name );
327 + }
328 +
329 + return $query;
330 + }
331 +
332 + /**
333 + * Add query hash.
334 + *
335 + * Register new endpoint query and sort the rules the way they should be
336 + * displayed in the final stylesheet based on the device and the viewport
337 + * width.
338 + *
339 + * @since 1.2.0
340 + * @access private
341 + *
342 + * @param string $query_hash Hashed string of the query.
343 + */
344 + private function add_query_hash( $query_hash ) {
345 + $this->rules[ $query_hash ] = [];
346 +
347 + uksort(
348 + $this->rules, function( $a, $b ) {
349 + if ( 'all' === $a ) {
350 + return -1;
351 + }
352 +
353 + if ( 'all' === $b ) {
354 + return 1;
355 + }
356 +
357 + $a_query = $this->hash_to_query( $a );
358 +
359 + $b_query = $this->hash_to_query( $b );
360 +
361 + if ( isset( $a_query['min'] ) xor isset( $b_query['min'] ) ) {
362 + return 1;
363 + }
364 +
365 + if ( isset( $a_query['min'] ) ) {
366 + $range = $a_query['min'] - $b_query['min'];
367 +
368 + if ( $range ) {
369 + return $range;
370 + }
371 +
372 + $a_has_max = isset( $a_query['max'] );
373 +
374 + if ( $a_has_max xor isset( $b_query['max'] ) ) {
375 + return $a_has_max ? 1 : -1;
376 + }
377 +
378 + if ( ! $a_has_max ) {
379 + return 0;
380 + }
381 + }
382 +
383 + return $b_query['max'] - $a_query['max'];
384 + }
385 + );
386 + }
387 +
388 + /**
389 + * Get query hash style format.
390 + *
391 + * Retrieve formatted media query rule with the endpoint width settings.
392 + *
393 + * The method returns the CSS `@media` rule and supported viewport width in
394 + * pixels. It can also handle multiple width endpoints.
395 + *
396 + * @since 1.2.0
397 + * @access private
398 + *
399 + * @param string $query_hash The hash of the query.
400 + *
401 + * @return string CSS media query.
402 + */
403 + private function get_query_hash_style_format( $query_hash ) {
404 + $query = $this->hash_to_query( $query_hash );
405 +
406 + $style_format = [];
407 +
408 + foreach ( $query as $end_point => $value ) {
409 + $style_format[] = '(' . $end_point . '-width:' . $value . 'px)';
410 + }
411 +
412 + return '@media' . implode( ' and ', $style_format );
413 + }
414 + }
415 +