PageRenderTime 53ms CodeModel.GetById 26ms RepoModel.GetById 0ms app.codeStats 0ms

/core/Loader.php

http://github.com/titon/titon
PHP | 259 lines | 197 code | 13 blank | 49 comment | 3 complexity | 15ce556d59c3686024cb6b3e08f3af90 MD5 | raw file
  1. <?php
  2. /**
  3. * Titon: A PHP 5.4 Modular Framework
  4. *
  5. * @copyright Copyright 2010, Titon
  6. * @link http://github.com/titon
  7. * @license http://opensource.org/licenses/bsd-license.php (BSD License)
  8. */
  9. namespace titon\core;
  10. use titon\Titon;
  11. use \Closure;
  12. /**
  13. * Handles the autoloading, importing and including of files within the system.
  14. * Provides convenience functions for inflecting notation paths, namespace paths and file system paths.
  15. *
  16. * @package titon.core
  17. */
  18. class Loader {
  19. /**
  20. * Collection of loader detection closures.
  21. *
  22. * @access protected
  23. * @var array
  24. */
  25. protected $_loaders = [];
  26. /**
  27. * Define autoloader and attempt to autoload from include_paths first.
  28. *
  29. * @access public
  30. */
  31. public function __construct() {
  32. spl_autoload_extensions('.php');
  33. spl_autoload_register();
  34. spl_autoload_register([$this, 'autoload']);
  35. // Add default loader
  36. $this->setup('default', function($class) {
  37. return Titon::loader()->import($class);
  38. });
  39. // Set default include paths
  40. $this->includePath([TITON_APP, TITON, TITON_LIBS, VENDORS]);
  41. }
  42. /**
  43. * Cycle through all the defined loaders until the file is included.
  44. *
  45. * @access public
  46. * @param string $class
  47. * @return void
  48. */
  49. public function autoload($class) {
  50. if (class_exists($class, false) || interface_exists($class, false)) {
  51. return;
  52. }
  53. foreach ($this->_loaders as $loader) {
  54. if ($loader($class)) {
  55. break;
  56. }
  57. }
  58. }
  59. /**
  60. * Strips the namespace to return the base class name.
  61. *
  62. * @access public
  63. * @param string $class
  64. * @param string $separator
  65. * @return string
  66. */
  67. public function baseClass($class, $separator = '\\') {
  68. return $this->stripExt(trim(mb_strrchr($class, $separator), $separator));
  69. }
  70. /**
  71. * Returns a namespace with only the base package, and not the class name.
  72. *
  73. * @access public
  74. * @param string $class
  75. * @param string $separator
  76. * @return string
  77. */
  78. public function baseNamespace($class, $separator = '\\') {
  79. $class = $this->toNamespace($class);
  80. return mb_substr($class, 0, mb_strrpos($class, $separator));
  81. }
  82. /**
  83. * Converts OS directory separators to the standard forward slash.
  84. *
  85. * @access public
  86. * @param string $path
  87. * @param boolean $endSlash
  88. * @return string
  89. */
  90. public function ds($path, $endSlash = false) {
  91. $path = str_replace('\\', '/', $path);
  92. if ($endSlash && mb_substr($path, -1) !== '/') {
  93. $path .= '/';
  94. }
  95. return $path;
  96. }
  97. /**
  98. * Return the extension from a file path.
  99. *
  100. * @access public
  101. * @param string $path
  102. * @return string
  103. */
  104. public function ext($path) {
  105. return mb_strtolower(trim(mb_strrchr($path, '.'), '.'));
  106. }
  107. /**
  108. * Attempts to include files into the application based on namespace or given path.
  109. * Relies heavily on the defined include paths.
  110. *
  111. * @access public
  112. * @param string $path
  113. * @return boolean
  114. */
  115. public function import($path) {
  116. foreach ([TITON_APP, TITON, VENDORS, TITON_LIBS] as $root) {
  117. $source = $this->toPath($path, 'php', $root);
  118. if (file_exists($source)) {
  119. include_once $source;
  120. return true;
  121. }
  122. }
  123. return false;
  124. }
  125. /**
  126. * Define additional include paths for PHP to detect within.
  127. *
  128. * @access public
  129. * @param string|array $paths
  130. * @return \titon\core\Loader
  131. * @chainable
  132. */
  133. public function includePath($paths) {
  134. $current = [get_include_path()];
  135. if (is_array($paths)) {
  136. foreach ($paths as $path) {
  137. $current[] = $path;
  138. }
  139. } else {
  140. $current[] = $paths;
  141. }
  142. set_include_path(implode(PATH_SEPARATOR, $current));
  143. return $this;
  144. }
  145. /**
  146. * Delete an auto loader.
  147. *
  148. * @access public
  149. * @param string $key
  150. * @return \titon\core\Loader
  151. * @chainable
  152. */
  153. public function remove($key) {
  154. unset($this->_loaders[$key]);
  155. return $this;
  156. }
  157. /**
  158. * Primary method that deals with autoloading classes.
  159. * Defines a closure that is triggered to attempt to include a file.
  160. *
  161. * @access public
  162. * @param string $key
  163. * @param Closure $loader
  164. * @return \titon\core\Loader
  165. * @chainable
  166. */
  167. public function setup($key, Closure $loader) {
  168. $this->_loaders[$key] = $loader;
  169. return $this;
  170. }
  171. /**
  172. * Strip off the extension if it exists.
  173. *
  174. * @access public
  175. * @param string $path
  176. * @return string
  177. */
  178. public function stripExt($path) {
  179. if (mb_strpos($path, '.') !== false) {
  180. $path = mb_substr($path, 0, mb_strrpos($path, '.'));
  181. }
  182. return $path;
  183. }
  184. /**
  185. * Converts a path to a namespace package.
  186. *
  187. * @access public
  188. * @param string $path
  189. * @return string
  190. */
  191. public function toNamespace($path) {
  192. $path = $this->stripExt($path);
  193. if (mb_strpos($path, '/') !== false) {
  194. $path = str_replace($this->ds(VENDORS), '', $this->ds($path));
  195. $path = str_replace('/', '\\', $path);
  196. }
  197. return trim($path, '\\');
  198. }
  199. /**
  200. * Converts a namespace to a relative or absolute file system path.
  201. *
  202. * @access public
  203. * @param string $path
  204. * @param string $ext
  205. * @param mixed $root
  206. * @return string
  207. */
  208. public function toPath($path, $ext = 'php', $root = false) {
  209. $path = $this->ds($path);
  210. $dirs = explode('/', $path);
  211. $file = array_pop($dirs);
  212. $path = implode('/', $dirs) . '/' . str_replace('_', '/', $file);
  213. if ($ext && mb_substr($path, -mb_strlen($ext)) !== $ext) {
  214. $path .= '.' . $ext;
  215. }
  216. if ($root) {
  217. $path = $root . $path;
  218. }
  219. return $path;
  220. }
  221. }