/public/lib/Zend/Loader/Autoloader/Resource.php
PHP | 467 lines | 229 code | 38 blank | 200 comment | 32 complexity | f0c8186b43fb1f18e60a98c0cef5fcd3 MD5 | raw file
- <?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: Resource.php 23775 2011-03-01 17:25:24Z ralph $
- * @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];
- }
- }