Drupal investigation

ClassLoader.php 5.3KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204
  1. <?php
  2. /*
  3. * This file is part of the Symfony package.
  4. *
  5. * (c) Fabien Potencier <fabien@symfony.com>
  6. *
  7. * For the full copyright and license information, please view the LICENSE
  8. * file that was distributed with this source code.
  9. */
  10. namespace Symfony\Component\ClassLoader;
  11. /**
  12. * ClassLoader implements an PSR-0 class loader.
  13. *
  14. * See https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-0.md
  15. *
  16. * $loader = new ClassLoader();
  17. *
  18. * // register classes with namespaces
  19. * $loader->addPrefix('Symfony\Component', __DIR__.'/component');
  20. * $loader->addPrefix('Symfony', __DIR__.'/framework');
  21. *
  22. * // activate the autoloader
  23. * $loader->register();
  24. *
  25. * // to enable searching the include path (e.g. for PEAR packages)
  26. * $loader->setUseIncludePath(true);
  27. *
  28. * In this example, if you try to use a class in the Symfony\Component
  29. * namespace or one of its children (Symfony\Component\Console for instance),
  30. * the autoloader will first look for the class under the component/
  31. * directory, and it will then fallback to the framework/ directory if not
  32. * found before giving up.
  33. *
  34. * @author Fabien Potencier <fabien@symfony.com>
  35. * @author Jordi Boggiano <j.boggiano@seld.be>
  36. */
  37. class ClassLoader
  38. {
  39. private $prefixes = array();
  40. private $fallbackDirs = array();
  41. private $useIncludePath = false;
  42. /**
  43. * Returns prefixes.
  44. *
  45. * @return array
  46. */
  47. public function getPrefixes()
  48. {
  49. return $this->prefixes;
  50. }
  51. /**
  52. * Returns fallback directories.
  53. *
  54. * @return array
  55. */
  56. public function getFallbackDirs()
  57. {
  58. return $this->fallbackDirs;
  59. }
  60. /**
  61. * Adds prefixes.
  62. *
  63. * @param array $prefixes Prefixes to add
  64. */
  65. public function addPrefixes(array $prefixes)
  66. {
  67. foreach ($prefixes as $prefix => $path) {
  68. $this->addPrefix($prefix, $path);
  69. }
  70. }
  71. /**
  72. * Registers a set of classes.
  73. *
  74. * @param string $prefix The classes prefix
  75. * @param array|string $paths The location(s) of the classes
  76. */
  77. public function addPrefix($prefix, $paths)
  78. {
  79. if (!$prefix) {
  80. foreach ((array) $paths as $path) {
  81. $this->fallbackDirs[] = $path;
  82. }
  83. return;
  84. }
  85. if (isset($this->prefixes[$prefix])) {
  86. if (is_array($paths)) {
  87. $this->prefixes[$prefix] = array_unique(array_merge(
  88. $this->prefixes[$prefix],
  89. $paths
  90. ));
  91. } elseif (!in_array($paths, $this->prefixes[$prefix])) {
  92. $this->prefixes[$prefix][] = $paths;
  93. }
  94. } else {
  95. $this->prefixes[$prefix] = array_unique((array) $paths);
  96. }
  97. }
  98. /**
  99. * Turns on searching the include for class files.
  100. *
  101. * @param bool $useIncludePath
  102. */
  103. public function setUseIncludePath($useIncludePath)
  104. {
  105. $this->useIncludePath = (bool) $useIncludePath;
  106. }
  107. /**
  108. * Can be used to check if the autoloader uses the include path to check
  109. * for classes.
  110. *
  111. * @return bool
  112. */
  113. public function getUseIncludePath()
  114. {
  115. return $this->useIncludePath;
  116. }
  117. /**
  118. * Registers this instance as an autoloader.
  119. *
  120. * @param bool $prepend Whether to prepend the autoloader or not
  121. */
  122. public function register($prepend = false)
  123. {
  124. spl_autoload_register(array($this, 'loadClass'), true, $prepend);
  125. }
  126. /**
  127. * Unregisters this instance as an autoloader.
  128. */
  129. public function unregister()
  130. {
  131. spl_autoload_unregister(array($this, 'loadClass'));
  132. }
  133. /**
  134. * Loads the given class or interface.
  135. *
  136. * @param string $class The name of the class
  137. *
  138. * @return bool|null True, if loaded
  139. */
  140. public function loadClass($class)
  141. {
  142. if ($file = $this->findFile($class)) {
  143. require $file;
  144. return true;
  145. }
  146. }
  147. /**
  148. * Finds the path to the file where the class is defined.
  149. *
  150. * @param string $class The name of the class
  151. *
  152. * @return string|null The path, if found
  153. */
  154. public function findFile($class)
  155. {
  156. if (false !== $pos = strrpos($class, '\\')) {
  157. // namespaced class name
  158. $classPath = str_replace('\\', DIRECTORY_SEPARATOR, substr($class, 0, $pos)).DIRECTORY_SEPARATOR;
  159. $className = substr($class, $pos + 1);
  160. } else {
  161. // PEAR-like class name
  162. $classPath = null;
  163. $className = $class;
  164. }
  165. $classPath .= str_replace('_', DIRECTORY_SEPARATOR, $className).'.php';
  166. foreach ($this->prefixes as $prefix => $dirs) {
  167. if ($class === strstr($class, $prefix)) {
  168. foreach ($dirs as $dir) {
  169. if (file_exists($dir.DIRECTORY_SEPARATOR.$classPath)) {
  170. return $dir.DIRECTORY_SEPARATOR.$classPath;
  171. }
  172. }
  173. }
  174. }
  175. foreach ($this->fallbackDirs as $dir) {
  176. if (file_exists($dir.DIRECTORY_SEPARATOR.$classPath)) {
  177. return $dir.DIRECTORY_SEPARATOR.$classPath;
  178. }
  179. }
  180. if ($this->useIncludePath && $file = stream_resolve_include_path($classPath)) {
  181. return $file;
  182. }
  183. }
  184. }