/web/fuel/core/classes/autoloader.php

https://github.com/leonardteo/INSE6530 · PHP · 325 lines · 173 code · 32 blank · 120 comment · 18 complexity · 84b93a84a7c4496680353c64a1713928 MD5 · raw file

  1. <?php
  2. /**
  3. * Fuel is a fast, lightweight, community driven PHP5 framework.
  4. *
  5. * @package Fuel
  6. * @version 1.0
  7. * @author Fuel Development Team
  8. * @license MIT License
  9. * @copyright 2010 - 2011 Fuel Development Team
  10. * @link http://fuelphp.com
  11. */
  12. /**
  13. * The Autloader is responsible for all class loading. It allows you to define
  14. * different load paths based on namespaces. It also lets you set explicit paths
  15. * for classes to be loaded from.
  16. *
  17. * @package Fuel
  18. * @subpackage Core
  19. */
  20. class Autoloader {
  21. /**
  22. * @var array $classes holds all the classes and paths
  23. */
  24. protected static $classes = array();
  25. /**
  26. * @var array holds all the namespace paths
  27. */
  28. protected static $namespaces = array();
  29. /**
  30. * Holds all the PSR-0 compliant namespaces. These namespaces should
  31. * be loaded according to the PSR-0 standard.
  32. *
  33. * @var array
  34. */
  35. protected static $psr_namespaces = array();
  36. /**
  37. * @var array list off namespaces of which classes will be aliased to global namespace
  38. */
  39. protected static $core_namespaces = array('Fuel\\Core');
  40. /**
  41. * @var array the default path to look in if the class is not in a package
  42. */
  43. protected static $default_path = null;
  44. /**
  45. * @var bool whether to initialize a loaded class
  46. */
  47. protected static $auto_initialize = null;
  48. /**
  49. * Adds a namespace search path. Any class in the given namespace will be
  50. * looked for in the given path.
  51. *
  52. * @param string the namespace
  53. * @param string the path
  54. * @return void
  55. */
  56. public static function add_namespace($namespace, $path, $psr = false)
  57. {
  58. static::$namespaces[$namespace] = $path;
  59. if ($psr)
  60. {
  61. static::$psr_namespaces[$namespace] = $path;
  62. }
  63. }
  64. /**
  65. * Adds an array of namespace paths. See {add_namespace}.
  66. *
  67. * @param array the namespaces
  68. * @param bool whether to prepend the namespace to the search path
  69. * @return void
  70. */
  71. public static function add_namespaces(array $namespaces, $prepend = false)
  72. {
  73. if ( ! $prepend)
  74. {
  75. static::$namespaces = array_merge(static::$namespaces, $namespaces);
  76. }
  77. else
  78. {
  79. static::$namespaces = $namespaces + static::$namespaces;
  80. }
  81. }
  82. /**
  83. * Returns the namespace's path or false when it doesn't exist.
  84. *
  85. * @param string the namespace to get the path for
  86. * @return array|bool the namespace path or false
  87. */
  88. public static function namespace_path($namespace)
  89. {
  90. if ( ! array_key_exists($namespace, static::$namespaces))
  91. {
  92. return false;
  93. }
  94. return static::$namespaces[$namespace];
  95. }
  96. /**
  97. * Adds a classes load path. Any class added here will not be searched for
  98. * but explicitly loaded from the path.
  99. *
  100. * @param string the class name
  101. * @param string the path to the class file
  102. * @return void
  103. */
  104. public static function add_class($class, $path)
  105. {
  106. static::$classes[$class] = $path;
  107. }
  108. /**
  109. * Adds multiple class paths to the load path. See {@see Autoloader::add_class}.
  110. *
  111. * @param array the class names and paths
  112. * @return void
  113. */
  114. public static function add_classes($classes)
  115. {
  116. foreach ($classes as $class => $path)
  117. {
  118. static::$classes[$class] = $path;
  119. }
  120. }
  121. /**
  122. * Aliases the given class into the given Namespace. By default it will
  123. * add it to the global namespace.
  124. *
  125. * <code>
  126. * Autoloader::alias_to_namespace('Foo\\Bar');
  127. * Autoloader::alias_to_namespace('Foo\\Bar', '\\Baz');
  128. * </code>
  129. *
  130. * @param string $class the class name
  131. * @param string $namespace the namespace to alias to
  132. */
  133. public static function alias_to_namespace($class, $namespace = '')
  134. {
  135. ! empty($namespace) and $namespace = rtrim($namespace, '\\').'\\';
  136. $parts = explode('\\', $class);
  137. $root_class = $namespace.array_pop($parts);
  138. class_alias($class, $root_class);
  139. }
  140. /**
  141. * Register's the autoloader to the SPL autoload stack.
  142. *
  143. * @return void
  144. */
  145. public static function register()
  146. {
  147. spl_autoload_register('Autoloader::load', true, true);
  148. }
  149. /**
  150. * Returns the class with namespace prefix when available
  151. *
  152. * @param string
  153. * @return bool|string
  154. */
  155. protected static function is_core_class($class)
  156. {
  157. foreach (static::$core_namespaces as $ns)
  158. {
  159. if (array_key_exists($ns_class = $ns.'\\'.$class, static::$classes))
  160. {
  161. return $ns_class;
  162. }
  163. }
  164. return false;
  165. }
  166. /**
  167. * Add a namespace for which classes may be used without the namespace prefix and
  168. * will be auto-aliased to the global namespace.
  169. * Prefixing the classes will overwrite core classes and previously added namespaces.
  170. *
  171. * @param string
  172. * @param bool
  173. * @return void
  174. */
  175. public static function add_core_namespace($namespace, $prefix = true)
  176. {
  177. if ($prefix)
  178. {
  179. array_unshift(static::$core_namespaces, $namespace);
  180. }
  181. else
  182. {
  183. array_push(static::$core_namespaces, $namespace);
  184. }
  185. }
  186. public static function load($class)
  187. {
  188. $loaded = false;
  189. $class = ltrim($class, '\\');
  190. $namespaced = ($pos = strripos($class, '\\')) !== false;
  191. if (empty(static::$auto_initialize))
  192. {
  193. static::$auto_initialize = $class;
  194. }
  195. if (array_key_exists($class, static::$classes))
  196. {
  197. include str_replace('/', DS, static::$classes[$class]);
  198. static::_init_class($class);
  199. $loaded = true;
  200. }
  201. elseif ( ! $namespaced and $class_name = static::is_core_class($class))
  202. {
  203. ! class_exists($class_name, false) and include str_replace('/', DS, static::$classes[$class_name]);
  204. static::alias_to_namespace($class_name);
  205. static::_init_class($class);
  206. $loaded = true;
  207. }
  208. elseif ( ! $namespaced)
  209. {
  210. $file_path = str_replace('_', DS, $class);
  211. $file_path = APPPATH.'classes/'.strtolower($file_path).'.php';
  212. if (file_exists($file_path))
  213. {
  214. require $file_path;
  215. if ( ! class_exists($class, false) and class_exists($class_name = 'Fuel\\Core\\'.$class, false))
  216. {
  217. static::alias_to_namespace($class_name);
  218. }
  219. static::_init_class($class);
  220. $loaded = true;
  221. }
  222. }
  223. // This handles a namespaces class that a path does not exist for
  224. else
  225. {
  226. $namespace = substr($class, 0, $pos);
  227. foreach (static::$namespaces as $ns => $path)
  228. {
  229. $ns = ltrim($ns, '\\');
  230. if (strncasecmp($ns, $namespace, strlen($ns)) === 0)
  231. {
  232. if (array_key_exists($ns, static::$psr_namespaces))
  233. {
  234. static::psr_loader($path, $class);
  235. return true;
  236. }
  237. $class_no_ns = substr($class, $pos + 1);
  238. $sub_namespace = (strlen($namespace) == strlen($ns)) ? '' : substr($namespace, strlen($ns) + 1).DS;
  239. $file_path = $path.strtolower($sub_namespace.str_replace('_', DS, $class_no_ns).'.php');
  240. if (is_file($file_path))
  241. {
  242. require $file_path;
  243. static::_init_class($class);
  244. $loaded = true;
  245. break;
  246. }
  247. }
  248. }
  249. }
  250. // Prevent failed load from keeping other classes from initializing
  251. if (static::$auto_initialize == $class)
  252. {
  253. static::$auto_initialize = null;
  254. }
  255. return $loaded;
  256. }
  257. /**
  258. * A PSR-0 compatible class loader
  259. *
  260. * @param string path to the class
  261. * @param string classname
  262. */
  263. protected static function psr_loader($path, $class)
  264. {
  265. $class = ltrim($class, '\\');
  266. $file = '';
  267. if ($last_ns_pos = strripos($class, '\\'))
  268. {
  269. $namespace = substr($class, 0, $last_ns_pos);
  270. $class = substr($class, $last_ns_pos + 1);
  271. $file = str_replace('\\', DS, $namespace).DS;
  272. }
  273. $file .= str_replace('_', DS, $class).'.php';
  274. require $path.$file;
  275. }
  276. /**
  277. * Checks to see if the given class has a static _init() method. If so then
  278. * it calls it.
  279. *
  280. * @param string the class name
  281. */
  282. private static function _init_class($class)
  283. {
  284. if (static::$auto_initialize === $class)
  285. {
  286. static::$auto_initialize = null;
  287. if (method_exists($class, '_init') and is_callable($class.'::_init'))
  288. {
  289. call_user_func($class.'::_init');
  290. }
  291. }
  292. }
  293. }