source: trunk/library/Zend/Loader/PluginLoader.php @ 5146

Revision 5146, 14.4 KB checked in by wmerlotto, 12 years ago (diff)

Ticket #2305 - Enviando alteracoes, desenvolvidas internamente na Prognus. Library: adicionando arquivos.

Line 
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-2010 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 22603 2010-07-17 00:02:10Z ramon $
21 */
22
23/** Zend_Loader_PluginLoader_Interface */
24require_once 'Zend/Loader/PluginLoader/Interface.php';
25
26/** Zend_Loader */
27require_once 'Zend/Loader.php';
28
29/**
30 * Generic plugin class loader
31 *
32 * @category   Zend
33 * @package    Zend_Loader
34 * @subpackage PluginLoader
35 * @copyright  Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
36 * @license    http://framework.zend.com/license/new-bsd     New BSD License
37 */
38class Zend_Loader_PluginLoader implements Zend_Loader_PluginLoader_Interface
39{
40    /**
41     * Class map cache file
42     * @var string
43     */
44    protected static $_includeFileCache;
45
46    /**
47     * Instance loaded plugin paths
48     *
49     * @var array
50     */
51    protected $_loadedPluginPaths = array();
52
53    /**
54     * Instance loaded plugins
55     *
56     * @var array
57     */
58    protected $_loadedPlugins = array();
59
60    /**
61     * Instance registry property
62     *
63     * @var array
64     */
65    protected $_prefixToPaths = array();
66
67    /**
68     * Statically loaded plugin path mappings
69     *
70     * @var array
71     */
72    protected static $_staticLoadedPluginPaths = array();
73
74    /**
75     * Statically loaded plugins
76     *
77     * @var array
78     */
79    protected static $_staticLoadedPlugins = array();
80
81    /**
82     * Static registry property
83     *
84     * @var array
85     */
86    protected static $_staticPrefixToPaths = array();
87
88    /**
89     * Whether to use a statically named registry for loading plugins
90     *
91     * @var string|null
92     */
93    protected $_useStaticRegistry = null;
94
95    /**
96     * Constructor
97     *
98     * @param array $prefixToPaths
99     * @param string $staticRegistryName OPTIONAL
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     * Format prefix for internal use
120     *
121     * @param  string $prefix
122     * @return string
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     * Add prefixed paths to the registry of paths
140     *
141     * @param string $prefix
142     * @param string $path
143     * @return Zend_Loader_PluginLoader
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     * Get path stack
170     *
171     * @param  string $prefix
172     * @return false|array False if prefix does not exist, array otherwise
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     * Clear path stack
202     *
203     * @param  string $prefix
204     * @return bool False only if $prefix does not exist
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     * Remove a prefix (or prefixed-path) from the registry
238     *
239     * @param string $prefix
240     * @param string $path OPTIONAL
241     * @return Zend_Loader_PluginLoader
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     * Normalize plugin name
273     *
274     * @param  string $name
275     * @return string
276     */
277    protected function _formatName($name)
278    {
279        return ucfirst((string) $name);
280    }
281
282    /**
283     * Whether or not a Plugin by a specific name is loaded
284     *
285     * @param string $name
286     * @return Zend_Loader_PluginLoader
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     * Return full class name for a named plugin
300     *
301     * @param string $name
302     * @return string|false False if class not found, class name otherwise
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     * Get path to plugin class
320     *
321     * @param  mixed $name
322     * @return string|false False if not found
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     * Load a plugin via the name provided
352     *
353     * @param  string $name
354     * @param  bool $throwExceptions Whether or not to throw exceptions if the
355     * class is not resolved
356     * @return string|false Class name of loaded class; false if $throwExceptions
357     * if false and no class found
358     * @throws Zend_Loader_Exception if class not found
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     * Set path to class file cache
425     *
426     * Specify a path to a file that will add include_once statements for each
427     * plugin class loaded. This is an opt-in feature for performance purposes.
428     *
429     * @param  string $file
430     * @return void
431     * @throws Zend_Loader_PluginLoader_Exception if file is not writeable or path does not exist
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     * Retrieve class file cache path
458     *
459     * @return string|null
460     */
461    public static function getIncludeFileCache()
462    {
463        return self::$_includeFileCache;
464    }
465
466    /**
467     * Append an include_once statement to the class file cache
468     *
469     * @param  string $incFile
470     * @return void
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}
Note: See TracBrowser for help on using the repository browser.