Completed
Pull Request — master (#69)
by Vladimir
02:42
created

SassEngine::stringToFormatter()   A

Complexity

Conditions 4
Paths 4

Size

Total Lines 17

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 8
CRAP Score 4

Importance

Changes 0
Metric Value
dl 0
loc 17
ccs 8
cts 8
cp 1
rs 9.7
c 0
b 0
f 0
cc 4
nc 4
nop 1
crap 4
1
<?php
2
3
/**
4
 * @copyright 2018 Vladimir Jimenez
5
 * @license   https://github.com/allejo/stakx/blob/master/LICENSE.md MIT
6
 */
7
8
namespace allejo\stakx\AssetEngine;
9
10
use __;
11
use allejo\stakx\Configuration;
12
use allejo\stakx\Document\BasePageView;
13
use allejo\stakx\Document\StaticPageView;
14
use allejo\stakx\Filesystem\File;
15
use allejo\stakx\Filesystem\FilesystemLoader as fs;
16
use allejo\stakx\Manager\PageManager;
17
use allejo\stakx\Service;
18
use Leafo\ScssPhp\Compiler;
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
    private $fileSourceMap = false;
27
    private $configuration;
28
    private $pageManager;
29
    private $compiler;
30
    private $options = [];
31
32 4
    public function __construct(Configuration $configuration)
33
    {
34 4
        $this->configuration = $configuration;
35 4
        $this->compiler = new Compiler();
36 4
    }
37
38 4
    public function getConfigurationNamespace()
39
    {
40 4
        return 'scss';
41
    }
42
43 4
    public function getDefaultConfiguration()
44
    {
45
        return [
46 4
            'style' => 'compressed',
47
            'sourcemap' => false,
48
        ];
49
    }
50
51 4
    public function getFolder()
52
    {
53 4
        return '_sass';
54
    }
55
56 4
    public function getExtensions()
57
    {
58 4
        return ['scss'];
59
    }
60
61
    /**
62
     * @param string $content
63
     * @param $options = [
64
     *     'pageview' => new StaticPageView()
65
     * ]
66
     *
67
     * @return string
68
     */
69 4
    public function parse($content, array $options = [])
70
    {
71 4
        $sourceMapTargetPath = null;
72
73 4
        if ($this->fileSourceMap)
74
        {
75
            /** @var StaticPageView $pageView */
76
            $pageView = $options['pageview'];
77
78
            // Always put our source map next to the respective CSS file
79
            $sourceMapTargetPath = fs::appendPath(
80
                Service::getWorkingDirectory(),
81
                $this->configuration->getTargetFolder(),
82
                $pageView->getTargetFile() . '.map'
83
            );
84
            $sourceMapFilename = fs::getFilename($pageView->getTargetFile()) . '.map';
85
86
            $this->compiler->setSourceMapOptions([
87
                'sourceMapFilename' => $sourceMapFilename,
88
                'sourceMapURL' => $pageView->getPermalink() . '.map',
89
                'sourceMapWriteTo' => $sourceMapTargetPath,
90
                'sourceMapBasepath' => Service::getWorkingDirectory(),
91
            ]);
92
        }
93
94 4
        $sass = $this->compiler->compile($content);
95
96
        // Due to how our Sass Compiler is designed, the Source Map is automatically written to the given location. This
97
        // write happens *before* the stakx compiler writes out files, so if we write the source map to _site/, then it'll
98
        // be deleted when _site/ is cleaned.
99
        //
100
        // This is a workaround by creating a virtual file to store the source map contents, which will be written out by
101
        // the stakx compiler.
102 4
        if ($this->fileSourceMap)
103
        {
104
            $sourceMap = new File($sourceMapTargetPath);
105
            $sourceMapContents = $sourceMap->getContents();
106
107
            $sourceMapPageView = BasePageView::createVirtual([
108
                'permalink' => $pageView->getPermalink() . '.map',
0 ignored issues
show
Bug introduced by
The variable $pageView does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
109
            ], $sourceMapContents);
110
111
            $this->pageManager->trackNewPageView($sourceMapPageView);
112
        }
113
114 4
        return $sass;
115
    }
116
117 4
    public function setOptions(array $options)
118
    {
119 4
        $this->options = $options;
120
121 4
        $this->configureImportPath();
122 4
        $this->configureOutputStyle();
123 4
        $this->configureSourceMap();
124 4
    }
125
126
    public function setPageManager(PageManager $pageManager)
127
    {
128
        $this->pageManager = $pageManager;
129
    }
130
131 4
    private function configureImportPath()
132
    {
133 4
        $this->compiler->setImportPaths(Service::getWorkingDirectory() . '/_sass/');
134 4
    }
135
136 4
    private function configureOutputStyle()
137
    {
138 4
        $style = __::get($this->options, 'style', 'compressed');
139
140 4
        $this->compiler->setFormatter(self::stringToFormatter($style));
141 4
    }
142
143 4
    private function configureSourceMap()
144
    {
145 4
        $sourceMap = __::get($this->options, 'sourcemap');
146
147 4
        if ($sourceMap === 'inline') {
148
            $this->compiler->setSourceMap(Compiler::SOURCE_MAP_INLINE);
149
        }
150 4
        elseif ($sourceMap === true) {
151
            $this->compiler->setSourceMap(Compiler::SOURCE_MAP_FILE);
152
            $this->fileSourceMap = true;
153
        }
154
        else {
155 4
            $this->compiler->setSourceMap(Compiler::SOURCE_MAP_NONE);
156
        }
157 4
    }
158
159 4
    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...
160
    {
161 4
        if ($format == 'nested')
162
        {
163 1
            return Nested::class;
164
        }
165 3
        elseif ($format == 'expanded')
166
        {
167 1
            return Expanded::class;
168
        }
169 2
        elseif ($format == 'compact')
170
        {
171 1
            return Compact::class;
172
        }
173
174 1
        return Crunched::class;
175
    }
176
}
177