1<?php
2
3/** @file iteratoriterator.inc
4 * @ingroup SPL
5 * @brief class IteratorIterator
6 * @author  Marcus Boerger
7 * @date    2003 - 2009
8 *
9 * SPL - Standard PHP Library
10 */
11
12/** @ingroup SPL
13 * @brief Basic Iterator wrapper
14 * @since PHP 5.1
15 *
16 * This iterator wrapper allows to convert anything that is traversable into
17 * an Iterator. It is very important to understand that most classes that do
18 * not implement Iterator have their reasone to. Most likely they do not allow
19 * the full Iterator feature set. If so you need to provide techniques to
20 * prevent missuse. If you do not you must expect exceptions or fatal errors.
21 *
22 * It is also possible to derive the class and implement IteratorAggregate by
23 * downcasting the instances returned in getIterator. See the following
24 * example (assuming BaseClass implements Traversable):
25 \code
26 class SomeClass extends BaseClass implements IteratorAggregate
27 {
28   function getIterator()
29   {
30     return new IteratorIterator($this, 'BaseClass');
31   }
32 }
33 \endcode
34 *
35 * As you can see in the example this approach requires that the class to
36 * downcast to is actually a base class of the specified iterator to wrap.
37 * Omitting the downcast in the above example would result in an endless loop
38 * since IteratorIterator::__construct() would call SomeClass::getIterator().
39 */
40class IteratorIterator implements OuterIterator
41{
42	/** Construct an IteratorIterator from an Iterator or an IteratorAggregate.
43	 *
44	 * @param iterator  inner iterator
45	 * @param classname optional class the iterator has to be downcasted to
46	 */
47	function __construct(Traversable $iterator, $classname = null)
48	{
49		if ($iterator instanceof IteratorAggregate)
50		{
51		    $iterator = $iterator->getIterator();
52		}
53		if ($iterator instanceof Iterator)
54		{
55			$this->iterator = $iterator;
56		}
57		else
58		{
59			throw new Exception("Classes that only implement Traversable can be wrapped only after converting class IteratorIterator into c code");
60		}
61	}
62
63	/** \return the inner iterator as passed to the constructor
64	 */
65	function getInnerIterator()
66	{
67		return $this->iterator;
68	}
69
70	/** \return whether the iterator is valid
71	 */
72	function valid()
73	{
74		return $this->iterator->valid();
75	}
76
77	/** \return current key
78	 */
79	function key()
80	{
81		return $this->iterator->key();
82	}
83
84	/** \return current value
85	 */
86	function current()
87	{
88		return $this->iterator->current();
89	}
90
91	/** forward to next element
92	 */
93	function next()
94	{
95		return $this->iterator->next();
96	}
97
98	/** rewind to the first element
99	 */
100	function rewind()
101	{
102		return $this->iterator->rewind();
103	}
104
105	/** Aggregate the inner iterator
106	 *
107	 * @param func    Name of method to invoke
108	 * @param params  Array of parameters to pass to method
109	 */
110	function __call($func, $params)
111	{
112		return call_user_func_array(array($this->iterator, $func), $params);
113	}
114
115	/** The inner iterator must be private because when this class will be
116	 * converted to c code it won't no longer be available.
117	 */
118	private $iterator;
119}
120
121?>
122