diff -r 000000000000 -r 4eba9c11703f web/Zend/Loader/Autoloader/Resource.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/web/Zend/Loader/Autoloader/Resource.php Mon Dec 13 18:29:26 2010 +0100 @@ -0,0 +1,460 @@ +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 .= '_'; + } + Zend_Loader_Autoloader::getInstance()->unshiftAutoloader($this, $namespace); + } + + /** + * Overloading: methods + * + * Allow retrieving concrete resource object instances using 'get()' + * syntax. Example: + * + * $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 + * + * + * @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) + { + $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: + * + * $loader->addResourceTypes(array( + * 'model' => array( + * 'path' => 'models', + * 'namespace' => 'Model', + * ), + * 'form' => array( + * 'path' => 'forms', + * 'namespace' => 'Form', + * ), + * )); + * + * + * @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]; + } +}