Completed
Pull Request — master (#91)
by Vladimir
05:42
created

SassEngine::getName()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 0
Metric Value
dl 0
loc 4
c 0
b 0
f 0
rs 10
ccs 2
cts 2
cp 1
cc 1
nc 1
nop 0
crap 1
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 7
    private $options = [];
34
35 7
    public function __construct(Configuration $configuration)
36 7
    {
37 7
        $this->configuration = $configuration;
38
        $this->compiler = new Compiler();
39 7
    }
40
41 7
    public function getName()
42
    {
43
        return 'Sass';
44 7
    }
45
46
    public function getConfigurationNamespace()
47 7
    {
48
        return 'scss';
49
    }
50
51
    public function getDefaultConfiguration()
52 7
    {
53
        return [
54 7
            'style' => 'compressed',
55
            'sourcemap' => false,
56
        ];
57 7
    }
58
59 7
    public function getFolder()
60
    {
61
        return '_sass';
62
    }
63
64
    public function getExtensions()
65
    {
66
        return ['scss'];
67
    }
68
69
    /**
70 7
     * @param string $content
71
     * @param $options = [
72
     *     'pageview' => new StaticPageView()
73 7
     * ]
74
     *
75
     * @return string
76 7
     */
77
    public function parse($content, array $options = [])
78
    {
79 7
        $sourceMapOptions = [
80
            'sourceMapBasepath' => Service::getWorkingDirectory(),
81 6
        ];
82
83 6
        $this->handleThemeImports($content);
84
85
        // We don't need to write the source map to a file
86
        if (!$this->fileSourceMap)
87 1
        {
88
            $this->compiler->setSourceMapOptions($sourceMapOptions);
89
90 1
            return $this->compiler->compile($content);
91 1
        }
92
93 1
        /** @var StaticPageView $pageView */
94 1
        $pageView = $options['pageview'];
95 1
96 1
        // Always put our source map next to the respective CSS file
97
        $sourceMapTargetPath = $this->getSourceMapTargetFile($pageView);
98
        $sourceMapFilename = fs::getFilename($sourceMapTargetPath);
99 1
100 1
        $sourceMapOptions = array_merge($sourceMapOptions, [
101
            'sourceMapFilename' => $sourceMapFilename,
102 1
            'sourceMapURL' => $pageView->getPermalink() . '.map',
103
            'sourceMapWriteTo' => $sourceMapTargetPath,
104 1
        ]);
105 1
106 1
        $sourceMapGenerator = new SourceMapGenerator($sourceMapOptions);
107
        $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 1
109
        $sass = $this->compiler->compile($content);
110 1
111
        $sourceMapPageView = BasePageView::createVirtual([
112
            'permalink' => $pageView->getPermalink() . '.map',
113 7
        ], $sourceMapGenerator->getSourceMapContents());
114
115 7
        $this->pageManager->trackNewPageView($sourceMapPageView);
116
117 7
        return $sass;
118 7
    }
119 7
120 7
    public function setOptions(array $options)
121
    {
122 1
        $this->options = $options;
123
124 1
        $this->configureImportPath();
125 1
        $this->configureOutputStyle();
126
        $this->configureSourceMap();
127 7
    }
128
129 7
    public function setPageManager(PageManager $pageManager)
130 7
    {
131
        $this->pageManager = $pageManager;
132 7
    }
133
134 7
    public function loadCache(Folder $cacheDir)
135
    {
136 7
        $cachePath = $cacheDir->getPath()->appendToPath(self::CACHE_FILE);
137 7
138
        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...
139 7
        {
140
            list(
141 7
                $this->compiler
142
            ) = unserialize(file_get_contents($cachePath));
143 7
        }
144
    }
145 1
146
    public function saveCache(Folder $cacheDir)
147 6
    {
148
        $cachePath = $cacheDir->getPath()->appendToPath(self::CACHE_FILE);
149 1
        $cache = serialize([
150 1
            $this->compiler,
151
        ]);
152
153
        file_put_contents($cachePath, $cache);
154 5
    }
155
156 7
    private function configureImportPath()
157
    {
158 1
        $this->compiler->setImportPaths(Service::getWorkingDirectory() . '/_sass/');
159
    }
160 1
161 1
    private function configureOutputStyle()
162 1
    {
163
        $style = __::get($this->options, 'style', 'compressed');
164
165
        $this->compiler->setFormatter(self::stringToFormatter($style));
166 7
    }
167
168 7
    private function configureSourceMap()
169
    {
170
        $sourceMap = __::get($this->options, 'sourcemap');
171
172
        if ($sourceMap === 'inline')
173 7
        {
174
            $this->compiler->setSourceMap(Compiler::SOURCE_MAP_INLINE);
175
        }
176
        elseif ($sourceMap === true)
177 7
        {
178
            $this->compiler->setSourceMap(Compiler::SOURCE_MAP_FILE);
179 1
            $this->fileSourceMap = true;
180
        }
181 6
        else
182
        {
183 1
            $this->compiler->setSourceMap(Compiler::SOURCE_MAP_NONE);
184
        }
185 5
    }
186
187 1
    private function getSourceMapTargetFile(StaticPageView $pageView)
188
    {
189
        return fs::absolutePath(
190 4
            $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...
191
            $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...
192
        );
193
    }
194
195
    private function handleThemeImports(&$content)
196
    {
197
        if (($themeName = $this->configuration->getTheme()))
198
        {
199
            $themePath = "../_themes/${themeName}/_sass";
200
            $content = preg_replace("/(@import ['\"])(@theme)(.+)/", "$1${themePath}$3", $content);
201
        }
202
    }
203
204
    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...
205
    {
206
        if ($format == 'nested')
207
        {
208
            return Nested::class;
209
        }
210
        elseif ($format == 'expanded')
211
        {
212
            return Expanded::class;
213
        }
214
        elseif ($format == 'compact')
215
        {
216
            return Compact::class;
217
        }
218
219
        return Crunched::class;
220
    }
221
}
222