PageRenderTime 48ms CodeModel.GetById 20ms RepoModel.GetById 1ms app.codeStats 0ms

/library/Zend/Tool/Project/Profile/Resource/Container.php

https://github.com/obias/zf2
PHP | 426 lines | 183 code | 49 blank | 194 comment | 25 complexity | 5079ef5935f6d36f116253f80da63996 MD5 | raw file
  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_Tool
  17. * @subpackage Framework
  18. * @copyright Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com)
  19. * @license http://framework.zend.com/license/new-bsd New BSD License
  20. */
  21. /**
  22. * @namespace
  23. */
  24. namespace Zend\Tool\Project\Profile\Resource;
  25. use Zend\Tool\Project\Profile,
  26. Zend\Tool\Project\Profile\Exception;
  27. /**
  28. * This class is an iterator that will iterate only over enabled resources
  29. *
  30. * @uses Countable
  31. * @uses RecursiveIterator
  32. * @uses RecursiveIteratorIterator
  33. * @uses \Zend\Tool\Project\Context\Repository
  34. * @uses \Zend\Tool\Project\Profile\Exception
  35. * @uses \Zend\Tool\Project\Profile\Iterator\ContextFilter
  36. * @uses \Zend\Tool\Project\Profile\Resource\Resource
  37. * @uses \Zend\Tool\Project\Profile\Resource\SearchConstraints
  38. * @category Zend
  39. * @package Zend_Tool
  40. * @copyright Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com)
  41. * @license http://framework.zend.com/license/new-bsd New BSD License
  42. */
  43. class Container implements \RecursiveIterator, \Countable
  44. {
  45. /**
  46. * @var array
  47. */
  48. protected $_subResources = array();
  49. /**
  50. * @var int
  51. */
  52. protected $_position = 0;
  53. /**
  54. * @var bool
  55. */
  56. protected $_appendable = true;
  57. /**
  58. * @var array
  59. */
  60. protected $_attributes = array();
  61. /**
  62. * Finder method to be able to find resources by context name
  63. * and attributes. Example usage:
  64. *
  65. * <code>
  66. *
  67. * </code>
  68. *
  69. * @param \Zend\Tool\Project\Profile\Resource\SearchConstraints|string|array $searchParameters
  70. * @return \Zend\Tool\Project\Profile\Resource\Resource
  71. */
  72. public function search($matchSearchConstraints, $nonMatchSearchConstraints = null)
  73. {
  74. if (!$matchSearchConstraints instanceof SearchConstraints) {
  75. $matchSearchConstraints = new SearchConstraints($matchSearchConstraints);
  76. }
  77. $this->rewind();
  78. /**
  79. * @todo This should be re-written with better support for a filter iterator, its the way to go
  80. */
  81. if ($nonMatchSearchConstraints) {
  82. $filterIterator = new Profile\Iterator\ContextFilter($this, array('denyNames' => $nonMatchSearchConstraints));
  83. $riIterator = new \RecursiveIteratorIterator($filterIterator, \RecursiveIteratorIterator::SELF_FIRST);
  84. } else {
  85. $riIterator = new \RecursiveIteratorIterator($this, \RecursiveIteratorIterator::SELF_FIRST);
  86. }
  87. $foundResource = false;
  88. $currentConstraint = $matchSearchConstraints->getConstraint();
  89. $foundDepth = 0;
  90. foreach ($riIterator as $currentResource) {
  91. // if current depth is less than found depth, end
  92. if ($riIterator->getDepth() < $foundDepth) {
  93. break;
  94. }
  95. if (strtolower($currentResource->getName()) == strtolower($currentConstraint->name)) {
  96. $paramsMatch = true;
  97. // @todo check to ensure params match (perhaps)
  98. if (count($currentConstraint->params) > 0) {
  99. $currentResourceAttributes = $currentResource->getAttributes();
  100. if (!is_array($currentConstraint->params)) {
  101. throw new Exception\RuntimeException('Search parameter specifics must be in the form of an array for key "'
  102. . $currentConstraint->name .'"');
  103. }
  104. foreach ($currentConstraint->params as $paramName => $paramValue) {
  105. if (!isset($currentResourceAttributes[$paramName]) || $currentResourceAttributes[$paramName] != $paramValue) {
  106. $paramsMatch = false;
  107. break;
  108. }
  109. }
  110. }
  111. if ($paramsMatch) {
  112. $foundDepth = $riIterator->getDepth();
  113. if (($currentConstraint = $matchSearchConstraints->getConstraint()) == null) {
  114. $foundResource = $currentResource;
  115. break;
  116. }
  117. }
  118. }
  119. }
  120. return $foundResource;
  121. }
  122. /**
  123. * createResourceAt()
  124. *
  125. * @param array|\Zend\Tool\Project\Profile\Resource\SearchConstraints $appendResourceOrSearchConstraints
  126. * @param string $context
  127. * @param array $attributes
  128. * @return \Zend\Tool\Project\Profile\Resource\Resource
  129. */
  130. public function createResourceAt($appendResourceOrSearchConstraints, $context, Array $attributes = array())
  131. {
  132. if (!$appendResourceOrSearchConstraints instanceof Container) {
  133. if (($parentResource = $this->search($appendResourceOrSearchConstraints)) == false) {
  134. throw new Exception\InvalidArgumentException('No node was found to append to.');
  135. }
  136. } else {
  137. $parentResource = $appendResourceOrSearchConstraints;
  138. }
  139. return $parentResource->createResource($context, $attributes);
  140. }
  141. /**
  142. * createResource()
  143. *
  144. * Method to create a resource with a given context with specific attributes
  145. *
  146. * @param string $context
  147. * @param array $attributes
  148. * @return \Zend\Tool\Project\Profile\Resource\Resource
  149. */
  150. public function createResource($context, Array $attributes = array())
  151. {
  152. if (is_string($context)) {
  153. $contextRegistry = \Zend\Tool\Project\Context\Repository::getInstance();
  154. if ($contextRegistry->hasContext($context)) {
  155. $context = $contextRegistry->getContext($context);
  156. } else {
  157. throw new Exception\InvalidArgumentException('Context by name ' . $context . ' was not found in the context registry.');
  158. }
  159. } elseif (!$context instanceof \Zend\Tool\Project\Context) {
  160. throw new Exception\InvalidArgumentException('Context must be of type string or Zend\\Tool\\Project\\Context\\Interface.');
  161. }
  162. $newResource = new Resource($context);
  163. if ($attributes) {
  164. $newResource->setAttributes($attributes);
  165. }
  166. /**
  167. * Interesting logic here:
  168. *
  169. * First set the parentResource (this will also be done inside append). This will allow
  170. * the initialization routine to change the appendability of the parent resource. This
  171. * is important to allow specific resources to be appendable by very specific sub-resources.
  172. */
  173. $newResource->setParentResource($this);
  174. $newResource->initializeContext();
  175. $this->append($newResource);
  176. return $newResource;
  177. }
  178. /**
  179. * setAttributes()
  180. *
  181. * persist the attributes if the resource will accept them
  182. *
  183. * @param array $attributes
  184. * @return \Zend\Tool\Project\Profile\Resource\Container
  185. */
  186. public function setAttributes(Array $attributes)
  187. {
  188. foreach ($attributes as $attrName => $attrValue) {
  189. $setMethod = 'set' . $attrName;
  190. if (method_exists($this, $setMethod)) {
  191. $this->{$setMethod}($attrValue);
  192. } else {
  193. $this->setAttribute($attrName, $attrValue);
  194. }
  195. }
  196. return $this;
  197. }
  198. /**
  199. * getAttributes()
  200. *
  201. * @return array
  202. */
  203. public function getAttributes()
  204. {
  205. return $this->_attributes;
  206. }
  207. /**
  208. * setAttribute()
  209. *
  210. * @param string $name
  211. * @param mixed $value
  212. * @return \Zend\Tool\Project\Profile\Resource\Container
  213. */
  214. public function setAttribute($name, $value)
  215. {
  216. $this->_attributes[$name] = $value;
  217. return $this;
  218. }
  219. /**
  220. * getAttribute()
  221. *
  222. * @param string $name
  223. * @return \Zend\Tool\Project\Profile\Resource\Container
  224. */
  225. public function getAttribute($name)
  226. {
  227. return (array_key_exists($name, $this->_attributes)) ? $this->_attributes[$name] : null;
  228. }
  229. /**
  230. * hasAttribute()
  231. *
  232. * @param string $name
  233. * @return bool
  234. */
  235. public function hasAttribute($name)
  236. {
  237. return array_key_exists($name, $this->_attributes);
  238. }
  239. /**
  240. * setAppendable()
  241. *
  242. * @param bool $appendable
  243. * @return \Zend\Tool\Project\Profile\Resource\Container
  244. */
  245. public function setAppendable($appendable)
  246. {
  247. $this->_appendable = (bool) $appendable;
  248. return $this;
  249. }
  250. /**
  251. * isAppendable()
  252. *
  253. * @return bool
  254. */
  255. public function isAppendable()
  256. {
  257. return $this->_appendable;
  258. }
  259. /**
  260. * setParentResource()
  261. *
  262. * @param \Zend\Tool\Project\Profile\Resource\Container $parentResource
  263. * @return \Zend\Tool\Project\Profile\Resource\Container
  264. */
  265. public function setParentResource(Container $parentResource)
  266. {
  267. $this->_parentResource = $parentResource;
  268. return $this;
  269. }
  270. /**
  271. * getParentResource()
  272. *
  273. * @return \Zend\Tool\Project\Profile\Resource\Container
  274. */
  275. public function getParentResource()
  276. {
  277. return $this->_parentResource;
  278. }
  279. /**
  280. * append()
  281. *
  282. * @param \Zend\Tool\Project\Profile\Resource\Container $resource
  283. * @return \Zend\Tool\Project\Profile\Resource\Container
  284. */
  285. public function append(Container $resource)
  286. {
  287. if (!$this->isAppendable()) {
  288. throw new Exception\InvalidArgumentException('Resource by name ' . (string) $this . ' is not appendable');
  289. }
  290. array_push($this->_subResources, $resource);
  291. $resource->setParentResource($this);
  292. return $this;
  293. }
  294. /**
  295. * current() - required by RecursiveIterator
  296. *
  297. * @return \Zend\Tool\Project\Profile\Resource\Resource
  298. */
  299. public function current()
  300. {
  301. return current($this->_subResources);
  302. }
  303. /**
  304. * key() - required by RecursiveIterator
  305. *
  306. * @return int
  307. */
  308. public function key()
  309. {
  310. return key($this->_subResources);
  311. }
  312. /**
  313. * next() - required by RecursiveIterator
  314. *
  315. * @return bool
  316. */
  317. public function next()
  318. {
  319. return next($this->_subResources);
  320. }
  321. /**
  322. * rewind() - required by RecursiveIterator
  323. *
  324. * @return bool
  325. */
  326. public function rewind()
  327. {
  328. return reset($this->_subResources);
  329. }
  330. /**
  331. * valid() - - required by RecursiveIterator
  332. *
  333. * @return bool
  334. */
  335. public function valid()
  336. {
  337. return (bool) $this->current();
  338. }
  339. /**
  340. * hasChildren()
  341. *
  342. * @return bool
  343. */
  344. public function hasChildren()
  345. {
  346. return (count($this->_subResources > 0)) ? true : false;
  347. }
  348. /**
  349. * getChildren()
  350. *
  351. * @return array
  352. */
  353. public function getChildren()
  354. {
  355. return $this->current();
  356. }
  357. /**
  358. * count()
  359. *
  360. * @return int
  361. */
  362. public function count()
  363. {
  364. return count($this->_subResources);
  365. }
  366. /**
  367. * __clone()
  368. *
  369. */
  370. public function __clone()
  371. {
  372. $this->rewind();
  373. foreach ($this->_subResources as $index => $resource) {
  374. $this->_subResources[$index] = clone $resource;
  375. }
  376. }
  377. }