Passed
Pull Request — master (#67)
by Eugene
02:40
created

Processor::processFile()   B

Complexity

Conditions 5
Paths 7

Size

Total Lines 22
Code Lines 15

Duplication

Lines 0
Ratio 0 %

Importance

Changes 4
Bugs 0 Features 1
Metric Value
c 4
b 0
f 1
dl 0
loc 22
rs 8.6737
cc 5
eloc 15
nc 7
nop 1
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 SASSCompiler;
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 SASSCompiler
43
     */
44
    private $sass;
45
    /**
46
     * @var LESSCompiler
47
     */
48
    private $less;
49
50
    public function __construct(IOInterface $io)
51
    {
52
        $this->io = $io;
53
        $this->initCompilers();
54
    }
55
56
    protected function initCompilers()
57
    {
58
        $this->less = new LESSCompiler();
59
        $this->sass = new SASSCompiler();
60
        /** attaches compass functionality to the SASS compiler */
61
        new CompassCompiler($this->sass);
62
    }
63
64
    /**
65
     * @param string $inputPath
66
     * @param string $outputPath
67
     *
68
     * @throws \Exception
69
     */
70
    public function attachFiles($inputPath, $outputPath)
71
    {
72
        if (is_dir($inputPath)) {
73
            $files = scandir($inputPath);
74
            unset($files[0], $files[1]);
75
76
            foreach ($files as $file) {
77
                $this->attachFiles("$inputPath/$file", $outputPath);
78
            }
79
        } else if (is_file($inputPath)) {
80
            $this->files[] = new FileContainer($inputPath, $outputPath);
81
        } else {
82
            throw new \Exception("file doesn't exists");
83
        }
84
    }
85
86
    /**
87
     * @return FileContainer[]
88
     */
89
    public function getFiles()
90
    {
91
        return $this->files;
92
    }
93
94
    /**
95
     * @return string[]
96
     */
97
    protected function concatOutput()
98
    {
99
        $outputMap = [];
100
        foreach ($this->files as $file) {
101
            if (!isset($outputMap[$file->getOutputPath()])) {
102
                $outputMap[$file->getOutputPath()] = '';
103
            }
104
105
            $outputMap[$file->getOutputPath()] .= $file->getOutputContent();
106
        }
107
108
        return $outputMap;
109
    }
110
111
    /**
112
     * save output into file
113
     */
114
    public function saveOutput()
115
    {
116
        foreach ($this->concatOutput() as $path => $content) {
117
            $directory = dirname($path);
118
            if (!is_dir($directory)) {
119
                $this->io->write("<info>creating directory</info>: {$directory}");
120
                mkdir($directory, 0755, true);
121
            }
122
123
            $this->io->write("<info>save output into</info>: {$path}");
124
            file_put_contents($path, $content);
125
        }
126
    }
127
128
    /**
129
     * @param string $formatter
130
     *
131
     * @throws CompilerException
132
     */
133
    public function processFiles($formatter)
134
    {
135
        $this->sass->setFormatter($this->getFormatterClass($formatter));
136
        $this->io->write("<info>use '{$formatter}' formatting</info>");
137
138
        foreach ($this->files as $file) {
139
            $this->io->write("<info>processing</info>: {$file->getInputPath()}");
140
            $this->fetchInputContextIntoFile($file);
141
142
            try {
143
                $this->processFile($file);
144
            } catch (CompilerException $e) {
145
                $this->io->writeError("<error>failed to process: {$file->getOutputPath()}</error>");
146
            }
147
        }
148
    }
149
150
    /**
151
     * @param FileContainer $file
152
     *
153
     * @return FileContainer
154
     * @throws CompilerException
155
     */
156
    public function processFile(FileContainer $file)
157
    {
158
        switch ($file->getType()) {
159
            case FileContainer::TYPE_SCSS:
0 ignored issues
show
Coding Style introduced by
There must be a comment when fall-through is intentional in a non-empty case body
Loading history...
160
                try {
161
                    $this->sass->addImportPath(dirname($file->getInputPath()));
162
                    $content = $this->sass->compile($file->getInputContent());
163
164
                    return $file->setOutputContent($content);
165
                } catch (ParserException $e) {
166
                    throw new CompilerException($e->getMessage(), 1, $e);
167
                }
168
            case FileContainer::TYPE_LESS:
169
                try {
170
                    return $file->setOutputContent($this->less->compileFile($file->getInputPath()));
171
                } catch (\Exception $e) {
172
                    throw new CompilerException($e->getMessage(), 1, $e);
173
                }
174
        }
175
176
        throw new CompilerException('unknown compiler');
177
    }
178
179
    /**
180
     * @param string $formatter
181
     *
182
     * @return string
183
     */
184
    protected function getFormatterClass($formatter)
185
    {
186
        if (!in_array($formatter, static::$supportedFormatters)) {
187
            throw new \InvalidArgumentException('unknown formatter, available options are: ' . print_r(static::$supportedFormatters, true));
188
        }
189
190
        return 'Leafo\\ScssPhp\\Formatter\\' . ucfirst($formatter);
191
    }
192
193
    /**
194
     * @param FileContainer $file
195
     *
196
     * @throws FileException
197
     */
198
    protected function fetchInputContextIntoFile(FileContainer $file)
199
    {
200
        if (!file_exists($file->getInputPath())) {
201
            throw new FileException("file: {$file->getInputPath()} doesn't exists");
202
        }
203
204
        $file->setInputContent(file_get_contents($file->getInputPath()));
205
    }
206
}
207