Completed
Push — master ( a20e35...2a3e96 )
by Greg
03:21
created

src/Task/Assets/CssPreprocessor.php (1 issue)

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

1
<?php
2
3
namespace Robo\Task\Assets;
4
5
use Robo\Result;
6
use Robo\Task\BaseTask;
7
8
abstract class CssPreprocessor extends BaseTask
9
{
10
    const FORMAT_NAME = '';
11
12
    /**
13
     * Default compiler to use.
14
     *
15
     * @var string
16
     */
17
    protected $compiler;
18
19
    /**
20
     * Available compilers list
21
     *
22
     * @var string[]
23
     */
24
    protected $compilers = [];
25
26
    /**
27
     * Compiler options.
28
     *
29
     * @var array
30
     */
31
    protected $compilerOptions = [];
32
33
    /**
34
     * @var array
35
     */
36
    protected $files = [];
37
38
    /**
39
     * Constructor. Accepts array of file paths.
40
     *
41
     * @param array $input
42
     */
43
    public function __construct(array $input)
44
    {
45
        $this->files = $input;
46
47
        $this->setDefaultCompiler();
48
    }
49
50
    protected function setDefaultCompiler()
51
    {
52
        if (isset($this->compilers[0])) {
53
            //set first compiler as default
54
            $this->compiler = $this->compilers[0];
55
        }
56
    }
57
58
    /**
59
     * Sets import directories
60
     * Alias for setImportPaths
61
     * @see CssPreprocessor::setImportPaths
62
     *
63
     * @param array|string $dirs
64
     *
65
     * @return $this
66
     */
67
    public function importDir($dirs)
68
    {
69
        return $this->setImportPaths($dirs);
70
    }
71
72
    /**
73
     * Adds import directory
74
     *
75
     * @param string $dir
76
     *
77
     * @return $this
78
     */
79
    public function addImportPath($dir)
80
    {
81
        if (!isset($this->compilerOptions['importDirs'])) {
82
            $this->compilerOptions['importDirs'] = [];
83
        }
84
85
        if (!in_array($dir, $this->compilerOptions['importDirs'], true)) {
86
            $this->compilerOptions['importDirs'][] = $dir;
87
        }
88
89
        return $this;
90
    }
91
92
    /**
93
     * Sets import directories
94
     *
95
     * @param array|string $dirs
96
     *
97
     * @return $this
98
     */
99
    public function setImportPaths($dirs)
100
    {
101
        if (!is_array($dirs)) {
102
            $dirs = [$dirs];
103
        }
104
105
        $this->compilerOptions['importDirs'] = $dirs;
106
107
        return $this;
108
    }
109
110
    /**
111
     * @param string $formatterName
112
     *
113
     * @return $this
114
     */
115
    public function setFormatter($formatterName)
116
    {
117
        $this->compilerOptions['formatter'] = $formatterName;
118
119
        return $this;
120
    }
121
122
    /**
123
     * Sets the compiler.
124
     *
125
     * @param string $compiler
126
     * @param array $options
127
     *
128
     * @return $this
129
     */
130
    public function compiler($compiler, array $options = [])
131
    {
132
        $this->compiler = $compiler;
133
        $this->compilerOptions = array_merge($this->compilerOptions, $options);
134
135
        return $this;
136
    }
137
138
    /**
139
     * Compiles file
140
     *
141
     * @param $file
142
     *
143
     * @return bool|mixed
144
     */
145
    protected function compile($file)
146
    {
147
        if (is_callable($this->compiler)) {
148
            return call_user_func($this->compiler, $file, $this->compilerOptions);
149
        }
150
151
        if (method_exists($this, $this->compiler)) {
152
            return $this->{$this->compiler}($file);
153
        }
154
155
        return false;
156
    }
157
158
    /**
159
     * {@inheritdoc}
160
     */
161
    public function run()
162
    {
163 View Code Duplication
        if (!in_array($this->compiler, $this->compilers, true)
0 ignored issues
show
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
164
            && !is_callable($this->compiler)
165
        ) {
166
            $message = sprintf('Invalid ' . static::FORMAT_NAME . ' compiler %s!', $this->compiler);
167
168
            return Result::error($this, $message);
169
        }
170
171
        foreach ($this->files as $in => $out) {
172
            if (!file_exists($in)) {
173
                $message = sprintf('File %s not found.', $in);
174
175
                return Result::error($this, $message);
176
            }
177
            if (file_exists($out) && !is_writable($out)) {
178
                return Result::error($this, 'Destination already exists and cannot be overwritten.');
179
            }
180
        }
181
182
        foreach ($this->files as $in => $out) {
183
            $css = $this->compile($in);
184
185
            if ($css instanceof Result) {
186
                return $css;
187
            } elseif (false === $css) {
188
                $message = sprintf(
189
                    ucfirst(static::FORMAT_NAME) . ' compilation failed for %s.',
190
                    $in
191
                );
192
193
                return Result::error($this, $message);
194
            }
195
196
            $dst = $out . '.part';
197
            $write_result = file_put_contents($dst, $css);
198
199
            if (false === $write_result) {
200
                $message = sprintf('File write failed: %s', $out);
201
202
                @unlink($dst);
203
                return Result::error($this, $message);
204
            }
205
206
            // Cannot be cross-volume: should always succeed
207
            @rename($dst, $out);
208
209
            $this->printTaskSuccess('Wrote CSS to {filename}', ['filename' => $out]);
210
        }
211
212
        return Result::success($this, 'All ' . static::FORMAT_NAME . ' files compiled.');
213
    }
214
}
215