PageRenderTime 23ms CodeModel.GetById 16ms RepoModel.GetById 0ms app.codeStats 0ms

/tine20/library/Zend/Loader/PluginLoader.php

https://gitlab.com/rsilveira1987/Expresso
PHP | 475 lines | 371 code | 15 blank | 89 comment | 8 complexity | c1dc970fb583316412376b5f9fd0744b MD5 | raw file
  1. <?php
  2. /**
  3. * Zend Framework
  4. *
  5. * LICENSE
  6. *
  7. * This source file is subject to the new BSD license that is bundled
  8. * with this package in the file LICENSE.txt.
  9. * It is also available through the world-wide-web at this URL:
  10. * http://framework.zend.com/license/new-bsd
  11. * If you did not receive a copy of the license and are unable to
  12. * obtain it through the world-wide-web, please send an email
  13. * to license@zend.com so we can send you a copy immediately.
  14. *
  15. * @category Zend
  16. * @package Zend_Loader
  17. * @subpackage PluginLoader
  18. * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
  19. * @license http://framework.zend.com/license/new-bsd New BSD License
  20. * @version $Id: PluginLoader.php 10020 2009-08-18 14:34:09Z j.fischer@metaways.de $
  21. */
  22. /** Zend_Loader_PluginLoader_Interface */
  23. require_once 'Zend/Loader/PluginLoader/Interface.php';
  24. /** Zend_Loader */
  25. require_once 'Zend/Loader.php';
  26. /**
  27. * Generic plugin class loader
  28. *
  29. * @category Zend
  30. * @package Zend_Loader
  31. * @subpackage PluginLoader
  32. * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
  33. * @license http://framework.zend.com/license/new-bsd New BSD License
  34. */
  35. class Zend_Loader_PluginLoader implements Zend_Loader_PluginLoader_Interface
  36. {
  37. /**
  38. * Class map cache file
  39. * @var string
  40. */
  41. protected static $_includeFileCache;
  42. /**
  43. * Instance loaded plugin paths
  44. *
  45. * @var array
  46. */
  47. protected $_loadedPluginPaths = array();
  48. /**
  49. * Instance loaded plugins
  50. *
  51. * @var array
  52. */
  53. protected $_loadedPlugins = array();
  54. /**
  55. * Instance registry property
  56. *
  57. * @var array
  58. */
  59. protected $_prefixToPaths = array();
  60. /**
  61. * Statically loaded plugin path mappings
  62. *
  63. * @var array
  64. */
  65. protected static $_staticLoadedPluginPaths = array();
  66. /**
  67. * Statically loaded plugins
  68. *
  69. * @var array
  70. */
  71. protected static $_staticLoadedPlugins = array();
  72. /**
  73. * Static registry property
  74. *
  75. * @var array
  76. */
  77. protected static $_staticPrefixToPaths = array();
  78. /**
  79. * Whether to use a statically named registry for loading plugins
  80. *
  81. * @var string|null
  82. */
  83. protected $_useStaticRegistry = null;
  84. /**
  85. * Constructor
  86. *
  87. * @param array $prefixToPaths
  88. * @param string $staticRegistryName OPTIONAL
  89. */
  90. public function __construct(Array $prefixToPaths = array(), $staticRegistryName = null)
  91. {
  92. if (is_string($staticRegistryName) && !empty($staticRegistryName)) {
  93. $this->_useStaticRegistry = $staticRegistryName;
  94. if(!isset(self::$_staticPrefixToPaths[$staticRegistryName])) {
  95. self::$_staticPrefixToPaths[$staticRegistryName] = array();
  96. }
  97. if(!isset(self::$_staticLoadedPlugins[$staticRegistryName])) {
  98. self::$_staticLoadedPlugins[$staticRegistryName] = array();
  99. }
  100. }
  101. foreach ($prefixToPaths as $prefix => $path) {
  102. $this->addPrefixPath($prefix, $path);
  103. }
  104. }
  105. /**
  106. * Format prefix for internal use
  107. *
  108. * @param string $prefix
  109. * @return string
  110. */
  111. protected function _formatPrefix($prefix)
  112. {
  113. if($prefix == "") {
  114. return $prefix;
  115. }
  116. return rtrim($prefix, '_') . '_';
  117. }
  118. /**
  119. * Add prefixed paths to the registry of paths
  120. *
  121. * @param string $prefix
  122. * @param string $path
  123. * @return Zend_Loader_PluginLoader
  124. */
  125. public function addPrefixPath($prefix, $path)
  126. {
  127. if (!is_string($prefix) || !is_string($path)) {
  128. require_once 'Zend/Loader/PluginLoader/Exception.php';
  129. throw new Zend_Loader_PluginLoader_Exception('Zend_Loader_PluginLoader::addPrefixPath() method only takes strings for prefix and path.');
  130. }
  131. $prefix = $this->_formatPrefix($prefix);
  132. $path = rtrim($path, '/\\') . '/';
  133. if ($this->_useStaticRegistry) {
  134. self::$_staticPrefixToPaths[$this->_useStaticRegistry][$prefix][] = $path;
  135. } else {
  136. $this->_prefixToPaths[$prefix][] = $path;
  137. }
  138. return $this;
  139. }
  140. /**
  141. * Get path stack
  142. *
  143. * @param string $prefix
  144. * @return false|array False if prefix does not exist, array otherwise
  145. */
  146. public function getPaths($prefix = null)
  147. {
  148. if ((null !== $prefix) && is_string($prefix)) {
  149. $prefix = $this->_formatPrefix($prefix);
  150. if ($this->_useStaticRegistry) {
  151. if (isset(self::$_staticPrefixToPaths[$this->_useStaticRegistry][$prefix])) {
  152. return self::$_staticPrefixToPaths[$this->_useStaticRegistry][$prefix];
  153. }
  154. return false;
  155. }
  156. if (isset($this->_prefixToPaths[$prefix])) {
  157. return $this->_prefixToPaths[$prefix];
  158. }
  159. return false;
  160. }
  161. if ($this->_useStaticRegistry) {
  162. return self::$_staticPrefixToPaths[$this->_useStaticRegistry];
  163. }
  164. return $this->_prefixToPaths;
  165. }
  166. /**
  167. * Clear path stack
  168. *
  169. * @param string $prefix
  170. * @return bool False only if $prefix does not exist
  171. */
  172. public function clearPaths($prefix = null)
  173. {
  174. if ((null !== $prefix) && is_string($prefix)) {
  175. $prefix = $this->_formatPrefix($prefix);
  176. if ($this->_useStaticRegistry) {
  177. if (isset(self::$_staticPrefixToPaths[$this->_useStaticRegistry][$prefix])) {
  178. unset(self::$_staticPrefixToPaths[$this->_useStaticRegistry][$prefix]);
  179. return true;
  180. }
  181. return false;
  182. }
  183. if (isset($this->_prefixToPaths[$prefix])) {
  184. unset($this->_prefixToPaths[$prefix]);
  185. return true;
  186. }
  187. return false;
  188. }
  189. if ($this->_useStaticRegistry) {
  190. self::$_staticPrefixToPaths[$this->_useStaticRegistry] = array();
  191. } else {
  192. $this->_prefixToPaths = array();
  193. }
  194. return true;
  195. }
  196. /**
  197. * Remove a prefix (or prefixed-path) from the registry
  198. *
  199. * @param string $prefix
  200. * @param string $path OPTIONAL
  201. * @return Zend_Loader_PluginLoader
  202. */
  203. public function removePrefixPath($prefix, $path = null)
  204. {
  205. $prefix = $this->_formatPrefix($prefix);
  206. if ($this->_useStaticRegistry) {
  207. $registry =& self::$_staticPrefixToPaths[$this->_useStaticRegistry];
  208. } else {
  209. $registry =& $this->_prefixToPaths;
  210. }
  211. if (!isset($registry[$prefix])) {
  212. require_once 'Zend/Loader/PluginLoader/Exception.php';
  213. throw new Zend_Loader_PluginLoader_Exception('Prefix ' . $prefix . ' was not found in the PluginLoader.');
  214. }
  215. if ($path != null) {
  216. $pos = array_search($path, $registry[$prefix]);
  217. if ($pos === null) {
  218. require_once 'Zend/Loader/PluginLoader/Exception.php';
  219. throw new Zend_Loader_PluginLoader_Exception('Prefix ' . $prefix . ' / Path ' . $path . ' was not found in the PluginLoader.');
  220. }
  221. unset($registry[$prefix][$pos]);
  222. } else {
  223. unset($registry[$prefix]);
  224. }
  225. return $this;
  226. }
  227. /**
  228. * Normalize plugin name
  229. *
  230. * @param string $name
  231. * @return string
  232. */
  233. protected function _formatName($name)
  234. {
  235. return ucfirst((string) $name);
  236. }
  237. /**
  238. * Whether or not a Plugin by a specific name is loaded
  239. *
  240. * @param string $name
  241. * @return Zend_Loader_PluginLoader
  242. */
  243. public function isLoaded($name)
  244. {
  245. $name = $this->_formatName($name);
  246. if ($this->_useStaticRegistry) {
  247. return isset(self::$_staticLoadedPlugins[$this->_useStaticRegistry][$name]);
  248. }
  249. return isset($this->_loadedPlugins[$name]);
  250. }
  251. /**
  252. * Return full class name for a named plugin
  253. *
  254. * @param string $name
  255. * @return string|false False if class not found, class name otherwise
  256. */
  257. public function getClassName($name)
  258. {
  259. $name = $this->_formatName($name);
  260. if ($this->_useStaticRegistry
  261. && isset(self::$_staticLoadedPlugins[$this->_useStaticRegistry][$name])
  262. ) {
  263. return self::$_staticLoadedPlugins[$this->_useStaticRegistry][$name];
  264. } elseif (isset($this->_loadedPlugins[$name])) {
  265. return $this->_loadedPlugins[$name];
  266. }
  267. return false;
  268. }
  269. /**
  270. * Get path to plugin class
  271. *
  272. * @param mixed $name
  273. * @return string|false False if not found
  274. */
  275. public function getClassPath($name)
  276. {
  277. $name = $this->_formatName($name);
  278. if ($this->_useStaticRegistry
  279. && !empty(self::$_staticLoadedPluginPaths[$this->_useStaticRegistry][$name])
  280. ) {
  281. return self::$_staticLoadedPluginPaths[$this->_useStaticRegistry][$name];
  282. } elseif (!empty($this->_loadedPluginPaths[$name])) {
  283. return $this->_loadedPluginPaths[$name];
  284. }
  285. if ($this->isLoaded($name)) {
  286. $class = $this->getClassName($name);
  287. $r = new ReflectionClass($class);
  288. $path = $r->getFileName();
  289. if ($this->_useStaticRegistry) {
  290. self::$_staticLoadedPluginPaths[$this->_useStaticRegistry][$name] = $path;
  291. } else {
  292. $this->_loadedPluginPaths[$name] = $path;
  293. }
  294. return $path;
  295. }
  296. return false;
  297. }
  298. /**
  299. * Load a plugin via the name provided
  300. *
  301. * @param string $name
  302. * @param bool $throwExceptions Whether or not to throw exceptions if the
  303. * class is not resolved
  304. * @return string|false Class name of loaded class; false if $throwExceptions
  305. * if false and no class found
  306. * @throws Zend_Loader_Exception if class not found
  307. */
  308. public function load($name, $throwExceptions = true)
  309. {
  310. $name = $this->_formatName($name);
  311. if ($this->isLoaded($name)) {
  312. return $this->getClassName($name);
  313. }
  314. if ($this->_useStaticRegistry) {
  315. $registry = self::$_staticPrefixToPaths[$this->_useStaticRegistry];
  316. } else {
  317. $registry = $this->_prefixToPaths;
  318. }
  319. $registry = array_reverse($registry, true);
  320. $found = false;
  321. $classFile = str_replace('_', DIRECTORY_SEPARATOR, $name) . '.php';
  322. $incFile = self::getIncludeFileCache();
  323. foreach ($registry as $prefix => $paths) {
  324. $className = $prefix . $name;
  325. if (class_exists($className, false)) {
  326. $found = true;
  327. break;
  328. }
  329. $paths = array_reverse($paths, true);
  330. foreach ($paths as $path) {
  331. $loadFile = $path . $classFile;
  332. if (Zend_Loader::isReadable($loadFile)) {
  333. include_once $loadFile;
  334. if (class_exists($className, false)) {
  335. if (null !== $incFile) {
  336. self::_appendIncFile($loadFile);
  337. }
  338. $found = true;
  339. break 2;
  340. }
  341. }
  342. }
  343. }
  344. if (!$found) {
  345. if (!$throwExceptions) {
  346. return false;
  347. }
  348. $message = "Plugin by name '$name' was not found in the registry; used paths:";
  349. foreach ($registry as $prefix => $paths) {
  350. $message .= "\n$prefix: " . implode(PATH_SEPARATOR, $paths);
  351. }
  352. require_once 'Zend/Loader/PluginLoader/Exception.php';
  353. throw new Zend_Loader_PluginLoader_Exception($message);
  354. }
  355. if ($this->_useStaticRegistry) {
  356. self::$_staticLoadedPlugins[$this->_useStaticRegistry][$name] = $className;
  357. self::$_staticLoadedPluginPaths[$this->_useStaticRegistry][$name] = (isset($loadFile) ? $loadFile : '');
  358. } else {
  359. $this->_loadedPlugins[$name] = $className;
  360. $this->_loadedPluginPaths[$name] = (isset($loadFile) ? $loadFile : '');
  361. }
  362. return $className;
  363. }
  364. /**
  365. * Set path to class file cache
  366. *
  367. * Specify a path to a file that will add include_once statements for each
  368. * plugin class loaded. This is an opt-in feature for performance purposes.
  369. *
  370. * @param string $file
  371. * @return void
  372. * @throws Zend_Loader_PluginLoader_Exception if file is not writeable or path does not exist
  373. */
  374. public static function setIncludeFileCache($file)
  375. {
  376. if (null === $file) {
  377. self::$_includeFileCache = null;
  378. return;
  379. }
  380. if (!file_exists($file) && !file_exists(dirname($file))) {
  381. require_once 'Zend/Loader/PluginLoader/Exception.php';
  382. throw new Zend_Loader_PluginLoader_Exception('Specified file does not exist and/or directory does not exist (' . $file . ')');
  383. }
  384. if (file_exists($file) && !is_writable($file)) {
  385. require_once 'Zend/Loader/PluginLoader/Exception.php';
  386. throw new Zend_Loader_PluginLoader_Exception('Specified file is not writeable (' . $file . ')');
  387. }
  388. if (!file_exists($file) && file_exists(dirname($file)) && !is_writable(dirname($file))) {
  389. require_once 'Zend/Loader/PluginLoader/Exception.php';
  390. throw new Zend_Loader_PluginLoader_Exception('Specified file is not writeable (' . $file . ')');
  391. }
  392. self::$_includeFileCache = $file;
  393. }
  394. /**
  395. * Retrieve class file cache path
  396. *
  397. * @return string|null
  398. */
  399. public static function getIncludeFileCache()
  400. {
  401. return self::$_includeFileCache;
  402. }
  403. /**
  404. * Append an include_once statement to the class file cache
  405. *
  406. * @param string $incFile
  407. * @return void
  408. */
  409. protected static function _appendIncFile($incFile)
  410. {
  411. if (!file_exists(self::$_includeFileCache)) {
  412. $file = '<?php';
  413. } else {
  414. $file = file_get_contents(self::$_includeFileCache);
  415. }
  416. if (!strstr($file, $incFile)) {
  417. $file .= "\ninclude_once '$incFile';";
  418. file_put_contents(self::$_includeFileCache, $file);
  419. }
  420. }
  421. }