PluginProbe
TablePress – Tables in WordPress made easy / 3.4
TablePress – Tables in WordPress made easy v3.4
3.4 3.3.4 3.3.3 3.3.2 3.3.1 trunk 1.12 1.14 1.9.2 2.0.4 2.1.7 2.1.8 2.2 2.2.1 2.2.2 2.2.3 2.2.4 2.2.5 2.3 2.3.1 2.3.2 2.4 2.4.1 2.4.2 2.4.3 All 45 releases
← All changes | libraries/csstidy/class.csstidy.php +265 -330 2.1.7 → 3.4 View file →
@@ -7,28 +7,14 @@
7 7 * @author Florian Schmitz, Brett Zamir, Nikolay Matsievsky, Cedric Morin, Christopher Finke, Mark Scherer, Tobias Bäthge
8 8 * @since 1.0.0
9 9 */
10 10
11 +declare(strict_types=1);
12 +
11 13 // Prohibit direct script loading.
12 14 defined( 'ABSPATH' ) || die( 'No direct script access allowed!' );
13 15
14 16 /**
15 - * Defines constants.
16 - *
17 - * @TODO: Make these class constants of CSSTidy.
18 - * @since 1.0.0
19 - */
20 -define( 'AT_START', 1 );
21 -define( 'AT_END', 2 );
22 -define( 'SEL_START', 3 );
23 -define( 'SEL_END', 4 );
24 -define( 'PROPERTY', 5 );
25 -define( 'VALUE', 6 );
26 -define( 'COMMENT', 7 );
27 -define( 'IMPORTANT_COMMENT', 8 );
28 -define( 'DEFAULT_AT', 41 );
29 -
30 -/**
31 17 * Load the class for printing CSS code.
32 18 *
33 19 * @since 1.0.0
34 20 */
@@ -54,72 +40,79 @@
54 40 */
55 41 class TablePress_CSSTidy {
56 42
57 43 /**
44 + * Defines constants.
45 + *
46 + * @since 1.0.0
47 + */
48 + public const AT_START = 1;
49 + public const AT_END = 2;
50 + public const SEL_START = 3;
51 + public const SEL_END = 4;
52 + public const PROPERTY = 5;
53 + public const VALUE = 6;
54 + public const COMMENT = 7;
55 + public const IMPORTANT_COMMENT = 8;
56 + public const DEFAULT_AT = 41;
57 +
58 + /**
58 59 * The parsed CSS.
59 60 *
60 61 * This array is empty if preserve_css is on.
61 62 *
62 63 * @since 1.0.0
63 - * @var array
64 64 */
65 - public $css = array();
65 + public array $css = array();
66 66
67 67 /**
68 68 * The raw parsed CSS.
69 69 *
70 70 * @since 1.0.0
71 - * @var array
72 71 */
73 - public $tokens = array();
72 + public array $tokens = array();
74 73
75 74 /**
76 75 * Instance of the CSS Printer class.
77 76 *
78 77 * @since 1.0.0
79 - * @var TablePress_CSSTidy_print
80 78 */
81 - public $print;
79 + public \TablePress_CSSTidy_Print $print;
82 80
83 81 /**
84 82 * Instance of the CSS Optimiser class.
85 83 *
86 84 * @since 1.0.0
87 - * @var TablePress_CSSTidy_optimise
88 85 */
89 - public $optimise;
86 + public \TablePress_CSSTidy_Optimise $optimise;
90 87
91 88 /**
92 89 * The CSS charset.
93 90 *
94 91 * @since 1.0.0
95 - * @var string
96 92 */
97 - public $charset = '';
93 + public string $charset = '';
98 94
99 95 /**
100 96 * All @import URLs.
101 97 *
102 98 * @since 1.0.0
103 - * @var array
104 99 */
105 - public $import = array();
100 + public array $import = array();
106 101
107 102 /**
108 103 * The namespace.
109 104 *
110 105 * @since 1.0.0
111 - * @var string
112 106 */
113 - public $namespace = '';
107 + public string $namespace = '';
114 108
115 109 /**
116 110 * The settings.
117 111 *
118 112 * @since 1.0.0
119 - * @var array
120 113 */
121 - protected $settings = array();
114 + protected array $settings = array();
122 115
123 116 /**
124 117 * The parser-status.
125 118 *
@@ -131,25 +124,23 @@
131 124 * - ic = in comment (ignore everything)
132 125 * - at = in @-block
133 126 *
134 127 * @since 1.0.0
135 - * @var string
136 128 */
137 - protected $status = 'is';
129 + protected string $status = 'is';
138 130
139 131 /**
140 132 * The current at rule (@media).
141 133 *
142 134 * @since 1.0.0
143 - * @var string
144 135 */
145 - public $at = '';
136 + public string $at = '';
146 137
147 138 /**
148 139 * The at rule for next selector (during @font-face or other @).
149 140 *
150 141 * @since 1.0.0
151 - * @var string
142 + * @var string|int
152 143 */
153 144 protected $next_selector_at = '';
154 145
155 146 /**
@@ -155,35 +146,31 @@
155 146 /**
156 147 * The current selector.
157 148 *
158 149 * @since 1.0.0
159 - * @var string
160 150 */
161 - public $selector = '';
151 + public string $selector = '';
162 152
163 153 /**
164 154 * The current property.
165 155 *
166 156 * @since 1.0.0
167 - * @var string
168 157 */
169 - public $property = '';
158 + public string $property = '';
170 159
171 160 /**
172 161 * The position of , in selectors.
173 162 *
174 163 * @since 1.0.0
175 - * @var array
176 164 */
177 - protected $sel_separate = array();
165 + protected array $sel_separate = array();
178 166
179 167 /**
180 168 * The current value.
181 169 *
182 170 * @since 1.0.0
183 - * @var string
184 171 */
185 - public $value = '';
172 + public string $value = '';
186 173
187 174 /**
188 175 * The current sub-value.
189 176 *
@@ -192,107 +179,94 @@
192 179 * "url(foo.png)", "red", and "no-repeat" are sub-values,
193 180 * separated by whitespace.
194 181 *
195 182 * @since 1.0.0
196 - * @var string
197 183 */
198 - public $sub_value = '';
184 + public string $sub_value = '';
199 185
200 186 /**
201 187 * All sub-values for a property.
202 188 *
203 189 * @since 1.0.0
204 - * @var array
205 190 */
206 - protected $sub_value_arr = array();
191 + protected array $sub_value_arr = array();
207 192
208 193 /**
209 194 * The stack of characters that opened the current strings.
210 195 *
211 196 * @since 1.0.0
212 - * @var array
213 197 */
214 - public $str_char = array();
198 + public array $str_char = array();
215 199
216 200 /**
217 201 * [$cur_string description]
218 202 *
219 203 * @since 1.0.0
220 - * @var array
221 204 */
222 - public $cur_string = array();
205 + public array $cur_string = array();
223 206
224 207 /**
225 208 * Status from which the parser switched to ic or instr
226 209 *
227 210 * @since 1.0.0
228 - * @var array
229 211 */
230 - protected $from = array();
212 + protected array $from = array();
231 213
232 214 /**
233 215 * True if in invalid at-rule.
234 216 *
235 217 * @since 1.0.0
236 - * @var bool
237 218 */
238 - protected $invalid_at = false;
219 + protected bool $invalid_at = false;
239 220
240 221 /**
241 222 * True if something has been added to the current selector.
242 223 *
243 224 * @since 1.0.0
244 - * @var bool
245 225 */
246 - protected $added = false;
226 + protected bool $added = false;
247 227
248 228 /**
249 229 * The message log.
250 230 *
251 231 * @since 1.0.0
252 - * @var array
253 232 */
254 - public $log = array();
233 + public array $log = array();
255 234
256 235 /**
257 236 * The line number.
258 237 *
259 238 * @since 1.0.0
260 - * @var int
261 239 */
262 - protected $line = 1;
240 + protected int $line = 1;
263 241
264 242 /**
265 243 * Marks if we need to leave quotes for a string.
266 244 *
267 245 * @since 1.0.0
268 - * @var array
269 246 */
270 - protected $quoted_string = array();
247 + protected array $quoted_string = array();
271 248
272 249 /**
273 250 * List of tokens.
274 251 *
275 252 * @since 1.0.0
276 - * @var string
277 253 */
278 - protected $tokens_list = '';
254 + protected string $tokens_list = '';
279 255
280 256 /**
281 257 * Various CSS Data for CSSTidy.
282 258 *
283 259 * @since 1.0.0
284 - * @var array
285 260 */
286 - public $data = array();
261 + public array $data = array();
287 262
288 263 /**
289 264 * The output templates.
290 265 *
291 266 * @since 1.0.0
292 - * @var array
293 267 */
294 - public $template = array();
268 + public array $template = array();
295 269
296 270 /**
297 271 * Loads standard template and sets default settings.
298 272 *
@@ -304,8 +278,9 @@
304 278 $this->settings['remove_bslash'] = true;
305 279 $this->settings['compress_colors'] = true;
306 280 $this->settings['compress_font-weight'] = true;
307 281 $this->settings['lowercase_s'] = false;
282 +
308 283 /*
309 284 * 1 common shorthands optimization
310 285 * 2 + font property optimization
311 286 * 3 + background property optimization
@@ -313,13 +288,15 @@
313 288 $this->settings['optimise_shorthands'] = 1;
314 289 $this->settings['remove_last_;'] = true;
315 290 // Rewrite all properties with lower case, better for later gzipping.
316 291 $this->settings['case_properties'] = 1;
292 +
317 293 /*
318 - * Sort properties in alpabetic order, better for later gzipping,
319 - * but can cause trouble in case of overiding same properties or using hacks.
294 + * Sort properties in alphabetic order, better for later gzipping,
295 + * but can cause trouble in case of overriding same properties or using hacks.
320 296 */
321 297 $this->settings['sort_properties'] = false;
298 +
322 299 /*
323 300 * 1, 3, 5, etc -- Enable sorting selectors inside @media: a{}b{}c{}.
324 301 * 2, 5, 8, etc -- Enable sorting selectors inside one CSS declaration: a,b,c{}.
325 302 * Preserve order by default cause it can break functionality.
@@ -335,16 +312,16 @@
335 312 $this->settings['timestamp'] = false;
336 313 $this->settings['template'] = ''; // say that property exists.
337 314 $this->set_cfg( 'template', 'default' ); // Call load_template.
338 315
339 - $this->print = new TablePress_CSSTidy_print( $this );
340 - $this->optimise = new TablePress_CSSTidy_optimise( $this );
316 + $this->print = new TablePress_CSSTidy_Print( $this );
317 + $this->optimise = new TablePress_CSSTidy_Optimise( $this );
341 318
342 319 $this->tokens_list = &$this->data['csstidy']['tokens'];
343 320 }
344 321
345 322 /**
346 - * Get the value of a setting.
323 + * Gets the value of a setting.
347 324 *
348 325 * @since 1.0.0
349 326 *
350 327 * @param string $setting Setting to get.
@@ -349,9 +326,9 @@
349 326 *
350 327 * @param string $setting Setting to get.
351 328 * @return string|int|bool Value of the setting.
352 329 */
353 - public function get_cfg( $setting ) {
330 + public function get_cfg( string $setting ) /* : string|int|bool */ {
354 331 if ( isset( $this->settings[ $setting ] ) ) {
355 332 return $this->settings[ $setting ];
356 333 }
357 334 return false;
@@ -357,17 +334,17 @@
357 334 return false;
358 335 }
359 336
360 337 /**
361 - * Set the value of a setting.
338 + * Sets the value of a setting.
362 339 *
363 340 * @since 1.0.0
364 341 *
365 - * @param string $setting Setting.
366 - * @param mixed $value Optional. Value of the setting.
367 - * @return bool [return value]
342 + * @param string $setting Setting.
343 + * @param string|int|bool|null $value Optional. Value of the setting.
344 + * @return bool Whether the setting was set.
368 345 */
369 - public function set_cfg( $setting, $value = null ) {
346 + public function set_cfg( string $setting, $value = null ): bool {
370 347 if ( isset( $this->settings[ $setting ] ) && '' !== $value ) {
371 348 $this->settings[ $setting ] = $value;
372 349 if ( 'template' === $setting ) {
373 350 $this->load_template( $this->settings['template'] );
@@ -381,29 +358,29 @@
381 358 * Adds a token to $this->tokens.
382 359 *
383 360 * @since 1.0.0
384 361 *
385 - * @param mixed $type Type.
386 - * @param string $data Data.
387 - * @param bool $do Optional. Add a token even if preserve_css is off.
362 + * @param mixed $type Type.
363 + * @param string $data Data.
364 + * @param bool $force Optional. Add a token even if preserve_css is off.
388 365 */
389 - public function _add_token( $type, $data, $do = false ) {
390 - if ( $this->get_cfg( 'preserve_css' ) || $do ) {
366 + public function _add_token( $type, string $data, bool $force = false ): void {
367 + if ( $this->get_cfg( 'preserve_css' ) || $force ) {
391 368 // nested @...: if opening a new part we just closed, remove the previous closing instead of adding opening.
392 - if ( AT_START === $type
369 + if ( self::AT_START === $type
393 370 && count( $this->tokens )
394 - && ( $last = end( $this->tokens ) )
395 - && AT_END === $last[0]
371 + && ( $last = end( $this->tokens ) ) // phpcs:ignore Generic.CodeAnalysis.AssignmentInCondition.Found,Squiz.PHP.DisallowMultipleAssignments.FoundInControlStructure
372 + && self::AT_END === $last[0]
396 373 && trim( $data ) === $last[1] ) {
397 374 array_pop( $this->tokens );
398 375 } else {
399 - $this->tokens[] = array( $type, ( COMMENT === $type || IMPORTANT_COMMENT === $type ) ? $data : trim( $data ) );
376 + $this->tokens[] = array( $type, ( self::COMMENT === $type || self::IMPORTANT_COMMENT === $type ) ? $data : trim( $data ) );
400 377 }
401 378 }
402 379 }
403 380
404 381 /**
405 - * Add a message to the message log.
382 + * Adds a message to the message log.
406 383 *
407 384 * @since 1.0.0
408 385 *
409 386 * @param string $message Message.
@@ -409,9 +386,9 @@
409 386 * @param string $message Message.
410 387 * @param string $type Type.
411 388 * @param int $line Optional. Line number. -1 will use the current line.
412 389 */
413 - public function log( $message, $type, $line = -1 ) {
390 + public function log( string $message, string $type, int $line = -1 ): void {
414 391 if ( -1 === $line ) {
415 392 $line = $this->line;
416 393 }
417 394 $line = (int) $line;
@@ -424,30 +401,30 @@
424 401 }
425 402 }
426 403
427 404 /**
428 - * Parse Unicode notations and find a replacement character.
405 + * Parses Unicode notations and find a replacement character.
429 406 *
430 407 * @since 1.0.0
431 408 *
432 - * @param string $string String.
433 - * @param int $i i.
409 + * @param string $a_string String.
410 + * @param int $i i.
434 411 * @return string [return value]
435 412 */
436 - public function _unicode( &$string, &$i ) {
413 + public function _unicode( string &$a_string, int &$i ): string {
437 414 ++$i;
438 415 $add = '';
439 416 $replaced = false;
440 417
441 - while ( $i < strlen( $string ) && ( ctype_xdigit( $string[ $i ] ) || ctype_space( $string[ $i ] ) ) && strlen( $add ) < 6 ) {
442 - $add .= $string[ $i ];
443 - if ( ctype_space( $string[ $i ] ) ) {
418 + while ( $i < strlen( $a_string ) && ( ctype_xdigit( $a_string[ $i ] ) || ctype_space( $a_string[ $i ] ) ) && strlen( $add ) < 6 ) { // phpcs:ignore Squiz.PHP.DisallowSizeFunctionsInLoops.Found
419 + $add .= $a_string[ $i ];
420 + if ( ctype_space( $a_string[ $i ] ) ) {
444 421 break;
445 422 }
446 - $i++;
423 + ++$i;
447 424 }
448 425
449 - if ( hexdec( $add ) > 47 && hexdec( $add ) < 58 || hexdec( $add ) > 64 && hexdec( $add ) < 91 || hexdec( $add ) > 96 && hexdec( $add ) < 123 ) {
426 + if ( ( hexdec( $add ) > 47 && hexdec( $add ) < 58 ) || ( hexdec( $add ) > 64 && hexdec( $add ) < 91 ) || ( hexdec( $add ) > 96 && hexdec( $add ) < 123 ) ) {
450 427 $this->log( 'Replaced unicode notation: Changed \\' . $add . ' to ' . chr( hexdec( $add ) ), 'Information' );
451 428 $add = chr( hexdec( $add ) );
452 429 $replaced = true;
453 430 } else {
@@ -453,13 +430,13 @@
453 430 } else {
454 431 $add = trim( '\\' . $add );
455 432 }
456 433
457 - if ( @ctype_xdigit( $string[ $i + 1 ] ) && ctype_space( $string[ $i ] ) && ! $replaced || ! ctype_space( $string[ $i ] ) ) {
458 - $i--;
434 + if ( ( @ctype_xdigit( $a_string[ $i + 1 ] ) && ctype_space( $a_string[ $i ] ) && ! $replaced ) || ! ctype_space( $a_string[ $i ] ) ) { // phpcs:ignore WordPress.PHP.NoSilencedErrors.Discouraged
435 + --$i;
459 436 }
460 437
461 - if ( '\\' !== $add || ! $this->get_cfg( 'remove_bslash' ) || false !== strpos( $this->tokens_list, $string[ $i + 1 ] ) ) {
438 + if ( '\\' !== $add || ! $this->get_cfg( 'remove_bslash' ) || str_contains( $this->tokens_list, $a_string[ $i + 1 ] ) ) {
462 439 return $add;
463 440 }
464 441
465 442 if ( '\\' === $add ) {
@@ -469,62 +446,18 @@
469 446 return '';
470 447 }
471 448
472 449 /**
473 - * Write formatted output to a file.
474 - *
475 - * @since 1.0.0
476 - *
477 - * @param string $filename File name.
478 - */
479 - public function write_page( $filename ) {
480 - $this->write( $filename, true );
481 - }
482 -
483 - /**
484 - * Write plain output to a file.
485 - *
486 - * @since 1.0.0
487 - *
488 - * @param string $filename File name.
489 - * @param bool $formatted Optional. Whether to print formatted or not.
490 - * @param string $doctype Optional. When printing formatted, is a shorthand for the document type.
491 - * @param bool $externalcss Optional. When printing formatted, indicates whether styles to be attached internally or as an external stylesheet.
492 - * @param string $title Optional. When printing formatted, is the title to be added in the head of the document.
493 - * @param string $lang Optional. When printing formatted, gives a two-letter language code to be added to the output.
494 - */
495 - public function write( $filename, $formatted = false, $doctype = 'xhtml1.1', $externalcss = true, $title = '', $lang = 'en' ) {
496 - $filename .= ( $formatted ) ? '.xhtml' : '.css';
497 -
498 - if ( ! is_dir( 'temp' ) ) {
499 - $madedir = mkdir( 'temp' );
500 - if ( ! $madedir ) {
501 - print 'Could not make directory "temp" in ' . __DIR__;
502 - exit;
503 - }
504 - }
505 - $handle = fopen( 'temp/' . $filename, 'w' );
506 - if ( $handle ) {
507 - if ( ! $formatted ) {
508 - fwrite( $handle, $this->print->plain() );
509 - } else {
510 - fwrite( $handle, $this->print->formatted_page( $doctype, $externalcss, $title, $lang ) );
511 - }
512 - }
513 - fclose( $handle );
514 - }
515 -
516 - /**
517 450 * Loads a new template.
518 451 *
519 452 * @since 1.0.0
520 453 *
521 - * @link http://csstidy.sourceforge.net/templates.php
454 + * @link https://csstidy.sourceforge.net/templates.php
522 455 *
523 456 * @param string $content Either file name (if $from_file is true), content of a template file, "default", "low", high", or "highest".
524 457 * @param bool $from_file Optional. Uses $content as filename if true.
525 458 */
526 - protected function load_template( $content, $from_file = true ) {
459 + protected function load_template( string $content, bool $from_file = true ): void {
527 460 if ( in_array( $content, array( 'default', 'low', 'high', 'highest' ), true ) ) {
528 461 $this->template = $this->data['csstidy']['predefined_templates'][ $content ];
529 462 return;
530 463 }
@@ -543,12 +476,16 @@
543 476 *
544 477 * @since 1.0.0
545 478 *
546 479 * @param string $url URL.
547 - * @return bool
480 + * @return bool Whether the CSS code could be parsed successfully.
548 481 */
549 - protected function parse_from_url( $url ) {
550 - return $this->parse( @file_get_contents( $url ) );
482 + protected function parse_from_url( string $url ): bool {
483 + $data = file_get_contents( $url );
484 + if ( false === $data ) {
485 + return false;
486 + }
487 + return $this->parse( $data );
551 488 }
552 489
553 490 /**
554 491 * Checks if there is a token at the current position.
@@ -554,14 +491,14 @@
554 491 * Checks if there is a token at the current position.
555 492 *
556 493 * @since 1.0.0
557 494 *
558 - * @param string $string String.
495 + * @param string $a_string String.
559 496 * @param int $i i.
560 497 * @return bool [return value]
561 498 */
562 - protected function is_token( &$string, $i ) {
563 - return ( false !== strpos( $this->tokens_list, $string[ $i ] ) && ! $this->escaped( $string, $i ) );
499 + protected function is_token( string &$a_string, int $i ): bool {
500 + return ( str_contains( $this->tokens_list, $a_string[ $i ] ) && ! $this->escaped( $a_string, $i ) );
564 501 }
565 502
566 503 /**
567 504 * Parses CSS in a string. The output is saved as an array in $this->css.
@@ -567,27 +504,27 @@
567 504 * Parses CSS in a string. The output is saved as an array in $this->css.
568 505 *
569 506 * @since 1.0.0
570 507 *
571 - * @param string $string The CSS code.
572 - * @return bool [return value]
508 + * @param string $a_string The CSS code.
509 + * @return bool Whether the CSS code could be parsed successfully.
573 510 */
574 - public function parse( $string ) {
511 + public function parse( string $a_string ): bool {
575 512 // Temporarily set locale to en_US in order to handle floats properly.
576 - $old = @setlocale( LC_ALL, 0 );
577 - @setlocale( LC_ALL, 'C' );
513 + $old = @setlocale( LC_ALL, '0' ); // phpcs:ignore WordPress.PHP.NoSilencedErrors.Discouraged
514 + @setlocale( LC_ALL, 'C' ); // phpcs:ignore WordPress.PHP.NoSilencedErrors.Discouraged
578 515
579 516 $at_rules = &$this->data['csstidy']['at_rules'];
580 517 $quoted_string_properties = &$this->data['csstidy']['quoted_string_properties'];
581 518
582 519 $this->css = array();
583 - $this->print->input_css = $string;
584 - $string = str_replace( "\r\n", "\n", $string ) . ' ';
520 + $this->print->input_css = $a_string;
521 + $a_string = str_replace( "\r\n", "\n", $a_string ) . ' ';
585 522 $cur_comment = '';
586 523 $cur_at = '';
587 524
588 - for ( $i = 0, $size = strlen( $string ); $i < $size; $i++ ) {
589 - if ( "\n" === $string[ $i ] || "\r" === $string[ $i ] ) {
525 + for ( $i = 0, $size = strlen( $a_string ); $i < $size; $i++ ) {
526 + if ( "\n" === $a_string[ $i ] || "\r" === $a_string[ $i ] ) {
590 527 ++$this->line;
591 528 }
592 529
593 530 switch ( $this->status ) {
@@ -592,46 +529,45 @@
592 529
593 530 switch ( $this->status ) {
594 531 /* Case in at-block */
595 532 case 'at':
596 - if ( $this->is_token( $string, $i ) ) {
597 - if ( '/' === $string[ $i ] && '*' === @$string[ $i + 1 ] ) {
533 + if ( $this->is_token( $a_string, $i ) ) {
534 + if ( '/' === $a_string[ $i ] && '*' === @$a_string[ $i + 1 ] ) { // phpcs:ignore WordPress.PHP.NoSilencedErrors.Discouraged
598 535 $this->status = 'ic';
599 536 ++$i;
600 537 $this->from[] = 'at';
601 - } elseif ( '{' === $string[ $i ] ) {
538 + } elseif ( '{' === $a_string[ $i ] ) {
602 539 $this->status = 'is';
603 540 $this->at = $this->css_new_media_section( $this->at, $cur_at );
604 - $this->_add_token( AT_START, $this->at );
605 - } elseif ( ',' === $string[ $i ] ) {
541 + $this->_add_token( self::AT_START, $this->at );
542 + } elseif ( ',' === $a_string[ $i ] ) {
606 543 $cur_at = trim( $cur_at ) . ',';
607 - } elseif ( '\\' === $string[ $i ] ) {
608 - $cur_at .= $this->_unicode( $string, $i );
544 + } elseif ( '\\' === $a_string[ $i ] ) {
545 + $cur_at .= $this->_unicode( $a_string, $i );
546 + } elseif ( in_array( $a_string[ $i ], array( '(', ')', ':', '.', '/' ), true ) ) {
547 + // Fix for complicated media, i.e @media screen and (-webkit-min-device-pixel-ratio:1.5).
548 + // '/' is included for ratios in Opera: (-o-min-device-pixel-ratio: 3/2).
549 + $cur_at .= $a_string[ $i ];
609 550 }
610 - // Fix for complicated media, i.e @media screen and (-webkit-min-device-pixel-ratio:1.5)
611 - // '/' is included for ratios in Opera: (-o-min-device-pixel-ratio: 3/2)
612 - elseif ( in_array( $string[ $i ], array( '(', ')', ':', '.', '/' ), true ) ) {
613 - $cur_at .= $string[ $i ];
614 - }
615 551 } else {
616 552 $lastpos = strlen( $cur_at ) - 1;
617 - if ( ! ( ( ctype_space( $cur_at[ $lastpos ] ) || $this->is_token( $cur_at, $lastpos ) && ',' === $cur_at[ $lastpos ] ) && ctype_space( $string[ $i ] ) ) ) {
618 - $cur_at .= $string[ $i ];
553 + if ( ! ( ( ctype_space( $cur_at[ $lastpos ] ) || ( $this->is_token( $cur_at, $lastpos ) && ',' === $cur_at[ $lastpos ] ) ) && ctype_space( $a_string[ $i ] ) ) ) {
554 + $cur_at .= $a_string[ $i ];
619 555 }
620 556 }
621 557 break;
622 558 /* Case in-selector */
623 559 case 'is':
624 - if ( $this->is_token( $string, $i ) ) {
625 - if ( '/' === $string[ $i ] && '*' === @$string[ $i + 1 ] && '' === trim( $this->selector ) ) {
560 + if ( $this->is_token( $a_string, $i ) ) {
561 + if ( '/' === $a_string[ $i ] && '*' === @$a_string[ $i + 1 ] && '' === trim( $this->selector ) ) { // phpcs:ignore WordPress.PHP.NoSilencedErrors.Discouraged
626 562 $this->status = 'ic';
627 563 ++$i;
628 564 $this->from[] = 'is';
629 - } elseif ( '@' === $string[ $i ] && '' === trim( $this->selector ) ) {
565 + } elseif ( '@' === $a_string[ $i ] && '' === trim( $this->selector ) ) { // phpcs:ignore WordPress.PHP.NoSilencedErrors.Discouraged
630 566 // Check for at-rule.
631 567 $this->invalid_at = true;
632 568 foreach ( $at_rules as $name => $type ) {
633 - if ( ! strcasecmp( substr( $string, $i + 1, strlen( $name ) ), $name ) ) {
569 + if ( ! strcasecmp( substr( $a_string, $i + 1, strlen( $name ) ), $name ) ) {
634 570 if ( 'at' === $type ) {
635 571 $cur_at = '@' . $name;
636 572 } else {
637 573 $this->selector = '@' . $name;
@@ -636,9 +572,9 @@
636 572 } else {
637 573 $this->selector = '@' . $name;
638 574 }
639 575 if ( 'atis' === $type ) {
640 - $this->next_selector_at = ( $this->next_selector_at ? $this->next_selector_at : ( $this->at ? $this->at : DEFAULT_AT ) );
576 + $this->next_selector_at = ( $this->next_selector_at ? $this->next_selector_at : ( $this->at ? $this->at : self::DEFAULT_AT ) );
641 577 $this->at = $this->css_new_media_section( $this->at, ' ', true );
642 578 $type = 'is';
643 579 }
644 580 $this->status = $type;
@@ -651,23 +587,23 @@
651 587 if ( $this->invalid_at ) {
652 588 $this->selector = '@';
653 589 $invalid_at_name = '';
654 590 for ( $j = $i + 1; $j < $size; ++$j ) {
655 - if ( ! ctype_alpha( $string[ $j ] ) ) {
591 + if ( ! ctype_alpha( $a_string[ $j ] ) ) {
656 592 break;
657 593 }
658 - $invalid_at_name .= $string[ $j ];
594 + $invalid_at_name .= $a_string[ $j ];
659 595 }
660 596 $this->log( 'Invalid @-rule: ' . $invalid_at_name . ' (removed)', 'Warning' );
661 597 }
662 - } elseif ( ( '"' === $string[ $i ] || "'" === $string[ $i ] ) ) {
663 - $this->cur_string[] = $string[ $i ];
598 + } elseif ( ( '"' === $a_string[ $i ] || "'" === $a_string[ $i ] ) ) {
599 + $this->cur_string[] = $a_string[ $i ];
664 600 $this->status = 'instr';
665 - $this->str_char[] = $string[ $i ];
601 + $this->str_char[] = $a_string[ $i ];
666 602 $this->from[] = 'is';
667 603 /* Fixing CSS3 attribute selectors, i.e. a[href$=".mp3" */
668 - $this->quoted_string[] = ( '=' === $string[ $i - 1 ] );
669 - } elseif ( $this->invalid_at && ';' === $string[ $i ] ) {
604 + $this->quoted_string[] = ( '=' === $a_string[ $i - 1 ] );
605 + } elseif ( $this->invalid_at && ';' === $a_string[ $i ] ) {
670 606 $this->invalid_at = false;
671 607 $this->status = 'is';
672 608 if ( $this->next_selector_at ) {
673 609 $this->at = $this->css_close_media_section( $this->at );
@@ -673,57 +609,57 @@
673 609 $this->at = $this->css_close_media_section( $this->at );
674 610 $this->at = $this->css_new_media_section( $this->at, $this->next_selector_at );
675 611 $this->next_selector_at = '';
676 612 }
677 - } elseif ( '{' === $string[ $i ] ) {
613 + } elseif ( '{' === $a_string[ $i ] ) {
678 614 $this->status = 'ip';
679 615 if ( '' === $this->at ) {
680 - $this->at = $this->css_new_media_section( $this->at, DEFAULT_AT );
616 + $this->at = $this->css_new_media_section( $this->at, (string) self::DEFAULT_AT );
681 617 }
682 618 $this->selector = $this->css_new_selector( $this->at, $this->selector );
683 - $this->_add_token( SEL_START, $this->selector );
619 + $this->_add_token( self::SEL_START, $this->selector );
684 620 $this->added = false;
685 - } elseif ( '}' === $string[ $i ] ) {
686 - $this->_add_token( AT_END, $this->at );
621 + } elseif ( '}' === $a_string[ $i ] ) {
622 + $this->_add_token( self::AT_END, $this->at );
687 623 $this->at = $this->css_close_media_section( $this->at );
688 624 $this->selector = '';
689 625 $this->sel_separate = array();
690 - } elseif ( ',' === $string[ $i ] ) {
626 + } elseif ( ',' === $a_string[ $i ] ) {
691 627 $this->selector = trim( $this->selector ) . ',';
692 628 $this->sel_separate[] = strlen( $this->selector );
693 - } elseif ( '\\' === $string[ $i ] ) {
694 - $this->selector .= $this->_unicode( $string, $i );
695 - } elseif ( '*' === $string[ $i ] && @in_array( $string[ $i + 1 ], array( '.', '#', '[', ':' ), true ) && ( 0 === $i || '/' !== $string[ $i - 1 ] ) ) {
629 + } elseif ( '\\' === $a_string[ $i ] ) {
630 + $this->selector .= $this->_unicode( $a_string, $i );
631 + } elseif ( '*' === $a_string[ $i ] && @in_array( $a_string[ $i + 1 ], array( '.', '#', '[', ':' ), true ) && ( 0 === $i || '/' !== $a_string[ $i - 1 ] ) ) { // phpcs:ignore WordPress.PHP.NoSilencedErrors.Discouraged,Generic.CodeAnalysis.EmptyStatement.DetectedElseif
696 632 // Remove unnecessary universal selector, FS#147, but not comment in selector.
697 633 } else {
698 - $this->selector .= $string[ $i ];
634 + $this->selector .= $a_string[ $i ];
699 635 }
700 636 } else {
701 637 $lastpos = strlen( $this->selector ) - 1;
702 - if ( -1 === $lastpos || ! ( ( ctype_space( $this->selector[ $lastpos ] ) || $this->is_token( $this->selector, $lastpos ) && ',' === $this->selector[ $lastpos ] ) && ctype_space( $string[ $i ] ) ) ) {
703 - $this->selector .= $string[ $i ];
638 + if ( -1 === $lastpos || ! ( ( ctype_space( $this->selector[ $lastpos ] ) || ( $this->is_token( $this->selector, $lastpos ) && ',' === $this->selector[ $lastpos ] ) ) && ctype_space( $a_string[ $i ] ) ) ) {
639 + $this->selector .= $a_string[ $i ];
704 640 }
705 641 }
706 642 break;
707 643 /* Case in-property */
708 644 case 'ip':
709 - if ( $this->is_token( $string, $i ) ) {
710 - if ( ( ':' === $string[ $i ] || '=' === $string[ $i ] ) && '' !== $this->property ) {
645 + if ( $this->is_token( $a_string, $i ) ) {
646 + if ( ( ':' === $a_string[ $i ] || '=' === $a_string[ $i ] ) && '' !== $this->property ) {
711 647 $this->status = 'iv';
712 648 if ( ! $this->get_cfg( 'discard_invalid_properties' ) || $this->property_is_valid( $this->property ) ) {
713 649 $this->property = $this->css_new_property( $this->at, $this->selector, $this->property );
714 650 $this->property = strtolower( $this->property );
715 - $this->_add_token( PROPERTY, $this->property );
651 + $this->_add_token( self::PROPERTY, $this->property );
716 652 }
717 - } elseif ( '/' === $string[ $i ] && '*' === @$string[ $i + 1 ] && '' === $this->property ) {
653 + } elseif ( '/' === $a_string[ $i ] && '*' === @$a_string[ $i + 1 ] && '' === $this->property ) { // phpcs:ignore WordPress.PHP.NoSilencedErrors.Discouraged
718 654 $this->status = 'ic';
719 655 ++$i;
720 656 $this->from[] = 'ip';
721 - } elseif ( '}' === $string[ $i ] ) {
657 + } elseif ( '}' === $a_string[ $i ] ) {
722 658 $this->explode_selectors();
723 659 $this->status = 'is';
724 660 $this->invalid_at = false;
725 - $this->_add_token( SEL_END, $this->selector );
661 + $this->_add_token( self::SEL_END, $this->selector );
726 662 $this->selector = '';
727 663 $this->property = '';
728 664 if ( $this->next_selector_at ) {
729 665 $this->at = $this->css_close_media_section( $this->at );
@@ -729,42 +665,41 @@
729 665 $this->at = $this->css_close_media_section( $this->at );
730 666 $this->at = $this->css_new_media_section( $this->at, $this->next_selector_at );
731 667 $this->next_selector_at = '';
732 668 }
733 - } elseif ( ';' === $string[ $i ] ) {
669 + } elseif ( ';' === $a_string[ $i ] ) {
734 670 $this->property = '';
735 - } elseif ( '\\' === $string[ $i ] ) {
736 - $this->property .= $this->_unicode( $string, $i );
671 + } elseif ( '\\' === $a_string[ $i ] ) {
672 + $this->property .= $this->_unicode( $a_string, $i );
673 + } elseif ( ( '' === $this->property && ! ctype_space( $a_string[ $i ] ) ) || ( '/' === $this->property || '/' === $a_string[ $i ] ) ) {
674 + // else this is dumb IE a hack, keep it.
675 + // including /.
676 + $this->property .= $a_string[ $i ];
737 677 }
738 - // else this is dumb IE a hack, keep it
739 - // including /
740 - elseif ( ( '' === $this->property && ! ctype_space( $string[ $i ] ) ) || ( '/' === $this->property || '/' === $string[ $i ] ) ) {
741 - $this->property .= $string[ $i ];
742 - }
743 - } elseif ( ! ctype_space( $string[ $i ] ) ) {
744 - $this->property .= $string[ $i ];
678 + } elseif ( ! ctype_space( $a_string[ $i ] ) ) {
679 + $this->property .= $a_string[ $i ];
745 680 }
746 681 break;
747 682 /* Case in-value */
748 683 case 'iv':
749 - $pn = ( ( "\n" === $string[ $i ] || "\r" === $string[ $i ] ) && $this->property_is_next( $string, $i + 1 ) || ( strlen( $string ) - 1 ) === $i );
750 - if ( ( $this->is_token( $string, $i ) || $pn ) && ( ! ( ',' === $string[ $i ] && ! ctype_space( $string[ $i + 1 ] ) ) ) ) {
751 - if ( '/' === $string[ $i ] && '*' === @$string[ $i + 1 ] ) {
684 + $pn = ( ( ( "\n" === $a_string[ $i ] || "\r" === $a_string[ $i ] ) && $this->property_is_next( $a_string, $i + 1 ) ) || ( strlen( $a_string ) - 1 ) === $i );
685 + if ( ( $this->is_token( $a_string, $i ) || $pn ) && ( ! ( ',' === $a_string[ $i ] && ! ctype_space( $a_string[ $i + 1 ] ) ) ) ) {
686 + if ( '/' === $a_string[ $i ] && '*' === @$a_string[ $i + 1 ] ) { // phpcs:ignore WordPress.PHP.NoSilencedErrors.Discouraged
752 687 $this->status = 'ic';
753 688 ++$i;
754 689 $this->from[] = 'iv';
755 - } elseif ( ( '"' === $string[ $i ] || "'" === $string[ $i ] || '(' === $string[ $i ] ) ) {
756 - $this->cur_string[] = $string[ $i ];
757 - $this->str_char[] = ( '(' === $string[ $i ] ) ? ')' : $string[ $i ];
690 + } elseif ( ( '"' === $a_string[ $i ] || "'" === $a_string[ $i ] || '(' === $a_string[ $i ] ) ) {
691 + $this->cur_string[] = $a_string[ $i ];
692 + $this->str_char[] = ( '(' === $a_string[ $i ] ) ? ')' : $a_string[ $i ];
758 693 $this->status = 'instr';
759 694 $this->from[] = 'iv';
760 695 $this->quoted_string[] = in_array( strtolower( $this->property ), $quoted_string_properties, true );
761 - } elseif ( ',' === $string[ $i ] ) {
696 + } elseif ( ',' === $a_string[ $i ] ) {
762 697 $this->sub_value = trim( $this->sub_value ) . ',';
763 - } elseif ( '\\' === $string[ $i ] ) {
764 - $this->sub_value .= $this->_unicode( $string, $i );
765 - } elseif ( ';' === $string[ $i ] || $pn ) {
766 - if ( '@' === $this->selector[0] && isset( $at_rules[ substr( $this->selector, 1 ) ] ) && 'iv' === $at_rules[ substr( $this->selector, 1 ) ] ) {
698 + } elseif ( '\\' === $a_string[ $i ] ) {
699 + $this->sub_value .= $this->_unicode( $a_string, $i );
700 + } elseif ( ';' === $a_string[ $i ] || $pn ) {
701 + if ( '' !== $this->selector && '@' === $this->selector[0] && isset( $at_rules[ substr( $this->selector, 1 ) ] ) && 'iv' === $at_rules[ substr( $this->selector, 1 ) ] ) {
767 702 $this->status = 'is';
768 703
769 704 switch ( $this->selector ) {
770 705 case '@charset':
@@ -781,10 +716,10 @@
781 716 $this->sub_value = trim( $this->sub_value );
782 717
783 718 if ( empty( $this->sub_value_arr ) ) {
784 719 // Quote URLs in imports only if they're not already inside url() and not already quoted.
785 - if ( 'url(' !== substr( $this->sub_value, 0, 4 ) ) {
786 - if ( ! ( substr( $this->sub_value, -1 ) === $this->sub_value[0] && in_array( $this->sub_value[0], array( "'", '"' ), true ) ) ) {
720 + if ( ! str_starts_with( $this->sub_value, 'url(' ) ) {
721 + if ( ! str_ends_with( $this->sub_value, $this->sub_value[0] ) && in_array( $this->sub_value[0], array( "'", '"' ), true ) ) {
787 722 $this->sub_value = '"' . $this->sub_value . '"';
788 723 }
789 724 }
790 725 }
@@ -800,14 +735,14 @@
800 735 $this->sel_separate = array();
801 736 } else {
802 737 $this->status = 'ip';
803 738 }
804 - } elseif ( '}' !== $string[ $i ] ) {
805 - $this->sub_value .= $string[ $i ];
739 + } elseif ( '}' !== $a_string[ $i ] ) {
740 + $this->sub_value .= $a_string[ $i ];
806 741 }
807 - if ( ( '}' === $string[ $i ] || ';' === $string[ $i ] || $pn ) && ! empty( $this->selector ) ) {
742 + if ( ( '}' === $a_string[ $i ] || ';' === $a_string[ $i ] || $pn ) && ! empty( $this->selector ) ) {
808 743 if ( '' === $this->at ) {
809 - $this->at = $this->css_new_media_section( $this->at, DEFAULT_AT );
744 + $this->at = $this->css_new_media_section( $this->at, (string) self::DEFAULT_AT );
810 745 }
811 746
812 747 // Case settings.
813 748 if ( $this->get_cfg( 'lowercase_s' ) ) {
@@ -821,9 +756,9 @@
821 756 $this->sub_value = '';
822 757 }
823 758
824 759 $this->value = '';
825 - while ( count( $this->sub_value_arr ) ) {
760 + while ( count( $this->sub_value_arr ) ) { // phpcs:ignore Squiz.PHP.DisallowSizeFunctionsInLoops.Found
826 761 $sub = array_shift( $this->sub_value_arr );
827 762 if ( strstr( $this->selector, 'font-face' ) ) {
828 763 $sub = $this->quote_font_format( $sub );
829 764 }
@@ -828,9 +763,9 @@
828 763 $sub = $this->quote_font_format( $sub );
829 764 }
830 765
831 766 if ( '' !== $sub ) {
832 - if ( strlen( $this->value ) && ( ',' !== substr( $this->value, -1, 1 ) || $this->get_cfg( 'preserve_css' ) ) ) {
767 + if ( strlen( $this->value ) && ( ! str_ends_with( $this->value, ',' ) || $this->get_cfg( 'preserve_css' ) ) ) {
833 768 $this->value .= ' ';
834 769 }
835 770 $this->value .= $sub;
836 771 }
@@ -840,9 +775,9 @@
840 775
841 776 $valid = $this->property_is_valid( $this->property );
842 777 if ( ( ! $this->invalid_at || $this->get_cfg( 'preserve_css' ) ) && ( ! $this->get_cfg( 'discard_invalid_properties' ) || $valid ) ) {
843 778 $this->css_add_property( $this->at, $this->selector, $this->property, $this->value );
844 - $this->_add_token( VALUE, $this->value );
779 + $this->_add_token( self::VALUE, $this->value );
845 780 $this->optimise->shorthands();
846 781 }
847 782 if ( ! $valid ) {
848 783 if ( $this->get_cfg( 'discard_invalid_properties' ) ) {
@@ -855,11 +790,11 @@
855 790 $this->property = '';
856 791 $this->sub_value_arr = array();
857 792 $this->value = '';
858 793 }
859 - if ( '}' === $string[ $i ] ) {
794 + if ( '}' === $a_string[ $i ] ) {
860 795 $this->explode_selectors();
861 - $this->_add_token( SEL_END, $this->selector );
796 + $this->_add_token( self::SEL_END, $this->selector );
862 797 $this->status = 'is';
863 798 $this->invalid_at = false;
864 799 $this->selector = '';
865 800 if ( $this->next_selector_at ) {
@@ -868,11 +803,11 @@
868 803 $this->next_selector_at = '';
869 804 }
870 805 }
871 806 } elseif ( ! $pn ) {
872 - $this->sub_value .= $string[ $i ];
807 + $this->sub_value .= $a_string[ $i ];
873 808
874 - if ( ctype_space( $string[ $i ] ) || ',' === $string[ $i ] ) {
809 + if ( ctype_space( $a_string[ $i ] ) || ',' === $a_string[ $i ] ) {
875 810 $this->optimise->subvalue();
876 811 if ( '' !== $this->sub_value ) {
877 812 $this->sub_value_arr[] = $this->sub_value;
878 813 $this->sub_value = '';
@@ -884,21 +819,21 @@
884 819 case 'instr':
885 820 $_str_char = $this->str_char[ count( $this->str_char ) - 1 ];
886 821 $_cur_string = $this->cur_string[ count( $this->cur_string ) - 1 ];
887 822 $_quoted_string = $this->quoted_string[ count( $this->quoted_string ) - 1 ];
888 - $temp_add = $string[ $i ];
823 + $temp_add = $a_string[ $i ];
889 824
890 825 // Add another string to the stack. Strings can't be nested inside of quotes, only parentheses,
891 826 // but parentheticals can be nested more than once.
892 - if ( ')' === $_str_char && ( '(' === $string[ $i ] || '"' === $string[ $i ] || '\\' === $string[ $i ] ) && ! $this->escaped( $string, $i ) ) {
893 - $this->cur_string[] = $string[ $i ];
894 - $this->str_char[] = ( '(' === $string[ $i ] ) ? ')' : $string[ $i ];
827 + if ( ')' === $_str_char && ( '(' === $a_string[ $i ] || '"' === $a_string[ $i ] || '\\' === $a_string[ $i ] ) && ! $this->escaped( $a_string, $i ) ) {
828 + $this->cur_string[] = $a_string[ $i ];
829 + $this->str_char[] = ( '(' === $a_string[ $i ] ) ? ')' : $a_string[ $i ];
895 830 $this->from[] = 'instr';
896 - $this->quoted_string[] = ( ')' === $_str_char && '(' !== $string[ $i ] && '(' === trim( $_cur_string ) ) ? $_quoted_string : ( '(' !== $string[ $i ] );
831 + $this->quoted_string[] = ( ')' === $_str_char && '(' !== $a_string[ $i ] && '(' === trim( $_cur_string ) ) ? $_quoted_string : ( '(' !== $a_string[ $i ] );
897 832 continue 2;
898 833 }
899 834
900 - if ( ')' !== $_str_char && ( "\n" === $string[ $i ] || "\r" === $string[ $i ] ) && ! ( '\\' === $string[ $i - 1 ] && ! $this->escaped( $string, $i - 1 ) ) ) {
835 + if ( ')' !== $_str_char && ( "\n" === $a_string[ $i ] || "\r" === $a_string[ $i ] ) && ! ( '\\' === $a_string[ $i - 1 ] && ! $this->escaped( $a_string, $i - 1 ) ) ) {
901 836 $temp_add = '\\A';
902 837 $this->log( 'Fixed incorrect newline in string', 'Warning' );
903 838 }
904 839
@@ -903,22 +838,24 @@
903 838 }
904 839
905 840 $_cur_string .= $temp_add;
906 841
907 - if ( $string[ $i ] === $_str_char && ! $this->escaped( $string, $i ) ) {
842 + if ( $a_string[ $i ] === $_str_char && ! $this->escaped( $a_string, $i ) ) {
908 843 $this->status = array_pop( $this->from );
909 844
910 845 if ( ! preg_match( '|[' . implode( '', $this->data['csstidy']['whitespace'] ) . ']|uis', $_cur_string ) && 'content' !== $this->property ) {
911 846 if ( ! $_quoted_string ) {
912 847 if ( ')' !== $_str_char ) {
913 - // Convert properties like
914 - // font-family: 'Arial';
915 - // to
916 - // font-family: Arial;
917 - // or
918 - // url("abc")
919 - // to
920 - // url(abc)
848 + /*
849 + * Convert properties like
850 + * font-family: 'Arial';
851 + * to
852 + * font-family: Arial;
853 + * or
854 + * url("abc")
855 + * to
856 + * url(abc)
857 + */
921 858 $_cur_string = substr( $_cur_string, 1, -1 );
922 859 }
923 860 } else {
924 861 $_quoted_string = false;
@@ -934,14 +871,14 @@
934 871 }
935 872
936 873 if ( 'iv' === $this->status ) {
937 874 if ( ! $_quoted_string ) {
938 - if ( false !== strpos( $_cur_string, ',' ) ) {
939 - // We can on only remove space next to ','
875 + if ( str_contains( $_cur_string, ',' ) ) {
876 + // We can on only remove space next to ','.
940 877 $_cur_string = implode( ',', array_map( 'trim', explode( ',', $_cur_string ) ) );
941 878 }
942 879 // and multiple spaces (too expensive).
943 - if ( false !== strpos( $_cur_string, ' ' ) ) {
880 + if ( str_contains( $_cur_string, ' ' ) ) {
944 881 $_cur_string = preg_replace( ',\s+,', ' ', $_cur_string );
945 882 }
946 883 }
947 884 $this->sub_value .= $_cur_string;
@@ -955,20 +892,20 @@
955 892 }
956 893 break;
957 894 /* Case in-comment */
958 895 case 'ic':
959 - if ( '*' === $string[ $i ] && '/' === $string[ $i + 1 ] ) {
896 + if ( '*' === $a_string[ $i ] && '/' === $a_string[ $i + 1 ] ) {
960 897 $this->status = array_pop( $this->from );
961 - $i++;
962 - if ( strlen( $cur_comment ) > 1 && 0 === strncmp( $cur_comment, '!', 1 ) ) {
963 - $this->_add_token( IMPORTANT_COMMENT, $cur_comment );
898 + ++$i;
899 + if ( strlen( $cur_comment ) > 1 && str_starts_with( $cur_comment, '!' ) ) {
900 + $this->_add_token( self::IMPORTANT_COMMENT, $cur_comment );
964 901 $this->css_add_important_comment( $cur_comment );
965 902 } else {
966 - $this->_add_token( COMMENT, $cur_comment );
903 + $this->_add_token( self::COMMENT, $cur_comment );
967 904 }
968 905 $cur_comment = '';
969 906 } else {
970 - $cur_comment .= $string[ $i ];
907 + $cur_comment .= $a_string[ $i ];
971 908 }
972 909 break;
973 910 }
974 911 }
@@ -976,23 +913,23 @@
976 913 $this->optimise->postparse();
977 914 $this->print->_reset();
978 915
979 916 // Set locale back to original setting.
980 - @setlocale( LC_ALL, $old );
917 + @setlocale( LC_ALL, $old ); // phpcs:ignore WordPress.PHP.NoSilencedErrors.Discouraged
981 918
982 919 return ! ( empty( $this->css ) && empty( $this->import ) && empty( $this->charset ) && empty( $this->tokens ) && empty( $this->namespace ) );
983 920 }
984 921
985 922 /**
986 - * format() in font-face needs quoted values for somes browser (FF at least).
923 + * Quoting: format() in font-face needs quoted values for some browser (FF at least).
987 924 *
988 925 * @since 1.0.0
989 926 *
990 - * @param mixed $value Value.
927 + * @param string $value Value.
991 928 * @return string String.
992 929 */
993 - protected function quote_font_format( $value ) {
994 - if ( 0 === strncmp( $value, 'format', 6 ) ) {
930 + protected function quote_font_format( string $value ): string {
931 + if ( str_starts_with( $value, 'format' ) ) {
995 932 $p = strpos( $value, ')', 7 );
996 933 $end = substr( $value, $p );
997 934 $format_strings = $this->parse_string_list( substr( $value, 7, $p - 7 ) );
998 935 if ( ! $format_strings ) {
@@ -1012,9 +949,9 @@
1012 949 * Explodes selectors.
1013 950 *
1014 951 * @since 1.0.0
1015 952 */
1016 - protected function explode_selectors() {
953 + protected function explode_selectors(): void {
1017 954 // Explode multiple selectors.
1018 955 if ( 1 === $this->get_cfg( 'merge_selectors' ) ) {
1019 956 $new_sels = array();
1020 957 $lastpos = 0;
@@ -1020,9 +957,9 @@
1020 957 $lastpos = 0;
1021 958 $this->sel_separate[] = strlen( $this->selector );
1022 959 foreach ( $this->sel_separate as $num => $pos ) {
1023 960 if ( ( count( $this->sel_separate ) - 1 ) === $num ) {
1024 - $pos += 1;
961 + ++$pos;
1025 962 }
1026 963
1027 964 $new_sels[] = substr( $this->selector, $lastpos, $pos - $lastpos - 1 );
1028 965 $lastpos = $pos;
@@ -1040,28 +977,28 @@
1040 977 $this->sel_separate = array();
1041 978 }
1042 979
1043 980 /**
1044 - * Checks if a character is escaped (and returns true if it is).
981 + * Checks if a character is escaped.
1045 982 *
1046 983 * @since 1.0.0
1047 984 *
1048 - * @param string $string String.
985 + * @param string $a_string String.
1049 986 * @param int $pos Position.
1050 - * @return bool [return value]
987 + * @return bool Whether a character is escaped.
1051 988 */
1052 - public function escaped( &$string, $pos ) {
1053 - return $pos ? ! ( @( '\\' !== $string[ $pos - 1 ] ) || $this->escaped( $string, $pos - 1 ) ) : false;
989 + public function escaped( string &$a_string, int $pos ): bool {
990 + return $pos ? ! ( @( '\\' !== $a_string[ $pos - 1 ] ) || $this->escaped( $a_string, $pos - 1 ) ) : false; // phpcs:ignore WordPress.PHP.NoSilencedErrors.Discouraged
1054 991 }
1055 992
1056 993 /**
1057 - * Add an important comment to the CSS code (one we want to keep when minifying).
994 + * Adds an important comment to the CSS code (one we want to keep when minifying).
1058 995 *
1059 996 * @since 1.10.0
1060 997 *
1061 998 * @param string $comment CSS Comment.
1062 999 */
1063 - protected function css_add_important_comment( $comment ) {
1000 + protected function css_add_important_comment( string $comment ): void {
1064 1001 if ( $this->get_cfg( 'preserve_css' ) || '' === trim( $comment ) ) {
1065 1002 return;
1066 1003 }
1067 1004 if ( ! isset( $this->css['!'] ) ) {
@@ -1081,9 +1018,9 @@
1081 1018 * @param string $selector Selector.
1082 1019 * @param string $property Property.
1083 1020 * @param string $new_val New value.
1084 1021 */
1085 - protected function css_add_property( $media, $selector, $property, $new_val ) {
1022 + protected function css_add_property( string $media, string $selector, string $property, string $new_val ): void {
1086 1023 if ( $this->get_cfg( 'preserve_css' ) || '' === trim( $new_val ) ) {
1087 1024 return;
1088 1025 }
1089 1026
@@ -1097,9 +1034,9 @@
1097 1034 }
1098 1035 }
1099 1036
1100 1037 /**
1101 - * Check if a current media section is the continuation of the last one.
1038 + * Checks if a current media section is the continuation of the last one.
1102 1039 * If not increase the name of the media section to avoid a merging.
1103 1040 *
1104 1041 * @since 1.10.0
1105 1042 *
@@ -1105,16 +1042,15 @@
1105 1042 *
1106 1043 * @param int|string $media Media.
1107 1044 * @return int|string [return value]
1108 1045 */
1109 - protected function css_check_last_media_section_or_inc( $media ) {
1046 + protected function css_check_last_media_section_or_inc( $media ) /* : int|string */ {
1110 1047 // Are we starting?
1111 1048 if ( empty( $this->css ) || ! is_array( $this->css ) ) {
1112 1049 return $media;
1113 1050 }
1114 1051 // If the last @media is the same as this, keep it.
1115 - end( $this->css );
1116 - $at = key( $this->css );
1052 + $at = array_key_last( $this->css );
1117 1053 if ( $at === $media ) {
1118 1054 return $media;
1119 1055 }
1120 1056 // Otherwise increase the section in the array.
@@ -1119,9 +1055,9 @@
1119 1055 }
1120 1056 // Otherwise increase the section in the array.
1121 1057 while ( isset( $this->css[ $media ] ) ) {
1122 1058 if ( is_numeric( $media ) ) {
1123 - $media++;
1059 + ++$media;
1124 1060 } else {
1125 1061 $media .= ' ';
1126 1062 }
1127 1063 }
@@ -1128,20 +1064,20 @@
1128 1064 return $media;
1129 1065 }
1130 1066
1131 1067 /**
1132 - * Start a new media section.
1068 + * Starts a new media section.
1133 1069 *
1134 1070 * Check if the media is not already known, else rename it with extra spaces to avoid merging.
1135 1071 *
1136 1072 * @since 1.0.0
1137 1073 *
1138 - * @param string $current_media Media.
1139 - * @param string $new_media Media.
1140 - * @param bool $at_root Optional. Default false.
1141 - * @return string [return value]
1074 + * @param string|int $current_media Media.
1075 + * @param string $new_media Media.
1076 + * @param bool $at_root Optional. Default false.
1077 + * @return int|string [return value]
1142 1078 */
1143 - protected function css_new_media_section( $current_media, $new_media, $at_root = false ) {
1079 + protected function css_new_media_section( $current_media, string $new_media, bool $at_root = false ) /* : int|string */ {
1144 1080 if ( $this->get_cfg( 'preserve_css' ) ) {
1145 1081 return $new_media;
1146 1082 }
1147 1083 // If we already are in a media and CSS level is 3, manage nested medias.
@@ -1146,11 +1082,11 @@
1146 1082 }
1147 1083 // If we already are in a media and CSS level is 3, manage nested medias.
1148 1084 if ( $current_media
1149 1085 && ! $at_root
1150 - // numeric $current_media means DEFAULT_AT or inc
1086 + // Numeric $current_media means self::DEFAULT_AT or inc.
1151 1087 && ! is_numeric( $current_media )
1152 - && 0 === strncmp( $this->get_cfg( 'css_level' ), 'CSS3', 4 ) ) {
1088 + && str_starts_with( $this->get_cfg( 'css_level' ), 'CSS3' ) ) {
1153 1089 $new_media = rtrim( $current_media ) . '{' . rtrim( $new_media );
1154 1090 }
1155 1091 return $this->css_check_last_media_section_or_inc( $new_media );
1156 1092 }
@@ -1155,11 +1091,11 @@
1155 1091 return $this->css_check_last_media_section_or_inc( $new_media );
1156 1092 }
1157 1093
1158 1094 /**
1159 - * Close a media section.
1095 + * Closes a media section.
1160 1096 *
1161 - * Find the parent media we were in before or the root.
1097 + * Finds the parent media we were in before or the root.
1162 1098 *
1163 1099 * @since 1.10.0
1164 1100 *
1165 1101 * @param string $current_media Current Media.
@@ -1164,13 +1100,13 @@
1164 1100 *
1165 1101 * @param string $current_media Current Media.
1166 1102 * @return string [return value]
1167 1103 */
1168 - protected function css_close_media_section( $current_media ) {
1104 + protected function css_close_media_section( string $current_media ): string {
1169 1105 if ( $this->get_cfg( 'preserve_css' ) ) {
1170 1106 return '';
1171 1107 }
1172 - if ( false !== strpos( $current_media, '{' ) ) {
1108 + if ( str_contains( $current_media, '{' ) ) {
1173 1109 $current_media = explode( '{', $current_media );
1174 1110 array_pop( $current_media );
1175 1111 $current_media = implode( '{', $current_media );
1176 1112 return $current_media;
@@ -1179,9 +1115,9 @@
1179 1115 return '';
1180 1116 }
1181 1117
1182 1118 /**
1183 - * Start a new selector.
1119 + * Starts a new selector.
1184 1120 *
1185 1121 * If already referenced in this media section, rename it with extra space to avoid merging,
1186 1122 * except if merging is required, or last selector is the same (merge siblings).
1187 1123 * Never merge @font-face.
@@ -1191,14 +1127,14 @@
1191 1127 * @param string $media Media.
1192 1128 * @param string $selector Selector.
1193 1129 * @return string [return value]
1194 1130 */
1195 - protected function css_new_selector( $media, $selector ) {
1131 + protected function css_new_selector( string $media, string $selector ): string {
1196 1132 if ( $this->get_cfg( 'preserve_css' ) ) {
1197 1133 return $selector;
1198 1134 }
1199 1135 $selector = trim( $selector );
1200 - if ( 0 !== strncmp( $selector, '@font-face', 10 ) ) {
1136 + if ( ! str_starts_with( $selector, '@font-face' ) ) {
1201 1137 if ( false !== $this->settings['merge_selectors'] ) {
1202 1138 return $selector;
1203 1139 }
1204 1140
@@ -1206,10 +1142,9 @@
1206 1142 return $selector;
1207 1143 }
1208 1144
1209 1145 // If last is the same, keep it.
1210 - end( $this->css[ $media ] );
1211 - $sel = key( $this->css[ $media ] );
1146 + $sel = array_key_last( $this->css[ $media ] );
1212 1147 if ( $sel === $selector ) {
1213 1148 return $selector;
1214 1149 }
1215 1150 }
@@ -1220,11 +1155,11 @@
1220 1155 return $selector;
1221 1156 }
1222 1157
1223 1158 /**
1224 - * Start a new property.
1159 + * Starts a new property.
1225 1160 *
1226 - * If already references in this selector, rename it with extra space to avoid override.
1161 + * If already referenced in this selector, rename it with extra space to avoid override.
1227 1162 *
1228 1163 * @since 1.0.0
1229 1164 *
1230 1165 * @param string $media Media.
@@ -1231,9 +1166,9 @@
1231 1166 * @param string $selector Selector.
1232 1167 * @param string $property Property.
1233 1168 * @return string [return value]
1234 1169 */
1235 - protected function css_new_property( $media, $selector, $property ) {
1170 + protected function css_new_property( string $media, string $selector, string $property ): string {
1236 1171 if ( $this->get_cfg( 'preserve_css' ) ) {
1237 1172 return $property;
1238 1173 }
1239 1174 if ( empty( $this->css ) || ! isset( $this->css[ $media ][ $selector ] ) || ! $this->css[ $media ][ $selector ] ) {
@@ -1251,13 +1186,13 @@
1251 1186 * Adds CSS to an existing media/selector.
1252 1187 *
1253 1188 * @since 1.0.0
1254 1189 *
1255 - * @param string $media Media.
1256 - * @param string $selector Selector.
1257 - * @param array $css_add Additional CSS.
1190 + * @param string $media Media.
1191 + * @param string $selector Selector.
1192 + * @param array<string, string> $css_add Additional CSS.
1258 1193 */
1259 - public function merge_css_blocks( $media, $selector, array $css_add ) {
1194 + public function merge_css_blocks( string $media, string $selector, array $css_add ): void {
1260 1195 foreach ( $css_add as $property => $value ) {
1261 1196 $this->css_add_property( $media, $selector, $property, $value );
1262 1197 }
1263 1198 }
@@ -1269,11 +1204,11 @@
1269 1204 *
1270 1205 * @param string $value Value.
1271 1206 * @return bool Whether the value has the !important keyword.
1272 1207 */
1273 - public function is_important( &$value ) {
1208 + public function is_important( string &$value ): bool {
1274 1209 return (
1275 - false !== strpos( $value, '!' ) // Quick test.
1210 + str_contains( $value, '!' ) // Quick test.
1276 1211 && ! strcasecmp( substr( str_replace( $this->data['csstidy']['whitespace'], '', $value ), -10, 10 ), '!important' ) );
1277 1212 }
1278 1213
1279 1214 /**
@@ -1283,9 +1218,9 @@
1283 1218 *
1284 1219 * @param string $value Value.
1285 1220 * @return string Value without the !important;
1286 1221 */
1287 - public function gvw_important( $value ) {
1222 + public function gvw_important( string $value ): string {
1288 1223 if ( $this->is_important( $value ) ) {
1289 1224 $value = trim( $value );
1290 1225 $value = substr( $value, 0, -9 );
1291 1226 $value = trim( $value );
@@ -1304,9 +1239,9 @@
1304 1239 * @param string $istring String.
1305 1240 * @param int $pos Position.
1306 1241 * @return bool [return value]
1307 1242 */
1308 - protected function property_is_next( $istring, $pos ) {
1243 + protected function property_is_next( string $istring, int $pos ): bool {
1309 1244 $all_properties = &$this->data['csstidy']['all_properties'];
1310 1245 $istring = substr( $istring, $pos, strlen( $istring ) - $pos );
1311 1246 $pos = strpos( $istring, ':' );
1312 1247 if ( false === $pos ) {
@@ -1327,17 +1262,17 @@
1327 1262 *
1328 1263 * @param string $property Property.
1329 1264 * @return bool Whether the property is valid.
1330 1265 */
1331 - public function property_is_valid( $property ) {
1266 + public function property_is_valid( string $property ): bool {
1332 1267 $property = strtolower( $property );
1333 - if ( 0 === strpos( $property, '--' ) ) {
1268 + if ( str_starts_with( $property, '--' ) ) {
1334 1269 $property = '--custom'; // Replace custom properties with a temporary placeholder that is marked as valid in the list of properties.
1335 1270 } elseif ( in_array( trim( $property ), $this->data['csstidy']['multiple_properties'], true ) ) {
1336 1271 $property = trim( $property );
1337 1272 }
1338 1273 $all_properties = &$this->data['csstidy']['all_properties'];
1339 - return isset( $all_properties[ $property ] ) && false !== strpos( $all_properties[ $property ], strtoupper( $this->get_cfg( 'css_level' ) ) );
1274 + return isset( $all_properties[ $property ] ) && str_contains( $all_properties[ $property ], strtoupper( $this->get_cfg( 'css_level' ) ) );
1340 1275 }
1341 1276
1342 1277 /**
1343 1278 * Accepts a list of strings (e.g. the argument to format() in a @font-face src property)
@@ -1350,20 +1285,20 @@
1350 1285 * format("abc, def, ghi") => format("abc, def, ghi")
1351 1286 *
1352 1287 * @since 1.0.0
1353 1288 *
1354 - * @param [type] $value [description]
1355 - * @return [type] [description]
1289 + * @param string $value [description].
1290 + * @return string[] [description]
1356 1291 */
1357 - public function parse_string_list( $value ) {
1292 + public function parse_string_list( string $value ): array {
1358 1293 $value = trim( $value );
1359 1294
1360 - // Case: empty
1295 + // Case: empty.
1361 1296 if ( ! $value ) {
1362 1297 return array();
1363 1298 }
1364 1299
1365 - $strings = array();
1300 + $a_strings = array();
1366 1301
1367 1302 $in_str = false;
1368 1303 $current_string = '';
1369 1304
@@ -1369,13 +1304,13 @@
1369 1304
1370 1305 for ( $i = 0, $_len = strlen( $value ); $i < $_len; $i++ ) {
1371 1306 if ( ( ',' === $value[ $i ] || ' ' === $value[ $i ] ) && true === $in_str ) {
1372 1307 $in_str = false;
1373 - $strings[] = $current_string;
1308 + $a_strings[] = $current_string;
1374 1309 $current_string = '';
1375 1310 } elseif ( '"' === $value[ $i ] || "'" === $value[ $i ] ) {
1376 1311 if ( $in_str === $value[ $i ] ) {
1377 - $strings[] = $current_string;
1312 + $a_strings[] = $current_string;
1378 1313 $in_str = false;
1379 1314 $current_string = '';
1380 1315 continue;
1381 1316 } elseif ( ! $in_str ) {
@@ -1380,12 +1315,12 @@
1380 1315 continue;
1381 1316 } elseif ( ! $in_str ) {
1382 1317 $in_str = $value[ $i ];
1383 1318 }
1384 - } else {
1319 + } else { // phpcs:ignore Universal.ControlStructures.DisallowLonelyIf.Found
1385 1320 if ( $in_str ) {
1386 1321 $current_string .= $value[ $i ];
1387 - } else {
1322 + } else { // phpcs:ignore Universal.ControlStructures.DisallowLonelyIf.Found
1388 1323 if ( ! preg_match( '/[\s,]/', $value[ $i ] ) ) {
1389 1324 $in_str = true;
1390 1325 $current_string = $value[ $i ];
1391 1326 }
@@ -1393,11 +1328,11 @@
1393 1328 }
1394 1329 }
1395 1330
1396 1331 if ( $current_string ) {
1397 - $strings[] = $current_string;
1332 + $a_strings[] = $current_string;
1398 1333 }
1399 1334
1400 - return $strings;
1335 + return $a_strings;
1401 1336 }
1402 1337
1403 1338 } // class TablePress_CSSTidy