Completed
Pull Request — master (#69)
by Vladimir
05:16
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 7
    public function __construct(Configuration $configuration)
33
    {
34 7
        $this->configuration = $configuration;
35 7
        $this->compiler = new Compiler();
36 7
    }
37
38 7
    public function getConfigurationNamespace()
39
    {
40 7
        return 'scss';
41
    }
42
43 7
    public function getDefaultConfiguration()
44
    {
45
        return [
46 7
            'style' => 'compressed',
47
            'sourcemap' => false,
48
        ];
49
    }
50
51 7
    public function getFolder()
52
    {
53 7
        return '_sass';
54
    }
55
56 7
    public function getExtensions()
57
    {
58 7
        return ['scss'];
59
    }
60
61
    /**
62
     * @param string $content
63
     * @param $options = [
64
     *     'pageview' => new StaticPageView()
65
     * ]
66
     *
67
     * @return string
68
     */
69 7
    public function parse($content, array $options = [])
70
    {
71 7
        $sourceMapTargetPath = null;
72
        $sourceMapOptions = [
73 7
            'sourceMapBasepath' => Service::getWorkingDirectory(),
74
        ];
75
76 7
        if ($this->fileSourceMap)
77
        {
78
            /** @var StaticPageView $pageView */
79 1
            $pageView = $options['pageview'];
80
81
            // Always put our source map next to the respective CSS file
82 1
            $sourceMapTargetPath = fs::appendPath(
83 1
                Service::getWorkingDirectory(),
84 1
                $this->configuration->getTargetFolder(),
85 1
                $pageView->getTargetFile() . '.map'
86
            );
87 1
            $sourceMapFilename = fs::getFilename($pageView->getTargetFile()) . '.map';
88
89 1
            $sourceMapOptions = array_merge($sourceMapOptions, [
90 1
                'sourceMapFilename' => $sourceMapFilename,
91 1
                'sourceMapURL' => $pageView->getPermalink() . '.map',
92 1
                'sourceMapWriteTo' => $sourceMapTargetPath,
93
            ]);
94
        }
95
96 7
        $this->compiler->setSourceMapOptions($sourceMapOptions);
97 7
        $sass = $this->compiler->compile($content);
98
99
        // Due to how our Sass Compiler is designed, the Source Map is automatically written to the given location. This
100
        // write happens *before* the stakx compiler writes out files, so if we write the source map to _site/, then it'll
101
        // be deleted when _site/ is cleaned.
102
        //
103
        // This is a workaround by creating a virtual file to store the source map contents, which will be written out by
104
        // the stakx compiler.
105 7
        if ($this->fileSourceMap)
106
        {
107 1
            $sourceMap = new File($sourceMapTargetPath);
108 1
            $sourceMapContents = $sourceMap->getContents();
109
110 1
            $sourceMapPageView = BasePageView::createVirtual([
111 1
                '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...
112 1
            ], $sourceMapContents);
113
114 1
            $this->pageManager->trackNewPageView($sourceMapPageView);
115
        }
116
117 7
        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 7
    private function configureImportPath()
135
    {
136 7
        $this->compiler->setImportPaths(Service::getWorkingDirectory() . '/_sass/');
137 7
    }
138
139 7
    private function configureOutputStyle()
140
    {
141 7
        $style = __::get($this->options, 'style', 'compressed');
142
143 7
        $this->compiler->setFormatter(self::stringToFormatter($style));
144 7
    }
145
146 7
    private function configureSourceMap()
147
    {
148 7
        $sourceMap = __::get($this->options, 'sourcemap');
149
150 7
        if ($sourceMap === 'inline') {
151 1
            $this->compiler->setSourceMap(Compiler::SOURCE_MAP_INLINE);
152
        }
153 6
        elseif ($sourceMap === true) {
154 1
            $this->compiler->setSourceMap(Compiler::SOURCE_MAP_FILE);
155 1
            $this->fileSourceMap = true;
156
        }
157
        else {
158 5
            $this->compiler->setSourceMap(Compiler::SOURCE_MAP_NONE);
159
        }
160 7
    }
161
162 7
    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...
163
    {
164 7
        if ($format == 'nested')
165
        {
166 1
            return Nested::class;
167
        }
168 6
        elseif ($format == 'expanded')
169
        {
170 1
            return Expanded::class;
171
        }
172 5
        elseif ($format == 'compact')
173
        {
174 1
            return Compact::class;
175
        }
176
177 4
        return Crunched::class;
178
    }
179
}
180