1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
/* |
4
|
|
|
* This file is part of the Yosymfony config-loader. |
5
|
|
|
* |
6
|
|
|
* (c) YoSymfony <http://github.com/yosymfony> |
7
|
|
|
* |
8
|
|
|
* For the full copyright and license information, please view the LICENSE |
9
|
|
|
* file that was distributed with this source code. |
10
|
|
|
*/ |
11
|
|
|
|
12
|
|
|
namespace Yosymfony\ConfigLoader; |
13
|
|
|
|
14
|
|
|
use Yosymfony\ConfigLoader\Exception\FileNotFoundException; |
15
|
|
|
|
16
|
|
|
/** |
17
|
|
|
* FileLocator uses an array of pre-defined paths to find files |
18
|
|
|
* |
19
|
|
|
* This file is based on Symfony FileLocatorInterface (Config component) |
20
|
|
|
* Created by Fabien Potencier <[email protected]>. |
21
|
|
|
* |
22
|
|
|
* @author Victor Puertas <[email protected]> |
23
|
|
|
*/ |
24
|
|
|
class FileLocator implements FileLocatorInterface |
25
|
|
|
{ |
26
|
|
|
/** @var array */ |
27
|
|
|
protected $paths; |
28
|
|
|
|
29
|
|
|
/** |
30
|
|
|
* @param string[] $paths An array of paths where to look for resources |
31
|
|
|
*/ |
32
|
|
|
public function __construct(array $paths = []) |
33
|
|
|
{ |
34
|
|
|
$this->paths = $paths; |
35
|
|
|
} |
36
|
|
|
|
37
|
|
|
/** |
38
|
|
|
* {@inheritdoc} |
39
|
|
|
*/ |
40
|
|
|
public function locate(string $name, string $currentPath = null) : array |
41
|
|
|
{ |
42
|
|
|
return $this->locateFile($name, $currentPath, false); |
43
|
|
|
} |
44
|
|
|
|
45
|
|
|
/** |
46
|
|
|
* {@inheritdoc} |
47
|
|
|
*/ |
48
|
|
|
public function locateFirst(string $name, string $currentPath = null) : string |
49
|
|
|
{ |
50
|
|
|
return $this->locateFile($name, $currentPath, true); |
51
|
|
|
} |
52
|
|
|
|
53
|
|
|
/** |
54
|
|
|
* @return string|array |
55
|
|
|
*/ |
56
|
|
|
protected function locateFile(string $name, string $currentPath = null, bool $first) |
57
|
|
|
{ |
58
|
|
|
if ($name == '') { |
59
|
|
|
throw new \InvalidArgumentException('An empty file name is not valid to be located.'); |
60
|
|
|
} |
61
|
|
|
|
62
|
|
|
if ($this->isAbsolutePath($name)) { |
63
|
|
|
if (!file_exists($name)) { |
64
|
|
|
$this->throwFileNotFoundException($name); |
65
|
|
|
} |
66
|
|
|
|
67
|
|
|
return $name; |
68
|
|
|
} |
69
|
|
|
|
70
|
|
|
$paths = $this->paths; |
71
|
|
|
|
72
|
|
|
if ($currentPath !== null) { |
73
|
|
|
array_unshift($paths, $currentPath); |
74
|
|
|
} |
75
|
|
|
|
76
|
|
|
$paths = array_unique($paths); |
77
|
|
|
$filepaths = $notfound = []; |
78
|
|
|
|
79
|
|
|
foreach ($paths as $path) { |
80
|
|
|
if (@file_exists($file = $path.DIRECTORY_SEPARATOR.$name)) { |
81
|
|
|
if ($first) { |
82
|
|
|
return $file; |
83
|
|
|
} |
84
|
|
|
$filepaths[] = $file; |
85
|
|
|
} else { |
86
|
|
|
$notfound[] = $file; |
87
|
|
|
} |
88
|
|
|
} |
89
|
|
|
|
90
|
|
|
if (!$filepaths) { |
|
|
|
|
91
|
|
|
$this->throwFileNotFoundException($name, $paths, $notfound); |
92
|
|
|
} |
93
|
|
|
|
94
|
|
|
return $filepaths; |
95
|
|
|
} |
96
|
|
|
|
97
|
|
|
protected function isAbsolutePath(string $file) : bool |
98
|
|
|
{ |
99
|
|
|
if ('/' === $file[0] || '\\' === $file[0] |
100
|
|
|
|| ( |
101
|
|
|
strlen($file) > 3 && ctype_alpha($file[0]) |
102
|
|
|
&& ':' === $file[1] |
103
|
|
|
&& ('\\' === $file[2] || '/' === $file[2]) |
104
|
|
|
) |
105
|
|
|
|| null !== parse_url($file, PHP_URL_SCHEME) |
106
|
|
|
) { |
107
|
|
|
return true; |
108
|
|
|
} |
109
|
|
|
|
110
|
|
|
return false; |
111
|
|
|
} |
112
|
|
|
|
113
|
|
|
private function throwFileNotFoundException(string $file, array $paths = [], array $notFoundPaths = []) : void |
114
|
|
|
{ |
115
|
|
|
$message = "The file \"{$file}\" does not exist"; |
116
|
|
|
|
117
|
|
|
if (\count($paths) === 0) { |
118
|
|
|
$notFoundPaths[] = $file; |
119
|
|
|
} else { |
120
|
|
|
$pathsJoined = implode(', ', $paths); |
121
|
|
|
$message .= " in: {$pathsJoined}"; |
122
|
|
|
} |
123
|
|
|
|
124
|
|
|
$message .= '.'; |
125
|
|
|
|
126
|
|
|
throw new FileNotFoundException($message, 0, null, $notFoundPaths); |
127
|
|
|
} |
128
|
|
|
} |
129
|
|
|
|
This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.
Consider making the comparison explicit by using
empty(..)
or! empty(...)
instead.