30
30
either expressed or implied, of the FreeBSD Project.
31
31
*/
32
32
33
+
33
34
require_once __DIR__ . '/exceptions.php ' ;
34
35
require_once __DIR__ . '/Settings.php ' ;
35
36
require_once __DIR__ . '/Process.php ' ;
36
37
require_once __DIR__ . '/Output.php ' ;
37
38
require_once __DIR__ . '/Error.php ' ;
38
39
39
-
40
- class ArrayIterator extends \ArrayIterator
41
- {
42
- public function getNext ()
43
- {
44
- $ this ->next ();
45
- return $ this ->current ();
46
- }
47
- }
48
-
49
40
class Manager
50
41
{
51
42
const CODE_OK = 0 ,
@@ -58,6 +49,7 @@ class Manager
58
49
* @param array $arguments
59
50
* @return Settings
60
51
* @throws InvalidArgumentException
52
+ * @throws Exception
61
53
*/
62
54
public function parseArguments (array $ arguments )
63
55
{
@@ -68,24 +60,30 @@ public function parseArguments(array $arguments)
68
60
if ($ argument {0 } !== '- ' ) {
69
61
$ setting ->paths [] = $ argument ;
70
62
} else {
71
- switch (substr ( $ argument, 1 ) ) {
72
- case 'p ' :
63
+ switch ($ argument ) {
64
+ case '- p ' :
73
65
$ setting ->phpExecutable = $ arguments ->getNext ();
74
66
break ;
75
67
76
- case 'short ' :
68
+ case '-s ' :
69
+ case '--short ' :
77
70
$ setting ->shortTag = true ;
78
71
break ;
79
72
80
- case 'asp ' :
73
+ case '-a ' :
74
+ case '--asp ' :
81
75
$ setting ->aspTags = true ;
82
76
break ;
83
77
84
- case 'e ' :
78
+ case '--exclude ' :
79
+ $ setting ->excluded [] = $ arguments ->getNext ();
80
+ break ;
81
+
82
+ case '-e ' :
85
83
$ setting ->extensions = array_map ('trim ' , explode (', ' , $ arguments ->getNext ()));
86
84
break ;
87
85
88
- case 'j ' :
86
+ case '- j ' :
89
87
$ setting ->parallelJobs = max ((int ) $ arguments ->getNext (), 1 );
90
88
break ;
91
89
@@ -95,6 +93,10 @@ public function parseArguments(array $arguments)
95
93
}
96
94
}
97
95
96
+ if (empty ($ setting ->paths )) {
97
+ throw new Exception ('No path set. ' );
98
+ }
99
+
98
100
return $ setting ;
99
101
}
100
102
@@ -106,13 +108,17 @@ public function parseArguments(array $arguments)
106
108
public function run (Settings $ settings = null )
107
109
{
108
110
$ settings = $ settings ?: new Settings ;
111
+ $ output = $ this ->output ?: new Output (new ConsoleWriter );
109
112
110
113
$ this ->checkPhpExecutableExists ($ settings ->phpExecutable );
111
114
112
115
$ cmdLine = $ this ->getCmdLine ($ settings );
113
- $ files = $ this ->getFilesFromPaths ($ settings ->paths , $ settings ->extensions );
116
+ $ files = $ this ->getFilesFromPaths ($ settings ->paths , $ settings ->extensions , $ settings ->excluded );
117
+
118
+ if (empty ($ files )) {
119
+ throw new Exception ('No file found to check. ' );
120
+ }
114
121
115
- $ output = $ this ->output ?: new Output (new ConsoleWriter );
116
122
$ output ->setTotalFileCount (count ($ files ));
117
123
118
124
/** @var LintProcess[] $running */
@@ -216,10 +222,11 @@ protected function getCmdLine(Settings $settings)
216
222
/**
217
223
* @param array $paths
218
224
* @param array $extensions
225
+ * @param array $excluded
219
226
* @return array
220
227
* @throws NotExistsPathException
221
228
*/
222
- protected function getFilesFromPaths (array $ paths , array $ extensions )
229
+ protected function getFilesFromPaths (array $ paths , array $ extensions, array $ excluded = array () )
223
230
{
224
231
$ extensions = array_flip ($ extensions );
225
232
$ files = array ();
@@ -228,11 +235,17 @@ protected function getFilesFromPaths(array $paths, array $extensions)
228
235
if (is_file ($ path )) {
229
236
$ files [] = $ path ;
230
237
} else if (is_dir ($ path )) {
231
- $ directoryFiles = new \RecursiveIteratorIterator (new \RecursiveDirectoryIterator ($ path ));
232
- foreach ($ directoryFiles as $ directoryFile ) {
233
- $ directoryFile = (string ) $ directoryFile ;
234
- if (isset ($ extensions [pathinfo ($ directoryFile , PATHINFO_EXTENSION )])) {
235
- $ files [] = $ directoryFile ;
238
+
239
+ $ iterator = new \RecursiveDirectoryIterator ($ path );
240
+ if (!empty ($ excluded )) {
241
+ $ iterator = new ExcludeRecursiveDirectoryIterator ($ iterator , $ excluded );
242
+ }
243
+ $ iterator = new \RecursiveIteratorIterator ($ iterator );
244
+
245
+ /** @var \SplFileInfo[] $iterator */
246
+ foreach ($ iterator as $ directoryFile ) {
247
+ if (isset ($ extensions [$ directoryFile ->getExtension ()])) {
248
+ $ files [] = (string ) $ directoryFile ;
236
249
}
237
250
}
238
251
} else {
@@ -242,4 +255,145 @@ protected function getFilesFromPaths(array $paths, array $extensions)
242
255
243
256
return $ files ;
244
257
}
258
+ }
259
+
260
+ class ArrayIterator extends \ArrayIterator
261
+ {
262
+ public function getNext ()
263
+ {
264
+ $ this ->next ();
265
+ return $ this ->current ();
266
+ }
267
+ }
268
+
269
+ class ExcludeRecursiveDirectoryIterator implements \RecursiveIterator
270
+ {
271
+ /** @var array */
272
+ private $ excluded = array ();
273
+
274
+ /** @var \RecursiveDirectoryIterator */
275
+ private $ iterator ;
276
+
277
+ /**
278
+ * @param array $excluded
279
+ * @param \RecursiveDirectoryIterator $iterator
280
+ */
281
+ public function __construct (\RecursiveDirectoryIterator $ iterator , array $ excluded )
282
+ {
283
+ $ this ->iterator = $ iterator ;
284
+ $ this ->excluded = array_map (array ($ this , 'normalizePath ' ), $ excluded );
285
+ }
286
+
287
+ /**
288
+ * (PHP 5 >= 5.0.0)<br/>
289
+ * Return the current element
290
+ * @link http://php.net/manual/en/iterator.current.php
291
+ * @return mixed Can return any type.
292
+ */
293
+ public function current ()
294
+ {
295
+ return $ this ->iterator ->current ();
296
+ }
297
+
298
+ /**
299
+ * (PHP 5 >= 5.0.0)<br/>
300
+ * Move forward to next element
301
+ * @link http://php.net/manual/en/iterator.next.php
302
+ * @return void Any returned value is ignored.
303
+ */
304
+ public function next ()
305
+ {
306
+ $ this ->iterator ->next ();
307
+ }
308
+
309
+ /**
310
+ * (PHP 5 >= 5.0.0)<br/>
311
+ * Return the key of the current element
312
+ * @link http://php.net/manual/en/iterator.key.php
313
+ * @return mixed scalar on success, or null on failure.
314
+ */
315
+ public function key ()
316
+ {
317
+ return $ this ->iterator ->key ();
318
+ }
319
+
320
+ /**
321
+ * (PHP 5 >= 5.0.0)<br/>
322
+ * Checks if current position is valid
323
+ * @link http://php.net/manual/en/iterator.valid.php
324
+ * @return boolean The return value will be casted to boolean and then evaluated.
325
+ * Returns true on success or false on failure.
326
+ */
327
+ public function valid ()
328
+ {
329
+ return $ this ->iterator ->valid ();
330
+ }
331
+
332
+ /**
333
+ * (PHP 5 >= 5.0.0)<br/>
334
+ * Rewind the Iterator to the first element
335
+ * @link http://php.net/manual/en/iterator.rewind.php
336
+ * @return void Any returned value is ignored.
337
+ */
338
+ public function rewind ()
339
+ {
340
+ $ this ->iterator ->rewind ();
341
+ }
342
+
343
+ /**
344
+ * (PHP 5 >= 5.1.0)<br/>
345
+ * Returns if an iterator can be created for the current entry.
346
+ * @link http://php.net/manual/en/recursiveiterator.haschildren.php
347
+ * @return bool true if the current entry can be iterated over, otherwise returns false.
348
+ */
349
+ public function hasChildren ()
350
+ {
351
+ $ path = $ this ->normalizePath ($ this ->iterator ->getPathname ());
352
+ foreach ($ this ->excluded as $ exc ) {
353
+ if (strpos ($ path , $ exc ) === 0 ) {
354
+ return false ;
355
+ }
356
+ }
357
+
358
+ return $ this ->iterator ->hasChildren ();
359
+ }
360
+
361
+ /**
362
+ * (PHP 5 >= 5.1.0)<br/>
363
+ * Returns an iterator for the current entry.
364
+ * @link http://php.net/manual/en/recursiveiterator.getchildren.php
365
+ * @return \RecursiveIterator An iterator for the current entry.
366
+ */
367
+ public function getChildren ()
368
+ {
369
+ return new self ($ this ->iterator ->getChildren (), $ this ->excluded );
370
+ }
371
+
372
+
373
+ /**
374
+ * Source: http://stackoverflow.com/questions/4774116/c-realpath-without-resolving-symlinks
375
+ * @param string $path
376
+ * @return string
377
+ */
378
+ private function normalizePath ($ path )
379
+ {
380
+ if (!isset ($ path [0 ]) || $ path [0 ] !== DIRECTORY_SEPARATOR ) {
381
+ $ result = explode (DIRECTORY_SEPARATOR , getcwd ());
382
+ } else {
383
+ $ result = array ('' );
384
+ }
385
+
386
+ $ parts = explode (DIRECTORY_SEPARATOR , $ path );
387
+ foreach ($ parts as $ part ) {
388
+ if ($ part === '' || $ part === '. ' ) {
389
+ continue ;
390
+ } if ($ part === '.. ' ) {
391
+ array_pop ($ result );
392
+ } else {
393
+ $ result [] = $ part ;
394
+ }
395
+ }
396
+
397
+ return implode (DIRECTORY_SEPARATOR , $ result );
398
+ }
245
399
}
0 commit comments