Passed
Pull Request — master (#12)
by Albert
01:47
created

ScssAssetConverter::createDistFolderIfNotExists()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 7
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 5
CRAP Score 2

Importance

Changes 0
Metric Value
dl 0
loc 7
ccs 5
cts 5
cp 1
rs 9.4285
c 0
b 0
f 0
cc 2
eloc 4
nc 2
nop 1
crap 2
1
<?php
2
3
namespace lucidtaz\yii2scssphp;
4
5
use Leafo\ScssPhp\Compiler;
6
use lucidtaz\yii2scssphp\storage\FsStorage;
7
use lucidtaz\yii2scssphp\storage\Storage;
8
use RuntimeException;
9
use Yii;
10
use yii\base\Component;
11
use yii\helpers\FileHelper;
12
use yii\web\AssetConverterInterface;
13
14
class ScssAssetConverter extends Component implements AssetConverterInterface
15
{
16
    /**
17
     * @var Storage
18
     */
19
    public $storage;
20
21
    /**
22
     * @var boolean whether the source asset file should be converted even if
23
     * its result already exists. You may want to set this to be `true` during
24
     * the development stage to make sure the converted assets are always up-to-
25
     * date. Do not set this to true on production servers as it will
26
     * significantly degrade the performance.
27
     */
28
    public $forceConvert = false;
29
30
    /**
31
     * @var Compiler
32
     */
33
    private $compiler;
34
35
    /**
36
     * Set the destination folder where to copy the compiled css file.
37
     * If the value is null, then it will be generated into the sourcePath of the asset bundle.
38
     *
39
     * ```
40
     * 'assetManager' => [
41
     *     'converter' => [
42
     *         'class' => \lucidtaz\yii2scssphp\ScssAssetConverter::class,
43
     *         'distFolder' => 'css',
44
     *     ],
45
     * ],
46
     * ```
47
     *
48
     * @var string|null
49
     */
50
    public $distFolder;
51
52
    /**
53
     * @throws \yii\base\InvalidConfigException
54
     */
55 11
    public function init()
56
    {
57 11
        parent::init();
58 11
        if (!isset($this->storage)) {
59 1
            $this->storage = new FsStorage;
60
        }
61 11
        $this->compiler = Yii::createObject(Compiler::class);
62 11
    }
63
64
    /**
65
     * Converts a given SCSS asset file into a CSS file.
66
     * @param string $asset the asset file path, relative to $basePath
67
     * @param string $basePath the directory the $asset is relative to.
68
     * @return string the converted asset file path, relative to $basePath.
69
     * @throws \yii\base\Exception
70
     */
71 10
    public function convert($asset, $basePath)
72
    {
73 10
        $extension = $this->getExtension($asset);
74 10
        if ($extension !== 'scss') {
75 2
            return $asset;
76
        }
77 8
        $cssAsset = $this->replaceExtension($asset, 'css');
78
79 8
        $inFile = "$basePath/$asset";
80 8
        $outFile = $this->distFolder ? "$basePath/$this->distFolder/$cssAsset" : "$basePath/$cssAsset";
81
        
82 8
        $this->compiler->setImportPaths(dirname($inFile));
83
84 8
        if (!$this->storage->exists($inFile)) {
85 1
            Yii::error("Input file $inFile not found.", __METHOD__);
86 1
            return $asset;
87
        }
88
89 7
        $this->createDistFolderIfNotExists($outFile);
90 7
        $this->convertAndSaveIfNeeded($inFile, $outFile);
91
92 7
        return $this->distFolder ? $this->distFolder . '/' . $cssAsset : $cssAsset;
93
    }
94
95 10
    private function getExtension(string $filename): string
96
    {
97 10
        return pathinfo($filename, PATHINFO_EXTENSION);
98
    }
99
100 8
    private function replaceExtension(string $filename, string $newExtension): string
101
    {
102 8
        $extensionlessFilename = pathinfo($filename, PATHINFO_FILENAME);
103 8
        return "$extensionlessFilename.$newExtension";
104
    }
105
106 7
    private function convertAndSaveIfNeeded(string $inFile, string $outFile)
107
    {
108 7
        if ($this->shouldConvert($inFile, $outFile)) {
109 6
            $css = $this->compiler->compile($this->storage->get($inFile), $inFile);
110 6
            $this->storage->put($outFile, $css);
111
        }
112 7
    }
113
114 7
    private function shouldConvert(string $inFile, string $outFile): bool
115
    {
116 7
        if (!$this->storage->exists($outFile)) {
117 3
            return true;
118
        }
119 4
        if ($this->forceConvert) {
120 1
            return true;
121
        }
122
        try {
123 3
            return $this->isOlder($outFile, $inFile);
124 1
        } catch (RuntimeException $e) {
125 1
            Yii::warning('Encountered RuntimeException message "' . $e->getMessage() . '", going to convert.', __METHOD__);
126 1
            return true;
127
        }
128
    }
129
130 3
    private function isOlder(string $fileA, string $fileB): bool
131
    {
132 3
        return $this->storage->getMtime($fileA) < $this->storage->getMtime($fileB);
133
    }
134
135
    /**
136
     * @param $outFile
137
     * @throws \yii\base\Exception
138
     */
139 7
    private function createDistFolderIfNotExists($outFile)
140
    {
141 7
        $dir = dirname($outFile);
142 7
        if (!is_dir($dir)) {
143 1
            FileHelper::createDirectory($dir);
144
        }
145 7
    }
146
}
147