Passed
Push — master ( cbf6d3...d62b89 )
by Michiel
08:56
created

SassTask   F

Complexity

Total Complexity 96

Size/Duplication

Total Lines 991
Duplicated Lines 0 %

Test Coverage

Coverage 48.09%

Importance

Changes 0
Metric Value
wmc 96
eloc 214
dl 0
loc 991
ccs 126
cts 262
cp 0.4809
rs 2
c 0
b 0
f 0

55 Methods

Rating   Name   Duplication   Size   Complexity  
A setUseScssphp() 0 3 1
A setInput() 0 3 1
A setNewext() 0 3 1
A setOutputpath() 0 3 1
A setEncoding() 0 13 2
A setOutput() 0 3 1
A setExecutable() 0 3 1
A setFile() 0 3 1
A setFlags() 0 3 1
A setFailonerror() 0 3 1
A setRemoveoldext() 0 3 1
A setKeepsubdirectories() 0 3 1
A setPath() 0 4 1
A setExtfilter() 0 3 1
A setUseSass() 0 3 1
A setLineNumbers() 0 8 2
A getStyle() 0 3 1
A setUnixnewlines() 0 8 2
A createFileSet() 0 4 1
A getNested() 0 3 1
A getPath() 0 3 1
A getForce() 0 3 1
A getUseSass() 0 3 1
A getNewext() 0 3 1
A getExtfilter() 0 3 1
A getNoCache() 0 3 1
A setExpand() 0 7 2
A setStyle() 0 15 6
A getLineNumbers() 0 3 1
A getExpand() 0 3 1
A setTrace() 0 7 2
A getEncoding() 0 3 1
A getTrace() 0 3 1
A setNoCache() 0 8 2
A getUseScssPhp() 0 3 1
A getRemoveoldext() 0 3 1
A getOutputpath() 0 3 1
A getCompressed() 0 3 1
A getUnixnewlines() 0 3 1
A setCompact() 0 7 2
A setCrunched() 0 5 2
A getExecutable() 0 3 1
A getCheck() 0 3 1
A setForce() 0 8 2
A getFlags() 0 3 1
A setCheck() 0 8 2
A getKeepsubdirectories() 0 3 1
B main() 0 28 9
A setNested() 0 7 2
A getCompact() 0 3 1
A setCompressed() 0 7 2
A getCrunched() 0 3 1
A processFile() 0 27 5
A buildOutputFilePath() 0 21 5
B processFilesets() 0 34 9

How to fix   Complexity   

Complex Class

Complex classes like SassTask often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use SassTask, and based on these observations, apply Extract Interface, too.

1
<?php
2
/**
3
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
4
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
5
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
6
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
7
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
8
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
9
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
10
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
11
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
12
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
13
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
14
 *
15
 * This software consists of voluntary contributions made by many individuals
16
 * and is licensed under the LGPL. For more information please see
17
 * <http://phing.info>.
18
 *
19
 * @category Tasks
20
 * @package  phing.tasks.ext
21
 * @author   Paul Stuart <[email protected]>
22
 * @author   Ken Guest <[email protected]>
23
 * @license  LGPL (see http://www.gnu.org/licenses/lgpl.html)
24
 */
25
26
use Phing\Exception\BuildException;
27
use Phing\Io\FileSystem;
28
use Phing\Project;
29
use Phing\Task;
30
use Phing\Type\FileSet;
31
use Phing\Util\StringHelper;
32
33
/**
34
 * Executes Sass for a particular fileset.
35
 *
36
 * If the sass executable is not available, but scssphp is, then use that instead.
37
 *
38
 * @category Tasks
39
 * @package  phing.tasks.ext
40
 * @author   Paul Stuart <[email protected]>
41
 * @author   Ken Guest <[email protected]>
42
 * @license  LGPL (see http://www.gnu.org/licenses/lgpl.html)
43
 * @link     SassTask.php
44
 */
45
class SassTask extends Task
46
{
47
48
    /**
49
     * Style to generate to.
50
     *
51
     * @var string
52
     */
53
    protected $style = 'nested';
54
55
    /**
56
     * Stack trace on error.
57
     *
58
     * @var bool
59
     */
60
    protected $trace = false;
61
62
    /**
63
     * Unix-style newlines?
64
     *
65
     * @var bool
66
     */
67
    protected $unixnewlines = true;
68
69
    /**
70
     * Encoding
71
     *
72
     * @var string
73
     */
74
    protected $encoding = 'utf-8';
75
76
    /**
77
     * SASS import path.
78
     *
79
     * @var string
80
     */
81
    protected $loadPath = '';
82
83
    /**
84
     * Whether to just check syntax
85
     *
86
     * @var bool
87
     */
88
    protected $check = false;
89
90
    /**
91
     * Whether to use the sass command line tool.
92
     *
93
     * @var bool
94
     */
95
    protected $useSass = true;
96
97
    /**
98
     * Whether to use the scssphp compiler, if available.
99
     *
100
     * @var bool
101
     */
102
    protected $useScssphp = true;
103
104
    /**
105
     * Input filename if only processing one file is required.
106
     *
107
     * @var string|null
108
     */
109
    protected $file = null;
110
111
    /**
112
     * Output filename
113
     *
114
     * @var string|null
115
     */
116
    protected $output = null;
117
118
    /**
119
     * Contains the path info of our file to allow us to parse.
120
     *
121
     * @var array
122
     */
123
    protected $pathInfo = null;
124
125
    /**
126
     * The Sass executable.
127
     *
128
     * @var string
129
     */
130
    protected $executable = 'sass';
131
132
    /**
133
     * The ext type we are looking for when Verifyext is set to true.
134
     *
135
     * More than likely should be "scss" or "sass".
136
     *
137
     * @var string
138
     */
139
    protected $extfilter = '';
140
141
    /**
142
     * This flag means 'note errors to the output, but keep going'
143
     *
144
     * @var bool
145
     */
146
    protected $failonerror = true;
147
148
    /**
149
     * The fileset we will be running Sass on.
150
     *
151
     * @var array
152
     */
153
    protected $filesets = [];
154
155
    /**
156
     * Additional flags to pass to sass.
157
     *
158
     * @var string
159
     */
160
    protected $flags = '';
161
162
    /**
163
     * Indicates if we want to keep the directory structure of the files.
164
     *
165
     * @var bool
166
     */
167
    protected $keepsubdirectories = true;
168
169
    /**
170
     * When true we will remove the current file ext.
171
     *
172
     * @var bool
173
     */
174
    protected $removeoldext = true;
175
176
    /**
177
     * The new ext our files will have.
178
     *
179
     * @var string
180
     */
181
    protected $newext = 'css';
182
    /**
183
     * The path to send our output files to.
184
     *
185
     * If not defined they will be created in the same directory the
186
     * input is from.
187
     *
188
     * @var string
189
     */
190
    protected $outputpath = '';
191
192
    /**
193
     * @var bool
194
     */
195
    protected $force;
196
197
    /**
198
     * @var bool
199
     */
200
    protected $lineNumbers = false;
201
202
    /**
203
     * @var bool
204
     */
205
    protected $noCache;
206
207
    /**
208
     * Set input file (For example style.scss)
209
     *
210
     * Synonym for @see setFile
211
     *
212
     * @param string $file Filename
213
     *
214
     * @return void
215
     */
216
    public function setInput($file)
217
    {
218
        $this->setFile($file);
219
    }
220
221
    /**
222
     * Set name of output file.
223
     *
224
     * @param string $file Filename of [css] to output.
225
     *
226
     * @return void
227
     */
228
    public function setOutput($file)
229
    {
230
        $this->output = $file;
231
    }
232
233
    /**
234
     * Sets the failonerror flag. Default: true
235
     *
236
     * @param string $failonerror Jenkins style boolean value
237
     *
238
     * @access public
239
     * @return void
240
     */
241
    public function setFailonerror($failonerror)
242
    {
243
        $this->failonerror = StringHelper::booleanValue($failonerror);
244
    }
245
246
    /**
247
     * Sets the executable to use for sass. Default: sass
248
     *
249
     * The default assumes sass is in your path. If not you can provide the full
250
     * path to sass.
251
     *
252
     * @param string $executable Name of executable, optionally including full path
253
     *
254
     * @return void
255
     */
256 1
    public function setExecutable(string $executable): void
257
    {
258 1
        $this->executable = $executable;
259 1
    }
260
261
    /**
262
     * Return name/path of sass executable.
263
     */
264 4
    public function getExecutable(): string
265
    {
266 4
        return $this->executable;
267
    }
268
269
    /**
270
     * Sets the extfilter. Default: <none>
271
     *
272
     * This will filter the fileset to only process files that match
273
     * this extension. This could also be done with the fileset.
274
     *
275
     * @param string $extfilter Extension to filter for.
276
     *
277
     * @access public
278
     * @return void
279
     */
280
    public function setExtfilter($extfilter)
281
    {
282
        $this->extfilter = trim($extfilter, ' .');
283
    }
284
285
    /**
286
     * Return extfilter setting.
287
     *
288
     * @return string
289
     */
290 1
    public function getExtfilter()
291
    {
292 1
        return $this->extfilter;
293
    }
294
295
    /**
296
     * Additional flags to pass to sass.
297
     *
298
     * Command will be:
299
     * sass {$flags} {$inputfile} {$outputfile}
300
     *
301
     * @param string $flags Flags to pass
302
     *
303
     * @return void
304
     */
305
    public function setFlags(string $flags): void
306
    {
307
        $this->flags = trim($flags);
308
    }
309
310
    /**
311
     * Return flags to be used when running the sass executable.
312
     */
313 6
    public function getFlags(): string
314
    {
315 6
        return trim($this->flags);
316
    }
317
318
    /**
319
     * Sets the removeoldext flag. Default: true
320
     *
321
     * This will cause us to strip the existing extension off the output
322
     * file.
323
     *
324
     * @param string $removeoldext Jenkins style boolean value
325
     *
326
     * @access public
327
     * @return void
328
     */
329
    public function setRemoveoldext($removeoldext)
330
    {
331
        $this->removeoldext = StringHelper::booleanValue($removeoldext);
332
    }
333
334
    /**
335
     * Return removeoldext value (true/false)
336
     *
337
     * @return bool
338
     */
339 1
    public function getRemoveoldext()
340
    {
341 1
        return $this->removeoldext;
342
    }
343
344
    /**
345
     * Set default encoding
346
     *
347
     * @param string $encoding Default encoding to use.
348
     *
349
     * @return void
350
     */
351
    public function setEncoding($encoding)
352
    {
353
        $encoding = trim($encoding);
354
        if ($encoding !== '') {
355
            $this->flags .= " --default-encoding $encoding";
356
        } else {
357
            $this->flags = str_replace(
358
                ' --default-encoding ' . $this->encoding,
359
                '',
360
                $this->flags
361
            );
362
        }
363
        $this->encoding = $encoding;
364
    }
365
366
    /**
367
     * Return the output encoding.
368
     *
369
     * @return string
370
     */
371 2
    public function getEncoding()
372
    {
373 2
        return $this->encoding;
374
    }
375
376
    /**
377
     * Sets the newext value. Default: css
378
     *
379
     * This is the extension we will add on to the output file regardless
380
     * of if we remove the old one or not.
381
     *
382
     * @param string $newext New extension to use, e.g. css
383
     *
384
     * @access public
385
     * @return void
386
     */
387
    public function setNewext($newext)
388
    {
389
        $this->newext = trim($newext, ' .');
390
    }
391
392
    /**
393
     * Return extension added to output files.
394
     *
395
     * @return string
396
     */
397 1
    public function getNewext()
398
    {
399 1
        return $this->newext;
400
    }
401
402
    /**
403
     * Sets the outputpath value. Default: <none>
404
     *
405
     * This will force the output path to be something other than
406
     * the path of the fileset used.
407
     *
408
     * @param string $outputpath Path name
409
     *
410
     * @access public
411
     * @return void
412
     */
413 1
    public function setOutputpath($outputpath)
414
    {
415 1
        $this->outputpath = rtrim(trim($outputpath), DIRECTORY_SEPARATOR);
416 1
    }
417
418
    /**
419
     * Return the outputpath value.
420
     *
421
     * @return string
422
     */
423 1
    public function getOutputpath()
424
    {
425 1
        return $this->outputpath;
426
    }
427
428
    /**
429
     * Sets the keepsubdirectories value. Default: true
430
     *
431
     * When set to true we will keep the directory structure. So any input
432
     * files in subdirectories will have their output file in that same
433
     * sub-directory. If false, all output files will be put in the path
434
     * defined by outputpath or in the directory top directory of the fileset.
435
     *
436
     * @param bool $keepsubdirectories Jenkins style boolean
437
     *
438
     * @access public
439
     * @return void
440
     */
441
    public function setKeepsubdirectories($keepsubdirectories)
442
    {
443
        $this->keepsubdirectories = StringHelper::booleanValue($keepsubdirectories);
444
    }
445
446
    /**
447
     * Return keepsubdirectories value.
448
     *
449
     * @return bool
450
     */
451 1
    public function getKeepsubdirectories()
452
    {
453 1
        return $this->keepsubdirectories;
454
    }
455
456
    /**
457
     * Nested creator, creates a FileSet for this task
458
     *
459
     * @return FileSet The created fileset object
460
     */
461 3
    public function createFileSet()
462
    {
463 3
        $num = array_push($this->filesets, new FileSet());
464 3
        return $this->filesets[$num - 1];
465
    }
466
467
    /**
468
     * Whether to just check syntax.
469
     *
470
     * @param string $value Jenkins style boolean value
471
     *
472
     * @return void
473
     */
474
    public function setCheck($value)
475
    {
476
        $check = StringHelper::booleanValue($value);
477
        $this->check = $check;
478
        if ($check) {
479
            $this->flags .= ' --check ';
480
        } else {
481
            $this->flags = str_replace(' --check ', '', $this->flags);
482
        }
483
    }
484
485
    /**
486
     * Indicate if just a syntax check is required.
487
     *
488
     * @return boolean
489
     */
490 1
    public function getCheck()
491
    {
492 1
        return $this->check;
493
    }
494
495
    /**
496
     * Set style to compact
497
     *
498
     * @param string $value Jenkins style boolean value
499
     *
500
     * @return void
501
     */
502 1
    public function setCompact($value)
503
    {
504 1
        $compress = StringHelper::booleanValue($value);
505 1
        if ($compress) {
506 1
            $this->flags = str_replace(' --style ' . $this->style, '', $this->flags);
507 1
            $this->flags .= ' --style compact';
508 1
            $this->style = 'compact';
509
        }
510 1
    }
511
512
    /**
513
     * Indicate whether style is set to 'coompact'.
514
     *
515
     * @return bool
516
     * @see    setCompact
517
     */
518 5
    public function getCompact()
519
    {
520 5
        return $this->style === 'compact';
521
    }
522
523
    /**
524
     * Set style to compressed
525
     *
526
     * @param string $value Jenkins style boolean value
527
     *
528
     * @return void
529
     */
530 1
    public function setCompressed($value)
531
    {
532 1
        $compress = StringHelper::booleanValue($value);
533 1
        if ($compress) {
534 1
            $this->flags = str_replace(' --style ' . $this->style, '', $this->flags);
535 1
            $this->flags .= ' --style compressed';
536 1
            $this->style = 'compressed';
537
        }
538 1
    }
539
540
    /**
541
     * Indicate whether style is set to 'compressed'.
542
     *
543
     * @return bool
544
     * @see    setCompressed
545
     */
546 5
    public function getCompressed()
547
    {
548 5
        return $this->style === 'compressed';
549
    }
550
551
    /**
552
     * Set style to crunched. Supported by scssphp only.
553
     *
554
     * @param string $value Jenkins style boolean value
555
     *
556
     * @return void
557
     */
558
    public function setCrunched($value)
559
    {
560
        $compress = StringHelper::booleanValue($value);
561
        if ($compress) {
562
            $this->style = 'crunched';
563
        }
564
    }
565
566
    /**
567
     * Indicate whether style is set to 'crunched'.
568
     *
569
     * @return bool
570
     * @see    setCrunched
571
     */
572 5
    public function getCrunched()
573
    {
574 5
        return $this->style === 'crunched';
575
    }
576
577
    /**
578
     * Set style to expanded
579
     *
580
     * @param string $value Jenkins style boolean value
581
     *
582
     * @return void
583
     */
584
    public function setExpand($value)
585
    {
586
        $expand = StringHelper::booleanValue($value);
587
        if ($expand) {
588
            $this->flags = str_replace(' --style ' . $this->style, '', $this->flags);
589
            $this->flags .= ' --style expanded';
590
            $this->style = 'expanded';
591
        }
592
    }
593
594
    /**
595
     * Indicate whether style is set to 'expanded'.
596
     *
597
     * @return bool
598
     * @see    setExpand
599
     */
600 5
    public function getExpand()
601
    {
602 5
        return $this->style === 'expanded';
603
    }
604
605
    /**
606
     * Set style to nested
607
     *
608
     * @param string $value Jenkins style boolean value
609
     *
610
     * @return void
611
     */
612
    public function setNested($value)
613
    {
614
        $nested = StringHelper::booleanValue($value);
615
        if ($nested) {
616
            $this->flags = str_replace(' --style ' . $this->style, '', $this->flags);
617
            $this->flags .= ' --style nested';
618
            $this->style = 'nested';
619
        }
620
    }
621
622
    /**
623
     * Indicate whether style is set to 'nested'.
624
     *
625
     * @return bool
626
     * @see    setNested
627
     */
628 5
    public function getNested()
629
    {
630 5
        return $this->style === 'nested';
631
    }
632
633
    /**
634
     * Whether to force recompiled when --update is used.
635
     *
636
     * @param string $value Jenkins style boolean value
637
     *
638
     * @return void
639
     */
640
    public function setForce($value)
641
    {
642
        $force = StringHelper::booleanValue($value);
643
        $this->force = $force;
644
        if ($force) {
645
            $this->flags .= ' --force ';
646
        } else {
647
            $this->flags = str_replace(' --force ', '', $this->flags);
648
        }
649
    }
650
651
    /**
652
     * Return force value.
653
     *
654
     * @return bool
655
     */
656
    public function getForce()
657
    {
658
        return $this->force;
659
    }
660
661
    /**
662
     * Whether to cache parsed sass files.
663
     *
664
     * @param string $value Jenkins style boolean value
665
     *
666
     * @return void
667
     */
668
    public function setNoCache($value)
669
    {
670
        $noCache = StringHelper::booleanValue($value);
671
        $this->noCache = $noCache;
672
        if ($noCache) {
673
            $this->flags .= ' --no-cache ';
674
        } else {
675
            $this->flags = str_replace(' --no-cache ', '', $this->flags);
676
        }
677
    }
678
679
    /**
680
     * Return noCache value.
681
     *
682
     * @return bool
683
     */
684
    public function getNoCache()
685
    {
686
        return $this->noCache;
687
    }
688
689
    /**
690
     * Specify SASS import path
691
     *
692
     * @param string $path Import path
693
     *
694
     * @return void
695
     */
696
    public function setPath(string $path): void
697
    {
698
        $this->flags .= " --load-path $path ";
699
        $this->loadPath = $path;
700
    }
701
702
    /**
703
     * Return the SASS import path.
704
     */
705 2
    public function getPath(): string
706
    {
707 2
        return $this->loadPath;
708
    }
709
710
    /**
711
     * Set output style.
712
     *
713
     * @param string $style nested|compact|compressed|expanded|crunched
714
     *
715
     * @return void
716
     */
717 6
    public function setStyle(string $style): void
718
    {
719 6
        $style = strtolower($style);
720 6
        switch ($style) {
721 6
            case 'nested':
722 6
            case 'compact':
723 6
            case 'compressed':
724 6
            case 'expanded':
725 6
            case 'crunched':
726 4
                $this->flags = str_replace(" --style $this->style", '', $this->flags);
727 4
                $this->style = $style;
728 4
                $this->flags .= " --style $style ";
729 4
                break;
730
            default:
731 2
                $this->log("Style $style ignored", Project::MSG_INFO);
732
        }
733 6
    }
734
735
    /**
736
     * Return style used for generating output.
737
     */
738 6
    public function getStyle(): string
739
    {
740 6
        return $this->style;
741
    }
742
743
    /**
744
     * Set trace option.
745
     *
746
     * IE: Whether to output a stack trace on error.
747
     *
748
     * @param string $trace Jenkins style boolean value
749
     *
750
     * @return void
751
     */
752
    public function setTrace($trace)
753
    {
754
        $this->trace = StringHelper::booleanValue($trace);
755
        if ($this->trace) {
756
            $this->flags .= ' --trace ';
757
        } else {
758
            $this->flags = str_replace(' --trace ', '', $this->flags);
759
        }
760
    }
761
762
    /**
763
     * Return trace option.
764
     *
765
     * @return bool
766
     */
767 1
    public function getTrace()
768
    {
769 1
        return $this->trace;
770
    }
771
772
    /**
773
     * Whether to use unix-style newlines.
774
     *
775
     * @param string $newlines Jenkins style boolean value
776
     *
777
     * @return void
778
     */
779
    public function setUnixnewlines($newlines)
780
    {
781
        $unixnewlines = StringHelper::booleanValue($newlines);
782
        $this->unixnewlines = $unixnewlines;
783
        if ($unixnewlines) {
784
            $this->flags .= ' --unix-newlines ';
785
        } else {
786
            $this->flags = str_replace(' --unix-newlines ', '', $this->flags);
787
        }
788
    }
789
790
    /**
791
     * Return unix-newlines setting
792
     *
793
     * @return bool
794
     */
795 1
    public function getUnixnewlines()
796
    {
797 1
        return $this->unixnewlines;
798
    }
799
800
    /**
801
     * Whether to identify source-file and line number for generated CSS.
802
     *
803
     * @param string $lineNumbers Jenkins style boolean value
804
     */
805
    public function setLineNumbers(string $lineNumbers): void
806
    {
807
        $lineNumbers = StringHelper::booleanValue($lineNumbers);
808
        $this->lineNumbers = $lineNumbers;
809
        if ($lineNumbers) {
810
            $this->flags .= ' --line-numbers ';
811
        } else {
812
            $this->flags = str_replace(' --line-numbers ', '', $this->flags);
813
        }
814
    }
815
816
    /**
817
     * Return line-numbers setting.
818
     */
819 1
    public function getLineNumbers(): bool
820
    {
821 1
        return $this->lineNumbers;
822
    }
823
824
    /**
825
     * Whether to use the 'sass' command line tool.
826
     *
827
     * @param string $value Jenkins style boolean value.
828
     *
829
     * @return void
830
     * @link   http://sass-lang.com/install
831
     */
832 8
    public function setUseSass($value)
833
    {
834 8
        $this->useSass = StringHelper::booleanValue($value);
835 8
    }
836
837
    /**
838
     * Get useSass property value
839
     *
840
     * @return bool
841
     */
842 7
    public function getUseSass(): bool
843
    {
844 7
        return $this->useSass;
845
    }
846
847
    /**
848
     * Whether to use the scssphp compiler.
849
     *
850
     * @param string $value Jenkins style boolean value.
851
     *
852
     * @return void
853
     * @link   https://scssphp.github.io/scssphp/
854
     */
855 8
    public function setUseScssphp($value)
856
    {
857 8
        $this->useScssphp = StringHelper::booleanValue($value);
858 8
    }
859
860
    /**
861
     * Whether to use the Scss php library
862
     *
863
     * @return bool
864
     */
865 7
    public function getUseScssPhp(): bool
866
    {
867 7
        return $this->useScssphp;
868
    }
869
870
    /**
871
     * Set single filename to compile from scss to css.
872
     *
873
     * @param string $file Single filename to compile.
874
     *
875
     * @return void
876
     */
877
    public function setFile($file)
878
    {
879
        $this->file = $file;
880
    }
881
882
    /**
883
     * Our main execution of the task.
884
     *
885
     * @throws BuildException
886
     * @throws Exception
887
     *
888
     * @access public
889
     * @return void
890
     */
891 4
    public function main()
892
    {
893 4
        if ($this->useSass) {
894
            if (strlen($this->executable) < 0) {
895
                throw new BuildException("'executable' must be defined.");
896
            }
897
        }
898
899 4
        if (empty($this->filesets) && $this->file === null) {
900 1
            throw new BuildException(
901 1
                "Missing either a nested fileset or attribute 'file'"
902
            );
903
        }
904
905
        try {
906 3
            $compiler = (new SassTaskCompilerFactory(FileSystem::getFileSystem()))->prepareCompiler($this);
907 2
        } catch (BuildException $exception) {
908 2
            if ($this->failonerror) {
909 2
                throw $exception;
910
            }
911
            $this->log($exception->getMessage());
912
            return;
913
        }
914
915 1
        if (count($this->filesets) > 0) {
916 1
            $this->processFilesets($compiler);
917
        } elseif ($this->file !== null) {
918
            $this->processFile($compiler);
919
        }
920 1
    }
921
922
    /**
923
     * Compile a specified file.
924
     *
925
     * If output file is not specified, but outputpath is, place output in
926
     * that directory. If neither is specified, place .css file in the
927
     * directory that the input file is in.
928
     *
929
     * @param SassTaskCompiler $compiler Compiler to use for processing fileset
930
     *
931
     * @return void
932
     */
933
    public function processFile(SassTaskCompiler $compiler)
934
    {
935
        $this->log("Process file", Project::MSG_INFO);
936
        if (null === $this->output) {
937
            $specifiedOutputPath = (strlen($this->outputpath) > 0);
938
            $info = [];
939
            if ($specifiedOutputPath === false) {
940
                $info = pathinfo($this->file);
0 ignored issues
show
Bug introduced by
It seems like $this->file can also be of type null; however, parameter $path of pathinfo() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

940
                $info = pathinfo(/** @scrutinizer ignore-type */ $this->file);
Loading history...
941
                $path = $info['dirname'];
942
                $this->outputpath = $path;
943
            } else {
944
                $path = $this->outputpath;
945
            }
946
            $output = $path . DIRECTORY_SEPARATOR . isset($info['filename']) ?? $info['filename'];
947
            if (!$this->removeoldext) {
948
                $output .= '.' . $this->pathInfo['extension'];
949
            }
950
951
            if (strlen($this->newext) > 0) {
952
                $output .= '.' . $this->newext;
953
            }
954
            $this->output = $output;
955
        } else {
956
            $output = $this->output;
957
        }
958
959
        $compiler->compile($this->file, $output, $this->failonerror);
0 ignored issues
show
Bug introduced by
It seems like $this->file can also be of type null; however, parameter $inputFilePath of SassTaskCompiler::compile() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

959
        $compiler->compile(/** @scrutinizer ignore-type */ $this->file, $output, $this->failonerror);
Loading history...
960
    }
961
962
    /**
963
     * Process filesets - compiling/generating css files as required.
964
     *
965
     * @param SassTaskCompiler $compiler Compiler to use for processing fileset
966
     *
967
     * @return void
968
     */
969 1
    public function processFilesets(SassTaskCompiler $compiler): void
970
    {
971 1
        foreach ($this->filesets as $fs) {
972 1
            $ds = $fs->getDirectoryScanner($this->project);
973 1
            $files = $ds->getIncludedFiles();
974 1
            $dir = $fs->getDir($this->project)->getPath();
975
976
            // If output path isn't defined then set it to the path of our fileset.
977 1
            $specifiedOutputPath = (strlen($this->outputpath) > 0);
978 1
            if ($specifiedOutputPath === false) {
979
                $this->outputpath = $dir;
980
            }
981
982 1
            foreach ($files as $file) {
983 1
                $fullFilePath = $dir . DIRECTORY_SEPARATOR . $file;
984 1
                $this->pathInfo = pathinfo($file);
0 ignored issues
show
Documentation Bug introduced by
It seems like pathinfo($file) can also be of type string. However, the property $pathInfo is declared as type array. Maybe add an additional type check?

Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a mixed type is assigned to a property that is type hinted more strictly.

For example, imagine you have a variable $accountId that can either hold an Id object or false (if there is no account id yet). Your code now assigns that value to the id property of an instance of the Account class. This class holds a proper account, so the id value must no longer be false.

Either this assignment is in error or a type check should be added for that assignment.

class Id
{
    public $id;

    public function __construct($id)
    {
        $this->id = $id;
    }

}

class Account
{
    /** @var  Id $id */
    public $id;
}

$account_id = false;

if (starsAreRight()) {
    $account_id = new Id(42);
}

$account = new Account();
if ($account instanceof Id)
{
    $account->id = $account_id;
}
Loading history...
985
986 1
                $run = true;
987 1
                switch (strtolower($this->pathInfo['extension'])) {
988 1
                    case 'scss':
989
                    case 'sass':
990 1
                        break;
991
                    default:
992
                        $this->log('Ignoring ' . $file, Project::MSG_DEBUG);
993
                        $run = false;
994
                }
995
996
                if (
997 1
                    $run
998 1
                    && ($this->extfilter === ''
999 1
                        || $this->extfilter === $this->pathInfo['extension'])
1000
                ) {
1001 1
                    $outputFile = $this->buildOutputFilePath();
1002 1
                    $compiler->compile($fullFilePath, $outputFile, $this->failonerror);
1003
                }
1004
            }
1005
        }
1006 1
    }
1007
1008
    /**
1009
     * Builds the full path to the output file based on our settings.
1010
     *
1011
     * @return string
1012
     *
1013
     * @access protected
1014
     */
1015 1
    protected function buildOutputFilePath()
1016
    {
1017 1
        $outputFile = $this->outputpath . DIRECTORY_SEPARATOR;
1018
1019 1
        $subpath = trim($this->pathInfo['dirname'], ' .');
1020
1021 1
        if ($this->keepsubdirectories === true && strlen($subpath) > 0) {
1022
            $outputFile .= $subpath . DIRECTORY_SEPARATOR;
1023
        }
1024
1025 1
        $outputFile .= $this->pathInfo['filename'];
1026
1027 1
        if (!$this->removeoldext) {
1028
            $outputFile .= '.' . $this->pathInfo['extension'];
1029
        }
1030
1031 1
        if (strlen($this->newext) > 0) {
1032 1
            $outputFile .= '.' . $this->newext;
1033
        }
1034
1035 1
        return $outputFile;
1036
    }
1037
}
1038