You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

преди 11 години
преди 11 години
преди 7 години
преди 9 години
преди 7 години
преди 8 години
преди 9 години
преди 7 години
преди 8 години
преди 7 години
преди 9 години
преди 9 години
преди 11 години
преди 11 години
преди 11 години
преди 8 години
преди 8 години
преди 8 години
преди 8 години
преди 8 години
преди 11 години
преди 11 години
преди 11 години
преди 11 години
преди 11 години
преди 11 години
преди 11 години
преди 11 години
преди 10 години
преди 10 години
преди 10 години
преди 11 години
преди 11 години
преди 8 години
преди 8 години
преди 11 години
преди 8 години
преди 10 години
преди 11 години
преди 11 години
преди 8 години
преди 11 години
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190
  1. <?php
  2. declare(strict_types=1);
  3. /**
  4. * @copyright Copyright (c) 2016, ownCloud, Inc.
  5. *
  6. * @author Andreas Fischer <bantu@owncloud.com>
  7. * @author Arthur Schiwon <blizzz@arthur-schiwon.de>
  8. * @author Christoph Wurst <christoph@winzerhof-wurst.at>
  9. * @author Georg Ehrke <oc.list@georgehrke.com>
  10. * @author Joas Schilling <coding@schilljs.com>
  11. * @author Lukas Reschke <lukas@statuscode.ch>
  12. * @author Markus Goetz <markus@woboq.com>
  13. * @author Morris Jobke <hey@morrisjobke.de>
  14. * @author Robin Appelman <robin@icewind.nl>
  15. * @author Robin McCorkell <robin@mccorkell.me.uk>
  16. * @author Roeland Jago Douma <roeland@famdouma.nl>
  17. * @author Vincent Petry <vincent@nextcloud.com>
  18. *
  19. * @license AGPL-3.0
  20. *
  21. * This code is free software: you can redistribute it and/or modify
  22. * it under the terms of the GNU Affero General Public License, version 3,
  23. * as published by the Free Software Foundation.
  24. *
  25. * This program is distributed in the hope that it will be useful,
  26. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  27. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  28. * GNU Affero General Public License for more details.
  29. *
  30. * You should have received a copy of the GNU Affero General Public License, version 3,
  31. * along with this program. If not, see <http://www.gnu.org/licenses/>
  32. *
  33. */
  34. namespace OC;
  35. use \OCP\AutoloadNotAllowedException;
  36. use OCP\ILogger;
  37. class Autoloader {
  38. /** @var bool */
  39. private $useGlobalClassPath = true;
  40. /** @var array */
  41. private $validRoots = [];
  42. /**
  43. * Optional low-latency memory cache for class to path mapping.
  44. *
  45. * @var \OC\Memcache\Cache
  46. */
  47. protected $memoryCache;
  48. /**
  49. * Autoloader constructor.
  50. *
  51. * @param string[] $validRoots
  52. */
  53. public function __construct(array $validRoots) {
  54. foreach ($validRoots as $root) {
  55. $this->validRoots[$root] = true;
  56. }
  57. }
  58. /**
  59. * Add a path to the list of valid php roots for auto loading
  60. *
  61. * @param string $root
  62. */
  63. public function addValidRoot(string $root) {
  64. $root = stream_resolve_include_path($root);
  65. $this->validRoots[$root] = true;
  66. }
  67. /**
  68. * disable the usage of the global classpath \OC::$CLASSPATH
  69. */
  70. public function disableGlobalClassPath() {
  71. $this->useGlobalClassPath = false;
  72. }
  73. /**
  74. * enable the usage of the global classpath \OC::$CLASSPATH
  75. */
  76. public function enableGlobalClassPath() {
  77. $this->useGlobalClassPath = true;
  78. }
  79. /**
  80. * get the possible paths for a class
  81. *
  82. * @param string $class
  83. * @return array an array of possible paths
  84. */
  85. public function findClass(string $class): array {
  86. $class = trim($class, '\\');
  87. $paths = [];
  88. if ($this->useGlobalClassPath && array_key_exists($class, \OC::$CLASSPATH)) {
  89. $paths[] = \OC::$CLASSPATH[$class];
  90. /**
  91. * @TODO: Remove this when necessary
  92. * Remove "apps/" from inclusion path for smooth migration to multi app dir
  93. */
  94. if (strpos(\OC::$CLASSPATH[$class], 'apps/') === 0) {
  95. \OCP\Util::writeLog('core', 'include path for class "' . $class . '" starts with "apps/"', ILogger::DEBUG);
  96. $paths[] = str_replace('apps/', '', \OC::$CLASSPATH[$class]);
  97. }
  98. } elseif (strpos($class, 'OC_') === 0) {
  99. $paths[] = \OC::$SERVERROOT . '/lib/private/legacy/' . strtolower(str_replace('_', '/', substr($class, 3)) . '.php');
  100. } elseif (strpos($class, 'OCA\\') === 0) {
  101. [, $app, $rest] = explode('\\', $class, 3);
  102. $app = strtolower($app);
  103. $appPath = \OC_App::getAppPath($app);
  104. if ($appPath && stream_resolve_include_path($appPath)) {
  105. $paths[] = $appPath . '/' . strtolower(str_replace('\\', '/', $rest) . '.php');
  106. // If not found in the root of the app directory, insert '/lib' after app id and try again.
  107. $paths[] = $appPath . '/lib/' . strtolower(str_replace('\\', '/', $rest) . '.php');
  108. }
  109. } elseif ($class === 'Test\\TestCase') {
  110. // This File is considered public API, so we make sure that the class
  111. // can still be loaded, although the PSR-4 paths have not been loaded.
  112. $paths[] = \OC::$SERVERROOT . '/tests/lib/TestCase.php';
  113. }
  114. return $paths;
  115. }
  116. /**
  117. * @param string $fullPath
  118. * @return bool
  119. * @throws AutoloadNotAllowedException
  120. */
  121. protected function isValidPath(string $fullPath): bool {
  122. foreach ($this->validRoots as $root => $true) {
  123. if (substr($fullPath, 0, strlen($root) + 1) === $root . '/') {
  124. return true;
  125. }
  126. }
  127. throw new AutoloadNotAllowedException($fullPath);
  128. }
  129. /**
  130. * Load the specified class
  131. *
  132. * @param string $class
  133. * @return bool
  134. * @throws AutoloadNotAllowedException
  135. */
  136. public function load(string $class): bool {
  137. $pathsToRequire = null;
  138. if ($this->memoryCache) {
  139. $pathsToRequire = $this->memoryCache->get($class);
  140. }
  141. if (class_exists($class, false)) {
  142. return false;
  143. }
  144. if (!is_array($pathsToRequire)) {
  145. // No cache or cache miss
  146. $pathsToRequire = [];
  147. foreach ($this->findClass($class) as $path) {
  148. $fullPath = stream_resolve_include_path($path);
  149. if ($fullPath && $this->isValidPath($fullPath)) {
  150. $pathsToRequire[] = $fullPath;
  151. }
  152. }
  153. if ($this->memoryCache) {
  154. $this->memoryCache->set($class, $pathsToRequire, 60); // cache 60 sec
  155. }
  156. }
  157. foreach ($pathsToRequire as $fullPath) {
  158. require_once $fullPath;
  159. }
  160. return false;
  161. }
  162. /**
  163. * Sets the optional low-latency cache for class to path mapping.
  164. *
  165. * @param \OC\Memcache\Cache $memoryCache Instance of memory cache.
  166. */
  167. public function setMemoryCache(\OC\Memcache\Cache $memoryCache = null) {
  168. $this->memoryCache = $memoryCache;
  169. }
  170. }