Completed
Push — master ( 76ad1f...386b33 )
by Greg
05:49
created

CssPreprocessor::run()   C

Complexity

Conditions 11
Paths 13

Size

Total Lines 53

Duplication

Lines 7
Ratio 13.21 %

Importance

Changes 0
Metric Value
dl 7
loc 53
rs 6.8787
c 0
b 0
f 0
cc 11
nc 13
nop 0

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

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
Duplication introduced by
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);
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
203
                return Result::error($this, $message);
204
            }
205
206
            // Cannot be cross-volume: should always succeed
207
            @rename($dst, $out);
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
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