Completed
Pull Request — master (#248)
by Fabien
02:43
created

FileFinder::getPhpFiles()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 2
dl 0
loc 4
rs 10
c 0
b 0
f 0
cc 2
nc 2
nop 1
1
<?php declare(strict_types = 1);
2
3
namespace Churn\File;
4
5
use const DIRECTORY_SEPARATOR;
6
use Generator;
7
use function in_array;
8
use function preg_match;
9
use function preg_replace;
10
use RecursiveDirectoryIterator;
11
use RecursiveIteratorIterator;
12
use SplFileInfo;
13
use function str_replace;
14
15
class FileFinder
16
{
17
    /**
18
     * List of file extensions to look for.
19
     * @var array
20
     */
21
    private $fileExtensions;
22
23
    /**
24
     * List of files to ignore.
25
     * @var array
26
     */
27
    private $filesToIgnore;
28
29
    /**
30
     * Class constructor.
31
     * @param array $fileExtensions List of file extensions to look for.
32
     * @param array $filesToIgnore  List of files to ignore.
33
     */
34
    public function __construct(array $fileExtensions, array $filesToIgnore)
35
    {
36
        $this->fileExtensions = $fileExtensions;
37
        $this->filesToIgnore = $filesToIgnore;
38
    }
39
40
    /**
41
     * Recursively finds all files with the .php extension in the provided
42
     * $paths and returns list as array.
43
     * @param array $paths Paths in which to look for .php files.
44
     * @return Generator
45
     */
46
    public function getPhpFiles(array $paths): Generator
47
    {
48
        foreach ($paths as $path) {
49
            yield from $this->getPhpFilesFromPath($path);
50
        }
51
    }
52
53
    /**
54
     * Recursively finds all files with the .php extension in the provided
55
     * $path adds them to $this->files.
56
     * @param string $path Path in which to look for .php files.
57
     * @return Generator
58
     */
59
    private function getPhpFilesFromPath(string $path): Generator
60
    {
61
        foreach ($this->getPathIterator($path) as $file) {
62
            if (!in_array($file->getExtension(), $this->fileExtensions)
63
            || $this->fileShouldBeIgnored($file)) {
64
                continue;
65
            }
66
67
            yield new File($file->getRealPath(), $file->getPathName());
68
        }
69
    }
70
71
    /**
72
     * Returns a recursive iterator for a given directory.
73
     * @param string $path Path in which to look for .php files.
74
     * @return RecursiveIteratorIterator
75
     */
76
    private function getPathIterator(string $path): RecursiveIteratorIterator
77
    {
78
        $directoryIterator = new RecursiveDirectoryIterator($path);
79
        return new RecursiveIteratorIterator($directoryIterator);
80
    }
81
82
    /**
83
     * Determines if a file should be ignored.
84
     * @param \SplFileInfo $file File.
85
     * @return boolean
86
     */
87
    private function fileShouldBeIgnored(SplFileInfo $file): bool
88
    {
89
        foreach ($this->filesToIgnore as $fileToIgnore) {
90
            $regex = $this->patternToRegex($fileToIgnore);
91
            if (preg_match("#{$regex}#", $file->getRealPath())) {
92
                return true;
93
            }
94
        }
95
96
        return false;
97
    }
98
99
    /**
100
     * Translate file path pattern to regex string.
101
     * @param string $filePattern File pattern to be ignored.
102
     * @return string
103
     */
104
    private function patternToRegex(string $filePattern): string
105
    {
106
        $regex = preg_replace("#(.*)\*([\w.]*)$#", "$1.+$2$", $filePattern);
107
        if (DIRECTORY_SEPARATOR === '\\') {
108
            $regex = str_replace('/', '\\\\', $regex);
109
        }
110
111
        return $regex;
112
    }
113
}
114