1: <?php namespace Laravel;
2:
3: class Autoloader {
4:
5: /**
6: * The mappings from class names to file paths.
7: *
8: * @var array
9: */
10: public static $mappings = array();
11:
12: /**
13: * The directories that use the PSR-0 naming convention.
14: *
15: * @var array
16: */
17: public static $directories = array();
18:
19: /**
20: * The mappings for namespaces to directories.
21: *
22: * @var array
23: */
24: public static $namespaces = array();
25:
26: /**
27: * The mappings for underscored libraries to directories.
28: *
29: * @var array
30: */
31: public static $underscored = array();
32:
33: /**
34: * All of the class aliases registered with the auto-loader.
35: *
36: * @var array
37: */
38: public static $aliases = array();
39:
40: /**
41: * Load the file corresponding to a given class.
42: *
43: * This method is registered in the bootstrap file as an SPL auto-loader.
44: *
45: * @param string $class
46: * @return void
47: */
48: public static function load($class)
49: {
50: // First, we will check to see if the class has been aliased. If it has,
51: // we will register the alias, which may cause the auto-loader to be
52: // called again for the "real" class name to load its file.
53: if (isset(static::$aliases[$class]))
54: {
55: return class_alias(static::$aliases[$class], $class);
56: }
57:
58: // All classes in Laravel are statically mapped. There is no crazy search
59: // routine that digs through directories. It's just a simple array of
60: // class to file path maps for ultra-fast file loading.
61: elseif (isset(static::$mappings[$class]))
62: {
63: require static::$mappings[$class];
64:
65: return;
66: }
67:
68: // If the class namespace is mapped to a directory, we will load the
69: // class using the PSR-0 standards from that directory accounting
70: // for the root of the namespace by trimming it off.
71: foreach (static::$namespaces as $namespace => $directory)
72: {
73: if (starts_with($class, $namespace))
74: {
75: return static::load_namespaced($class, $namespace, $directory);
76: }
77: }
78:
79: static::load_psr($class);
80: }
81:
82: /**
83: * Load a namespaced class from a given directory.
84: *
85: * @param string $class
86: * @param string $namespace
87: * @param string $directory
88: * @return void
89: */
90: protected static function load_namespaced($class, $namespace, $directory)
91: {
92: return static::load_psr(substr($class, strlen($namespace)), $directory);
93: }
94:
95: /**
96: * Attempt to resolve a class using the PSR-0 standard.
97: *
98: * @param string $class
99: * @param string $directory
100: * @return void
101: */
102: protected static function load_psr($class, $directory = null)
103: {
104: // The PSR-0 standard indicates that class namespaces and underscores
105: // should be used to indicate the directory tree in which the class
106: // resides, so we'll convert them to slashes.
107: $file = str_replace(array('\\', '_'), '/', $class);
108:
109: $directories = $directory ?: static::$directories;
110:
111: $lower = strtolower($file);
112:
113: // Once we have formatted the class name, we'll simply spin through
114: // the registered PSR-0 directories and attempt to locate and load
115: // the class file into the script.
116: foreach ((array) $directories as $directory)
117: {
118: if (file_exists($path = $directory.$lower.EXT))
119: {
120: return require $path;
121: }
122: elseif (file_exists($path = $directory.$file.EXT))
123: {
124: return require $path;
125: }
126: }
127: }
128:
129: /**
130: * Register an array of class to path mappings.
131: *
132: * @param array $mappings
133: * @return void
134: */
135: public static function map($mappings)
136: {
137: static::$mappings = array_merge(static::$mappings, $mappings);
138: }
139:
140: /**
141: * Register a class alias with the auto-loader.
142: *
143: * @param string $class
144: * @param string $alias
145: * @return void
146: */
147: public static function alias($class, $alias)
148: {
149: static::$aliases[$alias] = $class;
150: }
151:
152: /**
153: * Register directories to be searched as a PSR-0 library.
154: *
155: * @param string|array $directory
156: * @return void
157: */
158: public static function directories($directory)
159: {
160: $directories = static::format($directory);
161:
162: static::$directories = array_unique(array_merge(static::$directories, $directories));
163: }
164:
165: /**
166: * Map namespaces to directories.
167: *
168: * @param array $mappings
169: * @param string $append
170: * @return void
171: */
172: public static function namespaces($mappings, $append = '\\')
173: {
174: $mappings = static::format_mappings($mappings, $append);
175:
176: static::$namespaces = array_merge($mappings, static::$namespaces);
177: }
178:
179: /**
180: * Register underscored "namespaces" to directory mappings.
181: *
182: * @param array $mappings
183: * @return void
184: */
185: public static function underscored($mappings)
186: {
187: static::namespaces($mappings, '_');
188: }
189:
190: /**
191: * Format an array of namespace to directory mappings.
192: *
193: * @param array $mappings
194: * @param string $append
195: * @return array
196: */
197: protected static function format_mappings($mappings, $append)
198: {
199: foreach ($mappings as $namespace => $directory)
200: {
201: // When adding new namespaces to the mappings, we will unset the previously
202: // mapped value if it existed. This allows previously registered spaces to
203: // be mapped to new directories on the fly.
204: $namespace = trim($namespace, $append).$append;
205:
206: unset(static::$namespaces[$namespace]);
207:
208: $namespaces[$namespace] = head(static::format($directory));
209: }
210:
211: return $namespaces;
212: }
213:
214: /**
215: * Format an array of directories with the proper trailing slashes.
216: *
217: * @param array $directories
218: * @return array
219: */
220: protected static function format($directories)
221: {
222: return array_map(function($directory)
223: {
224: return rtrim($directory, DS).DS;
225:
226: }, (array) $directories);
227: }
228:
229: }