PageRenderTime 120ms CodeModel.GetById 37ms RepoModel.GetById 4ms app.codeStats 0ms

/application/libraries/Zend/Loader/PluginLoader.php

https://github.com/grandison/budo16
PHP | 480 lines | 373 code | 15 blank | 92 comment | 8 complexity | 8b2b62dee33b1afc8af67334d54f7d6b 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 18207 2009-09-17 22:29:50Z beberlei $
  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. if (!isset($this->_prefixToPaths[$prefix])) {
  137. $this->_prefixToPaths[$prefix] = array();
  138. }
  139. if (!in_array($path, $this->_prefixToPaths[$prefix])) {
  140. $this->_prefixToPaths[$prefix][] = $path;
  141. }
  142. }
  143. return $this;
  144. }
  145. /**
  146. * Get path stack
  147. *
  148. * @param string $prefix
  149. * @return false|array False if prefix does not exist, array otherwise
  150. */
  151. public function getPaths($prefix = null)
  152. {
  153. if ((null !== $prefix) && is_string($prefix)) {
  154. $prefix = $this->_formatPrefix($prefix);
  155. if ($this->_useStaticRegistry) {
  156. if (isset(self::$_staticPrefixToPaths[$this->_useStaticRegistry][$prefix])) {
  157. return self::$_staticPrefixToPaths[$this->_useStaticRegistry][$prefix];
  158. }
  159. return false;
  160. }
  161. if (isset($this->_prefixToPaths[$prefix])) {
  162. return $this->_prefixToPaths[$prefix];
  163. }
  164. return false;
  165. }
  166. if ($this->_useStaticRegistry) {
  167. return self::$_staticPrefixToPaths[$this->_useStaticRegistry];
  168. }
  169. return $this->_prefixToPaths;
  170. }
  171. /**
  172. * Clear path stack
  173. *
  174. * @param string $prefix
  175. * @return bool False only if $prefix does not exist
  176. */
  177. public function clearPaths($prefix = null)
  178. {
  179. if ((null !== $prefix) && is_string($prefix)) {
  180. $prefix = $this->_formatPrefix($prefix);
  181. if ($this->_useStaticRegistry) {
  182. if (isset(self::$_staticPrefixToPaths[$this->_useStaticRegistry][$prefix])) {
  183. unset(self::$_staticPrefixToPaths[$this->_useStaticRegistry][$prefix]);
  184. return true;
  185. }
  186. return false;
  187. }
  188. if (isset($this->_prefixToPaths[$prefix])) {
  189. unset($this->_prefixToPaths[$prefix]);
  190. return true;
  191. }
  192. return false;
  193. }
  194. if ($this->_useStaticRegistry) {
  195. self::$_staticPrefixToPaths[$this->_useStaticRegistry] = array();
  196. } else {
  197. $this->_prefixToPaths = array();
  198. }
  199. return true;
  200. }
  201. /**
  202. * Remove a prefix (or prefixed-path) from the registry
  203. *
  204. * @param string $prefix
  205. * @param string $path OPTIONAL
  206. * @return Zend_Loader_PluginLoader
  207. */
  208. public function removePrefixPath($prefix, $path = null)
  209. {
  210. $prefix = $this->_formatPrefix($prefix);
  211. if ($this->_useStaticRegistry) {
  212. $registry =& self::$_staticPrefixToPaths[$this->_useStaticRegistry];
  213. } else {
  214. $registry =& $this->_prefixToPaths;
  215. }
  216. if (!isset($registry[$prefix])) {
  217. // require_once 'Zend/Loader/PluginLoader/Exception.php';
  218. throw new Zend_Loader_PluginLoader_Exception('Prefix ' . $prefix . ' was not found in the PluginLoader.');
  219. }
  220. if ($path != null) {
  221. $pos = array_search($path, $registry[$prefix]);
  222. if ($pos === null) {
  223. // require_once 'Zend/Loader/PluginLoader/Exception.php';
  224. throw new Zend_Loader_PluginLoader_Exception('Prefix ' . $prefix . ' / Path ' . $path . ' was not found in the PluginLoader.');
  225. }
  226. unset($registry[$prefix][$pos]);
  227. } else {
  228. unset($registry[$prefix]);
  229. }
  230. return $this;
  231. }
  232. /**
  233. * Normalize plugin name
  234. *
  235. * @param string $name
  236. * @return string
  237. */
  238. protected function _formatName($name)
  239. {
  240. return ucfirst((string) $name);
  241. }
  242. /**
  243. * Whether or not a Plugin by a specific name is loaded
  244. *
  245. * @param string $name
  246. * @return Zend_Loader_PluginLoader
  247. */
  248. public function isLoaded($name)
  249. {
  250. $name = $this->_formatName($name);
  251. if ($this->_useStaticRegistry) {
  252. return isset(self::$_staticLoadedPlugins[$this->_useStaticRegistry][$name]);
  253. }
  254. return isset($this->_loadedPlugins[$name]);
  255. }
  256. /**
  257. * Return full class name for a named plugin
  258. *
  259. * @param string $name
  260. * @return string|false False if class not found, class name otherwise
  261. */
  262. public function getClassName($name)
  263. {
  264. $name = $this->_formatName($name);
  265. if ($this->_useStaticRegistry
  266. && isset(self::$_staticLoadedPlugins[$this->_useStaticRegistry][$name])
  267. ) {
  268. return self::$_staticLoadedPlugins[$this->_useStaticRegistry][$name];
  269. } elseif (isset($this->_loadedPlugins[$name])) {
  270. return $this->_loadedPlugins[$name];
  271. }
  272. return false;
  273. }
  274. /**
  275. * Get path to plugin class
  276. *
  277. * @param mixed $name
  278. * @return string|false False if not found
  279. */
  280. public function getClassPath($name)
  281. {
  282. $name = $this->_formatName($name);
  283. if ($this->_useStaticRegistry
  284. && !empty(self::$_staticLoadedPluginPaths[$this->_useStaticRegistry][$name])
  285. ) {
  286. return self::$_staticLoadedPluginPaths[$this->_useStaticRegistry][$name];
  287. } elseif (!empty($this->_loadedPluginPaths[$name])) {
  288. return $this->_loadedPluginPaths[$name];
  289. }
  290. if ($this->isLoaded($name)) {
  291. $class = $this->getClassName($name);
  292. $r = new ReflectionClass($class);
  293. $path = $r->getFileName();
  294. if ($this->_useStaticRegistry) {
  295. self::$_staticLoadedPluginPaths[$this->_useStaticRegistry][$name] = $path;
  296. } else {
  297. $this->_loadedPluginPaths[$name] = $path;
  298. }
  299. return $path;
  300. }
  301. return false;
  302. }
  303. /**
  304. * Load a plugin via the name provided
  305. *
  306. * @param string $name
  307. * @param bool $throwExceptions Whether or not to throw exceptions if the
  308. * class is not resolved
  309. * @return string|false Class name of loaded class; false if $throwExceptions
  310. * if false and no class found
  311. * @throws Zend_Loader_Exception if class not found
  312. */
  313. public function load($name, $throwExceptions = true)
  314. {
  315. $name = $this->_formatName($name);
  316. if ($this->isLoaded($name)) {
  317. return $this->getClassName($name);
  318. }
  319. if ($this->_useStaticRegistry) {
  320. $registry = self::$_staticPrefixToPaths[$this->_useStaticRegistry];
  321. } else {
  322. $registry = $this->_prefixToPaths;
  323. }
  324. $registry = array_reverse($registry, true);
  325. $found = false;
  326. $classFile = str_replace('_', DIRECTORY_SEPARATOR, $name) . '.php';
  327. $incFile = self::getIncludeFileCache();
  328. foreach ($registry as $prefix => $paths) {
  329. $className = $prefix . $name;
  330. if (class_exists($className, false)) {
  331. $found = true;
  332. break;
  333. }
  334. $paths = array_reverse($paths, true);
  335. foreach ($paths as $path) {
  336. $loadFile = $path . $classFile;
  337. if (Zend_Loader::isReadable($loadFile)) {
  338. include_once $loadFile;
  339. if (class_exists($className, false)) {
  340. if (null !== $incFile) {
  341. self::_appendIncFile($loadFile);
  342. }
  343. $found = true;
  344. break 2;
  345. }
  346. }
  347. }
  348. }
  349. if (!$found) {
  350. if (!$throwExceptions) {
  351. return false;
  352. }
  353. $message = "Plugin by name '$name' was not found in the registry; used paths:";
  354. foreach ($registry as $prefix => $paths) {
  355. $message .= "\n$prefix: " . implode(PATH_SEPARATOR, $paths);
  356. }
  357. // require_once 'Zend/Loader/PluginLoader/Exception.php';
  358. throw new Zend_Loader_PluginLoader_Exception($message);
  359. }
  360. if ($this->_useStaticRegistry) {
  361. self::$_staticLoadedPlugins[$this->_useStaticRegistry][$name] = $className;
  362. self::$_staticLoadedPluginPaths[$this->_useStaticRegistry][$name] = (isset($loadFile) ? $loadFile : '');
  363. } else {
  364. $this->_loadedPlugins[$name] = $className;
  365. $this->_loadedPluginPaths[$name] = (isset($loadFile) ? $loadFile : '');
  366. }
  367. return $className;
  368. }
  369. /**
  370. * Set path to class file cache
  371. *
  372. * Specify a path to a file that will add include_once statements for each
  373. * plugin class loaded. This is an opt-in feature for performance purposes.
  374. *
  375. * @param string $file
  376. * @return void
  377. * @throws Zend_Loader_PluginLoader_Exception if file is not writeable or path does not exist
  378. */
  379. public static function setIncludeFileCache($file)
  380. {
  381. if (null === $file) {
  382. self::$_includeFileCache = null;
  383. return;
  384. }
  385. if (!file_exists($file) && !file_exists(dirname($file))) {
  386. // require_once 'Zend/Loader/PluginLoader/Exception.php';
  387. throw new Zend_Loader_PluginLoader_Exception('Specified file does not exist and/or directory does not exist (' . $file . ')');
  388. }
  389. if (file_exists($file) && !is_writable($file)) {
  390. // require_once 'Zend/Loader/PluginLoader/Exception.php';
  391. throw new Zend_Loader_PluginLoader_Exception('Specified file is not writeable (' . $file . ')');
  392. }
  393. if (!file_exists($file) && file_exists(dirname($file)) && !is_writable(dirname($file))) {
  394. // require_once 'Zend/Loader/PluginLoader/Exception.php';
  395. throw new Zend_Loader_PluginLoader_Exception('Specified file is not writeable (' . $file . ')');
  396. }
  397. self::$_includeFileCache = $file;
  398. }
  399. /**
  400. * Retrieve class file cache path
  401. *
  402. * @return string|null
  403. */
  404. public static function getIncludeFileCache()
  405. {
  406. return self::$_includeFileCache;
  407. }
  408. /**
  409. * Append an include_once statement to the class file cache
  410. *
  411. * @param string $incFile
  412. * @return void
  413. */
  414. protected static function _appendIncFile($incFile)
  415. {
  416. if (!file_exists(self::$_includeFileCache)) {
  417. $file = '<?php';
  418. } else {
  419. $file = file_get_contents(self::$_includeFileCache);
  420. }
  421. if (!strstr($file, $incFile)) {
  422. $file .= "\ninclude_once '$incFile';";
  423. file_put_contents(self::$_includeFileCache, $file);
  424. }
  425. }
  426. }