PageRenderTime 26ms CodeModel.GetById 16ms RepoModel.GetById 1ms app.codeStats 0ms

/libs/Nette/Collections/Collection.php

https://github.com/vohnicky/treeview
PHP | 384 lines | 147 code | 97 blank | 140 comment | 13 complexity | 3f71ffb958bb3e3b201f680446a7af9d MD5 | raw file
  1. <?php
  2. /**
  3. * Nette Framework
  4. *
  5. * @copyright Copyright (c) 2004, 2010 David Grudl
  6. * @license http://nettephp.com/license Nette license
  7. * @link http://nettephp.com
  8. * @category Nette
  9. * @package Nette\Collections
  10. */
  11. /**
  12. * SPL ArrayObject customization.
  13. *
  14. * @copyright Copyright (c) 2004, 2010 David Grudl
  15. * @package Nette\Collections
  16. *
  17. * @property-read bool $frozen
  18. */
  19. abstract class Collection extends ArrayObject implements ICollection
  20. {
  21. /** @var string type (class, interface, PHP type) */
  22. private $itemType;
  23. /** @var string function to verify type */
  24. private $checkFunc;
  25. /** @var bool */
  26. private $frozen = FALSE;
  27. /**
  28. * @param array to wrap
  29. * @param string class/interface name or ':type'
  30. * @throws InvalidArgumentException
  31. */
  32. public function __construct($arr = NULL, $type = NULL)
  33. {
  34. if (substr($type, 0, 1) === ':') {
  35. $this->itemType = substr($type, 1);
  36. $this->checkFunc = 'is_' . $this->itemType;
  37. } else {
  38. $this->itemType = $type;
  39. }
  40. if ($arr !== NULL) {
  41. $this->import($arr);
  42. }
  43. }
  44. /**
  45. * Appends the specified element to the end of this collection.
  46. * @param mixed
  47. * @return void
  48. * @throws InvalidArgumentException
  49. */
  50. public function append($item)
  51. {
  52. $this->beforeAdd($item);
  53. parent::append($item);
  54. }
  55. /**
  56. * Removes the first occurrence of the specified element.
  57. * @param mixed
  58. * @return bool true if this collection changed as a result of the call
  59. * @throws NotSupportedException
  60. */
  61. public function remove($item)
  62. {
  63. $this->updating();
  64. $index = $this->search($item);
  65. if ($index === FALSE) {
  66. return FALSE;
  67. } else {
  68. parent::offsetUnset($index);
  69. return TRUE;
  70. }
  71. }
  72. /**
  73. * Returns the index of the first occurrence of the specified element,.
  74. * or FALSE if this collection does not contain this element.
  75. * @param mixed
  76. * @return int|FALSE
  77. */
  78. protected function search($item)
  79. {
  80. return array_search($item, $this->getArrayCopy(), TRUE);
  81. }
  82. /**
  83. * Removes all of the elements from this collection.
  84. * @return void
  85. * @throws NotSupportedException
  86. */
  87. public function clear()
  88. {
  89. $this->updating();
  90. parent::exchangeArray(array());
  91. }
  92. /**
  93. * Returns true if this collection contains the specified item.
  94. * @param mixed
  95. * @return bool
  96. */
  97. public function contains($item)
  98. {
  99. return $this->search($item) !== FALSE;
  100. }
  101. /**
  102. * Import from array or any traversable object.
  103. * @param array|\Traversable
  104. * @return void
  105. * @throws InvalidArgumentException
  106. */
  107. public function import($arr)
  108. {
  109. if (!(is_array($arr) || $arr instanceof Traversable)) {
  110. throw new InvalidArgumentException("Argument must be traversable.");
  111. }
  112. $this->clear();
  113. foreach ($arr as $item) {
  114. $this->offsetSet(NULL, $item);
  115. }
  116. }
  117. /**
  118. * Returns the item type.
  119. * @return string
  120. */
  121. public function getItemType()
  122. {
  123. return $this->itemType;
  124. }
  125. /**
  126. * @deprecated
  127. */
  128. public function setReadOnly()
  129. {
  130. throw new DeprecatedException(__METHOD__ . '() is deprecated; use freeze() instead.');
  131. }
  132. /**
  133. * @deprecated
  134. */
  135. public function isReadOnly()
  136. {
  137. throw new DeprecatedException(__METHOD__ . '() is deprecated; use isFrozen() instead.');
  138. }
  139. /********************* internal notifications ****************d*g**/
  140. /**
  141. * Responds when the item is about to be added to the collection.
  142. * @param mixed
  143. * @return void
  144. * @throws InvalidArgumentException, \NotSupportedException
  145. */
  146. protected function beforeAdd($item)
  147. {
  148. $this->updating();
  149. if ($this->itemType !== NULL) {
  150. if ($this->checkFunc === NULL) {
  151. if (!($item instanceof $this->itemType)) {
  152. throw new InvalidArgumentException("Item must be '$this->itemType' object.");
  153. }
  154. } else {
  155. $fnc = $this->checkFunc;
  156. if (!$fnc($item)) {
  157. throw new InvalidArgumentException("Item must be $this->itemType type.");
  158. }
  159. }
  160. }
  161. }
  162. /********************* ArrayObject cooperation ****************d*g**/
  163. /**
  164. * Returns the iterator.
  165. * @return ArrayIterator
  166. */
  167. public function getIterator()
  168. {
  169. return new ArrayIterator($this->getArrayCopy());
  170. }
  171. /**
  172. * Not supported. Use import().
  173. */
  174. public function exchangeArray($array)
  175. {
  176. throw new NotSupportedException('Use ' . __CLASS__ . '::import()');
  177. }
  178. /**
  179. * Protected exchangeArray().
  180. * @param array new array
  181. * @return Collection provides a fluent interface
  182. */
  183. protected function setArray($array)
  184. {
  185. parent::exchangeArray($array);
  186. return $this;
  187. }
  188. /********************* Nette\Object behaviour ****************d*g**/
  189. /**
  190. * @return ClassReflection
  191. */
  192. public function getReflection()
  193. {
  194. return new ClassReflection($this);
  195. }
  196. /**
  197. * Call to undefined method.
  198. *
  199. * @throws MemberAccessException
  200. */
  201. public function __call($name, $args)
  202. {
  203. return ObjectMixin::call($this, $name, $args);
  204. }
  205. /**
  206. * Call to undefined static method.
  207. *
  208. * @throws MemberAccessException
  209. */
  210. public static function __callStatic($name, $args)
  211. {
  212. $class = get_called_class();
  213. throw new MemberAccessException("Call to undefined static method $class::$name().");
  214. }
  215. /**
  216. * Returns property value. Do not call directly.
  217. *
  218. * @throws MemberAccessException if the property is not defined.
  219. */
  220. public function &__get($name)
  221. {
  222. return ObjectMixin::get($this, $name);
  223. }
  224. /**
  225. * Sets value of a property. Do not call directly.
  226. *
  227. * @throws MemberAccessException if the property is not defined or is read-only
  228. */
  229. public function __set($name, $value)
  230. {
  231. return ObjectMixin::set($this, $name, $value);
  232. }
  233. /**
  234. * Is property defined?
  235. *
  236. * @param string property name
  237. * @return bool
  238. */
  239. public function __isset($name)
  240. {
  241. return ObjectMixin::has($this, $name);
  242. }
  243. /**
  244. * Access to undeclared property.
  245. *
  246. * @throws MemberAccessException
  247. */
  248. public function __unset($name)
  249. {
  250. throw new MemberAccessException("Cannot unset the property {$this->reflection->name}::\$$name.");
  251. }
  252. /********************* Nette\FreezableObject behaviour ****************d*g**/
  253. /**
  254. * Makes the object unmodifiable.
  255. * @return void
  256. */
  257. public function freeze()
  258. {
  259. $this->frozen = TRUE;
  260. }
  261. /**
  262. * Is the object unmodifiable?
  263. * @return bool
  264. */
  265. final public function isFrozen()
  266. {
  267. return $this->frozen;
  268. }
  269. /**
  270. * Creates a modifiable clone of the object.
  271. * @return void
  272. */
  273. public function __clone()
  274. {
  275. $this->frozen = FALSE;
  276. }
  277. /**
  278. * @return void
  279. */
  280. protected function updating()
  281. {
  282. if ($this->frozen) {
  283. $class = get_class($this);
  284. throw new InvalidStateException("Cannot modify a frozen object '$class'.");
  285. }
  286. }
  287. }