PageRenderTime 46ms CodeModel.GetById 14ms RepoModel.GetById 0ms app.codeStats 0ms

/Nette/Collections/Collection.php

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