CSS3Maximizer::clean()   F
last analyzed

Complexity

Conditions 45
Paths > 20000

Size

Total Lines 177
Code Lines 129

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 45
eloc 129
nc 2218752
nop 1
dl 0
loc 177
rs 2
c 0
b 0
f 0

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
/*
4
5
    CSS3Maximizer : v0.1 : mudcu.be
6
    ------------------------------------
7
    Adds compatibility for vendors through proprietary CSS properties.  No hassle!
8
    Use your favorite syntax and CSS3Maximizer fills in the holes.
9
10
11
    CSS3 Color Module
12
    ------------------
13
    #00FF00 // all browsers
14
    hsl(120, 100%, 50%); //
15
    hsla(120, 100%, 50%, 1); //
16
    rgb(0, 255, 0); //
17
    rgb(0, 100%, 0); //
18
    rgba(0, 255, 0%, 1); //
19
    rgba(0, 100%, 0%, 1); //
20
21
22
    CSS3 Gradient Module
23
    ---------------------
24
    linear-gradient(yellow, blue);
25
    linear-gradient(to top, blue, yellow);
26
    linear-gradient(180deg, yellow, blue);
27
    linear-gradient(to bottom, yellow 0%, blue 100%);
28
    -webkit-gradient(linear, left top, left bottom, color-stop(0%, #444444), color-stop(100%, #999999)); // Saf4+, Chrome
29
    -webkit-gradient(linear, left top, left bottom, from(#444444), to(#999999)); // Saf4+, Chrome
30
    -webkit-linear-gradient(top, #444444, #999999); // Chrome 10+, Saf5.1+
31
    -moz-linear-gradient(top, #444444, #999999); // FF3.6
32
    -ms-linear-gradient(top, #444444, #999999); // IE10
33
    -o-linear-gradient(top, #444444, #999999); // Opera 11.10+
34
    filter: progid:DXImageTransform.Microsoft.gradient(startColorStr='#444444', EndColorStr='#999999'); // IE6–IE9
35
36
37
    CSS3 Properties
38
    ----------------
39
    background-clip
40
    ----------------
41
           -moz-background-clip: padding;
42
        -webkit-background-clip: padding-box;
43
                background-clip: padding-box;
44
45
    background-size
46
    ----------------
47
           -moz-background-size: 100% 100%; // FF3.6
48
        -webkit-background-size: 100% 100%; // Saf3-4
49
                background-size: 100% 100%; // Opera, IE9, Saf5, Chrome, FF4
50
51
    border-radius
52
    --------------
53
             -moz-border-radius: 12px; // FF1-3.6
54
          -webkit-border-radius: 12px; // Saf3-4, iOS 1-3.2, Android <1.6
55
                  border-radius: 12px; // Opera 10.5, IE9, Saf5, Chrome, FF4, iOS 4, Android 2.1+
56
57
    box-shadow
58
    -----------
59
                -moz-box-shadow: 0px 0px 4px #ffffff; // FF3.5 - 3.6
60
             -webkit-box-shadow: 0px 0px 4px #ffffff; // Saf3.0+, Chrome
61
                     box-shadow: 0px 0px 4px #ffffff; // Opera 10.5, IE9, FF4+, Chrome 10+
62
63
    transition
64
    -----------
65
                -moz-transition: all 0.3s ease-out;  // FF4+
66
                  -o-transition: all 0.3s ease-out;  // Opera 10.5+
67
             -webkit-transition: all 0.3s ease-out;  // Saf3.2+, Chrome
68
                 -ms-transition: all 0.3s ease-out;  // IE10?
69
                     transition: all 0.3s ease-out;
70
71
    transform
72
    ----------
73
                 -moz-transform: rotate(7.5deg);  // FF3.5+
74
                   -o-transform: rotate(7.5deg);  // Opera 10.5
75
              -webkit-transform: rotate(7.5deg);  // Saf3.1+, Chrome
76
                  -ms-transform: rotate(7.5deg);  // IE9
77
                      transform: rotate(7.5deg);
78
    user-select
79
    ------------
80
                    user-select: none;
81
             -khtml-user-select: none;
82
               -moz-user-select: none;
83
                 -o-user-select: none;
84
            -webkit-user-select: none;
85
86
87
    TODO
88
    -----
89
    Maximize filter "opacity" for Internet Explorer:
90
        opacity: 0 === filter: alpha(opacity=0);
91
92
*/
93
94
class CSS3Maximizer
95
{
96
    private $ColorSpace;
97
    private $code;
98
99
    public function __construct()
100
    {
101
        $this->ColorSpace = new ColorSpace();
102
    }
103
104
    /* Direct conversions of properties between vendors */
105
106
    private $defAlias = [
107
        'background-clip'     => [
108
            'background-clip',
109
            '-moz-background-clip',
110
            '-webkit-background-clip',
111
        ],
112
        'background-size'     => [
113
            'background-size',
114
            '-moz-background-size',
115
            '-webkit-background-size',
116
        ],
117
        'border-radius'       => [
118
            'border-radius',
119
            '-moz-border-radius',
120
            '-webkit-border-radius',
121
        ],
122
        'box-shadow'          => [
123
            'box-shadow',
124
            '-moz-box-shadow',
125
            '-webkit-box-shadow',
126
        ],
127
        'text-shadow'         => [
128
            'text-shadow',
129
            '-moz-text-shadow',
130
        ],
131
        'transition'          => [
132
            'transition',
133
            '-moz-transition',
134
            '-ms-transition',
135
            '-o-transition',
136
            '-webkit-transition',
137
        ],
138
        'transition-property' => [
139
            'transition-property',
140
            '-moz-transition-property',
141
            '-ms-transition-property',
142
            '-o-transition-property',
143
            '-webkit-transition-property',
144
        ],
145
        'transition-duration' => [
146
            'transition-duration',
147
            '-moz-transition-duration',
148
            '-ms-transition-duration',
149
            '-o-transition-duration',
150
            '-webkit-transition-duration',
151
        ],
152
        'transform'           => [
153
            'transform',
154
            '-moz-transform',
155
            '-ms-transform',
156
            '-o-transform',
157
            '-webkit-transform',
158
        ],
159
        'user-select'         => [
160
            'user-select',
161
            '-khtml-user-select',
162
            '-moz-user-select',
163
            '-o-user-select',
164
            '-webkit-user-select',
165
        ],
166
    ];
167
168
    private $defStaticProps = [
169
        '0',
170
        'none',
171
        'transparent',
172
        'inherit',
173
    ];
174
175
    // Color Properties
176
177
    private $defColorFallback = [
178
        'color', // single value, rgba with hex fallback
179
        'background-color', // single value, rgba with hex fallback
180
        'border', // multiple values, rgba with hex fallback
181
        'border-color', // multiple values, rgba with hex fallback
182
    ];
183
184
    private $defColorProperties = [
185
        'color', // single value, rgba with hex fallback
186
        'background-color', // single value, rgba with hex fallback
187
        'border', // multiple values, rgba with hex fallback
188
        'border-color', // multiple values, rgba with hex fallback
189
        'box-shadow', // multiple values, can always use rgba
190
        'text-shadow', // multiple values, can always use rgba
191
    ];
192
193
    // Gradient Properties
194
195
    private $defGradientProperties = [
196
        'background',
197
        'background-image',
198
    ];
199
200
    private $defGradientLinear = [
201
        '-webkit-gradient',
202
        '-webkit-linear-gradient',
203
        '-moz-linear-gradient',
204
        '-ms-linear-gradient',
205
        '-o-linear-gradient',
206
        'linear-gradient',
207
        'filter',
208
    ];
209
210
    /* Color parsing and standardization */
211
212
    private function splitByColor($value)
213
    {
214
        $values = [];
215
        while (strlen($value)) {
216
            $ishex = strpos($value, '#');
217
            $isother = strpos($value, ')');
218
            if ($ishex === false) {
219
                $ishex = 99999999999;
220
            }
221
            if ($isother === false) {
222
                $isother = 99999999999;
223
            }
224
            if ($ishex < $isother) {
225
                $comma = strpos($value, ',');
226
                if ($comma === false) { // end of the line
227
                    array_push($values, $value);
228
                    $value = '';
229 View Code Duplication
                } else { // split by comma [hex]
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
230
                    array_push($values, substr($value, 0, $comma));
231
                    $value = trim(substr($value, $comma + 1));
232
                }
233 View Code Duplication
            } else { // split by comma [rgb, rgba, hsl, hsla]
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
234
                array_push($values, substr($value, 0, $isother + 1));
235
                $value = trim(substr($value, $isother + 2));
236
            }
237
        }
238
239
        return $values;
240
    }
241
242
    private function parseColors($colors, $doFallback = false)
243
    {
244
        $fallback = [];
245
        foreach ($colors as $key => $value) {
246
            $tmp = str_replace('  ', ' ', trim($value));
247
            if (in_array($tmp, $this->defStaticProps)) { // none, inherit, transparent
248
                return $tmp;
249
            }
250
            $pos = strpos($tmp, '(');
251
            if ($pos === false) { // split color from properties [hex]
252
                $pos = strpos($tmp, '#');
253
                $first = substr($tmp, 0, $pos);
254
                $color = substr($tmp, $pos);
255
            } else { // split color from properties [rgb, rgba, hsl or hsla]
256
                $pos = substr($tmp, 0, $pos);
257
                $backpos = strrpos($pos, ' ');
258
                if ($backpos === false) {
259
                    $backpos = -1;
260
                }
261
                $first = substr($pos, 0, $backpos + 1);
262
                $color = substr($tmp, $backpos + 1);
263
            }
264
            $color = $this->parseColor($color);
265
            if ($doFallback) { // include hex fallback when alpha is present
266
                if ($color['rgba']) {
267
                    $fallback[$key] = $first.$color['hex'];
268
                    $colors[$key] = $first.$color['rgba'];
269 View Code Duplication
                } else {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
270
                    $fallback[$key] = $first.$color['hex'];
271
                    $colors[$key] = $first.$color['hex'];
272
                }
273 View Code Duplication
            } else {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
274
                if ($color['rgba']) {
275
                    $colors[$key] = $first.$color['rgba'];
276
                } else { // everything is supported in hex!
277
                    $colors[$key] = $first.$color['hex'];
278
                }
279
            }
280
        }
281
        $colors = implode($colors, ', ');
282
        $fallback = implode($fallback, ', ');
283
        if ($doFallback && $colors !== $fallback) { // include fallback
284
            return [
285
                'hex'  => $fallback,
286
                'rgba' => $colors,
287
            ];
288
        } else { // no fallback necessary
289
            return $colors;
290
        }
291
    }
292
293
    private function parseColor($color)
294
    {
295
        $color = trim($color);
296
        if (strpos($color, '(')) { // rgb, rgba, hsl or hsla
297
            $first = strpos($color, '(');
298
            $type = substr($color, 0, $first);
299
            $color = substr($color, $first + 1, -1);
300
            $color = explode(',', $color);
301
            $alpha = isset($color[3]) ? floatval($color[3]) : 1;
302
            switch ($type) { // regularize to rgba and hex
303
                case 'rgb':
304
                case 'rgba':
305
                    if (strpos($color[0], '%')) {
306
                        $color[0] = round(intval($color[0]) / 100 * 255);
307
                        $color[1] = round(intval($color[1]) / 100 * 255);
308
                        $color[2] = round(intval($color[2]) / 100 * 255);
309
                    }
310
                    $color = [
311
                        R => $color[0],
312
                        G => $color[1],
313
                        B => $color[2],
314
                    ];
315
                    break;
316
                case 'hsl': // convert to rgb()
317
                case 'hsla': // convert to rgba()
318
                    $color = $this->ColorSpace->HSL_RGB([
319
                        H => $color[0],
320
                        S => $color[1],
321
                        L => $color[2],
322
                    ]);
323
                    break;
324
                default: // hex
325
                    break;
326
            }
327
            $hex = '#'.$this->ColorSpace->HEX_STRING($this->ColorSpace->RGB_HEX($color));
328
            if ($alpha === 1) {
329
                return ['hex' => $hex];
330
            } else { // requires alpha
331
                $r = max(0, min(255, round($color[R])));
332
                $g = max(0, min(255, round($color[G])));
333
                $b = max(0, min(255, round($color[B])));
334
335
                return [
336
                    'rgba' => 'rgba('.$r.', '.$g.', '.$b.', '.$alpha.')',
337
                    'hex'  => $hex,
338
                ];
339
            }
340
        } else {
341
            return [
342
                'hex' => $color,
343
            ];
344
        }
345
    }
346
347
    /* Gradient parsing and standardization */
348
349
    private function splitGradient($value)
350
    {
351
        $values = [];
352
        while (strlen($value)) {
353
            $ishex = strpos($value, ',');
354
            $isother = strpos($value, '(');
355
            if ($ishex === false) {
356
                $ishex = 99999999999;
357
            }
358
            if ($isother === false) {
359
                $isother = 99999999999;
360
            }
361
            if ($ishex < $isother) {
362
                $comma = strpos($value, ',');
363
                array_push($values, substr($value, 0, $comma));
364
                $value = trim(substr($value, $comma + 1));
365
            } else { // split by comma [rgb, rgba, hsl, hsla]
366
                $isother = strpos($value, ')');
367
                if ($isother === false) {
368
                    array_push($values, $value);
369
                    $value = '';
370
                } else {
371
                    $stop = substr($value, 0, $isother + 1);
372
                    if (substr_count($stop, '(') === 2) {
373
                        $isother += 1;
374
                        $stop = $stop.')';
375
                    }
376
                    array_push($values, $stop);
377
                    $value = trim(substr($value, $isother + 2));
378
                }
379
            }
380
        }
381
382
        return $values;
383
    }
384
385
    private function Webkit_Gradient_Position($value)
386
    {
387
        switch ($value) {
388
            case 'top':
389
                return ['y' => -1];
390
            case 'left':
391
                return ['x' => -1];
392
            case 'bottom':
393
                return ['y' => 1];
394
            case 'right':
395
                return ['x' => 1];
396
            default: // center
397
                return [];
398
        }
399
    }
400
401
    private function Webkit_to_W3C_Gradient($value)
402
    {
403
404
        ///--- webkit supports out-of-order color-stops (others fail)...
405
406
        array_shift($value); // type of gradient [assume linear]
407
        $start = explode(' ', array_shift($value));
408
        $end = explode(' ', array_shift($value));
409
        $aIsSame = $start[0] == $end[0];
410
        $bIsSame = $start[1] == $end[1];
411
        if ($aIsSame && !$bIsSame) {
412
            $start = 'top';
413
        } else {
414
            if (!$aIsSame && $bIsSame) {
415
                $start = 'left';
416
            } else {
417
                if (!$aIsSame && !$bIsSame) { // convert to angle
418
                    $p1 = array_merge(
419
                        ['x' => 0, 'y' => 0],
420
                        $this->Webkit_Gradient_Position($start[0]),
421
                        $this->Webkit_Gradient_Position($start[1])
422
                    );
423
                    $p2 = array_merge(
424
                        ['x' => 0, 'y' => 0],
425
                        $this->Webkit_Gradient_Position($end[0]),
426
                        $this->Webkit_Gradient_Position($end[1])
427
                    );
428
                    $dy = $p2[y] - $p1[y];
429
                    $dx = $p2[x] - $p1[x];
430
                    $start = round(rad2deg(atan2($dy, $dx))).'deg';
431
                } else { // is "left"
432
                    $start = 'left';
433
                }
434
            }
435
        }
436
        $values = [];
437
        $moz = [];
438
        //
439
        foreach ($value as $key) {
440
            $type = substr($key, 0, strpos($key, '('));
441
            $key = substr($key, strpos($key, '(') + 1);
442
            if ($type == 'from') {
443
                $position = '0%';
444
                $color = substr($key, 0, -1);
445
            } else {
446
                if ($type == 'to') {
447
                    $position = '100%';
448
                    $color = substr($key, 0, -1);
449
                } else {
450
                    $key = explode(',', $key, 2);
451
                    $position = $key[0];
452
                    if (!strpos($position, '%')) {
453
                        $position = round($position * 100).'%';
454
                    }
455
                    $color = substr($key[1], 0, -1);
456
                }
457
            }
458
            $color = $this->parseColor($color);
459
            if ($color['rgba']) {
460
                array_push($values, $color['rgba'].' '.$position);
461
            } else {
462
                array_push($values, $color['hex'].' '.$position);
463
            }
464
            array_push($moz, $color['hex'].' '.$position);
465
        }
466
467
        return [
468
            'microsoft' => [substr(reset($moz), 0, 7), substr(end($moz), 0, 7)],
469
            'moz'       => $start.', '.implode($moz, ', '),
470
            'w3c'       => $start.', '.implode($values, ', '),
471
        ];
472
    }
473
474
    private function W3C_to_Webkit_Gradient($value)
475
    {
476
        $start = array_shift($value);
477
        switch ($start) {
478
            case 'top':
479
                $start = 'center top, center bottom, ';
480
                break;
481
            case 'left':
482
                $start = 'left center, right center, ';
483
                break;
484
            default: // angle
485
                $start = deg2rad(intval($start));
486
                $x = round(cos($start) * 100);
487
                $y = round(sin($start) * 100);
488
                $start = $x.'% 0%, 0% '.$y.'%, ';
489
                break;
490
        }
491
        $count = count($value) - 1;
492
        $values = [];
493
        foreach ($value as $n => $key) {
494
            $key = explode(' ', $key);
495
            $color = $this->parseColor($key[0]);
496
            if ($color['rgba']) {
497
                $color = $color['rgba'];
498
            } else {
499
                $color = $color['hex'];
500
            }
501
            $position = $key[1];
502
            if (gettype($position) == 'NULL') {
503
                $position = round($n / $count * 100).'%';
504
            }
505
            if ($n === 0) {
506
                $first = $color;
507
                array_push($values, "from({$color})");
508
            } else {
509
                if ($n === $count) {
510
                    $last = $color;
511
                    array_push($values, "to({$color})");
512
                } else {
513
                    array_push($values, "color-stop({$position}, {$color})");
514
                }
515
            }
516
        }
517
518
        return [
519
            'microsoft' => [$first, $last],
0 ignored issues
show
Bug introduced by
The variable $first does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
Bug introduced by
The variable $last does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
520
            'webkit'    => 'linear, '.$start.implode($values, ', '),
521
        ];
522
    }
523
524
    private function parseGradient($property, $value)
0 ignored issues
show
Unused Code introduced by
The parameter $property is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
525
    {
526
        $type = substr($value, 0, strpos($value, '('));
527
        $tmp = substr($value, strpos($value, '(') + 1, -1);
528
        $values = [];
529
        if ($type == '-webkit-gradient') { // convert from webkit to other
530
            $value = $this->Webkit_to_W3C_Gradient($this->splitGradient($tmp));
531
            $value['webkit'] = $tmp;
532
        } else { // convert from other to webkit
533
            $value = $this->W3C_to_Webkit_Gradient($this->splitGradient($tmp));
534
            $value['w3c'] = $tmp;
535
        }
536
        foreach ($this->defGradientLinear as $key) {
537
            if ($key == '-webkit-gradient') {
538
                $values[$key] = $key.'('.$value['webkit'].')';
539
            } else {
540
                if ($key == 'filter') {
541
                    $color = $value['microsoft'];
542
                    $values[$key] = "filter: progid:DXImageTransform.Microsoft.gradient(startColorStr='{$color[0]}', EndColorStr='{$color[1]}')";
543
                } else {
544
                    $values[$key] = $key.'('.$value['w3c'].')';
545
                }
546
            }
547
        }
548
549
        return $values;
550
    }
551
552
    /* Convert CSS to Object */
553
554
    private function ParseCSS($str)
555
    {
556
        $css = [];
557
        $str = preg_replace("/\/\*(.*)?\*\//Usi", '', $str);
558
        $parts = explode('}', $str);
559
        $skipping = false;
560
        if (count($parts) > 0) {
561
            foreach ($parts as $part) {
562
                list($keystr, $codestr) = explode('{', $part);
563
                // @media queries [skip for now]
564
                if ($skipping) {
565
                    if (substr_count($part, '{') === 0) {
566
                        $skipping = false;
567
                        $css[$id[0]] .= "}\r";
0 ignored issues
show
Bug introduced by
The variable $id does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
568
                    } else {
569
                        $css[$id[0]] .= $part."}\r";
570
                        continue;
571
                    }
572
                }
573
                if (substr(trim($part), 0, 1) === '@') {
574
                    $id = explode(',', trim($keystr));
575
                    $css[$id[0]] = trim($part)."\r\t}";
576
                    $skipping = true;
577
                    continue;
578
                }
579
                // everything else
580
                $keys = explode(',', trim($keystr));
581
                if (count($keys) === 0) {
582
                    continue;
583
                }
584
                foreach ($keys as $key) {
585
                    if (strlen($key) === 0) {
586
                        continue;
587
                    }
588
                    $key = str_replace("\n", '', $key);
589
                    $key = str_replace('\\', '', $key);
590
                    $codestr = trim($codestr);
591
                    if (!isset($css[$key])) {
592
                        $css[$key] = [];
593
                    }
594
                    // only match ; without surrounding quotes
595
                    $codestr = preg_replace('/(?:["\'].*(;).*["\'])/e',
596
                        'str_replace(";","{{{RETAIN_SEPERATOR}}}","$0")', $codestr);
597
                    $codes = explode(';', $codestr);
598
                    if (count($codes) === 0) {
599
                        continue;
600
                    }
601
                    foreach ($codes as $code) {
602
                        // put back ; which were within surrounding quotes
603
                        $code = str_replace('{{{RETAIN_SEPERATOR}}}', ';', $code);
604
                        $code = trim($code);
605
                        list($codekey, $codevalue) = explode(':', $code, 2);
606
                        if (strlen($codekey) === 0) {
607
                            continue;
608
                        }
609
                        array_push($css[$key], [
610
                                'type'  => trim($codekey),
611
                                'value' => trim($codevalue),
612
                            ]
613
                        );
614
                    }
615
                }
616
            }
617
        }
618
619
        return $css;
620
    }
621
622
    /* Generate compatibility between vendors */
623
624
    public function clean($config)
625
    {
626
        $css = isset($config['css']) ? $config['css'] : '';
627
        $url = isset($config['url']) ? $config['url'] : '';
628
        $compress = isset($config['compress']) ? $config['compress'] : '';
629
        // load from file and write file
630
        if (strpos($css, '.css') && is_file($css)) {
631
            $this->code = file_get_contents($css);
632
        } else {
633
            $this->code = $css;
634
        }
635
636
        $cssObject = [];
637
        $cssText = '';
0 ignored issues
show
Unused Code introduced by
$cssText is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
638
        $css = $this->ParseCSS($this->code);
639
        // run through properties and add appropriate compatibility
640
        foreach ($css as $cssID => $cssProperties) {
641
            $properties = [];
642
            if (gettype($cssProperties) === 'string') {
643
                $cssObject[$cssID] = $cssProperties;
644
                continue;
645
            }
646
            foreach ($cssProperties as $value) {
647
                $type = $value['type'];
648
                $value = $value['value'];
649
                if (in_array($type, $this->defGradientProperties)) {
650
                    if (substr(trim($value), 0, 4) === 'url(') {
651
                        $value = substr(trim($value), 5, -1);
652
                        $value = str_replace(["'", '"'], [''], $value);
653
                        $value = 'url("'.$url.$value.'")';
654
                    } else {
655
                        if (strpos($value, 'gradient') !== false) { // background-gradient
656
                            $value = $this->parseGradient($type, $value);
657
                        } else { // background-color as "background"
658
                            $doFallback = in_array($type, $this->defColorFallback);
659
                            $value = $this->parseColors($this->splitByColor($value), $doFallback);
660
                        }
661
                    }
662
                } else {
663
                    if (in_array($type, $this->defColorProperties)) {
664
                        $doFallback = in_array($type, $this->defColorFallback);
665
                        $value = $this->parseColors($this->splitByColor($value), $doFallback);
666
                    }
667
                }
668
                $alias = [];
669
                foreach ($this->defAlias as $property) {
670
                    if (in_array($type, $property)) { // direct conversion between vendors
671
                        foreach ($property as $key) {
672
                            if ($key == '-moz-transition') {
673
                                $tmp = explode(' ', $value);
674
                                if ($tmp[0] == 'transform') {
675
                                    $tmp[0] = '-moz-transform';
676
                                }
677
                                $tmp = implode($tmp, ' ');
678
                                $alias[$key] = $tmp;
679
                            } else {
680
                                if ($key == '-moz-transition-property') {
681
                                    $tmp = $value;
682
                                    if ($tmp == 'transform') {
683
                                        $tmp = '-moz-transform';
684
                                    }
685
                                    $alias[$key] = $tmp;
686
                                } else {
687
                                    $alias[$key] = $value;
688
                                }
689
                            }
690
                        }
691
                    }
692
                }
693
                if (count($alias)) {
694
                    $value = $alias;
695
                }
696
                $merged = false;
697
                foreach ($properties as $key => $property) {
698
                    $typeof = gettype($property['value']);
699
                    if ($property['type'] == $type && gettype($value) === 'array') {
700
                        if ($typeof == 'string') {
701
                            $property['value'] = [
702
                                'hex' => $property['value'],
703
                            ];
704
                        }
705
                        $properties[$key]['value'] = array_merge(
706
                            $property['value'],
707
                            $value
708
                        );
709
                        $merged = true;
710
                    } else {
711
                        if ($typeof == 'array' && $property['value'][$type]) {
712
                            if ($type === 'filter') {
713
                                $value = [
714
                                    'filter' => $type.': '.$value,
715
                                ];
716
                            }
717
                            $properties[$key]['value'] = array_merge(
718
                                $property['value'],
719
                                $value
720
                            );
721
                            $merged = true;
722
                        } else {
723
                        }
724
                    }
725
                }
726
                if ($merged === false) {
727
                    array_push($properties, [
728
                        'type'  => $type,
729
                        'value' => $value,
730
                    ]);
731
                }
732
            }
733
            $cssObject[$cssID] = $properties;
734
        }
735
        $newline = $compress ? '' : "\n";
736
        $space = $compress ? '' : ' ';
737
        $tab = $compress ? '' : "\t";
738
        // composite $cssObject into $cssText
739
        $cssArray = [];
740
        foreach ($cssObject as $cssID => $cssProperties) {
741
            if (gettype($cssProperties) === 'string') {
742
                $cssText = substr($cssProperties, strpos($cssProperties, '{') + 1);
743
                $cssText = "\t".trim(substr($cssText, 0, strrpos($cssText, '}')))."\n";
744
                array_push($cssArray, [
745
                    'text' => $cssText,
746
                    'key'  => $cssID,
747
                ]);
748
                continue;
749
            }
750
            $cssText = '';
751
            foreach ($cssProperties as $value) {
752
                $type = $value['type'];
753
                $value = $value['value'];
754
                if (gettype($value) == 'string') { // general properties
755
                    if ($compress) {
756
                        $value = str_replace(', ', ',', $value);
757
                    }
758
                    $value = str_replace(['\"', "\'"], ['"', "'"], $value);
759
                    $cssText .= $tab.$type.":{$space}".$value.";{$newline}";
760
                } else { // multiple values
761
                    foreach ($value as $key => $tmp) {
762
                        if ($compress) {
763
                            $tmp = str_replace(', ', ',', $tmp);
764
                        }
765
                        $tmp = str_replace(['\"', "\'"], ['"', "'"], $tmp);
766
                        if ($key == 'hex' || $key == 'rgba' || in_array($key,
767
                                $this->defGradientLinear)
768
                        ) { // color or gradient variants
769
                            if ($key == 'filter') { // microsoft values
770
                                $cssText .= $tab.$tmp.";{$newline}";
771
                            } else {
772
                                $cssText .= $tab.$type.":{$space}".$tmp.";{$newline}";
773
                            }
774
                        } else { // direct conversion of vender variants
775
                            $cssText .= $tab.$key.":{$space}".$tmp.";{$newline}";
776
                        }
777
                    }
778
                }
779
            }
780
            array_push($cssArray, [
781
                'text' => $cssText,
782
                'key'  => $cssID,
783
            ]);
784
        }
785
        $cssText = '';
786
        foreach ($cssArray as $n => $value) {
787
            $cssID = $value['key'];
788
            $content1 = $cssArray[$n]['text'];
789
            $content2 = $cssArray[$n + 1]['text'];
790
            if ($content1 === $content2) {
791
                $cssText .= $cssID.$space.','.$newline;
792
            } else {
793
                $cssText .= $cssID.$space.'{'.$newline;
794
                $cssText .= $content1;
795
                $cssText .= '}'.$newline;
796
            }
797
        }
798
799
        return $cssText;
800
    }
801
}
802