Processor   A
last analyzed

Complexity

Total Complexity 26

Size/Duplication

Total Lines 205
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 7

Test Coverage

Coverage 100%

Importance

Changes 0
Metric Value
wmc 26
lcom 1
cbo 7
dl 0
loc 205
ccs 70
cts 70
cp 1
rs 10
c 0
b 0
f 0

11 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 8 1
A attachFiles() 0 15 4
A getFiles() 0 4 1
A concatOutput() 0 13 3
A saveOutput() 0 13 3
A processFiles() 0 16 3
A processFile() 0 11 3
A compileSCSS() 0 11 2
A compileLESS() 0 8 2
A getFormatterClass() 0 8 2
A fetchInputContextIntoFile() 0 8 2
1
<?php
2
3
namespace EM\CssCompiler\Processor;
4
5
use Composer\IO\IOInterface;
6
use EM\CssCompiler\Container\FileContainer;
7
use EM\CssCompiler\Exception\CompilerException;
8
use EM\CssCompiler\Exception\FileException;
9
use Leafo\ScssPhp\Compiler as SCSSCompiler;
10
use Leafo\ScssPhp\Exception\ParserException;
11
use lessc as LESSCompiler;
12
use scss_compass as CompassCompiler;
13
14
/**
15
 * @see   ProcessorTest
16
 *
17
 * @since 0.1
18
 */
19
class Processor
20
{
21
    const FORMATTER_COMPRESSED = 'compressed';
22
    const FORMATTER_CRUNCHED   = 'crunched';
23
    const FORMATTER_EXPANDED   = 'expanded';
24
    const FORMATTER_NESTED     = 'nested';
25
    const FORMATTER_COMPACT    = 'compact';
26
    public static $supportedFormatters = [
27
        self::FORMATTER_COMPRESSED,
28
        self::FORMATTER_CRUNCHED,
29
        self::FORMATTER_EXPANDED,
30
        self::FORMATTER_NESTED,
31
        self::FORMATTER_COMPACT
32
    ];
33
    /**
34
     * @var IOInterface
35
     */
36
    private $io;
37
    /**
38
     * @var FileContainer[]
39
     */
40
    private $files = [];
41
    /**
42
     * @var SCSSCompiler
43
     */
44
    private $scss;
45
    /**
46
     * @var LESSCompiler
47
     */
48
    private $less;
49
50 17
    public function __construct(IOInterface $io)
51
    {
52 17
        $this->io = $io;
53 17
        $this->less = new LESSCompiler();
54 17
        $this->scss = new SCSSCompiler();
55
        /** attaches compass functionality to the SCSS compiler */
56 17
        new CompassCompiler($this->scss);
57 17
    }
58
59
    /**
60
     * @param string $inputPath
61
     * @param string $outputPath
62
     *
63
     * @throws \Exception
64
     */
65 8
    public function attachFiles($inputPath, $outputPath)
66
    {
67 8
        if (is_dir($inputPath)) {
68 7
            $files = scandir($inputPath);
69 7
            unset($files[0], $files[1]);
70
71 7
            foreach ($files as $file) {
72 7
                $this->attachFiles("$inputPath/$file", $outputPath);
73
            }
74 8
        } else if (is_file($inputPath)) {
75 7
            $this->files[] = new FileContainer($inputPath, $outputPath);
76
        } else {
77 1
            throw new \Exception("file doesn't exists");
78
        }
79 7
    }
80
81
    /**
82
     * @return FileContainer[]
83
     */
84 5
    public function getFiles()
85
    {
86 5
        return $this->files;
87
    }
88
89
    /**
90
     * @return string[]
91
     */
92 2
    protected function concatOutput()
93
    {
94 2
        $outputMap = [];
95 2
        foreach ($this->files as $file) {
96 2
            if (!isset($outputMap[$file->getOutputPath()])) {
97 2
                $outputMap[$file->getOutputPath()] = '';
98
            }
99
100 2
            $outputMap[$file->getOutputPath()] .= $file->getOutputContent();
101
        }
102
103 2
        return $outputMap;
104
    }
105
106
    /**
107
     * save output into file
108
     */
109 2
    public function saveOutput()
110
    {
111 2
        foreach ($this->concatOutput() as $path => $content) {
112 2
            $directory = dirname($path);
113 2
            if (!is_dir($directory)) {
114 1
                $this->io->write("<info>creating directory</info>: {$directory}");
115 1
                mkdir($directory, 0755, true);
116
            }
117
118 2
            $this->io->write("<info>save output into</info>: {$path}");
119 2
            file_put_contents($path, $content);
120
        }
121 2
    }
122
123
    /**
124
     * @param string $formatter
125
     *
126
     * @throws CompilerException
127
     */
128 6
    public function processFiles($formatter)
129
    {
130 6
        $this->scss->setFormatter($this->getFormatterClass($formatter));
131 6
        $this->io->write("<info>use '{$formatter}' formatting</info>");
132
133 6
        foreach ($this->files as $file) {
134 6
            $this->io->write("<info>processing</info>: {$file->getInputPath()}");
135 6
            $this->fetchInputContextIntoFile($file);
136
137
            try {
138 6
                $this->processFile($file);
139 2
            } catch (CompilerException $e) {
140 6
                $this->io->writeError("<error>failed to process: {$file->getOutputPath()}</error>");
141
            }
142
        }
143 6
    }
144
145
    /**
146
     * @param FileContainer $file
147
     *
148
     * @return FileContainer
149
     * @throws CompilerException
150
     */
151 11
    public function processFile(FileContainer $file)
152
    {
153 11
        switch ($file->getType()) {
154 11
            case FileContainer::TYPE_SCSS:
155 6
                return $this->compileSCSS($file);
156 5
            case FileContainer::TYPE_LESS:
157 4
                return $this->compileLESS($file);
158
        }
159
160 1
        throw new CompilerException('unknown compiler');
161
    }
162
163
    /**
164
     * @param FileContainer $file
165
     *
166
     * @return $this
167
     * @throws CompilerException
168
     */
169 6
    protected function compileSCSS(FileContainer $file)
170
    {
171
        try {
172 6
            $this->scss->addImportPath(dirname($file->getInputPath()));
173 6
            $content = $this->scss->compile($file->getInputContent());
174
175 5
            return $file->setOutputContent($content);
176 1
        } catch (ParserException $e) {
177 1
            throw new CompilerException($e->getMessage(), 1, $e);
178
        }
179
    }
180
181
    /**
182
     * @param FileContainer $file
183
     *
184
     * @return $this
185
     * @throws CompilerException
186
     */
187 4
    protected function compileLESS(FileContainer $file)
188
    {
189
        try {
190 4
            return $file->setOutputContent($this->less->compileFile($file->getInputPath()));
191 1
        } catch (\Exception $e) {
192 1
            throw new CompilerException($e->getMessage(), 1, $e);
193
        }
194
    }
195
196
    /**
197
     * @param string $formatter
198
     *
199
     * @return string
200
     */
201 8
    protected function getFormatterClass($formatter)
202
    {
203 8
        if (!in_array($formatter, static::$supportedFormatters)) {
204 1
            throw new \InvalidArgumentException('unknown formatter, available options are: ' . print_r(static::$supportedFormatters, true));
205
        }
206
207 7
        return 'Leafo\\ScssPhp\\Formatter\\' . ucfirst($formatter);
208
    }
209
210
    /**
211
     * @param FileContainer $file
212
     *
213
     * @throws FileException
214
     */
215 8
    protected function fetchInputContextIntoFile(FileContainer $file)
216
    {
217 8
        if (!file_exists($file->getInputPath())) {
218 1
            throw new FileException("file: {$file->getInputPath()} doesn't exists");
219
        }
220
221 7
        $file->setInputContent(file_get_contents($file->getInputPath()));
222 7
    }
223
}
224