Completed
Pull Request — 2.x (#402)
by
unknown
02:04
created

Enumerator::getExcludePaths()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 11

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 6
CRAP Score 2

Importance

Changes 0
Metric Value
dl 0
loc 11
ccs 6
cts 6
cp 1
rs 9.9
c 0
b 0
f 0
cc 2
nc 2
nop 0
crap 2
1
<?php
2
/*
3
 * Go! AOP framework
4
 *
5
 * @copyright Copyright 2015, Lisachenko Alexander <[email protected]>
6
 *
7
 * This source file is subject to the license that is bundled
8
 * with this source code in the file LICENSE.
9
 */
10
11
namespace Go\Instrument\FileSystem;
12
13
use CallbackFilterIterator;
14
use InvalidArgumentException;
15
use LogicException;
16
use RecursiveIteratorIterator;
17
use SplFileInfo;
18
use Symfony\Component\Finder\Finder;
19
use UnexpectedValueException;
20
21
/**
22
 * Enumerates files in the concrete directory, applying filtration logic
23
 */
24
class Enumerator
25
{
26
27
    /**
28
     * Path to the root directory, where enumeration should start
29
     *
30
     * @var string
31
     */
32
    private $rootDirectory;
33
34
    /**
35
     * List of additional include paths, should be below rootDirectory
36
     *
37
     * @var array
38
     */
39
    private $includePaths;
40
41
    /**
42
     * List of additional exclude paths, should be below rootDirectory
43
     *
44
     * @var array
45
     */
46
    private $excludePaths;
47
48
    /**
49
     * Initializes an enumerator
50
     *
51
     * @param string $rootDirectory Path to the root directory
52
     * @param array  $includePaths  List of additional include paths
53
     * @param array  $excludePaths  List of additional exclude paths
54
     */
55 7
    public function __construct($rootDirectory, array $includePaths = [], array $excludePaths = [])
56
    {
57 7
        $this->rootDirectory = $rootDirectory;
58 7
        $this->includePaths = $includePaths;
59 7
        $this->excludePaths = $excludePaths;
60 7
    }
61
62
    /**
63
     * Returns an enumerator for files
64
     *
65
     * @return CallbackFilterIterator|RecursiveIteratorIterator|\IteratorIterator|SplFileInfo[]
66
     * @throws UnexpectedValueException
67
     * @throws InvalidArgumentException
68
     * @throws LogicException
69
     */
70 7
    public function enumerate()
71
    {
72 7
        $finder = new Finder();
73 7
        $finder->files()
74 7
            ->name('*.php')
75 7
            ->in($this->getInPaths());
76
77 7
        foreach ($this->getExcludePaths() as $path) {
78 4
            $finder->notPath($path);
79
        }
80
        
81 7
        $iterator = new \RecursiveIteratorIterator(
82 7
            new \RecursiveDirectoryIterator(
83 7
                $this->rootDirectory,
84 7
                \FilesystemIterator::SKIP_DOTS | \FilesystemIterator::UNIX_PATHS
85
            )
86
        );
87
88 7
        $callback = $this->getFilter();
89 7
        $iterator = new \CallbackFilterIterator($iterator, $callback);
90
91 7
        return $iterator;
92
93
        return $finder->getIterator();
0 ignored issues
show
Unused Code introduced by
return $finder->getIterator(); does not seem to be reachable.

This check looks for unreachable code. It uses sophisticated control flow analysis techniques to find statements which will never be executed.

Unreachable code is most often the result of return, die or exit statements that have been added for debug purposes.

function fx() {
    try {
        doSomething();
        return true;
    }
    catch (\Exception $e) {
        return false;
    }

    return false;
}

In the above example, the last return false will never be executed, because a return statement has already been met in every possible execution path.

Loading history...
94
    }
95
96
    /**
97
     * @return array
98
     * @throws UnexpectedValueException
99
     */
100 7
    private function getInPaths()
101
    {
102 7
        $inPaths = [];
103
104 7
        foreach ($this->includePaths as $path) {
105 1
            if (strpos($path, $this->rootDirectory, 0) === false) {
106
                throw new UnexpectedValueException(sprintf('Path %s is not in %s', $path, $this->rootDirectory));
107
            }
108
109 1
            $path = str_replace('*', '', $path);
110 1
            $inPaths[] = $path;
111
        }
112
113 7
        if (empty($inPaths)) {
114 6
            $inPaths[] = $this->rootDirectory;
115
        }
116
117 7
        return $inPaths;
118
    }
119
120
    /**
121
     * @return array
122
     */
123 7
    private function getExcludePaths()
124
    {
125 7
        $excludePaths = [];
126
127 7
        foreach ($this->excludePaths as $path) {
128 4
            $path = str_replace('*', '.*', $path);
129 4
            $excludePaths[] = '#' . str_replace($this->rootDirectory . '/', '', $path) . '#';
130
        }
131
132 7
        return $excludePaths;
133
    }
134
135
    /**
136
     * Returns a filter callback for enumerating files
137
     *
138
     * @return \Closure
139
     */
140 7
    public function getFilter()
141
    {
142 7
        $rootDirectory = $this->rootDirectory;
143 7
        $includePaths = $this->includePaths;
144 7
        $excludePaths = $this->excludePaths;
145
146 7
        return function (SplFileInfo $file) use ($rootDirectory, $includePaths, $excludePaths) {
147
148 7
            if ($file->getExtension() !== 'php') {
149
                return false;
150
            }
151
152 7
            $fullPath = $this->getFileFullPath($file);
153
            // Do not touch files that not under rootDirectory
154 7
            if (strpos($fullPath, $rootDirectory) !== 0) {
155
                return false;
156
            }
157
158 7
            if (!empty($includePaths)) {
159 1
                $found = false;
160 1
                foreach ($includePaths as $includePattern) {
161 1
                    if (fnmatch("{$includePattern}*", $fullPath, FNM_NOESCAPE)) {
162 1
                        $found = true;
163 1
                        break;
164
                    }
165
                }
166 1
                if (!$found) {
167
                    return false;
168
                }
169
            }
170
171 7
            foreach ($excludePaths as $excludePattern) {
172 4
                if (fnmatch("{$excludePattern}*", $fullPath, FNM_NOESCAPE)) {
173 4
                    return false;
174
                }
175
            }
176
177 5
            return true;
178 7
        };
179
    }
180
181
    /**
182
     * Return the real path of the given file
183
     *
184
     * This is used for testing purpose with virtual file system.
185
     * In a vfs the 'realPath' methode will always return false.
186
     * So we have a chance to mock this single function to return different path.
187
     *
188
     * @param SplFileInfo $file
189
     *
190
     * @return string
191
     */
192 1
    protected function getFileFullPath(SplFileInfo $file)
193
    {
194 1
        return $file->getRealPath();
195
    }
196
197
}
198