46 private $prefixLengthsPsr4 = array();
47 private $prefixDirsPsr4 = array();
48 private $fallbackDirsPsr4 = array();
51 private $prefixesPsr0 = array();
52 private $fallbackDirsPsr0 = array();
54 private $useIncludePath =
false;
55 private $classMap = array();
56 private $classMapAuthoritative =
false;
57 private $missingClasses = array();
62 if (!empty($this->prefixesPsr0)) {
63 return call_user_func_array(
'array_merge', $this->prefixesPsr0);
71 return $this->prefixDirsPsr4;
76 return $this->fallbackDirsPsr0;
81 return $this->fallbackDirsPsr4;
86 return $this->classMap;
94 if ($this->classMap) {
95 $this->classMap = array_merge($this->classMap, $classMap);
97 $this->classMap = $classMap;
109 public function add($prefix, $paths, $prepend =
false)
113 $this->fallbackDirsPsr0 = array_merge(
115 $this->fallbackDirsPsr0
118 $this->fallbackDirsPsr0 = array_merge(
119 $this->fallbackDirsPsr0,
128 if (!isset($this->prefixesPsr0[$first][$prefix])) {
129 $this->prefixesPsr0[$first][$prefix] = (array) $paths;
134 $this->prefixesPsr0[$first][$prefix] = array_merge(
136 $this->prefixesPsr0[$first][$prefix]
139 $this->prefixesPsr0[$first][$prefix] = array_merge(
140 $this->prefixesPsr0[$first][$prefix],
156 public function addPsr4($prefix, $paths, $prepend =
false)
161 $this->fallbackDirsPsr4 = array_merge(
163 $this->fallbackDirsPsr4
166 $this->fallbackDirsPsr4 = array_merge(
167 $this->fallbackDirsPsr4,
171 } elseif (!isset($this->prefixDirsPsr4[$prefix])) {
173 $length = strlen($prefix);
174 if (
'\\' !== $prefix[$length - 1]) {
175 throw new \InvalidArgumentException(
"A non-empty PSR-4 prefix must end with a namespace separator.");
177 $this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length;
178 $this->prefixDirsPsr4[$prefix] = (array) $paths;
179 } elseif ($prepend) {
181 $this->prefixDirsPsr4[$prefix] = array_merge(
183 $this->prefixDirsPsr4[$prefix]
187 $this->prefixDirsPsr4[$prefix] = array_merge(
188 $this->prefixDirsPsr4[$prefix],
201 public function set($prefix, $paths)
204 $this->fallbackDirsPsr0 = (array) $paths;
206 $this->prefixesPsr0[$prefix[0]][$prefix] = (array) $paths;
222 $this->fallbackDirsPsr4 = (array) $paths;
224 $length = strlen($prefix);
225 if (
'\\' !== $prefix[$length - 1]) {
226 throw new \InvalidArgumentException(
"A non-empty PSR-4 prefix must end with a namespace separator.");
228 $this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length;
229 $this->prefixDirsPsr4[$prefix] = (array) $paths;
240 $this->useIncludePath = $useIncludePath;
251 return $this->useIncludePath;
262 $this->classMapAuthoritative = $classMapAuthoritative;
272 return $this->classMapAuthoritative;
282 $this->apcuPrefix = function_exists(
'apcu_fetch') && ini_get(
'apc.enabled') ? $apcuPrefix :
null;
292 return $this->apcuPrefix;
300 public function register($prepend =
false)
302 spl_autoload_register(array($this,
'loadClass'),
true, $prepend);
310 spl_autoload_unregister(array($this,
'loadClass'));
321 if ($file = $this->
findFile($class)) {
338 if (isset($this->classMap[$class])) {
339 return $this->classMap[$class];
341 if ($this->classMapAuthoritative || isset($this->missingClasses[$class])) {
344 if (
null !== $this->apcuPrefix) {
345 $file = apcu_fetch($this->apcuPrefix.$class, $hit);
351 $file = $this->findFileWithExtension($class,
'.php');
354 if (
false === $file && defined(
'HHVM_VERSION')) {
355 $file = $this->findFileWithExtension($class,
'.hh');
358 if (
null !== $this->apcuPrefix) {
359 apcu_add($this->apcuPrefix.$class, $file);
362 if (
false === $file) {
364 $this->missingClasses[$class] =
true;
370 private function findFileWithExtension($class, $ext)
373 $logicalPathPsr4 = strtr($class,
'\\', DIRECTORY_SEPARATOR) . $ext;
376 if (isset($this->prefixLengthsPsr4[$first])) {
378 while (
false !== $lastPos = strrpos($subPath,
'\\')) {
379 $subPath = substr($subPath, 0, $lastPos);
380 $search = $subPath .
'\\';
381 if (isset($this->prefixDirsPsr4[$search])) {
382 $pathEnd = DIRECTORY_SEPARATOR . substr($logicalPathPsr4, $lastPos + 1);
383 foreach ($this->prefixDirsPsr4[$search] as $dir) {
384 if (file_exists($file = $dir . $pathEnd)) {
393 foreach ($this->fallbackDirsPsr4 as $dir) {
394 if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr4)) {
400 if (
false !== $pos = strrpos($class,
'\\')) {
402 $logicalPathPsr0 = substr($logicalPathPsr4, 0, $pos + 1)
403 . strtr(substr($logicalPathPsr4, $pos + 1),
'_', DIRECTORY_SEPARATOR);
406 $logicalPathPsr0 = strtr($class,
'_', DIRECTORY_SEPARATOR) . $ext;
409 if (isset($this->prefixesPsr0[$first])) {
410 foreach ($this->prefixesPsr0[$first] as $prefix => $dirs) {
411 if (0 === strpos($class, $prefix)) {
412 foreach ($dirs as $dir) {
413 if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) {
422 foreach ($this->fallbackDirsPsr0 as $dir) {
423 if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) {
429 if ($this->useIncludePath && $file = stream_resolve_include_path($logicalPathPsr0)) {