Completed
Pull Request — master (#578)
by Fabio
19:18 queued 07:13
created

TListIterator::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6
Code Lines 4

Duplication

Lines 0
Ratio 0 %
Metric Value
dl 0
loc 6
rs 9.4285
cc 1
eloc 4
nc 1
nop 1
1
<?php
2
/**
3
 * TList, TListIterator classes
4
 *
5
 * @author Qiang Xue <[email protected]>
6
 * @link https://github.com/pradosoft/prado
7
 * @copyright Copyright &copy; 2005-2016 The PRADO Group
8
 * @license https://github.com/pradosoft/prado/blob/master/COPYRIGHT
9
 * @package System.Collections
10
 */
11
12
/**
13
 * TList class
14
 *
15
 * TList implements an integer-indexed collection class.
16
 *
17
 * You can access, append, insert, remove an item by using
18
 * {@link itemAt}, {@link add}, {@link insertAt}, {@link remove}, and {@link removeAt}.
19
 * To get the number of the items in the list, use {@link getCount}.
20
 * TList can also be used like a regular array as follows,
21
 * <code>
22
 * $list[]=$item;  // append at the end
23
 * $list[$index]=$item; // $index must be between 0 and $list->Count
24
 * unset($list[$index]); // remove the item at $index
25
 * if(isset($list[$index])) // if the list has an item at $index
26
 * foreach($list as $index=>$item) // traverse each item in the list
27
 * $n=count($list); // returns the number of items in the list
28
 * </code>
29
 *
30
 * To extend TList by doing additional operations with each addition or removal
31
 * operation, override {@link insertAt()}, and {@link removeAt()}.
32
 *
33
 * @author Qiang Xue <[email protected]>
34
 * @package System.Collections
35
 * @since 3.0
36
 */
37
class TList extends TComponent implements IteratorAggregate,ArrayAccess,Countable
0 ignored issues
show
Coding Style introduced by
Expected 1 space before "ArrayAccess"; 0 found
Loading history...
Coding Style introduced by
Expected 1 space before "Countable"; 0 found
Loading history...
38
{
39
	/**
40
	 * internal data storage
41
	 * @var array
42
	 */
43
	private $_d=array();
44
	/**
45
	 * number of items
46
	 * @var integer
47
	 */
48
	private $_c=0;
49
	/**
50
	 * @var boolean whether this list is read-only
51
	 */
52
	private $_r=false;
53
54
	/**
55
	 * Constructor.
56
	 * Initializes the list with an array or an iterable object.
57
	 * @param array|Iterator the initial data. Default is null, meaning no initialization.
58
	 * @param boolean whether the list is read-only
59
	 * @throws TInvalidDataTypeException If data is not null and neither an array nor an iterator.
60
	 */
61
	public function __construct($data=null,$readOnly=false)
62
	{
63
		if($data!==null)
64
			$this->copyFrom($data);
65
		$this->setReadOnly($readOnly);
66
	}
67
68
	/**
69
	 * @return boolean whether this list is read-only or not. Defaults to false.
70
	 */
71
	public function getReadOnly()
72
	{
73
		return $this->_r;
74
	}
75
76
	/**
77
	 * @param boolean whether this list is read-only or not
78
	 */
79
	protected function setReadOnly($value)
80
	{
81
		$this->_r=TPropertyValue::ensureBoolean($value);
82
	}
83
84
	/**
85
	 * Returns an iterator for traversing the items in the list.
86
	 * This method is required by the interface IteratorAggregate.
87
	 * @return Iterator an iterator for traversing the items in the list.
0 ignored issues
show
Documentation introduced by
Consider making the return type a bit more specific; maybe use ArrayIterator.

This check looks for the generic type array as a return type and suggests a more specific type. This type is inferred from the actual code.

Loading history...
88
	 */
89
	public function getIterator()
90
	{
91
		return new ArrayIterator( $this->_d );
92
	}
93
94
	/**
95
	 * Returns the number of items in the list.
96
	 * This method is required by Countable interface.
97
	 * @return integer number of items in the list.
98
	 */
99
	public function count()
100
	{
101
		return $this->getCount();
102
	}
103
104
	/**
105
	 * @return integer the number of items in the list
106
	 */
107
	public function getCount()
108
	{
109
		return $this->_c;
110
	}
111
112
	/**
113
	 * Returns the item at the specified offset.
114
	 * This method is exactly the same as {@link offsetGet}.
115
	 * @param integer the index of the item
116
	 * @return mixed the item at the index
117
	 * @throws TInvalidDataValueException if the index is out of the range
118
	 */
119
	public function itemAt($index)
120
	{
121
		if($index>=0 && $index<$this->_c)
122
			return $this->_d[$index];
123
		else
124
			throw new TInvalidDataValueException('list_index_invalid',$index);
125
	}
126
127
	/**
128
	 * Appends an item at the end of the list.
129
	 * @param mixed new item
130
	 * @return integer the zero-based index at which the item is added
131
	 * @throws TInvalidOperationException if the list is read-only
132
	 */
133
	public function add($item)
134
	{
135
		$this->insertAt($this->_c,$item);
136
		return $this->_c-1;
137
	}
138
139
	/**
140
	 * Inserts an item at the specified position.
141
	 * Original item at the position and the next items
142
	 * will be moved one step towards the end.
143
	 * @param integer the specified position.
144
	 * @param mixed new item
145
	 * @throws TInvalidDataValueException If the index specified exceeds the bound
146
	 * @throws TInvalidOperationException if the list is read-only
147
	 */
148
	public function insertAt($index,$item)
149
	{
150
		if(!$this->_r)
151
		{
152
			if($index===$this->_c)
153
				$this->_d[$this->_c++]=$item;
154
			else if($index>=0 && $index<$this->_c)
155
			{
156
				array_splice($this->_d,$index,0,array($item));
157
				$this->_c++;
158
			}
159
			else
160
				throw new TInvalidDataValueException('list_index_invalid',$index);
161
		}
162
		else
163
			throw new TInvalidOperationException('list_readonly',get_class($this));
164
	}
165
166
	/**
167
	 * Removes an item from the list.
168
	 * The list will first search for the item.
169
	 * The first item found will be removed from the list.
170
	 * @param mixed the item to be removed.
171
	 * @return integer the index at which the item is being removed
172
	 * @throws TInvalidDataValueException If the item does not exist
173
	 * @throws TInvalidOperationException if the list is read-only
174
	 */
175
	public function remove($item)
176
	{
177
		if(!$this->_r)
178
		{
179
			if(($index=$this->indexOf($item))>=0)
180
			{
181
				$this->removeAt($index);
182
				return $index;
183
			}
184
			else
185
				throw new TInvalidDataValueException('list_item_inexistent');
186
		}
187
		else
188
			throw new TInvalidOperationException('list_readonly',get_class($this));
189
	}
190
191
	/**
192
	 * Removes an item at the specified position.
193
	 * @param integer the index of the item to be removed.
194
	 * @return mixed the removed item.
195
	 * @throws TInvalidDataValueException If the index specified exceeds the bound
196
	 * @throws TInvalidOperationException if the list is read-only
197
	 */
198
	public function removeAt($index)
199
	{
200
		if(!$this->_r)
201
		{
202
			if($index>=0 && $index<$this->_c)
203
			{
204
				$this->_c--;
205
				if($index===$this->_c)
206
					return array_pop($this->_d);
207
				else
208
				{
209
					$item=$this->_d[$index];
210
					array_splice($this->_d,$index,1);
211
					return $item;
212
				}
213
			}
214
			else
215
				throw new TInvalidDataValueException('list_index_invalid',$index);
216
		}
217
		else
218
			throw new TInvalidOperationException('list_readonly',get_class($this));
219
	}
220
221
	/**
222
	 * Removes all items in the list.
223
	 * @throws TInvalidOperationException if the list is read-only
224
	 */
225
	public function clear()
226
	{
227
		for($i=$this->_c-1;$i>=0;--$i)
228
			$this->removeAt($i);
229
	}
230
231
	/**
232
	 * @param mixed the item
233
	 * @return boolean whether the list contains the item
234
	 */
235
	public function contains($item)
236
	{
237
		return $this->indexOf($item)>=0;
238
	}
239
240
	/**
241
	 * @param mixed the item
242
	 * @return integer the index of the item in the list (0 based), -1 if not found.
243
	 */
244
	public function indexOf($item)
245
	{
246
		if(($index=array_search($item,$this->_d,true))===false)
247
			return -1;
248
		else
249
			return $index;
250
	}
251
252
	/**
253
	 * Finds the base item.  If found, the item is inserted before it.
254
	 * @param mixed the base item which will be pushed back by the second parameter
255
	 * @param mixed the item
256
	 * @return int the index where the item is inserted
257
	 * @throws TInvalidDataValueException if the base item is not within this list
258
	 * @throws TInvalidOperationException if the list is read-only
259
	 * @since 3.2a
260
	 */
261
	public function insertBefore($baseitem, $item)
262
	{
263
		if(!$this->_r)
264
		{
265
			if(($index = $this->indexOf($baseitem)) == -1)
266
				throw new TInvalidDataValueException('list_item_inexistent');
267
268
			$this->insertAt($index, $item);
269
270
			return $index;
271
		}
272
		else
273
			throw new TInvalidOperationException('list_readonly',get_class($this));
274
	}
275
276
	/**
277
	 * Finds the base item.  If found, the item is inserted after it.
278
	 * @param mixed the base item which comes before the second parameter when added to the list
279
	 * @param mixed the item
280
	 * @return int the index where the item is inserted
281
	 * @throws TInvalidDataValueException if the base item is not within this list
282
	 * @throws TInvalidOperationException if the list is read-only
283
	 * @since 3.2a
284
	 */
285
	public function insertAfter($baseitem, $item)
286
	{
287
		if(!$this->_r)
288
		{
289
			if(($index = $this->indexOf($baseitem)) == -1)
290
				throw new TInvalidDataValueException('list_item_inexistent');
291
292
			$this->insertAt($index + 1, $item);
293
294
			return $index + 1;
295
		}
296
		else
297
			throw new TInvalidOperationException('list_readonly',get_class($this));
298
	}
299
300
	/**
301
	 * @return array the list of items in array
302
	 */
303
	public function toArray()
304
	{
305
		return $this->_d;
306
	}
307
308
	/**
309
	 * Copies iterable data into the list.
310
	 * Note, existing data in the list will be cleared first.
311
	 * @param mixed the data to be copied from, must be an array or object implementing Traversable
312
	 * @throws TInvalidDataTypeException If data is neither an array nor a Traversable.
313
	 */
314
	public function copyFrom($data)
315
	{
316
		if(is_array($data) || ($data instanceof Traversable))
317
		{
318
			if($this->_c>0)
319
				$this->clear();
320
			foreach($data as $item)
321
				$this->add($item);
322
		}
323
		else if($data!==null)
324
			throw new TInvalidDataTypeException('list_data_not_iterable');
325
	}
326
327
	/**
328
	 * Merges iterable data into the map.
329
	 * New data will be appended to the end of the existing data.
330
	 * @param mixed the data to be merged with, must be an array or object implementing Traversable
331
	 * @throws TInvalidDataTypeException If data is neither an array nor an iterator.
332
	 */
333
	public function mergeWith($data)
334
	{
335
		if(is_array($data) || ($data instanceof Traversable))
336
		{
337
			foreach($data as $item)
338
				$this->add($item);
339
		}
340
		else if($data!==null)
341
			throw new TInvalidDataTypeException('list_data_not_iterable');
342
	}
343
344
	/**
345
	 * Returns whether there is an item at the specified offset.
346
	 * This method is required by the interface ArrayAccess.
347
	 * @param integer the offset to check on
348
	 * @return boolean
349
	 */
350
	public function offsetExists($offset)
351
	{
352
		return ($offset>=0 && $offset<$this->_c);
353
	}
354
355
	/**
356
	 * Returns the item at the specified offset.
357
	 * This method is required by the interface ArrayAccess.
358
	 * @param integer the offset to retrieve item.
359
	 * @return mixed the item at the offset
360
	 * @throws TInvalidDataValueException if the offset is invalid
361
	 */
362
	public function offsetGet($offset)
363
	{
364
		return $this->itemAt($offset);
365
	}
366
367
	/**
368
	 * Sets the item at the specified offset.
369
	 * This method is required by the interface ArrayAccess.
370
	 * @param integer the offset to set item
371
	 * @param mixed the item value
372
	 */
373
	public function offsetSet($offset,$item)
374
	{
375
		if($offset===null || $offset===$this->_c)
376
			$this->insertAt($this->_c,$item);
377
		else
378
		{
379
			$this->removeAt($offset);
380
			$this->insertAt($offset,$item);
381
		}
382
	}
383
384
	/**
385
	 * Unsets the item at the specified offset.
386
	 * This method is required by the interface ArrayAccess.
387
	 * @param integer the offset to unset item
388
	 */
389
	public function offsetUnset($offset)
390
	{
391
		$this->removeAt($offset);
392
	}
393
}
394
395
396
/**
397
 * TListIterator class
398
 *
399
 * TListIterator implements Iterator interface.
400
 *
401
 * TListIterator is used by TList. It allows TList to return a new iterator
402
 * for traversing the items in the list.
403
 *
404
 * @deprecated Issue 264 : ArrayIterator should be used instead
405
 * @author Qiang Xue <[email protected]>
406
 * @package System.Collections
407
 * @since 3.0
408
 */
409
class TListIterator extends ArrayIterator
410
{
411
}
412
413