Completed
Push — master ( d607f5...fbc455 )
by Carlos
02:33
created

Linter::setProcessLimit()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 6
rs 9.4285
c 0
b 0
f 0
cc 1
eloc 3
nc 1
nop 1
1
<?php
2
3
/*
4
 * This file is part of the overtrue/phplint.
5
 *
6
 * (c) 2016 overtrue <[email protected]>
7
 */
8
9
namespace Overtrue\PHPLint;
10
11
use Overtrue\PHPLint\Process\Lint;
12
use Symfony\Component\Finder\Finder;
13
use SplFileInfo;
14
use InvalidArgumentException;
15
16
/**
17
 * Class Linter.
18
 */
19
class Linter
20
{
21
    /**
22
     * @var callable
23
     */
24
    private $processCallback;
25
26
    /**
27
     * @var array
28
     */
29
    private $files = [];
30
31
    /**
32
     * @var array
33
     */
34
    private $cache = [];
35
36
    /**
37
     * @var string|array
38
     */
39
    private $path;
40
41
    /**
42
     * @var array
43
     */
44
    private $excludes;
45
46
    /**
47
     * @var array
48
     */
49
    private $extensions;
50
51
    /**
52
     * @var int
53
     */
54
    private $procLimit = 5;
55
56
    /**
57
     * Constructor.
58
     *
59
     * @param string|array $path
60
     * @param array        $excludes
61
     * @param array        $extensions
62
     */
63
    public function __construct($path, array $excludes = [], array $extensions = ['php'])
64
    {
65
        $this->path = $path;
66
        $this->excludes = $excludes;
67
        $this->extensions = $extensions;
68
    }
69
70
    /**
71
     * Check the files.
72
     *
73
     * @param array $files
74
     * @param bool  $cache
75
     *
76
     * @return array
77
     */
78
    public function lint($files = [], $cache = true)
79
    {
80
        if (empty($files)) {
81
            $files = $this->getFiles();
82
        }
83
84
        $processCallback = is_callable($this->processCallback) ? $this->processCallback : function () {
85
        };
86
87
        $errors = [];
88
        $running = [];
89
        $newCache = [];
90
91
        while (!empty($files) || !empty($running)) {
92
            for ($i = count($running); !empty($files) && $i < $this->procLimit; ++$i) {
93
                $file = array_shift($files);
94
                $filename = $file->getRealpath();
95
96
                if (!isset($this->cache[$filename]) || $this->cache[$filename] !== md5_file($filename)) {
97
                    $running[$filename] = new Lint(PHP_BINARY.' -d error_reporting=E_ALL -d display_errors=On -l '.escapeshellarg($filename));
98
                    $running[$filename]->start();
99
                } else {
100
                    $newCache[$filename] = $this->cache[$filename];
101
                }
102
            }
103
104
            foreach ($running as $filename => $lintProcess) {
105
                if ($lintProcess->isRunning()) {
106
                    continue;
107
                }
108
109
                unset($running[$filename]);
110
                if ($lintProcess->hasSyntaxError()) {
111
                    $processCallback('error', $filename);
112
                    $errors[$filename] = array_merge(['file' => $filename], $lintProcess->getSyntaxError());
113
                } else {
114
                    $newCache[$filename] = md5_file($filename);
115
                    $processCallback('ok', $filename);
116
                }
117
            }
118
119
            $cache && Cache::put($newCache);
120
        }
121
122
        return $errors;
123
    }
124
125
    /**
126
     * Cache setter.
127
     *
128
     * @param array $cache
129
     */
130
    public function setCache($cache = [])
131
    {
132
        if (is_array($cache)) {
133
            $this->cache = $cache;
134
        } else {
135
            $this->cache = [];
136
        }
137
    }
138
139
    /**
140
     * Fetch files.
141
     *
142
     * @return array
143
     */
144
    public function getFiles()
145
    {
146
        if (empty($this->files)) {
147
            foreach ((array) $this->path as $path) {
148
                if (is_dir($path)) {
149
                    $this->files = array_merge($this->files, $this->getFilesFromDir($path));
150
                } else if (is_file($path)) {
151
                    $file = new SplFileInfo($path);
152
                    $this->files[$file->getRealPath()] = $file;
153
                }
154
            }
155
        }
156
157
        return $this->files;
158
    }
159
160
    /**
161
     * Get files from directory.
162
     *
163
     * @param  string $dir
164
     *
165
     * @return array
166
     */
167
    protected function getFilesFromDir($dir)
168
    {
169
        $finder = new Finder();
170
        $finder->files()->ignoreUnreadableDirs()->in(realpath($dir));
171
172
        foreach ($this->excludes as $exclude) {
173
            $finder->notPath($exclude);
174
        }
175
176
        foreach ($this->extensions as $extension) {
177
            $finder->name('*.'.$extension);
178
        }
179
180
        return iterator_to_array($finder);
181
    }
182
183
    /**
184
     * Set Files.
185
     *
186
     * @param array $files
187
     *
188
     * @return \Overtrue\PHPLint\Linter
189
     */
190
    public function setFiles(array $files)
191
    {
192
        foreach ($files as $file) {
193
            if (is_file($file)) {
194
                $file = new SplFileInfo($file);
195
            }
196
197
            if (!($file instanceof SplFileInfo)) {
198
                throw new InvalidArgumentException("File $file not exists.");
199
            }
200
201
            $file = new SplFileInfo($path);
0 ignored issues
show
Bug introduced by
The variable $path does not exist. Did you forget to declare it?

This check marks access to variables or properties that have not been declared yet. While PHP has no explicit notion of declaring a variable, accessing it before a value is assigned to it is most likely a bug.

Loading history...
202
            $this->files[$file->getRealPath()] = $file;
203
        }
204
205
        return $this;
206
    }
207
208
    /**
209
     * Set process callback.
210
     *
211
     * @param callable $processCallback
212
     *
213
     * @return Linter
214
     */
215
    public function setProcessCallback($processCallback)
216
    {
217
        $this->processCallback = $processCallback;
218
219
        return $this;
220
    }
221
222
    /**
223
     * Set process limit.
224
     *
225
     * @param int $procLimit
226
     */
227
    public function setProcessLimit($procLimit)
228
    {
229
        $this->procLimit = $procLimit;
230
231
        return $this;
232
    }
233
}
234