00001 <?php
00024 require_once 'Zend/Loader/Autoloader/Interface.php';
00025
00035 class Zend_Loader_Autoloader_Resource implements Zend_Loader_Autoloader_Interface
00036 {
00040 protected $_basePath;
00041
00045 protected $_components = array();
00046
00050 protected $_defaultResourceType;
00051
00055 protected $_namespace;
00056
00060 protected $_resourceTypes = array();
00061
00068 public function __construct($options)
00069 {
00070 if ($options instanceof Zend_Config) {
00071 $options = $options->toArray();
00072 }
00073 if (!is_array($options)) {
00074 require_once 'Zend/Loader/Exception.php';
00075 throw new Zend_Loader_Exception('Options must be passed to resource loader constructor');
00076 }
00077
00078 $this->setOptions($options);
00079
00080 $namespace = $this->getNamespace();
00081 if ((null === $namespace)
00082 || (null === $this->getBasePath())
00083 ) {
00084 require_once 'Zend/Loader/Exception.php';
00085 throw new Zend_Loader_Exception('Resource loader requires both a namespace and a base path for initialization');
00086 }
00087
00088 if (!empty($namespace)) {
00089 $namespace .= '_';
00090 }
00091 Zend_Loader_Autoloader::getInstance()->unshiftAutoloader($this, $namespace);
00092 }
00093
00114 public function __call($method, $args)
00115 {
00116 if ('get' == substr($method, 0, 3)) {
00117 $type = strtolower(substr($method, 3));
00118 if (!$this->hasResourceType($type)) {
00119 require_once 'Zend/Loader/Exception.php';
00120 throw new Zend_Loader_Exception("Invalid resource type $type; cannot load resource");
00121 }
00122 if (empty($args)) {
00123 require_once 'Zend/Loader/Exception.php';
00124 throw new Zend_Loader_Exception("Cannot load resources; no resource specified");
00125 }
00126 $resource = array_shift($args);
00127 return $this->load($resource, $type);
00128 }
00129
00130 require_once 'Zend/Loader/Exception.php';
00131 throw new Zend_Loader_Exception("Method '$method' is not supported");
00132 }
00133
00140 public function getClassPath($class)
00141 {
00142 $segments = explode('_', $class);
00143 $namespaceTopLevel = $this->getNamespace();
00144 $namespace = '';
00145
00146 if (!empty($namespaceTopLevel)) {
00147 $namespace = array_shift($segments);
00148 if ($namespace != $namespaceTopLevel) {
00149
00150 return false;
00151 }
00152 }
00153
00154 if (count($segments) < 2) {
00155
00156 return false;
00157 }
00158
00159 $final = array_pop($segments);
00160 $component = $namespace;
00161 $lastMatch = false;
00162 do {
00163 $segment = array_shift($segments);
00164 $component .= empty($component) ? $segment : '_' . $segment;
00165 if (isset($this->_components[$component])) {
00166 $lastMatch = $component;
00167 }
00168 } while (count($segments));
00169
00170 if (!$lastMatch) {
00171 return false;
00172 }
00173
00174 $final = substr($class, strlen($lastMatch) + 1);
00175 $path = $this->_components[$lastMatch];
00176 $classPath = $path . '/' . str_replace('_', '/', $final) . '.php';
00177
00178 if (Zend_Loader::isReadable($classPath)) {
00179 return $classPath;
00180 }
00181
00182 return false;
00183 }
00184
00191 public function autoload($class)
00192 {
00193 $classPath = $this->getClassPath($class);
00194 if (false !== $classPath) {
00195 return include $classPath;
00196 }
00197 return false;
00198 }
00199
00206 public function setOptions(array $options)
00207 {
00208 $methods = get_class_methods($this);
00209 foreach ($options as $key => $value) {
00210 $method = 'set' . ucfirst($key);
00211 if (in_array($method, $methods)) {
00212 $this->$method($value);
00213 }
00214 }
00215 return $this;
00216 }
00217
00224 public function setNamespace($namespace)
00225 {
00226 $this->_namespace = rtrim((string) $namespace, '_');
00227 return $this;
00228 }
00229
00235 public function getNamespace()
00236 {
00237 return $this->_namespace;
00238 }
00239
00246 public function setBasePath($path)
00247 {
00248 $this->_basePath = (string) $path;
00249 return $this;
00250 }
00251
00257 public function getBasePath()
00258 {
00259 return $this->_basePath;
00260 }
00261
00270 public function addResourceType($type, $path, $namespace = null)
00271 {
00272 $type = strtolower($type);
00273 if (!isset($this->_resourceTypes[$type])) {
00274 if (null === $namespace) {
00275 require_once 'Zend/Loader/Exception.php';
00276 throw new Zend_Loader_Exception('Initial definition of a resource type must include a namespace');
00277 }
00278 $namespaceTopLevel = $this->getNamespace();
00279 $namespace = ucfirst(trim($namespace, '_'));
00280 $this->_resourceTypes[$type] = array(
00281 'namespace' => empty($namespaceTopLevel) ? $namespace : $namespaceTopLevel . '_' . $namespace,
00282 );
00283 }
00284 if (!is_string($path)) {
00285 require_once 'Zend/Loader/Exception.php';
00286 throw new Zend_Loader_Exception('Invalid path specification provided; must be string');
00287 }
00288 $this->_resourceTypes[$type]['path'] = $this->getBasePath() . '/' . rtrim($path, '\/');
00289
00290 $component = $this->_resourceTypes[$type]['namespace'];
00291 $this->_components[$component] = $this->_resourceTypes[$type]['path'];
00292 return $this;
00293 }
00294
00321 public function addResourceTypes(array $types)
00322 {
00323 foreach ($types as $type => $spec) {
00324 if (!is_array($spec)) {
00325 require_once 'Zend/Loader/Exception.php';
00326 throw new Zend_Loader_Exception('addResourceTypes() expects an array of arrays');
00327 }
00328 if (!isset($spec['path'])) {
00329 require_once 'Zend/Loader/Exception.php';
00330 throw new Zend_Loader_Exception('addResourceTypes() expects each array to include a paths element');
00331 }
00332 $paths = $spec['path'];
00333 $namespace = null;
00334 if (isset($spec['namespace'])) {
00335 $namespace = $spec['namespace'];
00336 }
00337 $this->addResourceType($type, $paths, $namespace);
00338 }
00339 return $this;
00340 }
00341
00349 public function setResourceTypes(array $types)
00350 {
00351 $this->clearResourceTypes();
00352 return $this->addResourceTypes($types);
00353 }
00354
00360 public function getResourceTypes()
00361 {
00362 return $this->_resourceTypes;
00363 }
00364
00371 public function hasResourceType($type)
00372 {
00373 return isset($this->_resourceTypes[$type]);
00374 }
00375
00382 public function removeResourceType($type)
00383 {
00384 if ($this->hasResourceType($type)) {
00385 $namespace = $this->_resourceTypes[$type]['namespace'];
00386 unset($this->_components[$namespace]);
00387 unset($this->_resourceTypes[$type]);
00388 }
00389 return $this;
00390 }
00391
00397 public function clearResourceTypes()
00398 {
00399 $this->_resourceTypes = array();
00400 $this->_components = array();
00401 return $this;
00402 }
00403
00410 public function setDefaultResourceType($type)
00411 {
00412 if ($this->hasResourceType($type)) {
00413 $this->_defaultResourceType = $type;
00414 }
00415 return $this;
00416 }
00417
00423 public function getDefaultResourceType()
00424 {
00425 return $this->_defaultResourceType;
00426 }
00427
00440 public function load($resource, $type = null)
00441 {
00442 if (null === $type) {
00443 $type = $this->getDefaultResourceType();
00444 if (empty($type)) {
00445 require_once 'Zend/Loader/Exception.php';
00446 throw new Zend_Loader_Exception('No resource type specified');
00447 }
00448 }
00449 if (!$this->hasResourceType($type)) {
00450 require_once 'Zend/Loader/Exception.php';
00451 throw new Zend_Loader_Exception('Invalid resource type specified');
00452 }
00453 $namespace = $this->_resourceTypes[$type]['namespace'];
00454 $class = $namespace . '_' . ucfirst($resource);
00455 if (!isset($this->_resources[$class])) {
00456 $this->_resources[$class] = new $class;
00457 }
00458 return $this->_resources[$class];
00459 }
00460 }