1: <?php
2: /**
3: * PHP version 5
4: * @package generalDriver
5: * @author Christian Schiffler <c.schiffler@cyberspectrum.de>
6: * @author Stefan Heimes <stefan_heimes@hotmail.com>
7: * @author Tristan Lins <tristan.lins@bit3.de>
8: * @copyright The MetaModels team.
9: * @license LGPL.
10: * @filesource
11: */
12:
13: namespace DcGeneral\Data;
14:
15: use DcGeneral\Exception\DcGeneralException;
16: use DcGeneral\Exception\DcGeneralRuntimeException;
17:
18: /**
19: * Class DefaultCollection.
20: *
21: * This is the default implementation of a model collection in DcGeneral.
22: * Internally it simply holds an array.
23: *
24: * @package DcGeneral\Data
25: */
26: class DefaultCollection implements CollectionInterface
27: {
28: /**
29: * The list of contained models.
30: *
31: * @var ModelInterface[]
32: */
33: protected $arrCollection = array();
34:
35: /**
36: * Get length of this collection.
37: *
38: * @return int
39: */
40: public function length()
41: {
42: return count($this->arrCollection);
43: }
44:
45: /**
46: * Get the model at a specific index.
47: *
48: * @param int $intIndex The index of the model to retrieve.
49: *
50: * @return ModelInterface
51: */
52: public function get($intIndex)
53: {
54: if (array_key_exists($intIndex, $this->arrCollection))
55: {
56: return $this->arrCollection[$intIndex];
57: }
58:
59: return null;
60: }
61:
62: /**
63: * Alias for push - Append a model to the end of this collection.
64: *
65: * @param ModelInterface $objModel The model to append to the collection.
66: *
67: * @return void
68: *
69: * @throws DcGeneralRuntimeException When no model has been passed.
70: *
71: * @deprecated Use push.
72: */
73: public function add(ModelInterface $objModel)
74: {
75: $this->push($objModel);
76: }
77:
78: /**
79: * Append a model to the end of this collection.
80: *
81: * @param ModelInterface $objModel The model to append to the collection.
82: *
83: * @return void
84: *
85: * @throws DcGeneralRuntimeException When no model has been passed.
86: */
87: public function push(ModelInterface $objModel)
88: {
89: if (!$objModel)
90: {
91: throw new DcGeneralRuntimeException('push() - no model passed', 1);
92: }
93:
94: if ($objModel->hasProperties())
95: {
96: array_push($this->arrCollection, $objModel);
97: }
98: }
99:
100: /**
101: * Remove the model at the end of the collection and return it.
102: *
103: * If the collection is empty, null will be returned.
104: *
105: * @return ModelInterface
106: */
107: public function pop()
108: {
109: if (count($this->arrCollection) != 0)
110: {
111: return array_pop($this->arrCollection);
112: }
113:
114: return null;
115: }
116:
117: /**
118: * Insert a model at the beginning of the collection.
119: *
120: * @param ModelInterface $objModel The model to insert into the collection.
121: *
122: * @return void
123: */
124: public function unshift(ModelInterface $objModel)
125: {
126: if ($objModel->hasProperties())
127: {
128: array_unshift($this->arrCollection, $objModel);
129: }
130: }
131:
132: /**
133: * Remove the model from the beginning of the collection and return it.
134: *
135: * If the collection is empty, null will be returned.
136: *
137: * @return ModelInterface
138: */
139: public function shift()
140: {
141: if (count($this->arrCollection) != 0)
142: {
143: return array_shift($this->arrCollection);
144: }
145:
146: return null;
147: }
148:
149: /**
150: * Insert a record at the specific position.
151: *
152: * Move all records at position >= $index one index up.
153: * If $index is out of bounds, just add at the end (does not fill with empty records!).
154: *
155: * @param int $intIndex The index where the model shall be placed.
156: *
157: * @param ModelInterface $objModel The model to insert.
158: *
159: * @return void
160: */
161: public function insert($intIndex, ModelInterface $objModel)
162: {
163: if ($objModel->hasProperties())
164: {
165: array_insert($this->arrCollection, $intIndex, array($objModel));
166: }
167: }
168:
169: /**
170: * Remove the given index or model from the collection and renew the index.
171: *
172: * ATTENTION: Don't use key to unset in foreach because of the new index.
173: *
174: * @param mixed $mixedValue The index (integer) or InterfaceGeneralModel instance to remove.
175: *
176: * @return void
177: */
178: public function remove($mixedValue)
179: {
180: if (is_object($mixedValue))
181: {
182: foreach ($this->arrCollection as $intIndex => $objModel)
183: {
184: if ($mixedValue === $objModel)
185: {
186: unset($this->arrCollection[$intIndex]);
187: }
188: }
189: }
190: else
191: {
192: unset($this->arrCollection[$mixedValue]);
193: }
194:
195: $this->arrCollection = array_values($this->arrCollection);
196: }
197:
198: /**
199: * Make a reverse sorted collection of this collection.
200: *
201: * @return CollectionInterface
202: */
203: public function reverse()
204: {
205: $newCollection = clone $this;
206:
207: $newCollection->arrCollection = array_reverse($this->arrCollection);
208:
209: return $newCollection;
210: }
211:
212: /**
213: * Sort the records with the given callback and return the new sorted collection.
214: *
215: * @param callback $callback The callback function to use.
216: *
217: * @return CollectionInterface
218: */
219: public function sort($callback)
220: {
221: $newCollection = clone $this;
222: uasort($newCollection->arrCollection, $callback);
223:
224: $newCollection->arrCollection = array_values($newCollection->arrCollection);
225:
226: return $newCollection;
227: }
228:
229: /**
230: * Get a iterator for this collection.
231: *
232: * @return \IteratorAggregate
233: */
234: public function getIterator()
235: {
236: return new \ArrayIterator($this->arrCollection);
237: }
238: }
239: