PageRenderTime 50ms CodeModel.GetById 19ms RepoModel.GetById 0ms app.codeStats 0ms

/src/ClassLoader/UniversalClassLoader.php

http://github.com/Herzult/php-ssh
PHP | 224 lines | 104 code | 15 blank | 105 comment | 6 complexity | 066ba5bd87504203edc57c4f430bdf2e MD5 | raw file
  1. <?php
  2. namespace ClassLoader;
  3. /**
  4. * UniversalClassLoader implements a "universal" autoloader for PHP 5.3.
  5. *
  6. * It is able to load classes that use either:
  7. *
  8. * * The technical interoperability standards for PHP 5.3 namespaces and
  9. * class names (http://groups.google.com/group/php-standards/web/psr-0-final-proposal);
  10. *
  11. * * The PEAR naming convention for classes (http://pear.php.net/).
  12. *
  13. * Classes from a sub-namespace or a sub-hierarchy of PEAR classes can be
  14. * looked for in a list of locations to ease the vendoring of a sub-set of
  15. * classes for large projects.
  16. *
  17. * Example usage:
  18. *
  19. * $loader = new UniversalClassLoader();
  20. *
  21. * // register classes with namespaces
  22. * $loader->registerNamespaces(array(
  23. * 'Symfony\Component' => __DIR__.'/component',
  24. * 'Symfony' => __DIR__.'/framework',
  25. * 'Sensio' => array(__DIR__.'/src', __DIR__.'/vendor'),
  26. * ));
  27. *
  28. * // register a library using the PEAR naming convention
  29. * $loader->registerPrefixes(array(
  30. * 'Swift_' => __DIR__.'/Swift',
  31. * ));
  32. *
  33. * // activate the autoloader
  34. * $loader->register();
  35. *
  36. * In this example, if you try to use a class in the Symfony\Component
  37. * namespace or one of its children (Symfony\Component\Console for instance),
  38. * the autoloader will first look for the class under the component/
  39. * directory, and it will then fallback to the framework/ directory if not
  40. * found before giving up.
  41. *
  42. * @author Fabien Potencier <fabien@symfony.com>
  43. */
  44. class UniversalClassLoader
  45. {
  46. protected $namespaces = array();
  47. protected $prefixes = array();
  48. protected $namespaceFallback = array();
  49. protected $prefixFallback = array();
  50. /**
  51. * Gets the configured namespaces.
  52. *
  53. * @return array A hash with namespaces as keys and directories as values
  54. */
  55. public function getNamespaces()
  56. {
  57. return $this->namespaces;
  58. }
  59. /**
  60. * Gets the configured class prefixes.
  61. *
  62. * @return array A hash with class prefixes as keys and directories as values
  63. */
  64. public function getPrefixes()
  65. {
  66. return $this->prefixes;
  67. }
  68. /**
  69. * Gets the directory(ies) to use as a fallback for namespaces.
  70. *
  71. * @return array An array of directories
  72. */
  73. public function getNamespaceFallback()
  74. {
  75. return $this->namespaceFallback;
  76. }
  77. /**
  78. * Gets the directory(ies) to use as a fallback for class prefixes.
  79. *
  80. * @return array An array of directories
  81. */
  82. public function getPrefixFallback()
  83. {
  84. return $this->prefixFallback;
  85. }
  86. /**
  87. * Registers the directory to use as a fallback for namespaces.
  88. *
  89. * @param string|array $dirs A directory path or an array of directories
  90. */
  91. public function registerNamespaceFallback($dirs)
  92. {
  93. $this->namespaceFallback = (array) $dirs;
  94. }
  95. /**
  96. * Registers the directory to use as a fallback for class prefixes.
  97. *
  98. * @param string|array $dirs A directory path or an array of directories
  99. */
  100. public function registerPrefixFallback($dirs)
  101. {
  102. $this->prefixFallback = (array) $dirs;
  103. }
  104. /**
  105. * Registers an array of namespaces
  106. *
  107. * @param array $namespaces An array of namespaces (namespaces as keys and locations as values)
  108. */
  109. public function registerNamespaces(array $namespaces)
  110. {
  111. foreach ($namespaces as $namespace => $locations) {
  112. $this->namespaces[$namespace] = (array) $locations;
  113. }
  114. }
  115. /**
  116. * Registers a namespace.
  117. *
  118. * @param string $namespace The namespace
  119. * @param array|string $paths The location(s) of the namespace
  120. */
  121. public function registerNamespace($namespace, $paths)
  122. {
  123. $this->namespaces[$namespace] = (array) $paths;
  124. }
  125. /**
  126. * Registers an array of classes using the PEAR naming convention.
  127. *
  128. * @param array $classes An array of classes (prefixes as keys and locations as values)
  129. */
  130. public function registerPrefixes(array $classes)
  131. {
  132. foreach ($classes as $prefix => $locations) {
  133. $this->prefixes[$prefix] = (array) $locations;
  134. }
  135. }
  136. /**
  137. * Registers a set of classes using the PEAR naming convention.
  138. *
  139. * @param string $prefix The classes prefix
  140. * @param array|string $paths The location(s) of the classes
  141. */
  142. public function registerPrefix($prefix, $paths)
  143. {
  144. $this->prefixes[$prefix] = (array) $paths;
  145. }
  146. /**
  147. * Registers this instance as an autoloader.
  148. *
  149. * @param Boolean $prepend Whether to prepend the autoloader or not
  150. */
  151. public function register($prepend = false)
  152. {
  153. spl_autoload_register(array($this, 'loadClass'), true, $prepend);
  154. }
  155. /**
  156. * Loads the given class or interface.
  157. *
  158. * @param string $class The name of the class
  159. */
  160. public function loadClass($class)
  161. {
  162. $class = ltrim($class, '\\');
  163. if (false !== ($pos = strrpos($class, '\\'))) {
  164. // namespaced class name
  165. $namespace = substr($class, 0, $pos);
  166. foreach ($this->namespaces as $ns => $dirs) {
  167. foreach ($dirs as $dir) {
  168. if (0 === strpos($namespace, $ns)) {
  169. $className = substr($class, $pos + 1);
  170. $file = $dir.DIRECTORY_SEPARATOR.str_replace('\\', DIRECTORY_SEPARATOR, $namespace).DIRECTORY_SEPARATOR.str_replace('_', DIRECTORY_SEPARATOR, $className).'.php';
  171. if (file_exists($file)) {
  172. require $file;
  173. return;
  174. }
  175. }
  176. }
  177. }
  178. foreach ($this->namespaceFallback as $dir) {
  179. $file = $dir.DIRECTORY_SEPARATOR.str_replace('\\', DIRECTORY_SEPARATOR, $class).'.php';
  180. if (file_exists($file)) {
  181. require $file;
  182. return;
  183. }
  184. }
  185. } else {
  186. // PEAR-like class name
  187. foreach ($this->prefixes as $prefix => $dirs) {
  188. foreach ($dirs as $dir) {
  189. if (0 === strpos($class, $prefix)) {
  190. $file = $dir.DIRECTORY_SEPARATOR.str_replace('_', DIRECTORY_SEPARATOR, $class).'.php';
  191. if (file_exists($file)) {
  192. require $file;
  193. return;
  194. }
  195. }
  196. }
  197. }
  198. foreach ($this->prefixFallback as $dir) {
  199. $file = $dir.DIRECTORY_SEPARATOR.str_replace('_', DIRECTORY_SEPARATOR, $class).'.php';
  200. if (file_exists($file)) {
  201. require $file;
  202. return;
  203. }
  204. }
  205. }
  206. }
  207. }