1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
namespace Doctrine\Persistence\Mapping\Driver; |
4
|
|
|
|
5
|
|
|
use Doctrine\Persistence\Mapping\MappingException; |
6
|
|
|
use InvalidArgumentException; |
7
|
|
|
use RecursiveDirectoryIterator; |
8
|
|
|
use RecursiveIteratorIterator; |
9
|
|
|
use const DIRECTORY_SEPARATOR; |
10
|
|
|
use function array_keys; |
11
|
|
|
use function array_merge; |
12
|
|
|
use function is_dir; |
13
|
|
|
use function is_file; |
14
|
|
|
use function realpath; |
15
|
|
|
use function str_replace; |
16
|
|
|
use function strlen; |
17
|
|
|
use function strpos; |
18
|
|
|
use function strrpos; |
19
|
|
|
use function strtr; |
20
|
|
|
use function substr; |
21
|
|
|
|
22
|
|
|
/** |
23
|
|
|
* The Symfony File Locator makes a simplifying assumptions compared |
24
|
|
|
* to the DefaultFileLocator. By assuming paths only contain entities of a certain |
25
|
|
|
* namespace the mapping files consists of the short classname only. |
26
|
|
|
*/ |
27
|
|
|
class SymfonyFileLocator implements FileLocator |
28
|
|
|
{ |
29
|
|
|
/** |
30
|
|
|
* The paths where to look for mapping files. |
31
|
|
|
* |
32
|
|
|
* @var string[] |
33
|
|
|
*/ |
34
|
|
|
protected $paths = []; |
35
|
|
|
|
36
|
|
|
/** |
37
|
|
|
* A map of mapping directory path to namespace prefix used to expand class shortnames. |
38
|
|
|
* |
39
|
|
|
* @var string[] |
40
|
|
|
*/ |
41
|
|
|
protected $prefixes = []; |
42
|
|
|
|
43
|
|
|
/** |
44
|
|
|
* File extension that is searched for. |
45
|
|
|
* |
46
|
|
|
* @var string|null |
47
|
|
|
*/ |
48
|
|
|
protected $fileExtension; |
49
|
|
|
|
50
|
|
|
/** |
51
|
|
|
* Represents PHP namespace delimiters when looking for files |
52
|
|
|
* |
53
|
|
|
* @var string |
54
|
|
|
*/ |
55
|
|
|
private $nsSeparator; |
56
|
|
|
|
57
|
|
|
/** |
58
|
|
|
* @param string[] $prefixes |
59
|
|
|
* @param string|null $fileExtension |
60
|
|
|
* @param string $nsSeparator String which would be used when converting FQCN to filename and vice versa. Should not be empty |
61
|
|
|
*/ |
62
|
14 |
|
public function __construct(array $prefixes, $fileExtension = null, $nsSeparator = '.') |
63
|
|
|
{ |
64
|
14 |
|
$this->addNamespacePrefixes($prefixes); |
65
|
14 |
|
$this->fileExtension = $fileExtension; |
66
|
|
|
|
67
|
14 |
|
if (empty($nsSeparator)) { |
68
|
1 |
|
throw new InvalidArgumentException('Namespace separator should not be empty'); |
69
|
|
|
} |
70
|
|
|
|
71
|
13 |
|
$this->nsSeparator = (string) $nsSeparator; |
72
|
13 |
|
} |
73
|
|
|
|
74
|
|
|
/** |
75
|
|
|
* Adds Namespace Prefixes. |
76
|
|
|
* |
77
|
|
|
* @param string[] $prefixes |
78
|
|
|
* |
79
|
|
|
* @return void |
80
|
|
|
*/ |
81
|
14 |
|
public function addNamespacePrefixes(array $prefixes) |
82
|
|
|
{ |
83
|
14 |
|
$this->prefixes = array_merge($this->prefixes, $prefixes); |
84
|
14 |
|
$this->paths = array_merge($this->paths, array_keys($prefixes)); |
85
|
14 |
|
} |
86
|
|
|
|
87
|
|
|
/** |
88
|
|
|
* Gets Namespace Prefixes. |
89
|
|
|
* |
90
|
|
|
* @return string[] |
91
|
|
|
*/ |
92
|
1 |
|
public function getNamespacePrefixes() |
93
|
|
|
{ |
94
|
1 |
|
return $this->prefixes; |
95
|
|
|
} |
96
|
|
|
|
97
|
|
|
/** |
98
|
|
|
* {@inheritDoc} |
99
|
|
|
*/ |
100
|
1 |
|
public function getPaths() |
101
|
|
|
{ |
102
|
1 |
|
return $this->paths; |
103
|
|
|
} |
104
|
|
|
|
105
|
|
|
/** |
106
|
|
|
* {@inheritDoc} |
107
|
|
|
*/ |
108
|
1 |
|
public function getFileExtension() |
109
|
|
|
{ |
110
|
1 |
|
return $this->fileExtension; |
111
|
|
|
} |
112
|
|
|
|
113
|
|
|
/** |
114
|
|
|
* Sets the file extension used to look for mapping files under. |
115
|
|
|
* |
116
|
|
|
* @param string $fileExtension The file extension to set. |
117
|
|
|
* |
118
|
|
|
* @return void |
119
|
|
|
*/ |
120
|
1 |
|
public function setFileExtension($fileExtension) |
121
|
|
|
{ |
122
|
1 |
|
$this->fileExtension = $fileExtension; |
123
|
1 |
|
} |
124
|
|
|
|
125
|
|
|
/** |
126
|
|
|
* {@inheritDoc} |
127
|
|
|
*/ |
128
|
1 |
|
public function fileExists($className) |
129
|
|
|
{ |
130
|
1 |
|
$defaultFileName = str_replace('\\', $this->nsSeparator, $className) . $this->fileExtension; |
131
|
1 |
|
foreach ($this->paths as $path) { |
132
|
1 |
|
if (! isset($this->prefixes[$path])) { |
133
|
|
|
// global namespace class |
134
|
|
|
if (is_file($path . DIRECTORY_SEPARATOR . $defaultFileName)) { |
135
|
|
|
return true; |
136
|
|
|
} |
137
|
|
|
|
138
|
|
|
continue; |
139
|
|
|
} |
140
|
|
|
|
141
|
1 |
|
$prefix = $this->prefixes[$path]; |
142
|
|
|
|
143
|
1 |
|
if (strpos($className, $prefix . '\\') !== 0) { |
144
|
|
|
continue; |
145
|
|
|
} |
146
|
|
|
|
147
|
1 |
|
$filename = $path . '/' . strtr(substr($className, strlen($prefix) + 1), '\\', $this->nsSeparator) . $this->fileExtension; |
148
|
1 |
|
if (is_file($filename)) { |
149
|
1 |
|
return true; |
150
|
|
|
} |
151
|
|
|
} |
152
|
|
|
|
153
|
1 |
|
return false; |
154
|
|
|
} |
155
|
|
|
|
156
|
|
|
/** |
157
|
|
|
* {@inheritDoc} |
158
|
|
|
*/ |
159
|
3 |
|
public function getAllClassNames($globalBasename = null) |
160
|
|
|
{ |
161
|
3 |
|
$classes = []; |
162
|
|
|
|
163
|
3 |
|
if ($this->paths) { |
|
|
|
|
164
|
3 |
|
foreach ((array) $this->paths as $path) { |
165
|
3 |
|
if (! is_dir($path)) { |
166
|
|
|
throw MappingException::fileMappingDriversRequireConfiguredDirectoryPath($path); |
167
|
|
|
} |
168
|
|
|
|
169
|
3 |
|
$iterator = new RecursiveIteratorIterator( |
170
|
3 |
|
new RecursiveDirectoryIterator($path), |
171
|
3 |
|
RecursiveIteratorIterator::LEAVES_ONLY |
172
|
|
|
); |
173
|
|
|
|
174
|
3 |
|
foreach ($iterator as $file) { |
175
|
3 |
|
$fileName = $file->getBasename($this->fileExtension); |
176
|
|
|
|
177
|
3 |
|
if ($fileName === $file->getBasename() || $fileName === $globalBasename) { |
178
|
3 |
|
continue; |
179
|
|
|
} |
180
|
|
|
|
181
|
|
|
// NOTE: All files found here means classes are not transient! |
182
|
3 |
|
if (isset($this->prefixes[$path])) { |
183
|
|
|
// Calculate namespace suffix for given prefix as a relative path from basepath to file path |
184
|
3 |
|
$nsSuffix = strtr( |
185
|
3 |
|
substr(realpath($file->getPath()), strlen(realpath($path))), |
186
|
3 |
|
$this->nsSeparator, |
187
|
3 |
|
'\\' |
188
|
|
|
); |
189
|
|
|
|
190
|
3 |
|
$classes[] = $this->prefixes[$path] . str_replace(DIRECTORY_SEPARATOR, '\\', $nsSuffix) . '\\' . str_replace($this->nsSeparator, '\\', $fileName); |
191
|
|
|
} else { |
192
|
3 |
|
$classes[] = str_replace($this->nsSeparator, '\\', $fileName); |
193
|
|
|
} |
194
|
|
|
} |
195
|
|
|
} |
196
|
|
|
} |
197
|
|
|
|
198
|
3 |
|
return $classes; |
199
|
|
|
} |
200
|
|
|
|
201
|
|
|
/** |
202
|
|
|
* {@inheritDoc} |
203
|
|
|
*/ |
204
|
6 |
|
public function findMappingFile($className) |
205
|
|
|
{ |
206
|
6 |
|
$defaultFileName = str_replace('\\', $this->nsSeparator, $className) . $this->fileExtension; |
207
|
6 |
|
foreach ($this->paths as $path) { |
208
|
6 |
|
if (! isset($this->prefixes[$path])) { |
209
|
|
|
if (is_file($path . DIRECTORY_SEPARATOR . $defaultFileName)) { |
210
|
|
|
return $path . DIRECTORY_SEPARATOR . $defaultFileName; |
211
|
|
|
} |
212
|
|
|
|
213
|
|
|
continue; |
214
|
|
|
} |
215
|
|
|
|
216
|
6 |
|
$prefix = $this->prefixes[$path]; |
217
|
|
|
|
218
|
6 |
|
if (strpos($className, $prefix . '\\') !== 0) { |
219
|
|
|
continue; |
220
|
|
|
} |
221
|
|
|
|
222
|
6 |
|
$filename = $path . '/' . strtr(substr($className, strlen($prefix) + 1), '\\', $this->nsSeparator) . $this->fileExtension; |
223
|
6 |
|
if (is_file($filename)) { |
224
|
6 |
|
return $filename; |
225
|
|
|
} |
226
|
|
|
} |
227
|
|
|
|
228
|
1 |
|
throw MappingException::mappingFileNotFound($className, substr($className, strrpos($className, '\\') + 1) . $this->fileExtension); |
229
|
|
|
} |
230
|
|
|
} |
231
|
|
|
|
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.