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_optimise.php +201 -306 1.9.2 → 3.4 View file →
@@ -7,108 +7,71 @@
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 - * CSSTidy - CSS Parser and Optimiser
16 - *
17 17 * CSS Optimising Class
18 - * This class optimises CSS data generated by CSSTidy.
19 18 *
20 - * Copyright 2005, 2006, 2007 Florian Schmitz
21 - *
22 - * This file is part of CSSTidy.
23 - *
24 - * CSSTidy is free software; you can redistribute it and/or modify
25 - * it under the terms of the GNU Lesser General Public License as published by
26 - * the Free Software Foundation; either version 2.1 of the License, or
27 - * (at your option) any later version.
28 - *
29 - * CSSTidy is distributed in the hope that it will be useful,
30 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
31 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
32 - * GNU Lesser General Public License for more details.
33 - *
34 - * You should have received a copy of the GNU Lesser General Public License
35 - * along with this program. If not, see <https://www.gnu.org/licenses/>.
36 - *
37 - * @license https://opensource.org/licenses/lgpl-license.php GNU Lesser General Public License
38 - * @package CSSTidy
39 - * @author Florian Schmitz (floele at gmail dot com) 2005-2007
40 - * @author Brett Zamir (brettz9 at yahoo dot com) 2007
41 - * @author Nikolay Matsievsky (speed at webo dot name) 2009-2010
42 - * @author Cedric Morin (cedric at yterium dot com) 2010-2012
43 - */
44 -
45 -/**
46 - * CSS Optimising Class
47 - *
48 19 * This class optimises CSS data generated by CSSTidy.
49 20 *
50 21 * @package CSSTidy
51 - * @author Florian Schmitz (floele at gmail dot com) 2005-2006
52 22 * @version 1.0
53 23 */
54 -class TablePress_CSSTidy_optimise {
24 +class TablePress_CSSTidy_Optimise {
55 25
56 26 /**
57 - * CSSTidy instance.
27 + * TablePress_CSSTidy instance.
58 28 *
59 29 * @since 1.0.0
60 - * @var CSSTidy
61 30 */
62 - public $parser;
31 + public \TablePress_CSSTidy $parser;
63 32
64 33 /**
65 34 * The parsed CSS.
66 35 *
67 36 * @since 1.0.0
68 - * @var array
69 37 */
70 - public $css = array();
38 + public array $css = array();
71 39
72 40 /**
73 41 * The current sub-value.
74 42 *
75 43 * @since 1.0.0
76 - * @var string
77 44 */
78 - public $sub_value = '';
45 + public string $sub_value = '';
79 46
80 47 /**
81 48 * The current at rule (@media).
82 49 *
83 50 * @since 1.0.0
84 - * @var string
85 51 */
86 - public $at = '';
52 + public string $at = '';
87 53
88 54 /**
89 55 * The current selector.
90 56 *
91 57 * @since 1.0.0
92 - * @var string
93 58 */
94 - public $selector = '';
59 + public string $selector = '';
95 60
96 61 /**
97 62 * The current property.
98 63 *
99 64 * @since 1.0.0
100 - * @var string
101 65 */
102 - public $property = '';
66 + public string $property = '';
103 67
104 68 /**
105 69 * The current value.
106 70 *
107 71 * @since 1.0.0
108 - * @var string
109 72 */
110 - public $value = '';
73 + public string $value = '';
111 74
112 75 /**
113 76 * Constructor.
114 77 *
@@ -113,18 +76,18 @@
113 76 * Constructor.
114 77 *
115 78 * @since 1.0.0
116 79 *
117 - * @param CSSTidy $css Instance of the CSSTidy class.
80 + * @param TablePress_CSSTidy $csstidy Instance of the TablePress_CSSTidy class.
118 81 */
119 - public function __construct( $css ) {
120 - $this->parser = $css;
121 - $this->css = &$css->css;
122 - $this->sub_value = &$css->sub_value;
123 - $this->at = &$css->at;
124 - $this->selector = &$css->selector;
125 - $this->property = &$css->property;
126 - $this->value = &$css->value;
82 + public function __construct( TablePress_CSSTidy $csstidy ) {
83 + $this->parser = $csstidy;
84 + $this->css = &$csstidy->css;
85 + $this->sub_value = &$csstidy->sub_value;
86 + $this->at = &$csstidy->at;
87 + $this->selector = &$csstidy->selector;
88 + $this->property = &$csstidy->property;
89 + $this->value = &$csstidy->value;
127 90 }
128 91
129 92 /**
130 93 * Optimises $css after parsing.
@@ -130,9 +93,9 @@
130 93 * Optimises $css after parsing.
131 94 *
132 95 * @since 1.0.0
133 96 */
134 - public function postparse() {
97 + public function postparse(): void {
135 98 if ( $this->parser->get_cfg( 'preserve_css' ) ) {
136 99 return;
137 100 }
138 101
@@ -137,36 +100,42 @@
137 100 }
138 101
139 102 if ( 2 === (int) $this->parser->get_cfg( 'merge_selectors' ) ) {
140 103 foreach ( $this->css as $medium => $value ) {
141 - $this->merge_selectors( $this->css[ $medium ] );
104 + if ( is_array( $value ) ) {
105 + $this->merge_selectors( $this->css[ $medium ] );
106 + }
142 107 }
143 108 }
144 109
145 110 if ( $this->parser->get_cfg( 'discard_invalid_selectors' ) ) {
146 111 foreach ( $this->css as $medium => $value ) {
147 - $this->discard_invalid_selectors( $this->css[ $medium ] );
112 + if ( is_array( $value ) ) {
113 + $this->discard_invalid_selectors( $this->css[ $medium ] );
114 + }
148 115 }
149 116 }
150 117
151 118 if ( $this->parser->get_cfg( 'optimise_shorthands' ) > 0 ) {
152 119 foreach ( $this->css as $medium => $value ) {
153 - foreach ( $value as $selector => $value1 ) {
154 - $this->css[ $medium ][ $selector ] = $this->merge_4value_shorthands( $this->css[ $medium ][ $selector ] );
120 + if ( is_array( $value ) ) {
121 + foreach ( $value as $selector => $value1 ) {
122 + $this->css[ $medium ][ $selector ] = $this->merge_4value_shorthands( $this->css[ $medium ][ $selector ] );
155 123
156 - if ( $this->parser->get_cfg( 'optimise_shorthands' ) < 2 ) {
157 - continue;
158 - }
124 + if ( $this->parser->get_cfg( 'optimise_shorthands' ) < 2 ) {
125 + continue;
126 + }
159 127
160 - $this->css[ $medium ][ $selector ] = $this->merge_font( $this->css[ $medium ][ $selector ] );
128 + $this->css[ $medium ][ $selector ] = $this->merge_font( $this->css[ $medium ][ $selector ] );
161 129
162 - if ( $this->parser->get_cfg( 'optimise_shorthands' ) < 3 ) {
163 - continue;
164 - }
130 + if ( $this->parser->get_cfg( 'optimise_shorthands' ) < 3 ) {
131 + continue;
132 + }
165 133
166 - $this->css[ $medium ][ $selector ] = $this->merge_bg( $this->css[ $medium ][ $selector ] );
167 - if ( empty( $this->css[ $medium ][ $selector ] ) ) {
168 - unset( $this->css[ $medium ][ $selector ] );
134 + $this->css[ $medium ][ $selector ] = $this->merge_bg( $this->css[ $medium ][ $selector ] );
135 + if ( empty( $this->css[ $medium ][ $selector ] ) ) {
136 + unset( $this->css[ $medium ][ $selector ] );
137 + }
169 138 }
170 139 }
171 140 }
172 141 }
@@ -176,14 +145,14 @@
176 145 * Optimises values
177 146 *
178 147 * @since 1.0.0
179 148 */
180 - public function value() {
149 + public function value(): void {
181 150 $shorthands = &$this->parser->data['csstidy']['shorthands'];
182 151
183 152 // Optimise shorthand properties.
184 153 if ( isset( $shorthands[ $this->property ] ) && $this->parser->get_cfg( 'optimise_shorthands' ) > 0 ) {
185 - $temp = $this->shorthand( $this->value ); // FIXME - move
154 + $temp = $this->shorthand( $this->value ); // FIXME - move.
186 155 if ( $temp !== $this->value ) {
187 156 $this->parser->log( 'Optimised shorthand notation (' . $this->property . '): Changed "' . $this->value . '" to "' . $temp . '"', 'Information' );
188 157 }
189 158 $this->value = $temp;
@@ -188,9 +157,9 @@
188 157 }
189 158 $this->value = $temp;
190 159 }
191 160
192 - // Remove whitespace at !important
161 + // Remove whitespace at !important.
193 162 if ( $this->value !== $this->compress_important( $this->value ) ) {
194 163 $this->parser->log( 'Optimised !important', 'Information' );
195 164 }
196 165 }
@@ -199,9 +168,9 @@
199 168 * Optimises shorthands.
200 169 *
201 170 * @since 1.0.0
202 171 */
203 - public function shorthands() {
172 + public function shorthands(): void {
204 173 $shorthands = &$this->parser->data['csstidy']['shorthands'];
205 174
206 175 if ( ! $this->parser->get_cfg( 'optimise_shorthands' ) || $this->parser->get_cfg( 'preserve_css' ) ) {
207 176 return;
@@ -227,13 +196,13 @@
227 196 * Optimises a sub-value.
228 197 *
229 198 * @since 1.0.0
230 199 */
231 - public function subvalue() {
200 + public function subvalue(): void {
232 201 $replace_colors = &$this->parser->data['csstidy']['replace_colors'];
233 202
234 203 $this->sub_value = trim( $this->sub_value );
235 - if ( '' === $this->sub_value ) { // caution : '0'
204 + if ( '' === $this->sub_value ) { // caution : '0'.
236 205 return;
237 206 }
238 207
239 208 $important = '';
@@ -285,9 +254,9 @@
285 254 *
286 255 * @param string $value Shorthand value.
287 256 * @return string Compressed value.
288 257 */
289 - public function shorthand( $value ) {
258 + public function shorthand( string $value ): string {
290 259 $important = '';
291 260 if ( $this->parser->is_important( $value ) ) {
292 261 $values = $this->parser->gvw_important( $value );
293 262 $important = ' !important';
@@ -327,16 +296,16 @@
327 296 * Removes unnecessary whitespace in ! important.
328 297 *
329 298 * @since 1.0.0
330 299 *
331 - * @param string $string String.
300 + * @param string $a_string String.
332 301 * @return string Cleaned string.
333 302 */
334 - public function compress_important( &$string ) {
335 - if ( $this->parser->is_important( $string ) ) {
336 - $string = $this->parser->gvw_important( $string ) . ' !important';
303 + public function compress_important( string &$a_string ): string {
304 + if ( $this->parser->is_important( $a_string ) ) {
305 + $a_string = $this->parser->gvw_important( $a_string ) . ' !important';
337 306 }
338 - return $string;
307 + return $a_string;
339 308 }
340 309
341 310 /**
342 311 * Color compression function. Converts all rgb() values to #-values and uses the short-form if possible. Also replaces 4 color names by #-values.
@@ -345,23 +314,23 @@
345 314 *
346 315 * @param string $color Color value.
347 316 * @return string Compressed color.
348 317 */
349 - public function cut_color( $color ) {
318 + public function cut_color( string $color ): string {
350 319 $replace_colors = &$this->parser->data['csstidy']['replace_colors'];
351 320
352 - // If it's a string, don't touch!
353 - if ( 0 === strncmp( $color, "'", 1 ) || 0 === strncmp( $color, '"', 1 ) ) {
321 + // If it's a string, don't touch it!
322 + if ( str_starts_with( $color, "'" ) || str_starts_with( $color, '"' ) ) {
354 323 return $color;
355 324 }
356 325
357 - // Complex gradient expressions
358 - if ( false !== strpos( $color, '(' ) && 0 !== strncmp( $color, 'rgb(', 4 ) ) {
359 - // Don't touch properties within MSIE filters, those are to sensitive.
326 + // Complex gradient expressions.
327 + if ( str_contains( $color, '(' ) && 0 !== strncasecmp( $color, 'rgb(', 4 ) && 0 !== strncasecmp( $color, 'rgba(', 5 ) ) {
328 + // Don't touch properties within MSIE filters, those are too sensitive.
360 329 if ( false !== stripos( $color, 'progid:' ) ) {
361 330 return $color;
362 331 }
363 - preg_match_all( ',rgb\([^)]+\),i', $color, $matches, PREG_SET_ORDER );
332 + preg_match_all( ',rgba?\([^)]+\),i', $color, $matches, PREG_SET_ORDER );
364 333 if ( count( $matches ) ) {
365 334 foreach ( $matches as $m ) {
366 335 $color = str_replace( $m[0], $this->cut_color( $m[0] ), $color );
367 336 }
@@ -374,27 +343,50 @@
374 343 }
375 344 return $color;
376 345 }
377 346
378 - // rgb(0,0,0) -> #000000 (or #000 in this case later)
379 - if ( 0 === strncasecmp( $color, 'rgb(', 4 ) ) {
380 - $color_tmp = substr( $color, 4, strlen( $color ) - 5 );
381 - $color_tmp = explode( ',', $color_tmp );
382 - for ( $i = 0; $i < count( $color_tmp ); $i++ ) {
383 - $color_tmp[ $i ] = trim( $color_tmp[ $i ] );
384 - if ( '%' === substr( $color_tmp[ $i ], -1 ) ) {
385 - $color_tmp[ $i ] = round( ( 255 * $color_tmp[ $i ] ) / 100 );
347 + // rgb(0,0,0) -> #000000 (or #000 in this case later).
348 + if (
349 + // Be sure to not corrupt a rgb with calc() value.
350 + ( 0 === strncasecmp( $color, 'rgb(', 4 ) && false === strpos( $color, '(', 4 ) ) || ( 0 === strncasecmp( $color, 'rgba(', 5 ) && false === strpos( $color, '(', 5 ) )
351 + ) {
352 + $color_tmp = explode( '(', $color, 2 );
353 + $color_tmp = rtrim( end( $color_tmp ), ')' );
354 + if ( str_contains( $color_tmp, '/' ) ) {
355 + $color_tmp = explode( '/', $color_tmp, 2 );
356 + $color_parts = explode( ' ', trim( reset( $color_tmp ) ), 3 );
357 + while ( count( $color_parts ) < 3 ) { // phpcs:ignore Squiz.PHP.DisallowSizeFunctionsInLoops.Found
358 + $color_parts[] = 0;
386 359 }
387 - if ( $color_tmp[ $i ] > 255 ) {
388 - $color_tmp[ $i ] = 255;
360 + $color_parts[] = end( $color_tmp );
361 + } else {
362 + $color_parts = explode( ',', $color_tmp, 4 );
363 + }
364 + $color_parts_count = count( $color_parts );
365 + for ( $i = 0; $i < $color_parts_count; $i++ ) {
366 + $color_parts[ $i ] = trim( $color_parts[ $i ] );
367 + if ( str_ends_with( $color_parts[ $i ], '%' ) ) {
368 + $color_parts[ $i ] = round( ( 255 * intval( $color_parts[ $i ] ) ) / 100 );
369 + } elseif ( $i > 2 ) {
370 + // 4th argument is alpha layer between 0 and 1 (if not %).
371 + $color_parts[ $i ] = round( 255 * floatval( $color_parts[ $i ] ) );
389 372 }
373 + $color_parts[ $i ] = intval( $color_parts[ $i ] );
374 + if ( $color_parts[ $i ] > 255 ) {
375 + $color_parts[ $i ] = 255;
376 + }
390 377 }
391 378 $color = '#';
392 - for ( $i = 0; $i < 3; $i++ ) {
393 - if ( $color_tmp[ $i ] < 16 ) {
394 - $color .= '0' . dechex( $color_tmp[ $i ] );
379 + // 3 or 4 parts depending on alpha layer.
380 + $nb = min( max( count( $color_parts ), 3 ), 4 );
381 + for ( $i = 0; $i < $nb; $i++ ) {
382 + if ( ! isset( $color_parts[ $i ] ) ) {
383 + $color_parts[ $i ] = 0;
384 + }
385 + if ( $color_parts[ $i ] < 16 ) {
386 + $color .= '0' . dechex( $color_parts[ $i ] );
395 387 } else {
396 - $color .= dechex( $color_tmp[ $i ] );
388 + $color .= dechex( $color_parts[ $i ] );
397 389 }
398 390 }
399 391 }
400 392
@@ -402,14 +394,20 @@
402 394 if ( isset( $replace_colors[ strtolower( $color ) ] ) ) {
403 395 $color = $replace_colors[ strtolower( $color ) ];
404 396 }
405 397
406 - // #aabbcc -> #abc
407 398 if ( 7 === strlen( $color ) ) {
399 + // #aabbcc -> #abc
408 400 $color_temp = strtolower( $color );
409 401 if ( '#' === $color_temp[0] && $color_temp[1] === $color_temp[2] && $color_temp[3] === $color_temp[4] && $color_temp[5] === $color_temp[6] ) {
410 402 $color = '#' . $color[1] . $color[3] . $color[5];
411 403 }
404 + } elseif ( 9 === strlen( $color ) ) {
405 + // #aabbccdd -> #abcd
406 + $color_temp = strtolower( $color );
407 + if ( '#' === $color_temp[0] && $color_temp[1] === $color_temp[2] && $color_temp[3] === $color_temp[4] && $color_temp[5] === $color_temp[6] && $color_temp[7] === $color_temp[8] ) {
408 + $color = '#' . $color[1] . $color[3] . $color[5] . $color[7];
409 + }
412 410 }
413 411
414 412 switch ( strtolower( $color ) ) {
415 413 /* color name -> hex code */
@@ -455,13 +453,13 @@
455 453 *
456 454 * @param string $subvalue Value.
457 455 * @return string Compressed value.
458 456 */
459 - public function compress_numbers( $subvalue ) {
457 + public function compress_numbers( string $subvalue ): string {
460 458 $unit_values = &$this->parser->data['csstidy']['unit_values'];
461 459 $color_values = &$this->parser->data['csstidy']['color_values'];
462 460
463 - // for font:1em/1em sans-serif...;
461 + // for font:1em/1em sans-serif...;.
464 462 if ( 'font' === $this->property ) {
465 463 $temp = explode( '/', $subvalue );
466 464 } else {
467 465 $temp = array( $subvalue );
@@ -466,17 +464,18 @@
466 464 } else {
467 465 $temp = array( $subvalue );
468 466 }
469 467
470 - for ( $l = 0; $l < count( $temp ); $l++ ) {
468 + $temp_count = count( $temp );
469 + for ( $l = 0; $l < $temp_count; $l++ ) {
471 470 // If we are not dealing with a number at this point, do not optimize anything.
472 - $number = $this->AnalyseCssNumber( $temp[ $l ] );
471 + $number = $this->analyse_css_number( $temp[ $l ] );
473 472 if ( false === $number ) {
474 473 return $subvalue;
475 474 }
476 475
477 476 // Fix bad colors.
478 - if ( in_array( $this->property, $color_values ) ) {
477 + if ( in_array( $this->property, $color_values, true ) ) {
479 478 if ( 3 === strlen( $temp[ $l ] ) || 6 === strlen( $temp[ $l ] ) ) {
480 479 $temp[ $l ] = '#' . $temp[ $l ];
481 480 } else {
482 481 $temp[ $l ] = '0';
@@ -502,14 +501,14 @@
502 501 * Checks if a given string is a CSS valid number. If it is, an array containing the value and unit is returned.
503 502 *
504 503 * @since 1.0.0
505 504 *
506 - * @param string $string String.
507 - * @return array ('unit' if unit is found or '' if no unit exists, number value) or false if no number.
505 + * @param string $a_string String.
506 + * @return array{int|string, string}|false ('unit' if unit is found or '' if no unit exists, number value) or false if no number.
508 507 */
509 - public function analyseCssNumber( $string ) {
510 - // most simple checks first
511 - if ( 0 === strlen( $string ) || ctype_alpha( $string[0] ) ) {
508 + public function analyse_css_number( string $a_string ) /* : array|false */ {
509 + // Most simple checks first.
510 + if ( 0 === strlen( $a_string ) || ctype_alpha( $a_string[0] ) ) {
512 511 return false;
513 512 }
514 513
515 514 $units = &$this->parser->data['csstidy']['units'];
@@ -514,31 +513,31 @@
514 513
515 514 $units = &$this->parser->data['csstidy']['units'];
516 515 $return = array( 0, '' );
517 516
518 - $return[0] = floatval( $string );
517 + $return[0] = (float) $a_string;
519 518 if ( abs( $return[0] ) > 0 && abs( $return[0] ) < 1 ) {
520 519 if ( $return[0] < 0 ) {
521 - $return[0] = '-' . ltrim( substr( $return[0], 1 ), '0' );
520 + $return[0] = '-' . ltrim( substr( (string) $return[0], 1 ), '0' );
522 521 } else {
523 - $return[0] = ltrim( $return[0], '0' );
522 + $return[0] = ltrim( (string) $return[0], '0' );
524 523 }
525 524 }
526 525
527 - // Look for unit and split from value if exists
526 + // Look for unit and split from value if exists.
528 527 foreach ( $units as $unit ) {
529 - $expectUnitAt = strlen( $string ) - strlen( $unit );
530 - if ( ! ( $unitInString = stristr( $string, $unit ) ) ) { // mb_strpos() fails with "false"
528 + $expect_unit_at = strlen( $a_string ) - strlen( $unit );
529 + if ( ! ( $unit_in_string = stristr( $a_string, $unit ) ) ) { // phpcs:ignore Generic.CodeAnalysis.AssignmentInCondition.Found,Squiz.PHP.DisallowMultipleAssignments.FoundInControlStructure
531 530 continue;
532 531 }
533 - $actualPosition = strpos( $string, $unitInString );
534 - if ( $expectUnitAt === $actualPosition ) {
532 + $actual_position = strpos( $a_string, $unit_in_string );
533 + if ( $expect_unit_at === $actual_position ) {
535 534 $return[1] = $unit;
536 - $string = substr( $string, 0, - strlen( $unit ) );
535 + $a_string = substr( $a_string, 0, - strlen( $unit ) );
537 536 break;
538 537 }
539 538 }
540 - if ( ! is_numeric( $string ) ) {
539 + if ( ! is_numeric( $a_string ) ) {
541 540 return false;
542 541 }
543 542 return $return;
544 543 }
@@ -548,13 +547,12 @@
548 547 * Very basic and has at least one bug. Hopefully there is a replacement soon.
549 548 *
550 549 * @since 1.0.0
551 550 *
552 - * @param array $array
553 - * @return array
551 + * @param array<string, mixed> $an_array List of selectors. This parameter is modified by reference.
554 552 */
555 - public function merge_selectors( array &$array ) {
556 - $css = $array;
553 + public function merge_selectors( array &$an_array ): void {
554 + $css = $an_array;
557 555 foreach ( $css as $key => $value ) {
558 556 if ( ! isset( $css[ $key ] ) ) {
559 557 continue;
560 558 }
@@ -560,9 +558,9 @@
560 558 }
561 559
562 560 // Check if properties also exist in another selector.
563 561 $keys = array();
564 - // PHP bug (?) without $css = $array; here
562 + // PHP bug (?) without $css = $an_array; here.
565 563 foreach ( $css as $selector => $vali ) {
566 564 if ( $selector === $key ) {
567 565 continue;
568 566 }
@@ -581,9 +579,9 @@
581 579 }
582 580 $css[ $newsel ] = $value;
583 581 }
584 582 }
585 - $array = $css;
583 + $an_array = $css;
586 584 }
587 585
588 586 /**
589 587 * Removes invalid selectors and their corresponding rule-sets as
@@ -592,12 +590,12 @@
592 590 * regular expression.
593 591 *
594 592 * @since 1.0.0
595 593 *
596 - * @param [type] $array [description]
594 + * @param array<string, mixed> $an_array [description].
597 595 */
598 - public function discard_invalid_selectors( &$array ) {
599 - foreach ( $array as $selector => $decls ) {
596 + public function discard_invalid_selectors( array &$an_array ): void {
597 + foreach ( $an_array as $selector => $decls ) {
600 598 $ok = true;
601 599 $selectors = array_map( 'trim', explode( ',', $selector ) );
602 600 foreach ( $selectors as $s ) {
603 601 $simple_selectors = preg_split( '/\s*[+>~\s]\s*/', $s );
@@ -604,14 +602,13 @@
604 602 foreach ( $simple_selectors as $ss ) {
605 603 if ( '' === $ss ) {
606 604 $ok = false;
607 605 }
608 - // could also check $ss for internal structure,
609 - // but that probably would be too slow
606 + // Could also check $ss for internal structure, but that probably would be too slow.
610 607 }
611 608 }
612 609 if ( ! $ok ) {
613 - unset( $array[ $selector ] );
610 + unset( $an_array[ $selector ] );
614 611 }
615 612 }
616 613 }
617 614
@@ -619,14 +616,13 @@
619 616 * Dissolves properties like padding:10px 10px 10px to padding-top:10px;padding-bottom:10px;...
620 617 *
621 618 * @since 1.0.0
622 619 *
623 - * @param string $property [description]
624 - * @param string $value [description]
625 - *
626 - * @return [type] [description]
620 + * @param string $property [description].
621 + * @param string $value [description].
622 + * @return array [description]
627 623 */
628 - public function dissolve_4value_shorthands( $property, $value ) {
624 + public function dissolve_4value_shorthands( string $property, string $value ): array {
629 625 $return = array();
630 626
631 627 $shorthands = &$this->parser->data['csstidy']['shorthands'];
632 628 if ( ! is_array( $shorthands[ $property ] ) ) {
@@ -667,37 +663,37 @@
667 663 * Explodes a string as explode() does, however, not if $sep is escaped or within a string.
668 664 *
669 665 * @since 1.0.0
670 666 *
671 - * @param string $sep Separator.
672 - * @param string $string String.
673 - * @return array
667 + * @param string $sep Separator.
668 + * @param string $a_string String.
669 + * @return array [description]
674 670 */
675 - public function explode_ws( $sep, $string ) {
671 + public function explode_ws( string $sep, string $a_string ): array {
676 672 $status = 'st';
677 673 $to = '';
678 674
679 675 $output = array();
680 676 $num = 0;
681 - for ( $i = 0, $len = strlen( $string ); $i < $len; $i++ ) {
677 + for ( $i = 0, $len = strlen( $a_string ); $i < $len; $i++ ) {
682 678 switch ( $status ) {
683 679 case 'st':
684 - if ( $string[ $i ] === $sep && ! $this->parser->escaped( $string, $i ) ) {
680 + if ( $a_string[ $i ] === $sep && ! $this->parser->escaped( $a_string, $i ) ) {
685 681 ++$num;
686 - } elseif ( '"' === $string[ $i ] || "'" === $string[ $i ] || '(' === $string[ $i ] && ! $this->parser->escaped( $string, $i ) ) {
682 + } elseif ( '"' === $a_string[ $i ] || "'" === $a_string[ $i ] || ( '(' === $a_string[ $i ] && ! $this->parser->escaped( $a_string, $i ) ) ) {
687 683 $status = 'str';
688 - $to = ( '(' === $string[ $i ] ) ? ')' : $string[ $i ];
689 - ( isset( $output[ $num ] ) ) ? $output[ $num ] .= $string[ $i ] : $output[ $num ] = $string[ $i ];
684 + $to = ( '(' === $a_string[ $i ] ) ? ')' : $a_string[ $i ];
685 + ( isset( $output[ $num ] ) ) ? $output[ $num ] .= $a_string[ $i ] : $output[ $num ] = $a_string[ $i ];
690 686 } else {
691 - ( isset( $output[ $num ] ) ) ? $output[ $num ] .= $string[ $i ] : $output[ $num ] = $string[ $i ];
687 + ( isset( $output[ $num ] ) ) ? $output[ $num ] .= $a_string[ $i ] : $output[ $num ] = $a_string[ $i ];
692 688 }
693 689 break;
694 690
695 691 case 'str':
696 - if ( $string[ $i ] === $to && ! $this->parser->escaped( $string, $i ) ) {
692 + if ( $a_string[ $i ] === $to && ! $this->parser->escaped( $a_string, $i ) ) {
697 693 $status = 'st';
698 694 }
699 - ( isset( $output[ $num ] ) ) ? $output[ $num ] .= $string[ $i ] : $output[ $num ] = $string[ $i ];
695 + ( isset( $output[ $num ] ) ) ? $output[ $num ] .= $a_string[ $i ] : $output[ $num ] = $a_string[ $i ];
700 696 break;
701 697 }
702 698 }
703 699
@@ -712,23 +708,22 @@
712 708 * Merges Shorthand properties again, the opposite of dissolve_4value_shorthands().
713 709 *
714 710 * @since 1.0.0
715 711 *
716 - * @param [type] $array [description]
717 - * @return [type] [description]
712 + * @param array<string, mixed> $an_array [description].
713 + * @return array<string, mixed> [description]
718 714 */
719 - public function merge_4value_shorthands( $array ) {
720 - $return = $array;
715 + public function merge_4value_shorthands( array $an_array ): array {
716 + $return = $an_array;
721 717 $shorthands = &$this->parser->data['csstidy']['shorthands'];
722 718
723 719 foreach ( $shorthands as $key => $value ) {
724 - if ( isset( $array[ $value[0] ] ) && isset( $array[ $value[1] ] )
725 - && isset( $array[ $value[2] ] ) && isset( $array[ $value[3] ] ) && 0 !== $value ) {
720 + if ( 0 !== $value && isset( $an_array[ $value[0] ], $an_array[ $value[1] ], $an_array[ $value[2] ], $an_array[ $value[3] ] ) ) {
726 721 $return[ $key ] = '';
727 722
728 723 $important = '';
729 724 for ( $i = 0; $i < 4; $i++ ) {
730 - $val = $array[ $value[ $i ] ];
725 + $val = $an_array[ $value[ $i ] ];
731 726 if ( $this->parser->is_important( $val ) ) {
732 727 $important = ' !important';
733 728 $return[ $key ] .= $this->parser->gvw_important( $val ) . ' ';
734 729 } else {
@@ -744,17 +739,17 @@
744 739
745 740 /**
746 741 * Dissolve background property.
747 742 *
748 - * @TODO Full CSS3 compliance.
743 + * @todo Full CSS3 compliance.
749 744 *
750 745 * @since 1.0.0
751 746 *
752 747 * @param string $str_value String value.
753 - * @return array Array.
748 + * @return array<string, string|null> Array.
754 749 */
755 - public function dissolve_short_bg( $str_value ) {
756 - // Don't try to explose background gradient!
750 + public function dissolve_short_bg( string $str_value ): array {
751 + // Don't try to explode background gradient!
757 752 if ( false !== stripos( $str_value, 'gradient(' ) ) {
758 753 return array( 'background' => $str_value );
759 754 }
760 755
@@ -782,9 +777,10 @@
782 777 }
783 778
784 779 $have = array();
785 780 $str_value = $this->explode_ws( ',', $str_value );
786 - for ( $i = 0; $i < count( $str_value ); $i++ ) {
781 + $str_value_count = count( $str_value );
782 + for ( $i = 0; $i < $str_value_count; $i++ ) {
787 783 $have['clip'] = false;
788 784 $have['pos'] = false;
789 785 $have['color'] = false;
790 786 $have['bg'] = false;
@@ -793,10 +789,11 @@
793 789 $str_value[ $i ] = $str_value[ $i ][0];
794 790 }
795 791 $str_value[ $i ] = $this->explode_ws( ' ', trim( $str_value[ $i ] ) );
796 792
797 - for ( $j = 0; $j < count( $str_value[ $i ] ); $j++ ) {
798 - if ( false === $have['bg'] && ( 'url(' === substr( $str_value[ $i ][ $j ], 0, 4 ) || 'none' === $str_value[ $i ][ $j ] ) ) {
793 + $str_value_i_count = count( $str_value[ $i ] );
794 + for ( $j = 0; $j < $str_value_i_count; $j++ ) {
795 + if ( false === $have['bg'] && ( str_starts_with( $str_value[ $i ][ $j ], 'url(' ) || 'none' === $str_value[ $i ][ $j ] ) ) {
799 796 $return['background-image'] .= $str_value[ $i ][ $j ] . ',';
800 797 $have['bg'] = true;
801 798 } elseif ( in_array( $str_value[ $i ][ $j ], $repeat, true ) ) {
802 799 $return['background-repeat'] .= $str_value[ $i ][ $j ] . ',';
@@ -808,9 +805,9 @@
808 805 } elseif ( in_array( $str_value[ $i ][ $j ], $origin, true ) ) {
809 806 $return['background-origin'] .= $str_value[ $i ][ $j ] . ',';
810 807 } elseif ( '(' === $str_value[ $i ][ $j ][0] ) {
811 808 $return['background-size'] .= substr( $str_value[ $i ][ $j ], 1, -1 ) . ',';
812 - } elseif ( in_array( $str_value[ $i ][ $j ], $pos, true ) || is_numeric( $str_value[ $i ][ $j ][0] ) || null === $str_value[ $i ][ $j ][0] || '-' === $str_value[ $i ][ $j ][0] || '.' === $str_value[ $i ][ $j ][0] ) {
809 + } elseif ( in_array( $str_value[ $i ][ $j ], $pos, true ) || is_numeric( $str_value[ $i ][ $j ][0] ) || is_null( $str_value[ $i ][ $j ][0] ) || '-' === $str_value[ $i ][ $j ][0] || '.' === $str_value[ $i ][ $j ][0] ) {
813 810 $return['background-position'] .= $str_value[ $i ][ $j ];
814 811 if ( ! $have['pos'] ) {
815 812 $return['background-position'] .= ' ';
816 813 } else {
@@ -836,21 +833,21 @@
836 833
837 834 /**
838 835 * Merges all background properties.
839 836 *
840 - * @TODO Full CSS3 compliance.
837 + * @todo Full CSS3 compliance.
841 838 *
842 839 * @since 1.0.0
843 840 *
844 - * @param array $input_css CSS.
845 - * @return array Array.
841 + * @param array<string, mixed> $input_css CSS.
842 + * @return array<string, mixed> Array.
846 843 */
847 - public function merge_bg( array $input_css ) {
844 + public function merge_bg( array $input_css ): array {
848 845 $background_prop_default = &$this->parser->data['csstidy']['background_prop_default'];
849 846 // Max number of background images. CSS3 not yet fully implemented.
850 - $number_of_values = @max( count( $this->explode_ws( ',', $input_css['background-image'] ) ), count( $this->explode_ws( ',', $input_css['background-color'] ) ), 1 );
847 + $number_of_values = @max( count( $this->explode_ws( ',', $input_css['background-image'] ) ), count( $this->explode_ws( ',', $input_css['background-color'] ) ), 1 ); // phpcs:ignore WordPress.PHP.NoSilencedErrors.Discouraged
851 848 // Array with background images to check if BG image exists.
852 - $bg_img_array = @$this->explode_ws( ',', $this->parser->gvw_important( $input_css['background-image'] ) );
849 + $bg_img_array = @$this->explode_ws( ',', $this->parser->gvw_important( $input_css['background-image'] ) ); // phpcs:ignore WordPress.PHP.NoSilencedErrors.Discouraged
853 850 $new_bg_value = '';
854 851 $important = '';
855 852
856 853 // If background properties is here and not empty, don't try anything.
@@ -924,12 +921,12 @@
924 921 * Dissolve font property.
925 922 *
926 923 * @since 1.0.0
927 924 *
928 - * @param [type] $str_value [description]
929 - * @return [type] [description]
925 + * @param string $str_value [description].
926 + * @return array<string, string|null> [description]
930 927 */
931 - public function dissolve_short_font( $str_value ) {
928 + public function dissolve_short_font( string $str_value ): array {
932 929 $font_prop_default = &$this->parser->data['csstidy']['font_prop_default'];
933 930 $font_weight = array( 'normal', 'bold', 'bolder', 'lighter', 100, 200, 300, 400, 500, 600, 700, 800, 900 );
934 931 $font_variant = array( 'normal', 'small-caps' );
935 932 $font_style = array( 'normal', 'italic', 'oblique' );
@@ -960,19 +957,20 @@
960 957 $str_value = $this->explode_ws( ',', trim( $str_value ) );
961 958
962 959 $str_value[0] = $this->explode_ws( ' ', trim( $str_value[0] ) );
963 960
964 - for ( $j = 0; $j < count( $str_value[0] ); $j++ ) {
965 - if ( false === $have['weight'] && in_array( $str_value[0][ $j ], $font_weight ) ) {
961 + $str_value_0_count = count( $str_value[0] );
962 + for ( $j = 0; $j < $str_value_0_count; $j++ ) {
963 + if ( false === $have['weight'] && in_array( $str_value[0][ $j ], $font_weight, false ) ) { // phpcs:ignore WordPress.PHP.StrictInArray.FoundNonStrictFalse
966 964 $return['font-weight'] = $str_value[0][ $j ];
967 965 $have['weight'] = true;
968 - } elseif ( false === $have['variant'] && in_array( $str_value[0][ $j ], $font_variant ) ) {
966 + } elseif ( false === $have['variant'] && in_array( $str_value[0][ $j ], $font_variant, true ) ) {
969 967 $return['font-variant'] = $str_value[0][ $j ];
970 968 $have['variant'] = true;
971 - } elseif ( false === $have['style'] && in_array( $str_value[0][ $j ], $font_style ) ) {
969 + } elseif ( false === $have['style'] && in_array( $str_value[0][ $j ], $font_style, true ) ) {
972 970 $return['font-style'] = $str_value[0][ $j ];
973 971 $have['style'] = true;
974 - } elseif ( false === $have['size'] && ( is_numeric( $str_value[0][ $j ][0] ) || null === $str_value[0][ $j ][0] || '.' === $str_value[0][ $j ][0] ) ) {
972 + } elseif ( false === $have['size'] && ( is_numeric( $str_value[0][ $j ][0] ) || is_null( $str_value[0][ $j ][0] ) || '.' === $str_value[0][ $j ][0] ) ) {
975 973 $size = $this->explode_ws( '/', trim( $str_value[0][ $j ] ) );
976 974 $return['font-size'] = $size[0];
977 975 if ( isset( $size[1] ) ) {
978 976 $return['line-height'] = $size[1];
@@ -979,9 +977,9 @@
979 977 } else {
980 978 $return['line-height'] = ''; // Don't add 'normal'!
981 979 }
982 980 $have['size'] = true;
983 - } else {
981 + } else { // phpcs:ignore Universal.ControlStructures.DisallowLonelyIf.Found
984 982 if ( isset( $return['font-family'] ) ) {
985 983 $return['font-family'] .= ' ' . $str_value[0][ $j ];
986 984 $multiwords = true;
987 985 } else {
@@ -989,15 +987,15 @@
989 987 }
990 988 }
991 989 }
992 990 // Add quotes if we have several words in font-family.
993 - if ( false !== $multiwords ) {
991 + if ( $multiwords ) {
994 992 $return['font-family'] = '"' . $return['font-family'] . '"';
995 993 }
996 994 $i = 1;
997 995 while ( isset( $str_value[ $i ] ) ) {
998 996 $return['font-family'] .= ',' . trim( $str_value[ $i ] );
999 - $i++;
997 + ++$i;
1000 998 }
1001 999
1002 1000 // Fix for font-size 100 and higher.
1003 1001 if ( false === $have['size'] && isset( $return['font-weight'] ) && is_numeric( $return['font-weight'][0] ) ) {
@@ -1019,33 +1017,31 @@
1019 1017 * Merges all fonts properties.
1020 1018 *
1021 1019 * @since 1.0.0
1022 1020 *
1023 - * @param [type] $input_css [description]
1024 - * @return [type] [description]
1021 + * @param array<string, string> $input_css [description].
1022 + * @return array<string, string> [description]
1025 1023 */
1026 - public function merge_font( $input_css ) {
1024 + public function merge_font( array $input_css ): array {
1027 1025 $font_prop_default = &$this->parser->data['csstidy']['font_prop_default'];
1028 1026 $new_font_value = '';
1029 1027 $important = '';
1030 1028 // Skip if no font-family and font-size set.
1031 - if ( isset( $input_css['font-family'] ) && isset( $input_css['font-size'] ) && 'inherit' !== $input_css['font-family'] ) {
1029 + if ( isset( $input_css['font-family'], $input_css['font-size'] ) && 'inherit' !== $input_css['font-family'] ) {
1032 1030 // Fix several words in font-family - add quotes.
1033 - if ( isset( $input_css['font-family'] ) ) {
1034 - $families = explode( ',', $input_css['font-family'] );
1035 - $result_families = array();
1036 - foreach ( $families as $family ) {
1037 - $family = trim( $family );
1038 - $len = strlen( $family );
1039 - if ( strpos( $family, ' ' ) &&
1040 - ! ( ( '"' === $family[0] && '"' === $family[ $len - 1 ] ) ||
1041 - ( "'" === $family[0] && "'" === $family[ $len - 1 ] ) ) ) {
1042 - $family = '"' . $family . '"';
1043 - }
1044 - $result_families[] = $family;
1031 + $families = explode( ',', $input_css['font-family'] );
1032 + $result_families = array();
1033 + foreach ( $families as $family ) {
1034 + $family = trim( $family );
1035 + $len = strlen( $family );
1036 + if ( str_contains( $family, ' ' ) &&
1037 + ! ( ( '"' === $family[0] && '"' === $family[ $len - 1 ] ) ||
1038 + ( "'" === $family[0] && "'" === $family[ $len - 1 ] ) ) ) {
1039 + $family = '"' . $family . '"';
1045 1040 }
1046 - $input_css['font-family'] = implode( ',', $result_families );
1041 + $result_families[] = $family;
1047 1042 }
1043 + $input_css['font-family'] = implode( ',', $result_families );
1048 1044 foreach ( $font_prop_default as $font_property => $default_value ) {
1049 1045 // Skip if property does not exist.
1050 1046 if ( ! isset( $input_css[ $font_property ] ) ) {
1051 1047 continue;
@@ -1086,106 +1082,5 @@
1086 1082
1087 1083 return $input_css;
1088 1084 }
1089 1085
1090 -} // class TablePress_CSSTidy_optimise
1091 -
1092 -/**
1093 - * Sanitization class
1094 - */
1095 -class TablePress_CSSTidy_custom_sanitize extends TablePress_CSSTidy_optimise {
1096 -
1097 - /**
1098 - * [$props_w_urls description]
1099 - *
1100 - * @since 1.0.0
1101 - * @var array
1102 - */
1103 - protected $props_w_urls = array( 'background', 'background-image', 'list-style', 'list-style-image' );
1104 -
1105 - /**
1106 - * [$allowed_protocols description]
1107 - *
1108 - * @since 1.0.0
1109 - * @var array
1110 - */
1111 - protected $allowed_protocols = array( 'http', 'https' );
1112 -
1113 - /**
1114 - * [__construct description]
1115 - *
1116 - * @since 1.0.0
1117 - *
1118 - * @param [type] $css [description]
1119 - */
1120 - public function __construct( $css ) {
1121 - return parent::__construct( $css );
1122 - }
1123 -
1124 - /**
1125 - * [postparse description]
1126 - *
1127 - * @since 1.0.0
1128 - *
1129 - * @return [type] [description]
1130 - */
1131 - public function postparse() {
1132 - if ( ! empty( $this->parser->import ) ) {
1133 - $this->parser->import = array();
1134 - }
1135 - if ( ! empty( $this->parser->charset ) ) {
1136 - $this->parser->charset = array();
1137 - }
1138 -
1139 - return parent::postparse();
1140 - }
1141 -
1142 - /**
1143 - * [subvalue description]
1144 - *
1145 - * @since 1.0.0
1146 - *
1147 - * @return [type] [description]
1148 - */
1149 - public function subvalue() {
1150 - $this->sub_value = trim( $this->sub_value );
1151 -
1152 - // Send any urls through our filter
1153 - if ( preg_match( '!^\\s*url\\s*(?:\\(|\\\\0028)(.*)(?:\\)|\\\\0029).*$!Dis', $this->sub_value, $matches ) ) {
1154 - $this->sub_value = $this->clean_url( $matches[1] );
1155 - }
1156 -
1157 - // Strip any expressions
1158 - if ( preg_match( '!^\\s*expression!Dis', $this->sub_value ) ) {
1159 - $this->sub_value = '';
1160 - }
1161 -
1162 - return parent::subvalue();
1163 - }
1164 -
1165 - /**
1166 - * [clean_url description]
1167 - *
1168 - * @since 1.0.0
1169 - *
1170 - * @param [type] $url [description]
1171 - * @return [type] [description]
1172 - */
1173 - protected function clean_url( $url ) {
1174 - // Clean up the string.
1175 - $url = trim( $url, "'\"\r\n " );
1176 -
1177 - // Check against whitelist for properties allowed to have URL values.
1178 - if ( ! in_array( $this->property, $this->props_w_urls ) ) {
1179 - return '';
1180 - }
1181 -
1182 - $url = wp_kses_bad_protocol_once( $url, $this->allowed_protocols );
1183 -
1184 - if ( empty( $url ) ) {
1185 - return '';
1186 - }
1187 -
1188 - return "url('$url')";
1189 - }
1190 -
1191 -} // class TablePress_CSSTidy_custom_sanitize
1086 +} // class TablePress_CSSTidy_Optimise