1: <?php
2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21:
22:
23:
24: require_once 'Zend/Loader/PluginLoader/Interface.php';
25:
26:
27: require_once 'Zend/Loader.php';
28:
29: 30: 31: 32: 33: 34: 35: 36: 37:
38: class Zend_Loader_PluginLoader implements Zend_Loader_PluginLoader_Interface
39: {
40: 41: 42: 43:
44: protected static $_includeFileCache;
45:
46: 47: 48: 49: 50:
51: protected $_loadedPluginPaths = array();
52:
53: 54: 55: 56: 57:
58: protected $_loadedPlugins = array();
59:
60: 61: 62: 63: 64:
65: protected $_prefixToPaths = array();
66:
67: 68: 69: 70: 71:
72: protected static $_staticLoadedPluginPaths = array();
73:
74: 75: 76: 77: 78:
79: protected static $_staticLoadedPlugins = array();
80:
81: 82: 83: 84: 85:
86: protected static $_staticPrefixToPaths = array();
87:
88: 89: 90: 91: 92:
93: protected $_useStaticRegistry = null;
94:
95: 96: 97: 98: 99: 100:
101: public function __construct(Array $prefixToPaths = array(), $staticRegistryName = null)
102: {
103: if (is_string($staticRegistryName) && !empty($staticRegistryName)) {
104: $this->_useStaticRegistry = $staticRegistryName;
105: if(!isset(self::$_staticPrefixToPaths[$staticRegistryName])) {
106: self::$_staticPrefixToPaths[$staticRegistryName] = array();
107: }
108: if(!isset(self::$_staticLoadedPlugins[$staticRegistryName])) {
109: self::$_staticLoadedPlugins[$staticRegistryName] = array();
110: }
111: }
112:
113: foreach ($prefixToPaths as $prefix => $path) {
114: $this->addPrefixPath($prefix, $path);
115: }
116: }
117:
118: 119: 120: 121: 122: 123:
124: protected function _formatPrefix($prefix)
125: {
126: if($prefix == "") {
127: return $prefix;
128: }
129:
130: $last = strlen($prefix) - 1;
131: if ($prefix{$last} == '\\') {
132: return $prefix;
133: }
134:
135: return rtrim($prefix, '_') . '_';
136: }
137:
138: 139: 140: 141: 142: 143: 144:
145: public function addPrefixPath($prefix, $path)
146: {
147: if (!is_string($prefix) || !is_string($path)) {
148: require_once 'Zend/Loader/PluginLoader/Exception.php';
149: throw new Zend_Loader_PluginLoader_Exception('Zend_Loader_PluginLoader::addPrefixPath() method only takes strings for prefix and path.');
150: }
151:
152: $prefix = $this->_formatPrefix($prefix);
153: $path = rtrim($path, '/\\') . '/';
154:
155: if ($this->_useStaticRegistry) {
156: self::$_staticPrefixToPaths[$this->_useStaticRegistry][$prefix][] = $path;
157: } else {
158: if (!isset($this->_prefixToPaths[$prefix])) {
159: $this->_prefixToPaths[$prefix] = array();
160: }
161: if (!in_array($path, $this->_prefixToPaths[$prefix])) {
162: $this->_prefixToPaths[$prefix][] = $path;
163: }
164: }
165: return $this;
166: }
167:
168: 169: 170: 171: 172: 173:
174: public function getPaths($prefix = null)
175: {
176: if ((null !== $prefix) && is_string($prefix)) {
177: $prefix = $this->_formatPrefix($prefix);
178: if ($this->_useStaticRegistry) {
179: if (isset(self::$_staticPrefixToPaths[$this->_useStaticRegistry][$prefix])) {
180: return self::$_staticPrefixToPaths[$this->_useStaticRegistry][$prefix];
181: }
182:
183: return false;
184: }
185:
186: if (isset($this->_prefixToPaths[$prefix])) {
187: return $this->_prefixToPaths[$prefix];
188: }
189:
190: return false;
191: }
192:
193: if ($this->_useStaticRegistry) {
194: return self::$_staticPrefixToPaths[$this->_useStaticRegistry];
195: }
196:
197: return $this->_prefixToPaths;
198: }
199:
200: 201: 202: 203: 204: 205:
206: public function clearPaths($prefix = null)
207: {
208: if ((null !== $prefix) && is_string($prefix)) {
209: $prefix = $this->_formatPrefix($prefix);
210: if ($this->_useStaticRegistry) {
211: if (isset(self::$_staticPrefixToPaths[$this->_useStaticRegistry][$prefix])) {
212: unset(self::$_staticPrefixToPaths[$this->_useStaticRegistry][$prefix]);
213: return true;
214: }
215:
216: return false;
217: }
218:
219: if (isset($this->_prefixToPaths[$prefix])) {
220: unset($this->_prefixToPaths[$prefix]);
221: return true;
222: }
223:
224: return false;
225: }
226:
227: if ($this->_useStaticRegistry) {
228: self::$_staticPrefixToPaths[$this->_useStaticRegistry] = array();
229: } else {
230: $this->_prefixToPaths = array();
231: }
232:
233: return true;
234: }
235:
236: 237: 238: 239: 240: 241: 242:
243: public function removePrefixPath($prefix, $path = null)
244: {
245: $prefix = $this->_formatPrefix($prefix);
246: if ($this->_useStaticRegistry) {
247: $registry =& self::$_staticPrefixToPaths[$this->_useStaticRegistry];
248: } else {
249: $registry =& $this->_prefixToPaths;
250: }
251:
252: if (!isset($registry[$prefix])) {
253: require_once 'Zend/Loader/PluginLoader/Exception.php';
254: throw new Zend_Loader_PluginLoader_Exception('Prefix ' . $prefix . ' was not found in the PluginLoader.');
255: }
256:
257: if ($path != null) {
258: $pos = array_search($path, $registry[$prefix]);
259: if (false === $pos) {
260: require_once 'Zend/Loader/PluginLoader/Exception.php';
261: throw new Zend_Loader_PluginLoader_Exception('Prefix ' . $prefix . ' / Path ' . $path . ' was not found in the PluginLoader.');
262: }
263: unset($registry[$prefix][$pos]);
264: } else {
265: unset($registry[$prefix]);
266: }
267:
268: return $this;
269: }
270:
271: 272: 273: 274: 275: 276:
277: protected function _formatName($name)
278: {
279: return ucfirst((string) $name);
280: }
281:
282: 283: 284: 285: 286: 287:
288: public function isLoaded($name)
289: {
290: $name = $this->_formatName($name);
291: if ($this->_useStaticRegistry) {
292: return isset(self::$_staticLoadedPlugins[$this->_useStaticRegistry][$name]);
293: }
294:
295: return isset($this->_loadedPlugins[$name]);
296: }
297:
298: 299: 300: 301: 302: 303:
304: public function getClassName($name)
305: {
306: $name = $this->_formatName($name);
307: if ($this->_useStaticRegistry
308: && isset(self::$_staticLoadedPlugins[$this->_useStaticRegistry][$name])
309: ) {
310: return self::$_staticLoadedPlugins[$this->_useStaticRegistry][$name];
311: } elseif (isset($this->_loadedPlugins[$name])) {
312: return $this->_loadedPlugins[$name];
313: }
314:
315: return false;
316: }
317:
318: 319: 320: 321: 322: 323:
324: public function getClassPath($name)
325: {
326: $name = $this->_formatName($name);
327: if ($this->_useStaticRegistry
328: && !empty(self::$_staticLoadedPluginPaths[$this->_useStaticRegistry][$name])
329: ) {
330: return self::$_staticLoadedPluginPaths[$this->_useStaticRegistry][$name];
331: } elseif (!empty($this->_loadedPluginPaths[$name])) {
332: return $this->_loadedPluginPaths[$name];
333: }
334:
335: if ($this->isLoaded($name)) {
336: $class = $this->getClassName($name);
337: $r = new ReflectionClass($class);
338: $path = $r->getFileName();
339: if ($this->_useStaticRegistry) {
340: self::$_staticLoadedPluginPaths[$this->_useStaticRegistry][$name] = $path;
341: } else {
342: $this->_loadedPluginPaths[$name] = $path;
343: }
344: return $path;
345: }
346:
347: return false;
348: }
349:
350: 351: 352: 353: 354: 355: 356: 357: 358: 359:
360: public function load($name, $throwExceptions = true)
361: {
362: $name = $this->_formatName($name);
363: if ($this->isLoaded($name)) {
364: return $this->getClassName($name);
365: }
366:
367: if ($this->_useStaticRegistry) {
368: $registry = self::$_staticPrefixToPaths[$this->_useStaticRegistry];
369: } else {
370: $registry = $this->_prefixToPaths;
371: }
372:
373: $registry = array_reverse($registry, true);
374: $found = false;
375: $classFile = str_replace('_', DIRECTORY_SEPARATOR, $name) . '.php';
376: $incFile = self::getIncludeFileCache();
377: foreach ($registry as $prefix => $paths) {
378: $className = $prefix . $name;
379:
380: if (class_exists($className, false)) {
381: $found = true;
382: break;
383: }
384:
385: $paths = array_reverse($paths, true);
386:
387: foreach ($paths as $path) {
388: $loadFile = $path . $classFile;
389: if (Zend_Loader::isReadable($loadFile)) {
390: include_once $loadFile;
391: if (class_exists($className, false)) {
392: if (null !== $incFile) {
393: self::_appendIncFile($loadFile);
394: }
395: $found = true;
396: break 2;
397: }
398: }
399: }
400: }
401:
402: if (!$found) {
403: if (!$throwExceptions) {
404: return false;
405: }
406:
407: $message = "Plugin by name '$name' was not found in the registry; used paths:";
408: foreach ($registry as $prefix => $paths) {
409: $message .= "\n$prefix: " . implode(PATH_SEPARATOR, $paths);
410: }
411: require_once 'Zend/Loader/PluginLoader/Exception.php';
412: throw new Zend_Loader_PluginLoader_Exception($message);
413: }
414:
415: if ($this->_useStaticRegistry) {
416: self::$_staticLoadedPlugins[$this->_useStaticRegistry][$name] = $className;
417: } else {
418: $this->_loadedPlugins[$name] = $className;
419: }
420: return $className;
421: }
422:
423: 424: 425: 426: 427: 428: 429: 430: 431: 432:
433: public static function setIncludeFileCache($file)
434: {
435: if (null === $file) {
436: self::$_includeFileCache = null;
437: return;
438: }
439:
440: if (!file_exists($file) && !file_exists(dirname($file))) {
441: require_once 'Zend/Loader/PluginLoader/Exception.php';
442: throw new Zend_Loader_PluginLoader_Exception('Specified file does not exist and/or directory does not exist (' . $file . ')');
443: }
444: if (file_exists($file) && !is_writable($file)) {
445: require_once 'Zend/Loader/PluginLoader/Exception.php';
446: throw new Zend_Loader_PluginLoader_Exception('Specified file is not writeable (' . $file . ')');
447: }
448: if (!file_exists($file) && file_exists(dirname($file)) && !is_writable(dirname($file))) {
449: require_once 'Zend/Loader/PluginLoader/Exception.php';
450: throw new Zend_Loader_PluginLoader_Exception('Specified file is not writeable (' . $file . ')');
451: }
452:
453: self::$_includeFileCache = $file;
454: }
455:
456: 457: 458: 459: 460:
461: public static function getIncludeFileCache()
462: {
463: return self::$_includeFileCache;
464: }
465:
466: 467: 468: 469: 470: 471:
472: protected static function _appendIncFile($incFile)
473: {
474: if (!file_exists(self::$_includeFileCache)) {
475: $file = '<?php';
476: } else {
477: $file = file_get_contents(self::$_includeFileCache);
478: }
479: if (!strstr($file, $incFile)) {
480: $file .= "\ninclude_once '$incFile';";
481: file_put_contents(self::$_includeFileCache, $file);
482: }
483: }
484: }
485: