PageRenderTime 58ms CodeModel.GetById 27ms RepoModel.GetById 0ms app.codeStats 0ms

/lib/Zend/Loader/Autoloader/Resource.php

https://bitbucket.org/claudiu_marginean/magento-hg-mirror
PHP | 460 lines | 212 code | 37 blank | 211 comment | 31 complexity | 1684a317d3d0849e35de4a901443e890 MD5 | raw file
Possible License(s): CC-BY-SA-3.0, LGPL-2.1, GPL-2.0, WTFPL
  1. <?php
  2. /**
  3. * Zend Framework
  4. *
  5. * LICENSE
  6. *
  7. * This source file is subject to the new BSD license that is bundled
  8. * with this package in the file LICENSE.txt.
  9. * It is also available through the world-wide-web at this URL:
  10. * http://framework.zend.com/license/new-bsd
  11. * If you did not receive a copy of the license and are unable to
  12. * obtain it through the world-wide-web, please send an email
  13. * to license@zend.com so we can send you a copy immediately.
  14. *
  15. * @category Zend
  16. * @package Zend_Loader
  17. * @subpackage Autoloader
  18. * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
  19. * @version $Id: Resource.php 20096 2010-01-06 02:05:09Z bkarwin $
  20. * @license http://framework.zend.com/license/new-bsd New BSD License
  21. */
  22. /** Zend_Loader_Autoloader_Interface */
  23. #require_once 'Zend/Loader/Autoloader/Interface.php';
  24. /**
  25. * Resource loader
  26. *
  27. * @uses Zend_Loader_Autoloader_Interface
  28. * @package Zend_Loader
  29. * @subpackage Autoloader
  30. * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
  31. * @license http://framework.zend.com/license/new-bsd New BSD License
  32. */
  33. class Zend_Loader_Autoloader_Resource implements Zend_Loader_Autoloader_Interface
  34. {
  35. /**
  36. * @var string Base path to resource classes
  37. */
  38. protected $_basePath;
  39. /**
  40. * @var array Components handled within this resource
  41. */
  42. protected $_components = array();
  43. /**
  44. * @var string Default resource/component to use when using object registry
  45. */
  46. protected $_defaultResourceType;
  47. /**
  48. * @var string Namespace of classes within this resource
  49. */
  50. protected $_namespace;
  51. /**
  52. * @var array Available resource types handled by this resource autoloader
  53. */
  54. protected $_resourceTypes = array();
  55. /**
  56. * Constructor
  57. *
  58. * @param array|Zend_Config $options Configuration options for resource autoloader
  59. * @return void
  60. */
  61. public function __construct($options)
  62. {
  63. if ($options instanceof Zend_Config) {
  64. $options = $options->toArray();
  65. }
  66. if (!is_array($options)) {
  67. #require_once 'Zend/Loader/Exception.php';
  68. throw new Zend_Loader_Exception('Options must be passed to resource loader constructor');
  69. }
  70. $this->setOptions($options);
  71. $namespace = $this->getNamespace();
  72. if ((null === $namespace)
  73. || (null === $this->getBasePath())
  74. ) {
  75. #require_once 'Zend/Loader/Exception.php';
  76. throw new Zend_Loader_Exception('Resource loader requires both a namespace and a base path for initialization');
  77. }
  78. if (!empty($namespace)) {
  79. $namespace .= '_';
  80. }
  81. Zend_Loader_Autoloader::getInstance()->unshiftAutoloader($this, $namespace);
  82. }
  83. /**
  84. * Overloading: methods
  85. *
  86. * Allow retrieving concrete resource object instances using 'get<Resourcename>()'
  87. * syntax. Example:
  88. * <code>
  89. * $loader = new Zend_Loader_Autoloader_Resource(array(
  90. * 'namespace' => 'Stuff_',
  91. * 'basePath' => '/path/to/some/stuff',
  92. * ))
  93. * $loader->addResourceType('Model', 'models', 'Model');
  94. *
  95. * $foo = $loader->getModel('Foo'); // get instance of Stuff_Model_Foo class
  96. * </code>
  97. *
  98. * @param string $method
  99. * @param array $args
  100. * @return mixed
  101. * @throws Zend_Loader_Exception if method not beginning with 'get' or not matching a valid resource type is called
  102. */
  103. public function __call($method, $args)
  104. {
  105. if ('get' == substr($method, 0, 3)) {
  106. $type = strtolower(substr($method, 3));
  107. if (!$this->hasResourceType($type)) {
  108. #require_once 'Zend/Loader/Exception.php';
  109. throw new Zend_Loader_Exception("Invalid resource type $type; cannot load resource");
  110. }
  111. if (empty($args)) {
  112. #require_once 'Zend/Loader/Exception.php';
  113. throw new Zend_Loader_Exception("Cannot load resources; no resource specified");
  114. }
  115. $resource = array_shift($args);
  116. return $this->load($resource, $type);
  117. }
  118. #require_once 'Zend/Loader/Exception.php';
  119. throw new Zend_Loader_Exception("Method '$method' is not supported");
  120. }
  121. /**
  122. * Helper method to calculate the correct class path
  123. *
  124. * @param string $class
  125. * @return False if not matched other wise the correct path
  126. */
  127. public function getClassPath($class)
  128. {
  129. $segments = explode('_', $class);
  130. $namespaceTopLevel = $this->getNamespace();
  131. $namespace = '';
  132. if (!empty($namespaceTopLevel)) {
  133. $namespace = array_shift($segments);
  134. if ($namespace != $namespaceTopLevel) {
  135. // wrong prefix? we're done
  136. return false;
  137. }
  138. }
  139. if (count($segments) < 2) {
  140. // assumes all resources have a component and class name, minimum
  141. return false;
  142. }
  143. $final = array_pop($segments);
  144. $component = $namespace;
  145. $lastMatch = false;
  146. do {
  147. $segment = array_shift($segments);
  148. $component .= empty($component) ? $segment : '_' . $segment;
  149. if (isset($this->_components[$component])) {
  150. $lastMatch = $component;
  151. }
  152. } while (count($segments));
  153. if (!$lastMatch) {
  154. return false;
  155. }
  156. $final = substr($class, strlen($lastMatch) + 1);
  157. $path = $this->_components[$lastMatch];
  158. $classPath = $path . '/' . str_replace('_', '/', $final) . '.php';
  159. if (Zend_Loader::isReadable($classPath)) {
  160. return $classPath;
  161. }
  162. return false;
  163. }
  164. /**
  165. * Attempt to autoload a class
  166. *
  167. * @param string $class
  168. * @return mixed False if not matched, otherwise result if include operation
  169. */
  170. public function autoload($class)
  171. {
  172. $classPath = $this->getClassPath($class);
  173. if (false !== $classPath) {
  174. return include $classPath;
  175. }
  176. return false;
  177. }
  178. /**
  179. * Set class state from options
  180. *
  181. * @param array $options
  182. * @return Zend_Loader_Autoloader_Resource
  183. */
  184. public function setOptions(array $options)
  185. {
  186. $methods = get_class_methods($this);
  187. foreach ($options as $key => $value) {
  188. $method = 'set' . ucfirst($key);
  189. if (in_array($method, $methods)) {
  190. $this->$method($value);
  191. }
  192. }
  193. return $this;
  194. }
  195. /**
  196. * Set namespace that this autoloader handles
  197. *
  198. * @param string $namespace
  199. * @return Zend_Loader_Autoloader_Resource
  200. */
  201. public function setNamespace($namespace)
  202. {
  203. $this->_namespace = rtrim((string) $namespace, '_');
  204. return $this;
  205. }
  206. /**
  207. * Get namespace this autoloader handles
  208. *
  209. * @return string
  210. */
  211. public function getNamespace()
  212. {
  213. return $this->_namespace;
  214. }
  215. /**
  216. * Set base path for this set of resources
  217. *
  218. * @param string $path
  219. * @return Zend_Loader_Autoloader_Resource
  220. */
  221. public function setBasePath($path)
  222. {
  223. $this->_basePath = (string) $path;
  224. return $this;
  225. }
  226. /**
  227. * Get base path to this set of resources
  228. *
  229. * @return string
  230. */
  231. public function getBasePath()
  232. {
  233. return $this->_basePath;
  234. }
  235. /**
  236. * Add resource type
  237. *
  238. * @param string $type identifier for the resource type being loaded
  239. * @param string $path path relative to resource base path containing the resource types
  240. * @param null|string $namespace sub-component namespace to append to base namespace that qualifies this resource type
  241. * @return Zend_Loader_Autoloader_Resource
  242. */
  243. public function addResourceType($type, $path, $namespace = null)
  244. {
  245. $type = strtolower($type);
  246. if (!isset($this->_resourceTypes[$type])) {
  247. if (null === $namespace) {
  248. #require_once 'Zend/Loader/Exception.php';
  249. throw new Zend_Loader_Exception('Initial definition of a resource type must include a namespace');
  250. }
  251. $namespaceTopLevel = $this->getNamespace();
  252. $namespace = ucfirst(trim($namespace, '_'));
  253. $this->_resourceTypes[$type] = array(
  254. 'namespace' => empty($namespaceTopLevel) ? $namespace : $namespaceTopLevel . '_' . $namespace,
  255. );
  256. }
  257. if (!is_string($path)) {
  258. #require_once 'Zend/Loader/Exception.php';
  259. throw new Zend_Loader_Exception('Invalid path specification provided; must be string');
  260. }
  261. $this->_resourceTypes[$type]['path'] = $this->getBasePath() . '/' . rtrim($path, '\/');
  262. $component = $this->_resourceTypes[$type]['namespace'];
  263. $this->_components[$component] = $this->_resourceTypes[$type]['path'];
  264. return $this;
  265. }
  266. /**
  267. * Add multiple resources at once
  268. *
  269. * $types should be an associative array of resource type => specification
  270. * pairs. Each specification should be an associative array containing
  271. * minimally the 'path' key (specifying the path relative to the resource
  272. * base path) and optionally the 'namespace' key (indicating the subcomponent
  273. * namespace to append to the resource namespace).
  274. *
  275. * As an example:
  276. * <code>
  277. * $loader->addResourceTypes(array(
  278. * 'model' => array(
  279. * 'path' => 'models',
  280. * 'namespace' => 'Model',
  281. * ),
  282. * 'form' => array(
  283. * 'path' => 'forms',
  284. * 'namespace' => 'Form',
  285. * ),
  286. * ));
  287. * </code>
  288. *
  289. * @param array $types
  290. * @return Zend_Loader_Autoloader_Resource
  291. */
  292. public function addResourceTypes(array $types)
  293. {
  294. foreach ($types as $type => $spec) {
  295. if (!is_array($spec)) {
  296. #require_once 'Zend/Loader/Exception.php';
  297. throw new Zend_Loader_Exception('addResourceTypes() expects an array of arrays');
  298. }
  299. if (!isset($spec['path'])) {
  300. #require_once 'Zend/Loader/Exception.php';
  301. throw new Zend_Loader_Exception('addResourceTypes() expects each array to include a paths element');
  302. }
  303. $paths = $spec['path'];
  304. $namespace = null;
  305. if (isset($spec['namespace'])) {
  306. $namespace = $spec['namespace'];
  307. }
  308. $this->addResourceType($type, $paths, $namespace);
  309. }
  310. return $this;
  311. }
  312. /**
  313. * Overwrite existing and set multiple resource types at once
  314. *
  315. * @see Zend_Loader_Autoloader_Resource::addResourceTypes()
  316. * @param array $types
  317. * @return Zend_Loader_Autoloader_Resource
  318. */
  319. public function setResourceTypes(array $types)
  320. {
  321. $this->clearResourceTypes();
  322. return $this->addResourceTypes($types);
  323. }
  324. /**
  325. * Retrieve resource type mappings
  326. *
  327. * @return array
  328. */
  329. public function getResourceTypes()
  330. {
  331. return $this->_resourceTypes;
  332. }
  333. /**
  334. * Is the requested resource type defined?
  335. *
  336. * @param string $type
  337. * @return bool
  338. */
  339. public function hasResourceType($type)
  340. {
  341. return isset($this->_resourceTypes[$type]);
  342. }
  343. /**
  344. * Remove the requested resource type
  345. *
  346. * @param string $type
  347. * @return Zend_Loader_Autoloader_Resource
  348. */
  349. public function removeResourceType($type)
  350. {
  351. if ($this->hasResourceType($type)) {
  352. $namespace = $this->_resourceTypes[$type]['namespace'];
  353. unset($this->_components[$namespace]);
  354. unset($this->_resourceTypes[$type]);
  355. }
  356. return $this;
  357. }
  358. /**
  359. * Clear all resource types
  360. *
  361. * @return Zend_Loader_Autoloader_Resource
  362. */
  363. public function clearResourceTypes()
  364. {
  365. $this->_resourceTypes = array();
  366. $this->_components = array();
  367. return $this;
  368. }
  369. /**
  370. * Set default resource type to use when calling load()
  371. *
  372. * @param string $type
  373. * @return Zend_Loader_Autoloader_Resource
  374. */
  375. public function setDefaultResourceType($type)
  376. {
  377. if ($this->hasResourceType($type)) {
  378. $this->_defaultResourceType = $type;
  379. }
  380. return $this;
  381. }
  382. /**
  383. * Get default resource type to use when calling load()
  384. *
  385. * @return string|null
  386. */
  387. public function getDefaultResourceType()
  388. {
  389. return $this->_defaultResourceType;
  390. }
  391. /**
  392. * Object registry and factory
  393. *
  394. * Loads the requested resource of type $type (or uses the default resource
  395. * type if none provided). If the resource has been loaded previously,
  396. * returns the previous instance; otherwise, instantiates it.
  397. *
  398. * @param string $resource
  399. * @param string $type
  400. * @return object
  401. * @throws Zend_Loader_Exception if resource type not specified or invalid
  402. */
  403. public function load($resource, $type = null)
  404. {
  405. if (null === $type) {
  406. $type = $this->getDefaultResourceType();
  407. if (empty($type)) {
  408. #require_once 'Zend/Loader/Exception.php';
  409. throw new Zend_Loader_Exception('No resource type specified');
  410. }
  411. }
  412. if (!$this->hasResourceType($type)) {
  413. #require_once 'Zend/Loader/Exception.php';
  414. throw new Zend_Loader_Exception('Invalid resource type specified');
  415. }
  416. $namespace = $this->_resourceTypes[$type]['namespace'];
  417. $class = $namespace . '_' . ucfirst($resource);
  418. if (!isset($this->_resources[$class])) {
  419. $this->_resources[$class] = new $class;
  420. }
  421. return $this->_resources[$class];
  422. }
  423. }