467 Zeilen
		
	
	
	
		
			14 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
			
		
		
	
	
			467 Zeilen
		
	
	
	
		
			14 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
| <?php
 | |
| /**
 | |
|  * Zend Framework
 | |
|  *
 | |
|  * LICENSE
 | |
|  *
 | |
|  * This source file is subject to the new BSD license that is bundled
 | |
|  * with this package in the file LICENSE.txt.
 | |
|  * It is also available through the world-wide-web at this URL:
 | |
|  * http://framework.zend.com/license/new-bsd
 | |
|  * If you did not receive a copy of the license and are unable to
 | |
|  * obtain it through the world-wide-web, please send an email
 | |
|  * to license@zend.com so we can send you a copy immediately.
 | |
|  *
 | |
|  * @category   Zend
 | |
|  * @package    Zend_Loader
 | |
|  * @subpackage Autoloader
 | |
|  * @copyright  Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com)
 | |
|  * @version    $Id$
 | |
|  * @license    http://framework.zend.com/license/new-bsd     New BSD License
 | |
|  */
 | |
| 
 | |
| /** Zend_Loader_Autoloader_Interface */
 | |
| require_once 'Zend/Loader/Autoloader/Interface.php';
 | |
| 
 | |
| /**
 | |
|  * Resource loader
 | |
|  *
 | |
|  * @uses       Zend_Loader_Autoloader_Interface
 | |
|  * @package    Zend_Loader
 | |
|  * @subpackage Autoloader
 | |
|  * @copyright  Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com)
 | |
|  * @license    http://framework.zend.com/license/new-bsd     New BSD License
 | |
|  */
 | |
| class Zend_Loader_Autoloader_Resource implements Zend_Loader_Autoloader_Interface
 | |
| {
 | |
|     /**
 | |
|      * @var string Base path to resource classes
 | |
|      */
 | |
|     protected $_basePath;
 | |
| 
 | |
|     /**
 | |
|      * @var array Components handled within this resource
 | |
|      */
 | |
|     protected $_components = array();
 | |
| 
 | |
|     /**
 | |
|      * @var string Default resource/component to use when using object registry
 | |
|      */
 | |
|     protected $_defaultResourceType;
 | |
| 
 | |
|     /**
 | |
|      * @var string Namespace of classes within this resource
 | |
|      */
 | |
|     protected $_namespace;
 | |
| 
 | |
|     /**
 | |
|      * @var array Available resource types handled by this resource autoloader
 | |
|      */
 | |
|     protected $_resourceTypes = array();
 | |
| 
 | |
|     /**
 | |
|      * Constructor
 | |
|      *
 | |
|      * @param  array|Zend_Config $options Configuration options for resource autoloader
 | |
|      * @return void
 | |
|      */
 | |
|     public function __construct($options)
 | |
|     {
 | |
|         if ($options instanceof Zend_Config) {
 | |
|             $options = $options->toArray();
 | |
|         }
 | |
|         if (!is_array($options)) {
 | |
|             require_once 'Zend/Loader/Exception.php';
 | |
|             throw new Zend_Loader_Exception('Options must be passed to resource loader constructor');
 | |
|         }
 | |
| 
 | |
|         $this->setOptions($options);
 | |
| 
 | |
|         $namespace = $this->getNamespace();
 | |
|         if ((null === $namespace)
 | |
|             || (null === $this->getBasePath())
 | |
|         ) {
 | |
|             require_once 'Zend/Loader/Exception.php';
 | |
|             throw new Zend_Loader_Exception('Resource loader requires both a namespace and a base path for initialization');
 | |
|         }
 | |
| 
 | |
|         if (!empty($namespace)) {
 | |
|             $namespace .= '_';
 | |
|         }
 | |
|         require_once 'Zend/Loader/Autoloader.php';
 | |
|         Zend_Loader_Autoloader::getInstance()->unshiftAutoloader($this, $namespace);
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Overloading: methods
 | |
|      *
 | |
|      * Allow retrieving concrete resource object instances using 'get<Resourcename>()'
 | |
|      * syntax. Example:
 | |
|      * <code>
 | |
|      * $loader = new Zend_Loader_Autoloader_Resource(array(
 | |
|      *     'namespace' => 'Stuff_',
 | |
|      *     'basePath'  => '/path/to/some/stuff',
 | |
|      * ))
 | |
|      * $loader->addResourceType('Model', 'models', 'Model');
 | |
|      *
 | |
|      * $foo = $loader->getModel('Foo'); // get instance of Stuff_Model_Foo class
 | |
|      * </code>
 | |
|      *
 | |
|      * @param  string $method
 | |
|      * @param  array $args
 | |
|      * @return mixed
 | |
|      * @throws Zend_Loader_Exception if method not beginning with 'get' or not matching a valid resource type is called
 | |
|      */
 | |
|     public function __call($method, $args)
 | |
|     {
 | |
|         if ('get' == substr($method, 0, 3)) {
 | |
|             $type  = strtolower(substr($method, 3));
 | |
|             if (!$this->hasResourceType($type)) {
 | |
|                 require_once 'Zend/Loader/Exception.php';
 | |
|                 throw new Zend_Loader_Exception("Invalid resource type $type; cannot load resource");
 | |
|             }
 | |
|             if (empty($args)) {
 | |
|                 require_once 'Zend/Loader/Exception.php';
 | |
|                 throw new Zend_Loader_Exception("Cannot load resources; no resource specified");
 | |
|             }
 | |
|             $resource = array_shift($args);
 | |
|             return $this->load($resource, $type);
 | |
|         }
 | |
| 
 | |
|         require_once 'Zend/Loader/Exception.php';
 | |
|         throw new Zend_Loader_Exception("Method '$method' is not supported");
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Helper method to calculate the correct class path
 | |
|      *
 | |
|      * @param string $class
 | |
|      * @return False if not matched other wise the correct path
 | |
|      */
 | |
|     public function getClassPath($class)
 | |
|     {
 | |
|         $segments          = explode('_', $class);
 | |
|         $namespaceTopLevel = $this->getNamespace();
 | |
|         $namespace         = '';
 | |
| 
 | |
|         if (!empty($namespaceTopLevel)) {
 | |
|             $namespace = array_shift($segments);
 | |
|             if ($namespace != $namespaceTopLevel) {
 | |
|                 // wrong prefix? we're done
 | |
|                 return false;
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         if (count($segments) < 2) {
 | |
|             // assumes all resources have a component and class name, minimum
 | |
|             return false;
 | |
|         }
 | |
| 
 | |
|         $final     = array_pop($segments);
 | |
|         $component = $namespace;
 | |
|         $lastMatch = false;
 | |
|         do {
 | |
|             $segment    = array_shift($segments);
 | |
|             $component .= empty($component) ? $segment : '_' . $segment;
 | |
|             if (isset($this->_components[$component])) {
 | |
|                 $lastMatch = $component;
 | |
|             }
 | |
|         } while (count($segments));
 | |
| 
 | |
|         if (!$lastMatch) {
 | |
|             return false;
 | |
|         }
 | |
| 
 | |
|         $final = substr($class, strlen($lastMatch) + 1);
 | |
|         $path = $this->_components[$lastMatch];
 | |
|         $classPath = $path . '/' . str_replace('_', '/', $final) . '.php';
 | |
| 
 | |
|         if (Zend_Loader::isReadable($classPath)) {
 | |
|             return $classPath;
 | |
|         }
 | |
| 
 | |
|         return false;
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Attempt to autoload a class
 | |
|      *
 | |
|      * @param  string $class
 | |
|      * @return mixed False if not matched, otherwise result if include operation
 | |
|      */
 | |
|     public function autoload($class)
 | |
|     {
 | |
|         $classPath = $this->getClassPath($class);
 | |
|         if (false !== $classPath) {
 | |
|             return include $classPath;
 | |
|         }
 | |
|         return false;
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Set class state from options
 | |
|      *
 | |
|      * @param  array $options
 | |
|      * @return Zend_Loader_Autoloader_Resource
 | |
|      */
 | |
|     public function setOptions(array $options)
 | |
|     {
 | |
|         // Set namespace first, see ZF-10836
 | |
|         if (isset($options['namespace'])) {
 | |
|             $this->setNamespace($options['namespace']);
 | |
|             unset($options['namespace']);
 | |
|         }
 | |
| 
 | |
|         $methods = get_class_methods($this);
 | |
|         foreach ($options as $key => $value) {
 | |
|             $method = 'set' . ucfirst($key);
 | |
|             if (in_array($method, $methods)) {
 | |
|                 $this->$method($value);
 | |
|             }
 | |
|         }
 | |
|         return $this;
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Set namespace that this autoloader handles
 | |
|      *
 | |
|      * @param  string $namespace
 | |
|      * @return Zend_Loader_Autoloader_Resource
 | |
|      */
 | |
|     public function setNamespace($namespace)
 | |
|     {
 | |
|         $this->_namespace = rtrim((string) $namespace, '_');
 | |
|         return $this;
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Get namespace this autoloader handles
 | |
|      *
 | |
|      * @return string
 | |
|      */
 | |
|     public function getNamespace()
 | |
|     {
 | |
|         return $this->_namespace;
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Set base path for this set of resources
 | |
|      *
 | |
|      * @param  string $path
 | |
|      * @return Zend_Loader_Autoloader_Resource
 | |
|      */
 | |
|     public function setBasePath($path)
 | |
|     {
 | |
|         $this->_basePath = (string) $path;
 | |
|         return $this;
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Get base path to this set of resources
 | |
|      *
 | |
|      * @return string
 | |
|      */
 | |
|     public function getBasePath()
 | |
|     {
 | |
|         return $this->_basePath;
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Add resource type
 | |
|      *
 | |
|      * @param  string $type identifier for the resource type being loaded
 | |
|      * @param  string $path path relative to resource base path containing the resource types
 | |
|      * @param  null|string $namespace sub-component namespace to append to base namespace that qualifies this resource type
 | |
|      * @return Zend_Loader_Autoloader_Resource
 | |
|      */
 | |
|     public function addResourceType($type, $path, $namespace = null)
 | |
|     {
 | |
|         $type = strtolower($type);
 | |
|         if (!isset($this->_resourceTypes[$type])) {
 | |
|             if (null === $namespace) {
 | |
|                 require_once 'Zend/Loader/Exception.php';
 | |
|                 throw new Zend_Loader_Exception('Initial definition of a resource type must include a namespace');
 | |
|             }
 | |
|             $namespaceTopLevel = $this->getNamespace();
 | |
|             $namespace = ucfirst(trim($namespace, '_'));
 | |
|             $this->_resourceTypes[$type] = array(
 | |
|                 'namespace' => empty($namespaceTopLevel) ? $namespace : $namespaceTopLevel . '_' . $namespace,
 | |
|             );
 | |
|         }
 | |
|         if (!is_string($path)) {
 | |
|             require_once 'Zend/Loader/Exception.php';
 | |
|             throw new Zend_Loader_Exception('Invalid path specification provided; must be string');
 | |
|         }
 | |
|         $this->_resourceTypes[$type]['path'] = $this->getBasePath() . '/' . rtrim($path, '\/');
 | |
| 
 | |
|         $component = $this->_resourceTypes[$type]['namespace'];
 | |
|         $this->_components[$component] = $this->_resourceTypes[$type]['path'];
 | |
|         return $this;
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Add multiple resources at once
 | |
|      *
 | |
|      * $types should be an associative array of resource type => specification
 | |
|      * pairs. Each specification should be an associative array containing
 | |
|      * minimally the 'path' key (specifying the path relative to the resource
 | |
|      * base path) and optionally the 'namespace' key (indicating the subcomponent
 | |
|      * namespace to append to the resource namespace).
 | |
|      *
 | |
|      * As an example:
 | |
|      * <code>
 | |
|      * $loader->addResourceTypes(array(
 | |
|      *     'model' => array(
 | |
|      *         'path'      => 'models',
 | |
|      *         'namespace' => 'Model',
 | |
|      *     ),
 | |
|      *     'form' => array(
 | |
|      *         'path'      => 'forms',
 | |
|      *         'namespace' => 'Form',
 | |
|      *     ),
 | |
|      * ));
 | |
|      * </code>
 | |
|      *
 | |
|      * @param  array $types
 | |
|      * @return Zend_Loader_Autoloader_Resource
 | |
|      */
 | |
|     public function addResourceTypes(array $types)
 | |
|     {
 | |
|         foreach ($types as $type => $spec) {
 | |
|             if (!is_array($spec)) {
 | |
|                 require_once 'Zend/Loader/Exception.php';
 | |
|                 throw new Zend_Loader_Exception('addResourceTypes() expects an array of arrays');
 | |
|             }
 | |
|             if (!isset($spec['path'])) {
 | |
|                 require_once 'Zend/Loader/Exception.php';
 | |
|                 throw new Zend_Loader_Exception('addResourceTypes() expects each array to include a paths element');
 | |
|             }
 | |
|             $paths  = $spec['path'];
 | |
|             $namespace = null;
 | |
|             if (isset($spec['namespace'])) {
 | |
|                 $namespace = $spec['namespace'];
 | |
|             }
 | |
|             $this->addResourceType($type, $paths, $namespace);
 | |
|         }
 | |
|         return $this;
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Overwrite existing and set multiple resource types at once
 | |
|      *
 | |
|      * @see    Zend_Loader_Autoloader_Resource::addResourceTypes()
 | |
|      * @param  array $types
 | |
|      * @return Zend_Loader_Autoloader_Resource
 | |
|      */
 | |
|     public function setResourceTypes(array $types)
 | |
|     {
 | |
|         $this->clearResourceTypes();
 | |
|         return $this->addResourceTypes($types);
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Retrieve resource type mappings
 | |
|      *
 | |
|      * @return array
 | |
|      */
 | |
|     public function getResourceTypes()
 | |
|     {
 | |
|         return $this->_resourceTypes;
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Is the requested resource type defined?
 | |
|      *
 | |
|      * @param  string $type
 | |
|      * @return bool
 | |
|      */
 | |
|     public function hasResourceType($type)
 | |
|     {
 | |
|         return isset($this->_resourceTypes[$type]);
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Remove the requested resource type
 | |
|      *
 | |
|      * @param  string $type
 | |
|      * @return Zend_Loader_Autoloader_Resource
 | |
|      */
 | |
|     public function removeResourceType($type)
 | |
|     {
 | |
|         if ($this->hasResourceType($type)) {
 | |
|             $namespace = $this->_resourceTypes[$type]['namespace'];
 | |
|             unset($this->_components[$namespace]);
 | |
|             unset($this->_resourceTypes[$type]);
 | |
|         }
 | |
|         return $this;
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Clear all resource types
 | |
|      *
 | |
|      * @return Zend_Loader_Autoloader_Resource
 | |
|      */
 | |
|     public function clearResourceTypes()
 | |
|     {
 | |
|         $this->_resourceTypes = array();
 | |
|         $this->_components    = array();
 | |
|         return $this;
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Set default resource type to use when calling load()
 | |
|      *
 | |
|      * @param  string $type
 | |
|      * @return Zend_Loader_Autoloader_Resource
 | |
|      */
 | |
|     public function setDefaultResourceType($type)
 | |
|     {
 | |
|         if ($this->hasResourceType($type)) {
 | |
|             $this->_defaultResourceType = $type;
 | |
|         }
 | |
|         return $this;
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Get default resource type to use when calling load()
 | |
|      *
 | |
|      * @return string|null
 | |
|      */
 | |
|     public function getDefaultResourceType()
 | |
|     {
 | |
|         return $this->_defaultResourceType;
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Object registry and factory
 | |
|      *
 | |
|      * Loads the requested resource of type $type (or uses the default resource
 | |
|      * type if none provided). If the resource has been loaded previously,
 | |
|      * returns the previous instance; otherwise, instantiates it.
 | |
|      *
 | |
|      * @param  string $resource
 | |
|      * @param  string $type
 | |
|      * @return object
 | |
|      * @throws Zend_Loader_Exception if resource type not specified or invalid
 | |
|      */
 | |
|     public function load($resource, $type = null)
 | |
|     {
 | |
|         if (null === $type) {
 | |
|             $type = $this->getDefaultResourceType();
 | |
|             if (empty($type)) {
 | |
|                 require_once 'Zend/Loader/Exception.php';
 | |
|                 throw new Zend_Loader_Exception('No resource type specified');
 | |
|             }
 | |
|         }
 | |
|         if (!$this->hasResourceType($type)) {
 | |
|             require_once 'Zend/Loader/Exception.php';
 | |
|             throw new Zend_Loader_Exception('Invalid resource type specified');
 | |
|         }
 | |
|         $namespace = $this->_resourceTypes[$type]['namespace'];
 | |
|         $class     = $namespace . '_' . ucfirst($resource);
 | |
|         if (!isset($this->_resources[$class])) {
 | |
|             $this->_resources[$class] = new $class;
 | |
|         }
 | |
|         return $this->_resources[$class];
 | |
|     }
 | |
| }
 |