Packages

  • Nette
    • Application
    • Caching
    • Collections
    • Config
    • Forms
    • IO
    • Loaders
    • Mail
    • Reflection
    • Security
    • Templates
    • Web
  • None
  • PHP

Classes

  • NArrayList
  • NCollection
  • NHashtable
  • NSet

Interfaces

  • ICollection
  • IList
  • IMap
  • ISet

Exceptions

  • NKeyNotFoundException
  • Overview
  • Package
  • Class
  • Tree
  • Other releases
  1: <?php
  2: 
  3: /**
  4:  * This file is part of the Nette Framework (https://nette.org)
  5:  *
  6:  * Copyright (c) 2004 David Grudl (http://davidgrudl.com)
  7:  *
  8:  * For the full copyright and license information, please view
  9:  * the file license.txt that was distributed with this source code.
 10:  * @package Nette\Collections
 11:  */
 12: 
 13: 
 14: 
 15: /**
 16:  * SPL ArrayObject customization.
 17:  *
 18:  * @author     David Grudl
 19:  *
 20:  * @property-read bool $frozen
 21:  * @package Nette\Collections
 22:  */
 23: abstract class NCollection extends ArrayObject implements ICollection
 24: {
 25:     /** @var string  type (class, interface, PHP type) */
 26:     private $itemType;
 27: 
 28:     /** @var string  function to verify type */
 29:     private $checkFunc;
 30: 
 31:     /** @var bool */
 32:     private $frozen = FALSE;
 33: 
 34: 
 35: 
 36:     /**
 37:      * @param  array to wrap
 38:      * @param  string class/interface name or ':type'
 39:      * @throws InvalidArgumentException
 40:      */
 41:     public function __construct($arr = NULL, $type = NULL)
 42:     {
 43:         if (substr($type, 0, 1) === ':') {
 44:             $this->itemType = substr($type, 1);
 45:             $this->checkFunc = 'is_' . $this->itemType;
 46:         } else {
 47:             $this->itemType = $type;
 48:         }
 49: 
 50:         if ($arr !== NULL) {
 51:             $this->import($arr);
 52:         }
 53:     }
 54: 
 55: 
 56: 
 57:     /**
 58:      * Appends the specified element to the end of this collection.
 59:      * @param  mixed
 60:      * @return void
 61:      * @throws InvalidArgumentException
 62:      */
 63:     public function append($item)
 64:     {
 65:         $this->beforeAdd($item);
 66:         parent::append($item);
 67:     }
 68: 
 69: 
 70: 
 71:     /**
 72:      * Removes the first occurrence of the specified element.
 73:      * @param  mixed
 74:      * @return bool  true if this collection changed as a result of the call
 75:      * @throws NotSupportedException
 76:      */
 77:     public function remove($item)
 78:     {
 79:         $this->updating();
 80:         $index = $this->search($item);
 81:         if ($index === FALSE) {
 82:             return FALSE;
 83:         } else {
 84:             parent::offsetUnset($index);
 85:             return TRUE;
 86:         }
 87:     }
 88: 
 89: 
 90: 
 91:     /**
 92:      * Returns the index of the first occurrence of the specified element,.
 93:      * or FALSE if this collection does not contain this element.
 94:      * @param  mixed
 95:      * @return int|FALSE
 96:      */
 97:     protected function search($item)
 98:     {
 99:         return array_search($item, $this->getArrayCopy(), TRUE);
100:     }
101: 
102: 
103: 
104:     /**
105:      * Removes all of the elements from this collection.
106:      * @return void
107:      * @throws NotSupportedException
108:      */
109:     public function clear()
110:     {
111:         $this->updating();
112:         parent::exchangeArray(array());
113:     }
114: 
115: 
116: 
117:     /**
118:      * Returns true if this collection contains the specified item.
119:      * @param  mixed
120:      * @return bool
121:      */
122:     public function contains($item)
123:     {
124:         return $this->search($item) !== FALSE;
125:     }
126: 
127: 
128: 
129:     /**
130:      * Import from array or any traversable object.
131:      * @param  array|Traversable
132:      * @return void
133:      * @throws InvalidArgumentException
134:      */
135:     public function import($arr)
136:     {
137:         if (!(is_array($arr) || $arr instanceof Traversable)) {
138:             throw new InvalidArgumentException("Argument must be traversable.");
139:         }
140: 
141:         $this->clear();
142:         foreach ($arr as $item) {
143:             $this->offsetSet(NULL, $item);
144:         }
145:     }
146: 
147: 
148: 
149:     /**
150:      * Returns the item type.
151:      * @return string
152:      */
153:     public function getItemType()
154:     {
155:         return $this->itemType;
156:     }
157: 
158: 
159: 
160:     /**
161:      * @deprecated
162:      */
163:     public function setReadOnly()
164:     {
165:         throw new DeprecatedException(__METHOD__ . '() is deprecated; use freeze() instead.');
166:     }
167: 
168: 
169: 
170:     /**
171:      * @deprecated
172:      */
173:     public function isReadOnly()
174:     {
175:         throw new DeprecatedException(__METHOD__ . '() is deprecated; use isFrozen() instead.');
176:     }
177: 
178: 
179: 
180:     /********************* internal notifications ****************d*g**/
181: 
182: 
183: 
184:     /**
185:      * Responds when the item is about to be added to the collection.
186:      * @param  mixed
187:      * @return void
188:      * @throws InvalidArgumentException, NotSupportedException
189:      */
190:     protected function beforeAdd($item)
191:     {
192:         $this->updating();
193: 
194:         if ($this->itemType !== NULL) {
195:             if ($this->checkFunc === NULL) {
196:                 if (!($item instanceof $this->itemType)) {
197:                     throw new InvalidArgumentException("Item must be '$this->itemType' object.");
198:                 }
199:             } else {
200:                 $fnc = $this->checkFunc;
201:                 if (!$fnc($item)) {
202:                     throw new InvalidArgumentException("Item must be $this->itemType type.");
203:                 }
204:             }
205:         }
206:     }
207: 
208: 
209: 
210:     /********************* ArrayObject cooperation ****************d*g**/
211: 
212: 
213: 
214:     /**
215:      * Returns the iterator.
216:      * @return NArrayIterator
217:      */
218:     public function getIterator()
219:     {
220:         return new ArrayIterator($this->getArrayCopy());
221:     }
222: 
223: 
224: 
225:     /**
226:      * Not supported. Use import().
227:      */
228:     public function exchangeArray($array)
229:     {
230:         throw new NotSupportedException('Use ' . __CLASS__ . '::import()');
231:     }
232: 
233: 
234: 
235:     /**
236:      * Protected exchangeArray().
237:      * @param  array  new array
238:      * @return NCollection  provides a fluent interface
239:      */
240:     protected function setArray($array)
241:     {
242:         parent::exchangeArray($array);
243:         return $this;
244:     }
245: 
246: 
247: 
248:     /********************* NObject behaviour ****************d*g**/
249: 
250: 
251: 
252:     /**
253:      * @return NClassReflection
254:      */
255:     public function getReflection()
256:     {
257:         return new NClassReflection($this);
258:     }
259: 
260: 
261: 
262:     /**
263:      * Call to undefined method.
264:      * @throws MemberAccessException
265:      */
266:     public function __call($name, $args)
267:     {
268:         return NObjectMixin::call($this, $name, $args);
269:     }
270: 
271: 
272: 
273:     /**
274:      * Call to undefined static method.
275:      * @throws MemberAccessException
276:      */
277:     public static function __callStatic($name, $args)
278:     {
279:         $class = __CLASS__;
280:         throw new MemberAccessException("Call to undefined static method $class::$name().");
281:     }
282: 
283: 
284: 
285:     /**
286:      * Returns property value. Do not call directly.
287:      * @throws MemberAccessException if the property is not defined.
288:      */
289:     public function &__get($name)
290:     {
291:         return NObjectMixin::get($this, $name);
292:     }
293: 
294: 
295: 
296:     /**
297:      * Sets value of a property. Do not call directly.
298:      * @throws MemberAccessException if the property is not defined or is read-only
299:      */
300:     public function __set($name, $value)
301:     {
302:         return NObjectMixin::set($this, $name, $value);
303:     }
304: 
305: 
306: 
307:     /**
308:      * Is property defined?
309:      * @param  string  property name
310:      * @return bool
311:      */
312:     public function __isset($name)
313:     {
314:         return NObjectMixin::has($this, $name);
315:     }
316: 
317: 
318: 
319:     /**
320:      * Access to undeclared property.
321:      * @throws MemberAccessException
322:      */
323:     public function __unset($name)
324:     {
325:         throw new MemberAccessException("Cannot unset the property {$this->reflection->name}::\$$name.");
326:     }
327: 
328: 
329: 
330:     /********************* NFreezableObject behaviour ****************d*g**/
331: 
332: 
333: 
334:     /**
335:      * Makes the object unmodifiable.
336:      * @return void
337:      */
338:     public function freeze()
339:     {
340:         $this->frozen = TRUE;
341:     }
342: 
343: 
344: 
345:     /**
346:      * Is the object unmodifiable?
347:      * @return bool
348:      */
349:     final public function isFrozen()
350:     {
351:         return $this->frozen;
352:     }
353: 
354: 
355: 
356:     /**
357:      * Creates a modifiable clone of the object.
358:      * @return void
359:      */
360:     public function __clone()
361:     {
362:         $this->frozen = FALSE;
363:     }
364: 
365: 
366: 
367:     /**
368:      * @return void
369:      */
370:     protected function updating()
371:     {
372:         if ($this->frozen) {
373:             $class = get_class($this);
374:             throw new InvalidStateException("Cannot modify a frozen object '$class'.");
375:         }
376:     }
377: 
378: }
379: 
Nette Framework 0.9.7 (for PHP 5.2) API documentation generated by ApiGen 2.3.0