Completed
Pull Request — master (#91)
by Vladimir
02:23
created

SassEngine::loadCache()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 14

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 6

Importance

Changes 0
Metric Value
dl 0
loc 14
c 0
b 0
f 0
ccs 0
cts 7
cp 0
rs 9.7998
cc 2
nc 2
nop 1
crap 6
1
<?php
2
3
/**
4
 * @copyright 2018 Vladimir Jimenez
5
 * @license   https://github.com/stakx-io/stakx/blob/master/LICENSE.md MIT
6
 */
7
8
namespace allejo\stakx\AssetEngine\Sass;
9
10
use __;
11
use allejo\stakx\AssetEngine\AssetEngineInterface;
12
use allejo\stakx\Configuration;
13
use allejo\stakx\Document\BasePageView;
14
use allejo\stakx\Document\StaticPageView;
15
use allejo\stakx\Filesystem\FilesystemLoader as fs;
16
use allejo\stakx\Filesystem\Folder;
17
use allejo\stakx\Manager\PageManager;
18
use allejo\stakx\Service;
19
use Leafo\ScssPhp\Formatter\Compact;
20
use Leafo\ScssPhp\Formatter\Crunched;
21
use Leafo\ScssPhp\Formatter\Expanded;
22
use Leafo\ScssPhp\Formatter\Nested;
23
24
class SassEngine implements AssetEngineInterface
25
{
26
    const CACHE_FILE = 'sass_engine.cache';
27
28
    private $fileSourceMap = false;
29
    private $configuration;
30
    /** @var PageManager */
31
    private $pageManager;
32
    private $compiler;
33
    private $options = [];
34
35 7
    public function __construct(Configuration $configuration)
36
    {
37 7
        $this->configuration = $configuration;
38 7
        $this->compiler = new Compiler();
39 7
    }
40
41 1
    public function getName()
42
    {
43 1
        return 'Sass';
44
    }
45
46 7
    public function getConfigurationNamespace()
47
    {
48 7
        return 'scss';
49
    }
50
51 7
    public function getDefaultConfiguration()
52
    {
53
        return [
54 7
            'style' => 'compressed',
55
            'sourcemap' => false,
56
        ];
57
    }
58
59 7
    public function getFolder()
60
    {
61 7
        return '_sass';
62
    }
63
64 7
    public function getExtensions()
65
    {
66 7
        return ['scss'];
67
    }
68
69
    /**
70
     * @param string $content
71
     * @param $options = [
72
     *     'pageview' => new StaticPageView()
73
     * ]
74
     *
75
     * @return string
76
     */
77 7
    public function parse($content, array $options = [])
78
    {
79
        $sourceMapOptions = [
80 7
            'sourceMapBasepath' => Service::getWorkingDirectory(),
81
        ];
82
83 7
        $this->handleThemeImports($content);
84
85
        // We don't need to write the source map to a file
86 7
        if (!$this->fileSourceMap)
87
        {
88 6
            $this->compiler->setSourceMapOptions($sourceMapOptions);
89
90 6
            return $this->compiler->compile($content);
91
        }
92
93
        /** @var StaticPageView $pageView */
94 1
        $pageView = $options['pageview'];
95
96
        // Always put our source map next to the respective CSS file
97 1
        $sourceMapTargetPath = $this->getSourceMapTargetFile($pageView);
98 1
        $sourceMapFilename = fs::getFilename($sourceMapTargetPath);
99
100 1
        $sourceMapOptions = array_merge($sourceMapOptions, [
101 1
            'sourceMapFilename' => $sourceMapFilename,
102 1
            'sourceMapURL' => $pageView->getPermalink() . '.map',
103 1
            'sourceMapWriteTo' => $sourceMapTargetPath,
104
        ]);
105
106 1
        $sourceMapGenerator = new SourceMapGenerator($sourceMapOptions);
107 1
        $this->compiler->setSourceMap($sourceMapGenerator);
0 ignored issues
show
Documentation introduced by
$sourceMapGenerator is of type object<allejo\stakx\Asse...ass\SourceMapGenerator>, but the function expects a integer.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
108
109 1
        $sass = $this->compiler->compile($content);
110
111 1
        $sourceMapPageView = BasePageView::createVirtual([
112 1
            'permalink' => $pageView->getPermalink() . '.map',
113 1
        ], $sourceMapGenerator->getSourceMapContents());
114
115 1
        $this->pageManager->trackNewPageView($sourceMapPageView);
116
117 1
        return $sass;
118
    }
119
120 7
    public function setOptions(array $options)
121
    {
122 7
        $this->options = $options;
123
124 7
        $this->configureImportPath();
125 7
        $this->configureOutputStyle();
126 7
        $this->configureSourceMap();
127 7
    }
128
129 1
    public function setPageManager(PageManager $pageManager)
130
    {
131 1
        $this->pageManager = $pageManager;
132 1
    }
133
134
    public function loadCache(Folder $cacheDir)
135
    {
136
        $cachePath = $cacheDir
137
            ->getFilesystemPath()
138
            ->appendToPath(self::CACHE_FILE)
139
        ;
140
141
        if (fs::exists($cachePath))
0 ignored issues
show
Documentation introduced by
$cachePath is of type object<allejo\stakx\Filesystem\FilesystemPath>, but the function expects a object<string>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
142
        {
143
            list(
144
                $this->compiler
145
            ) = unserialize(file_get_contents($cachePath));
146
        }
147
    }
148
149 1
    public function saveCache(Folder $cacheDir)
150
    {
151
        $cachePath = $cacheDir
152 1
            ->getFilesystemPath()
153 1
            ->appendToPath(self::CACHE_FILE)
154
        ;
155
156 1
        $cache = serialize([
157 1
            $this->compiler,
158
        ]);
159
160 1
        file_put_contents($cachePath, $cache);
161 1
    }
162
163 7
    private function configureImportPath()
164
    {
165 7
        $this->compiler->setImportPaths(Service::getWorkingDirectory() . '/_sass/');
166 7
    }
167
168 7
    private function configureOutputStyle()
169
    {
170 7
        $style = __::get($this->options, 'style', 'compressed');
171
172 7
        $this->compiler->setFormatter(self::stringToFormatter($style));
173 7
    }
174
175 7
    private function configureSourceMap()
176
    {
177 7
        $sourceMap = __::get($this->options, 'sourcemap');
178
179 7
        if ($sourceMap === 'inline')
180
        {
181 1
            $this->compiler->setSourceMap(Compiler::SOURCE_MAP_INLINE);
182
        }
183 6
        elseif ($sourceMap === true)
184
        {
185 1
            $this->compiler->setSourceMap(Compiler::SOURCE_MAP_FILE);
186 1
            $this->fileSourceMap = true;
187
        }
188
        else
189
        {
190 5
            $this->compiler->setSourceMap(Compiler::SOURCE_MAP_NONE);
191
        }
192 7
    }
193
194 1
    private function getSourceMapTargetFile(StaticPageView $pageView)
195
    {
196 1
        return fs::absolutePath(
197 1
            $this->configuration->getTargetFolder(),
0 ignored issues
show
Documentation introduced by
$this->configuration->getTargetFolder() is of type string, but the function expects a object<string>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
198 1
            $pageView->getTargetFile() . '.map'
0 ignored issues
show
Unused Code introduced by
The call to FilesystemLoader::absolutePath() has too many arguments starting with $pageView->getTargetFile() . '.map'.

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.

In this case you can add the @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

Loading history...
199
        );
200
    }
201
202 7
    private function handleThemeImports(&$content)
203
    {
204 7
        if (($themeName = $this->configuration->getTheme()))
205
        {
206
            $themePath = "../_themes/${themeName}/_sass";
207
            $content = preg_replace("/(@import ['\"])(@theme)(.+)/", "$1${themePath}$3", $content);
208
        }
209 7
    }
210
211
    public static function stringToFormatter($format)
0 ignored issues
show
Documentation introduced by
The return type could not be reliably inferred; please add a @return annotation.

Our type inference engine in quite powerful, but sometimes the code does not provide enough clues to go by. In these cases we request you to add a @return annotation as described here.

Loading history...
212
    {
213 7
        if ($format == 'nested')
214
        {
215 1
            return Nested::class;
216
        }
217 6
        elseif ($format == 'expanded')
218
        {
219 1
            return Expanded::class;
220
        }
221 5
        elseif ($format == 'compact')
222
        {
223 1
            return Compact::class;
224
        }
225
226 4
        return Crunched::class;
227
    }
228
}
229