Skouter mortgage estimates. Web application with view written in PHP and Vue, but controller and models in Go.
No puede seleccionar más de 25 temas Los temas deben comenzar con una letra o número, pueden incluir guiones ('-') y pueden tener hasta 35 caracteres de largo.

ClassLoader.php 13 KiB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445
  1. <?php
  2. /*
  3. * This file is part of Composer.
  4. *
  5. * (c) Nils Adermann <naderman@naderman.de>
  6. * Jordi Boggiano <j.boggiano@seld.be>
  7. *
  8. * For the full copyright and license information, please view the LICENSE
  9. * file that was distributed with this source code.
  10. */
  11. namespace Composer\Autoload;
  12. /**
  13. * ClassLoader implements a PSR-0, PSR-4 and classmap class loader.
  14. *
  15. * $loader = new \Composer\Autoload\ClassLoader();
  16. *
  17. * // register classes with namespaces
  18. * $loader->add('Symfony\Component', __DIR__.'/component');
  19. * $loader->add('Symfony', __DIR__.'/framework');
  20. *
  21. * // activate the autoloader
  22. * $loader->register();
  23. *
  24. * // to enable searching the include path (eg. for PEAR packages)
  25. * $loader->setUseIncludePath(true);
  26. *
  27. * In this example, if you try to use a class in the Symfony\Component
  28. * namespace or one of its children (Symfony\Component\Console for instance),
  29. * the autoloader will first look for the class under the component/
  30. * directory, and it will then fallback to the framework/ directory if not
  31. * found before giving up.
  32. *
  33. * This class is loosely based on the Symfony UniversalClassLoader.
  34. *
  35. * @author Fabien Potencier <fabien@symfony.com>
  36. * @author Jordi Boggiano <j.boggiano@seld.be>
  37. * @see http://www.php-fig.org/psr/psr-0/
  38. * @see http://www.php-fig.org/psr/psr-4/
  39. */
  40. class ClassLoader
  41. {
  42. // PSR-4
  43. private $prefixLengthsPsr4 = array();
  44. private $prefixDirsPsr4 = array();
  45. private $fallbackDirsPsr4 = array();
  46. // PSR-0
  47. private $prefixesPsr0 = array();
  48. private $fallbackDirsPsr0 = array();
  49. private $useIncludePath = false;
  50. private $classMap = array();
  51. private $classMapAuthoritative = false;
  52. private $missingClasses = array();
  53. private $apcuPrefix;
  54. public function getPrefixes()
  55. {
  56. if (!empty($this->prefixesPsr0)) {
  57. return call_user_func_array('array_merge', $this->prefixesPsr0);
  58. }
  59. return array();
  60. }
  61. public function getPrefixesPsr4()
  62. {
  63. return $this->prefixDirsPsr4;
  64. }
  65. public function getFallbackDirs()
  66. {
  67. return $this->fallbackDirsPsr0;
  68. }
  69. public function getFallbackDirsPsr4()
  70. {
  71. return $this->fallbackDirsPsr4;
  72. }
  73. public function getClassMap()
  74. {
  75. return $this->classMap;
  76. }
  77. /**
  78. * @param array $classMap Class to filename map
  79. */
  80. public function addClassMap(array $classMap)
  81. {
  82. if ($this->classMap) {
  83. $this->classMap = array_merge($this->classMap, $classMap);
  84. } else {
  85. $this->classMap = $classMap;
  86. }
  87. }
  88. /**
  89. * Registers a set of PSR-0 directories for a given prefix, either
  90. * appending or prepending to the ones previously set for this prefix.
  91. *
  92. * @param string $prefix The prefix
  93. * @param array|string $paths The PSR-0 root directories
  94. * @param bool $prepend Whether to prepend the directories
  95. */
  96. public function add($prefix, $paths, $prepend = false)
  97. {
  98. if (!$prefix) {
  99. if ($prepend) {
  100. $this->fallbackDirsPsr0 = array_merge(
  101. (array) $paths,
  102. $this->fallbackDirsPsr0
  103. );
  104. } else {
  105. $this->fallbackDirsPsr0 = array_merge(
  106. $this->fallbackDirsPsr0,
  107. (array) $paths
  108. );
  109. }
  110. return;
  111. }
  112. $first = $prefix[0];
  113. if (!isset($this->prefixesPsr0[$first][$prefix])) {
  114. $this->prefixesPsr0[$first][$prefix] = (array) $paths;
  115. return;
  116. }
  117. if ($prepend) {
  118. $this->prefixesPsr0[$first][$prefix] = array_merge(
  119. (array) $paths,
  120. $this->prefixesPsr0[$first][$prefix]
  121. );
  122. } else {
  123. $this->prefixesPsr0[$first][$prefix] = array_merge(
  124. $this->prefixesPsr0[$first][$prefix],
  125. (array) $paths
  126. );
  127. }
  128. }
  129. /**
  130. * Registers a set of PSR-4 directories for a given namespace, either
  131. * appending or prepending to the ones previously set for this namespace.
  132. *
  133. * @param string $prefix The prefix/namespace, with trailing '\\'
  134. * @param array|string $paths The PSR-4 base directories
  135. * @param bool $prepend Whether to prepend the directories
  136. *
  137. * @throws \InvalidArgumentException
  138. */
  139. public function addPsr4($prefix, $paths, $prepend = false)
  140. {
  141. if (!$prefix) {
  142. // Register directories for the root namespace.
  143. if ($prepend) {
  144. $this->fallbackDirsPsr4 = array_merge(
  145. (array) $paths,
  146. $this->fallbackDirsPsr4
  147. );
  148. } else {
  149. $this->fallbackDirsPsr4 = array_merge(
  150. $this->fallbackDirsPsr4,
  151. (array) $paths
  152. );
  153. }
  154. } elseif (!isset($this->prefixDirsPsr4[$prefix])) {
  155. // Register directories for a new namespace.
  156. $length = strlen($prefix);
  157. if ('\\' !== $prefix[$length - 1]) {
  158. throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator.");
  159. }
  160. $this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length;
  161. $this->prefixDirsPsr4[$prefix] = (array) $paths;
  162. } elseif ($prepend) {
  163. // Prepend directories for an already registered namespace.
  164. $this->prefixDirsPsr4[$prefix] = array_merge(
  165. (array) $paths,
  166. $this->prefixDirsPsr4[$prefix]
  167. );
  168. } else {
  169. // Append directories for an already registered namespace.
  170. $this->prefixDirsPsr4[$prefix] = array_merge(
  171. $this->prefixDirsPsr4[$prefix],
  172. (array) $paths
  173. );
  174. }
  175. }
  176. /**
  177. * Registers a set of PSR-0 directories for a given prefix,
  178. * replacing any others previously set for this prefix.
  179. *
  180. * @param string $prefix The prefix
  181. * @param array|string $paths The PSR-0 base directories
  182. */
  183. public function set($prefix, $paths)
  184. {
  185. if (!$prefix) {
  186. $this->fallbackDirsPsr0 = (array) $paths;
  187. } else {
  188. $this->prefixesPsr0[$prefix[0]][$prefix] = (array) $paths;
  189. }
  190. }
  191. /**
  192. * Registers a set of PSR-4 directories for a given namespace,
  193. * replacing any others previously set for this namespace.
  194. *
  195. * @param string $prefix The prefix/namespace, with trailing '\\'
  196. * @param array|string $paths The PSR-4 base directories
  197. *
  198. * @throws \InvalidArgumentException
  199. */
  200. public function setPsr4($prefix, $paths)
  201. {
  202. if (!$prefix) {
  203. $this->fallbackDirsPsr4 = (array) $paths;
  204. } else {
  205. $length = strlen($prefix);
  206. if ('\\' !== $prefix[$length - 1]) {
  207. throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator.");
  208. }
  209. $this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length;
  210. $this->prefixDirsPsr4[$prefix] = (array) $paths;
  211. }
  212. }
  213. /**
  214. * Turns on searching the include path for class files.
  215. *
  216. * @param bool $useIncludePath
  217. */
  218. public function setUseIncludePath($useIncludePath)
  219. {
  220. $this->useIncludePath = $useIncludePath;
  221. }
  222. /**
  223. * Can be used to check if the autoloader uses the include path to check
  224. * for classes.
  225. *
  226. * @return bool
  227. */
  228. public function getUseIncludePath()
  229. {
  230. return $this->useIncludePath;
  231. }
  232. /**
  233. * Turns off searching the prefix and fallback directories for classes
  234. * that have not been registered with the class map.
  235. *
  236. * @param bool $classMapAuthoritative
  237. */
  238. public function setClassMapAuthoritative($classMapAuthoritative)
  239. {
  240. $this->classMapAuthoritative = $classMapAuthoritative;
  241. }
  242. /**
  243. * Should class lookup fail if not found in the current class map?
  244. *
  245. * @return bool
  246. */
  247. public function isClassMapAuthoritative()
  248. {
  249. return $this->classMapAuthoritative;
  250. }
  251. /**
  252. * APCu prefix to use to cache found/not-found classes, if the extension is enabled.
  253. *
  254. * @param string|null $apcuPrefix
  255. */
  256. public function setApcuPrefix($apcuPrefix)
  257. {
  258. $this->apcuPrefix = function_exists('apcu_fetch') && ini_get('apc.enabled') ? $apcuPrefix : null;
  259. }
  260. /**
  261. * The APCu prefix in use, or null if APCu caching is not enabled.
  262. *
  263. * @return string|null
  264. */
  265. public function getApcuPrefix()
  266. {
  267. return $this->apcuPrefix;
  268. }
  269. /**
  270. * Registers this instance as an autoloader.
  271. *
  272. * @param bool $prepend Whether to prepend the autoloader or not
  273. */
  274. public function register($prepend = false)
  275. {
  276. spl_autoload_register(array($this, 'loadClass'), true, $prepend);
  277. }
  278. /**
  279. * Unregisters this instance as an autoloader.
  280. */
  281. public function unregister()
  282. {
  283. spl_autoload_unregister(array($this, 'loadClass'));
  284. }
  285. /**
  286. * Loads the given class or interface.
  287. *
  288. * @param string $class The name of the class
  289. * @return bool|null True if loaded, null otherwise
  290. */
  291. public function loadClass($class)
  292. {
  293. if ($file = $this->findFile($class)) {
  294. includeFile($file);
  295. return true;
  296. }
  297. }
  298. /**
  299. * Finds the path to the file where the class is defined.
  300. *
  301. * @param string $class The name of the class
  302. *
  303. * @return string|false The path if found, false otherwise
  304. */
  305. public function findFile($class)
  306. {
  307. // class map lookup
  308. if (isset($this->classMap[$class])) {
  309. return $this->classMap[$class];
  310. }
  311. if ($this->classMapAuthoritative || isset($this->missingClasses[$class])) {
  312. return false;
  313. }
  314. if (null !== $this->apcuPrefix) {
  315. $file = apcu_fetch($this->apcuPrefix.$class, $hit);
  316. if ($hit) {
  317. return $file;
  318. }
  319. }
  320. $file = $this->findFileWithExtension($class, '.php');
  321. // Search for Hack files if we are running on HHVM
  322. if (false === $file && defined('HHVM_VERSION')) {
  323. $file = $this->findFileWithExtension($class, '.hh');
  324. }
  325. if (null !== $this->apcuPrefix) {
  326. apcu_add($this->apcuPrefix.$class, $file);
  327. }
  328. if (false === $file) {
  329. // Remember that this class does not exist.
  330. $this->missingClasses[$class] = true;
  331. }
  332. return $file;
  333. }
  334. private function findFileWithExtension($class, $ext)
  335. {
  336. // PSR-4 lookup
  337. $logicalPathPsr4 = strtr($class, '\\', DIRECTORY_SEPARATOR) . $ext;
  338. $first = $class[0];
  339. if (isset($this->prefixLengthsPsr4[$first])) {
  340. $subPath = $class;
  341. while (false !== $lastPos = strrpos($subPath, '\\')) {
  342. $subPath = substr($subPath, 0, $lastPos);
  343. $search = $subPath.'\\';
  344. if (isset($this->prefixDirsPsr4[$search])) {
  345. $pathEnd = DIRECTORY_SEPARATOR . substr($logicalPathPsr4, $lastPos + 1);
  346. foreach ($this->prefixDirsPsr4[$search] as $dir) {
  347. if (file_exists($file = $dir . $pathEnd)) {
  348. return $file;
  349. }
  350. }
  351. }
  352. }
  353. }
  354. // PSR-4 fallback dirs
  355. foreach ($this->fallbackDirsPsr4 as $dir) {
  356. if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr4)) {
  357. return $file;
  358. }
  359. }
  360. // PSR-0 lookup
  361. if (false !== $pos = strrpos($class, '\\')) {
  362. // namespaced class name
  363. $logicalPathPsr0 = substr($logicalPathPsr4, 0, $pos + 1)
  364. . strtr(substr($logicalPathPsr4, $pos + 1), '_', DIRECTORY_SEPARATOR);
  365. } else {
  366. // PEAR-like class name
  367. $logicalPathPsr0 = strtr($class, '_', DIRECTORY_SEPARATOR) . $ext;
  368. }
  369. if (isset($this->prefixesPsr0[$first])) {
  370. foreach ($this->prefixesPsr0[$first] as $prefix => $dirs) {
  371. if (0 === strpos($class, $prefix)) {
  372. foreach ($dirs as $dir) {
  373. if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) {
  374. return $file;
  375. }
  376. }
  377. }
  378. }
  379. }
  380. // PSR-0 fallback dirs
  381. foreach ($this->fallbackDirsPsr0 as $dir) {
  382. if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) {
  383. return $file;
  384. }
  385. }
  386. // PSR-0 include paths.
  387. if ($this->useIncludePath && $file = stream_resolve_include_path($logicalPathPsr0)) {
  388. return $file;
  389. }
  390. return false;
  391. }
  392. }
  393. /**
  394. * Scope isolated include.
  395. *
  396. * Prevents access to $this/self from included files.
  397. */
  398. function includeFile($file)
  399. {
  400. include $file;
  401. }