1: <?php
2:
3: 4: 5: 6: 7: 8: 9: 10: 11:
12:
13: namespace Composer\Autoload;
14:
15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42:
43: class ClassLoader
44: {
45:
46: private $prefixLengthsPsr4 = array();
47: private $prefixDirsPsr4 = array();
48: private $fallbackDirsPsr4 = array();
49:
50:
51: private $prefixesPsr0 = array();
52: private $fallbackDirsPsr0 = array();
53:
54: private $useIncludePath = false;
55: private $classMap = array();
56:
57: public function getPrefixes()
58: {
59: if (!empty($this->prefixesPsr0)) {
60: return call_user_func_array('array_merge', $this->prefixesPsr0);
61: }
62:
63: return array();
64: }
65:
66: public function getPrefixesPsr4()
67: {
68: return $this->prefixDirsPsr4;
69: }
70:
71: public function getFallbackDirs()
72: {
73: return $this->fallbackDirsPsr0;
74: }
75:
76: public function getFallbackDirsPsr4()
77: {
78: return $this->fallbackDirsPsr4;
79: }
80:
81: public function getClassMap()
82: {
83: return $this->classMap;
84: }
85:
86: 87: 88:
89: public function addClassMap(array $classMap)
90: {
91: if ($this->classMap) {
92: $this->classMap = array_merge($this->classMap, $classMap);
93: } else {
94: $this->classMap = $classMap;
95: }
96: }
97:
98: 99: 100: 101: 102: 103: 104: 105:
106: public function add($prefix, $paths, $prepend = false)
107: {
108: if (!$prefix) {
109: if ($prepend) {
110: $this->fallbackDirsPsr0 = array_merge(
111: (array) $paths,
112: $this->fallbackDirsPsr0
113: );
114: } else {
115: $this->fallbackDirsPsr0 = array_merge(
116: $this->fallbackDirsPsr0,
117: (array) $paths
118: );
119: }
120:
121: return;
122: }
123:
124: $first = $prefix[0];
125: if (!isset($this->prefixesPsr0[$first][$prefix])) {
126: $this->prefixesPsr0[$first][$prefix] = (array) $paths;
127:
128: return;
129: }
130: if ($prepend) {
131: $this->prefixesPsr0[$first][$prefix] = array_merge(
132: (array) $paths,
133: $this->prefixesPsr0[$first][$prefix]
134: );
135: } else {
136: $this->prefixesPsr0[$first][$prefix] = array_merge(
137: $this->prefixesPsr0[$first][$prefix],
138: (array) $paths
139: );
140: }
141: }
142:
143: 144: 145: 146: 147: 148: 149: 150: 151: 152:
153: public function addPsr4($prefix, $paths, $prepend = false)
154: {
155: if (!$prefix) {
156:
157: if ($prepend) {
158: $this->fallbackDirsPsr4 = array_merge(
159: (array) $paths,
160: $this->fallbackDirsPsr4
161: );
162: } else {
163: $this->fallbackDirsPsr4 = array_merge(
164: $this->fallbackDirsPsr4,
165: (array) $paths
166: );
167: }
168: } elseif (!isset($this->prefixDirsPsr4[$prefix])) {
169:
170: $length = strlen($prefix);
171: if ('\\' !== $prefix[$length - 1]) {
172: throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator.");
173: }
174: $this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length;
175: $this->prefixDirsPsr4[$prefix] = (array) $paths;
176: } elseif ($prepend) {
177:
178: $this->prefixDirsPsr4[$prefix] = array_merge(
179: (array) $paths,
180: $this->prefixDirsPsr4[$prefix]
181: );
182: } else {
183:
184: $this->prefixDirsPsr4[$prefix] = array_merge(
185: $this->prefixDirsPsr4[$prefix],
186: (array) $paths
187: );
188: }
189: }
190:
191: 192: 193: 194: 195: 196: 197:
198: public function set($prefix, $paths)
199: {
200: if (!$prefix) {
201: $this->fallbackDirsPsr0 = (array) $paths;
202: } else {
203: $this->prefixesPsr0[$prefix[0]][$prefix] = (array) $paths;
204: }
205: }
206:
207: 208: 209: 210: 211: 212: 213: 214: 215:
216: public function setPsr4($prefix, $paths)
217: {
218: if (!$prefix) {
219: $this->fallbackDirsPsr4 = (array) $paths;
220: } else {
221: $length = strlen($prefix);
222: if ('\\' !== $prefix[$length - 1]) {
223: throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator.");
224: }
225: $this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length;
226: $this->prefixDirsPsr4[$prefix] = (array) $paths;
227: }
228: }
229:
230: 231: 232: 233: 234:
235: public function setUseIncludePath($useIncludePath)
236: {
237: $this->useIncludePath = $useIncludePath;
238: }
239:
240: 241: 242: 243: 244: 245:
246: public function getUseIncludePath()
247: {
248: return $this->useIncludePath;
249: }
250:
251: 252: 253: 254: 255:
256: public function register($prepend = false)
257: {
258: spl_autoload_register(array($this, 'loadClass'), true, $prepend);
259: }
260:
261: 262: 263:
264: public function unregister()
265: {
266: spl_autoload_unregister(array($this, 'loadClass'));
267: }
268:
269: 270: 271: 272: 273: 274:
275: public function loadClass($class)
276: {
277: if ($file = $this->findFile($class)) {
278: includeFile($file);
279:
280: return true;
281: }
282: }
283:
284: 285: 286: 287: 288: 289: 290:
291: public function findFile($class)
292: {
293:
294: if ('\\' == $class[0]) {
295: $class = substr($class, 1);
296: }
297:
298:
299: if (isset($this->classMap[$class])) {
300: return $this->classMap[$class];
301: }
302:
303: $file = $this->findFileWithExtension($class, '.php');
304:
305:
306: if ($file === null && defined('HHVM_VERSION')) {
307: $file = $this->findFileWithExtension($class, '.hh');
308: }
309:
310: if ($file === null) {
311:
312: return $this->classMap[$class] = false;
313: }
314:
315: return $file;
316: }
317:
318: private function findFileWithExtension($class, $ext)
319: {
320:
321: $logicalPathPsr4 = strtr($class, '\\', DIRECTORY_SEPARATOR) . $ext;
322:
323: $first = $class[0];
324: if (isset($this->prefixLengthsPsr4[$first])) {
325: foreach ($this->prefixLengthsPsr4[$first] as $prefix => $length) {
326: if (0 === strpos($class, $prefix)) {
327: foreach ($this->prefixDirsPsr4[$prefix] as $dir) {
328: if (file_exists($file = $dir . DIRECTORY_SEPARATOR . substr($logicalPathPsr4, $length))) {
329: return $file;
330: }
331: }
332: }
333: }
334: }
335:
336:
337: foreach ($this->fallbackDirsPsr4 as $dir) {
338: if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr4)) {
339: return $file;
340: }
341: }
342:
343:
344: if (false !== $pos = strrpos($class, '\\')) {
345:
346: $logicalPathPsr0 = substr($logicalPathPsr4, 0, $pos + 1)
347: . strtr(substr($logicalPathPsr4, $pos + 1), '_', DIRECTORY_SEPARATOR);
348: } else {
349:
350: $logicalPathPsr0 = strtr($class, '_', DIRECTORY_SEPARATOR) . $ext;
351: }
352:
353: if (isset($this->prefixesPsr0[$first])) {
354: foreach ($this->prefixesPsr0[$first] as $prefix => $dirs) {
355: if (0 === strpos($class, $prefix)) {
356: foreach ($dirs as $dir) {
357: if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) {
358: return $file;
359: }
360: }
361: }
362: }
363: }
364:
365:
366: foreach ($this->fallbackDirsPsr0 as $dir) {
367: if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) {
368: return $file;
369: }
370: }
371:
372:
373: if ($this->useIncludePath && $file = stream_resolve_include_path($logicalPathPsr0)) {
374: return $file;
375: }
376: }
377: }
378:
379: 380: 381: 382: 383:
384: function includeFile($file)
385: {
386: include $file;
387: }
388: