SassTask::processFile()   A
last analyzed

Complexity

Conditions 5
Paths 9

Size

Total Lines 27
Code Lines 19

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 30

Importance

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

943
                $info = pathinfo(/** @scrutinizer ignore-type */ $this->file);
Loading history...
944
                $path = $info['dirname'];
945
                $this->outputpath = $path;
946
            } else {
947
                $path = $this->outputpath;
948
            }
949
            $output = $path . DIRECTORY_SEPARATOR . isset($info['filename']) ?? $info['filename'];
950
            if (!$this->removeoldext) {
951
                $output .= '.' . $this->pathInfo['extension'];
952
            }
953
954
            if (strlen($this->newext) > 0) {
955
                $output .= '.' . $this->newext;
956
            }
957
            $this->output = $output;
958
        } else {
959
            $output = $this->output;
960
        }
961
962
        $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 Phing\Task\Ext\Sass\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

962
        $compiler->compile(/** @scrutinizer ignore-type */ $this->file, $output, $this->failonerror);
Loading history...
963
    }
964
965
    /**
966
     * Process filesets - compiling/generating css files as required.
967
     *
968
     * @param SassTaskCompiler $compiler Compiler to use for processing fileset
969
     *
970
     * @return void
971
     */
972 1
    public function processFilesets(SassTaskCompiler $compiler): void
973
    {
974 1
        foreach ($this->filesets as $fs) {
975 1
            $ds = $fs->getDirectoryScanner($this->project);
976 1
            $files = $ds->getIncludedFiles();
977 1
            $dir = $fs->getDir($this->project)->getPath();
978
979
            // If output path isn't defined then set it to the path of our fileset.
980 1
            $specifiedOutputPath = (strlen($this->outputpath) > 0);
981 1
            if ($specifiedOutputPath === false) {
982
                $this->outputpath = $dir;
983
            }
984
985 1
            foreach ($files as $file) {
986 1
                $fullFilePath = $dir . DIRECTORY_SEPARATOR . $file;
987 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...
988
989 1
                $run = true;
990 1
                switch (strtolower($this->pathInfo['extension'])) {
991 1
                    case 'scss':
992
                    case 'sass':
993 1
                        break;
994
                    default:
995
                        $this->log('Ignoring ' . $file, Project::MSG_DEBUG);
996
                        $run = false;
997
                }
998
999
                if (
1000 1
                    $run
1001 1
                    && ($this->extfilter === ''
1002 1
                        || $this->extfilter === $this->pathInfo['extension'])
1003
                ) {
1004 1
                    $outputFile = $this->buildOutputFilePath();
1005 1
                    $compiler->compile($fullFilePath, $outputFile, $this->failonerror);
1006
                }
1007
            }
1008
        }
1009
    }
1010
1011
    /**
1012
     * Builds the full path to the output file based on our settings.
1013
     *
1014
     * @return string
1015
     *
1016
     * @access protected
1017
     */
1018 1
    protected function buildOutputFilePath()
1019
    {
1020 1
        $outputFile = $this->outputpath . DIRECTORY_SEPARATOR;
1021
1022 1
        $subpath = trim($this->pathInfo['dirname'], ' .');
1023
1024 1
        if ($this->keepsubdirectories === true && strlen($subpath) > 0) {
1025
            $outputFile .= $subpath . DIRECTORY_SEPARATOR;
1026
        }
1027
1028 1
        $outputFile .= $this->pathInfo['filename'];
1029
1030 1
        if (!$this->removeoldext) {
1031
            $outputFile .= '.' . $this->pathInfo['extension'];
1032
        }
1033
1034 1
        if (strlen($this->newext) > 0) {
1035 1
            $outputFile .= '.' . $this->newext;
1036
        }
1037
1038 1
        return $outputFile;
1039
    }
1040
}
1041