@@ -77,7 +77,7 @@ public function handleError(array $error, FatalErrorException $exception)
77
77
/**
78
78
* Tries to guess the full namespace for a given class name.
79
79
*
80
- * By default, it looks for PSR-0 classes registered via a Symfony or a Composer
80
+ * By default, it looks for PSR-0 and PSR-4 classes registered via a Symfony or a Composer
81
81
* autoloader (that should cover all common cases).
82
82
*
83
83
* @param string $class A class name (without its namespace)
@@ -101,7 +101,7 @@ private function getClassCandidates($class)
101
101
if ($ function [0 ] instanceof DebugClassLoader) {
102
102
$ function = $ function [0 ]->getClassLoader ();
103
103
104
- // Since 2.5, returning an object from DebugClassLoader::getClassLoader() is @ deprecated
104
+ // @deprecated since version 2.5. Returning an object from DebugClassLoader::getClassLoader() is deprecated.
105
105
if (is_object ($ function )) {
106
106
$ function = array ($ function );
107
107
}
@@ -118,6 +118,13 @@ private function getClassCandidates($class)
118
118
}
119
119
}
120
120
}
121
+ if ($ function [0 ] instanceof ComposerClassLoader) {
122
+ foreach ($ function [0 ]->getPrefixesPsr4 () as $ prefix => $ paths ) {
123
+ foreach ($ paths as $ path ) {
124
+ $ classes = array_merge ($ classes , $ this ->findClassInPath ($ path , $ class , $ prefix ));
125
+ }
126
+ }
127
+ }
121
128
}
122
129
123
130
return array_unique ($ classes );
@@ -132,13 +139,13 @@ private function getClassCandidates($class)
132
139
*/
133
140
private function findClassInPath ($ path , $ class , $ prefix )
134
141
{
135
- if (!$ path = realpath ($ path )) {
142
+ if (!$ path = realpath ($ path. ' / ' . strtr ( $ prefix , '\\ _ ' , ' // ' )) ?: realpath ( $ path . ' / ' . dirname ( strtr ( $ prefix , '\\ _ ' , ' // ' ))) ?: realpath ( $ path )) {
136
143
return array ();
137
144
}
138
145
139
146
$ classes = array ();
140
147
$ filename = $ class .'.php ' ;
141
- foreach (new \RecursiveIteratorIterator (new \RecursiveDirectoryIterator ($ path ), \RecursiveIteratorIterator::LEAVES_ONLY ) as $ file ) {
148
+ foreach (new \RecursiveIteratorIterator (new \RecursiveDirectoryIterator ($ path, \RecursiveDirectoryIterator:: SKIP_DOTS ), \RecursiveIteratorIterator::LEAVES_ONLY ) as $ file ) {
142
149
if ($ filename == $ file ->getFileName () && $ class = $ this ->convertFileToClass ($ path , $ file ->getPathName (), $ prefix )) {
143
150
$ classes [] = $ class ;
144
151
}
@@ -160,13 +167,21 @@ private function convertFileToClass($path, $file, $prefix)
160
167
// namespaced class
161
168
$ namespacedClass = str_replace (array ($ path .DIRECTORY_SEPARATOR , '.php ' , '/ ' ), array ('' , '' , '\\' ), $ file ),
162
169
// namespaced class (with target dir)
163
- $ namespacedClassTargetDir = $ prefix .str_replace (array ($ path .DIRECTORY_SEPARATOR , '.php ' , '/ ' ), array ('' , '' , '\\' ), $ file ),
170
+ $ prefix .$ namespacedClass ,
171
+ // namespaced class (with target dir and separator)
172
+ $ prefix .'\\' .$ namespacedClass ,
164
173
// PEAR class
165
174
str_replace ('\\' , '_ ' , $ namespacedClass ),
166
175
// PEAR class (with target dir)
167
- str_replace ('\\' , '_ ' , $ namespacedClassTargetDir ),
176
+ str_replace ('\\' , '_ ' , $ prefix .$ namespacedClass ),
177
+ // PEAR class (with target dir and separator)
178
+ str_replace ('\\' , '_ ' , $ prefix .'\\' .$ namespacedClass ),
168
179
);
169
180
181
+ if ($ prefix ) {
182
+ $ candidates = array_filter ($ candidates , function ($ candidate ) use ($ prefix ) {return 0 === strpos ($ candidate , $ prefix );});
183
+ }
184
+
170
185
// We cannot use the autoloader here as most of them use require; but if the class
171
186
// is not found, the new autoloader call will require the file again leading to a
172
187
// "cannot redeclare class" error.
0 commit comments