1: <?php
2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21:
22:
23:
24: require_once 'Zend/Loader/Autoloader/Interface.php';
25:
26: 27: 28: 29: 30: 31: 32: 33: 34:
35: class Zend_Loader_Autoloader_Resource implements Zend_Loader_Autoloader_Interface
36: {
37: 38: 39:
40: protected $_basePath;
41:
42: 43: 44:
45: protected $_components = array();
46:
47: 48: 49:
50: protected $_defaultResourceType;
51:
52: 53: 54:
55: protected $_namespace;
56:
57: 58: 59:
60: protected $_resourceTypes = array();
61:
62: 63: 64: 65: 66: 67:
68: public function __construct($options)
69: {
70: if ($options instanceof Zend_Config) {
71: $options = $options->toArray();
72: }
73: if (!is_array($options)) {
74: require_once 'Zend/Loader/Exception.php';
75: throw new Zend_Loader_Exception('Options must be passed to resource loader constructor');
76: }
77:
78: $this->setOptions($options);
79:
80: $namespace = $this->getNamespace();
81: if ((null === $namespace)
82: || (null === $this->getBasePath())
83: ) {
84: require_once 'Zend/Loader/Exception.php';
85: throw new Zend_Loader_Exception('Resource loader requires both a namespace and a base path for initialization');
86: }
87:
88: if (!empty($namespace)) {
89: $namespace .= '_';
90: }
91: require_once 'Zend/Loader/Autoloader.php';
92: Zend_Loader_Autoloader::getInstance()->unshiftAutoloader($this, $namespace);
93: }
94:
95: 96: 97: 98: 99: 100: 101: 102: 103: 104: 105: 106: 107: 108: 109: 110: 111: 112: 113: 114:
115: public function __call($method, $args)
116: {
117: if ('get' == substr($method, 0, 3)) {
118: $type = strtolower(substr($method, 3));
119: if (!$this->hasResourceType($type)) {
120: require_once 'Zend/Loader/Exception.php';
121: throw new Zend_Loader_Exception("Invalid resource type $type; cannot load resource");
122: }
123: if (empty($args)) {
124: require_once 'Zend/Loader/Exception.php';
125: throw new Zend_Loader_Exception("Cannot load resources; no resource specified");
126: }
127: $resource = array_shift($args);
128: return $this->load($resource, $type);
129: }
130:
131: require_once 'Zend/Loader/Exception.php';
132: throw new Zend_Loader_Exception("Method '$method' is not supported");
133: }
134:
135: 136: 137: 138: 139: 140:
141: public function getClassPath($class)
142: {
143: $segments = explode('_', $class);
144: $namespaceTopLevel = $this->getNamespace();
145: $namespace = '';
146:
147: if (!empty($namespaceTopLevel)) {
148: $namespace = array_shift($segments);
149: if ($namespace != $namespaceTopLevel) {
150:
151: return false;
152: }
153: }
154:
155: if (count($segments) < 2) {
156:
157: return false;
158: }
159:
160: $final = array_pop($segments);
161: $component = $namespace;
162: $lastMatch = false;
163: do {
164: $segment = array_shift($segments);
165: $component .= empty($component) ? $segment : '_' . $segment;
166: if (isset($this->_components[$component])) {
167: $lastMatch = $component;
168: }
169: } while (count($segments));
170:
171: if (!$lastMatch) {
172: return false;
173: }
174:
175: $final = substr($class, strlen($lastMatch) + 1);
176: $path = $this->_components[$lastMatch];
177: $classPath = $path . '/' . str_replace('_', '/', $final) . '.php';
178:
179: if (Zend_Loader::isReadable($classPath)) {
180: return $classPath;
181: }
182:
183: return false;
184: }
185:
186: 187: 188: 189: 190: 191:
192: public function autoload($class)
193: {
194: $classPath = $this->getClassPath($class);
195: if (false !== $classPath) {
196: return include $classPath;
197: }
198: return false;
199: }
200:
201: 202: 203: 204: 205: 206:
207: public function setOptions(array $options)
208: {
209:
210: if (isset($options['namespace'])) {
211: $this->setNamespace($options['namespace']);
212: unset($options['namespace']);
213: }
214:
215: $methods = get_class_methods($this);
216: foreach ($options as $key => $value) {
217: $method = 'set' . ucfirst($key);
218: if (in_array($method, $methods)) {
219: $this->$method($value);
220: }
221: }
222: return $this;
223: }
224:
225: 226: 227: 228: 229: 230:
231: public function setNamespace($namespace)
232: {
233: $this->_namespace = rtrim((string) $namespace, '_');
234: return $this;
235: }
236:
237: 238: 239: 240: 241:
242: public function getNamespace()
243: {
244: return $this->_namespace;
245: }
246:
247: 248: 249: 250: 251: 252:
253: public function setBasePath($path)
254: {
255: $this->_basePath = (string) $path;
256: return $this;
257: }
258:
259: 260: 261: 262: 263:
264: public function getBasePath()
265: {
266: return $this->_basePath;
267: }
268:
269: 270: 271: 272: 273: 274: 275: 276:
277: public function addResourceType($type, $path, $namespace = null)
278: {
279: $type = strtolower($type);
280: if (!isset($this->_resourceTypes[$type])) {
281: if (null === $namespace) {
282: require_once 'Zend/Loader/Exception.php';
283: throw new Zend_Loader_Exception('Initial definition of a resource type must include a namespace');
284: }
285: $namespaceTopLevel = $this->getNamespace();
286: $namespace = ucfirst(trim($namespace, '_'));
287: $this->_resourceTypes[$type] = array(
288: 'namespace' => empty($namespaceTopLevel) ? $namespace : $namespaceTopLevel . '_' . $namespace,
289: );
290: }
291: if (!is_string($path)) {
292: require_once 'Zend/Loader/Exception.php';
293: throw new Zend_Loader_Exception('Invalid path specification provided; must be string');
294: }
295: $this->_resourceTypes[$type]['path'] = $this->getBasePath() . '/' . rtrim($path, '\/');
296:
297: $component = $this->_resourceTypes[$type]['namespace'];
298: $this->_components[$component] = $this->_resourceTypes[$type]['path'];
299: return $this;
300: }
301:
302: 303: 304: 305: 306: 307: 308: 309: 310: 311: 312: 313: 314: 315: 316: 317: 318: 319: 320: 321: 322: 323: 324: 325: 326: 327:
328: public function addResourceTypes(array $types)
329: {
330: foreach ($types as $type => $spec) {
331: if (!is_array($spec)) {
332: require_once 'Zend/Loader/Exception.php';
333: throw new Zend_Loader_Exception('addResourceTypes() expects an array of arrays');
334: }
335: if (!isset($spec['path'])) {
336: require_once 'Zend/Loader/Exception.php';
337: throw new Zend_Loader_Exception('addResourceTypes() expects each array to include a paths element');
338: }
339: $paths = $spec['path'];
340: $namespace = null;
341: if (isset($spec['namespace'])) {
342: $namespace = $spec['namespace'];
343: }
344: $this->addResourceType($type, $paths, $namespace);
345: }
346: return $this;
347: }
348:
349: 350: 351: 352: 353: 354: 355:
356: public function setResourceTypes(array $types)
357: {
358: $this->clearResourceTypes();
359: return $this->addResourceTypes($types);
360: }
361:
362: 363: 364: 365: 366:
367: public function getResourceTypes()
368: {
369: return $this->_resourceTypes;
370: }
371:
372: 373: 374: 375: 376: 377:
378: public function hasResourceType($type)
379: {
380: return isset($this->_resourceTypes[$type]);
381: }
382:
383: 384: 385: 386: 387: 388:
389: public function removeResourceType($type)
390: {
391: if ($this->hasResourceType($type)) {
392: $namespace = $this->_resourceTypes[$type]['namespace'];
393: unset($this->_components[$namespace]);
394: unset($this->_resourceTypes[$type]);
395: }
396: return $this;
397: }
398:
399: 400: 401: 402: 403:
404: public function clearResourceTypes()
405: {
406: $this->_resourceTypes = array();
407: $this->_components = array();
408: return $this;
409: }
410:
411: 412: 413: 414: 415: 416:
417: public function setDefaultResourceType($type)
418: {
419: if ($this->hasResourceType($type)) {
420: $this->_defaultResourceType = $type;
421: }
422: return $this;
423: }
424:
425: 426: 427: 428: 429:
430: public function getDefaultResourceType()
431: {
432: return $this->_defaultResourceType;
433: }
434:
435: 436: 437: 438: 439: 440: 441: 442: 443: 444: 445: 446:
447: public function load($resource, $type = null)
448: {
449: if (null === $type) {
450: $type = $this->getDefaultResourceType();
451: if (empty($type)) {
452: require_once 'Zend/Loader/Exception.php';
453: throw new Zend_Loader_Exception('No resource type specified');
454: }
455: }
456: if (!$this->hasResourceType($type)) {
457: require_once 'Zend/Loader/Exception.php';
458: throw new Zend_Loader_Exception('Invalid resource type specified');
459: }
460: $namespace = $this->_resourceTypes[$type]['namespace'];
461: $class = $namespace . '_' . ucfirst($resource);
462: if (!isset($this->_resources[$class])) {
463: $this->_resources[$class] = new $class;
464: }
465: return $this->_resources[$class];
466: }
467: }
468: