1--TEST--
2foreach with iteratorAggregate
3--FILE--
4<?php
5class EnglishMealIterator implements Iterator {
6	private $pos=0;
7	private $myContent=array("breakfast", "dinner", "tea");
8
9	public function valid() {
10		global $indent;
11		echo "$indent--> " . __METHOD__ . " ($this->pos)\n";
12		return $this->pos < count($this->myContent);
13	}
14
15	public function next() {
16		global $indent;
17		echo "$indent--> " . __METHOD__ . " ($this->pos)\n";
18		$this->pos++;
19	}
20
21	public function rewind() {
22		global $indent;
23		echo "$indent--> " . __METHOD__ . " ($this->pos)\n";
24		$this->pos=0;
25	}
26
27	public function current() {
28		global $indent;
29		echo "$indent--> " . __METHOD__ . " ($this->pos)\n";
30		return $this->myContent[$this->pos];
31	}
32
33	public function key() {
34		global $indent;
35		echo "$indent--> " . __METHOD__ . " ($this->pos)\n";
36		return "meal " . $this->pos;
37	}
38
39}
40
41class FrenchMealIterator implements Iterator {
42	private $pos=0;
43	private $myContent=array("petit dejeuner", "dejeuner", "gouter", "dinner");
44
45	public function valid() {
46		global $indent;
47		echo "$indent--> " . __METHOD__ . " ($this->pos)\n";
48		return $this->pos < count($this->myContent);
49	}
50
51	public function next() {
52		global $indent;
53		echo "$indent--> " . __METHOD__ . " ($this->pos)\n";
54		$this->pos++;
55	}
56
57	public function rewind() {
58		global $indent;
59		echo "$indent--> " . __METHOD__ . " ($this->pos)\n";
60		$this->pos=0;
61	}
62
63	public function current() {
64		global $indent;
65		echo "$indent--> " . __METHOD__ . " ($this->pos)\n";
66		return $this->myContent[$this->pos];
67	}
68
69	public function key() {
70		global $indent;
71		echo "$indent--> " . __METHOD__ . " ($this->pos)\n";
72		return "meal " . $this->pos;
73	}
74
75}
76
77
78Class EuropeanMeals implements IteratorAggregate {
79
80	private $storedEnglishMealIterator;
81	private $storedFrenchMealIterator;
82
83	public function __construct() {
84		$this->storedEnglishMealIterator = new EnglishMealIterator;
85		$this->storedFrenchMealIterator = new FrenchMealIterator;
86	}
87
88	public function getIterator() {
89		global $indent;
90		echo "$indent--> " . __METHOD__  . "\n";
91
92		//Alternate between English and French meals
93		static $i = 0;
94		if ($i++%2 == 0) {
95			return $this->storedEnglishMealIterator;
96		} else {
97			return $this->storedFrenchMealIterator;
98		}
99	}
100
101}
102
103$f = new EuropeanMeals;
104var_dump($f);
105
106echo "-----( Simple iteration 1: )-----\n";
107foreach ($f as $k=>$v) {
108	echo "$k => $v\n";
109}
110echo "-----( Simple iteration 2: )-----\n";
111foreach ($f as $k=>$v) {
112	echo "$k => $v\n";
113}
114
115
116$indent = " ";
117echo "\n\n\n-----( Nested iteration: )-----\n";
118$count=1;
119foreach ($f as $k=>$v) {
120	echo "\nTop level "  .  $count++ . ": \n";
121	echo "$k => $v\n";
122	$indent = "     ";
123	foreach ($f as $k=>$v) {
124		echo "     $k => $v\n";
125	}
126	$indent = " ";
127}
128
129
130?>
131===DONE===
132--EXPECTF--
133object(EuropeanMeals)#%d (2) {
134  ["storedEnglishMealIterator":"EuropeanMeals":private]=>
135  object(EnglishMealIterator)#%d (2) {
136    ["pos":"EnglishMealIterator":private]=>
137    int(0)
138    ["myContent":"EnglishMealIterator":private]=>
139    array(3) {
140      [0]=>
141      string(9) "breakfast"
142      [1]=>
143      string(6) "dinner"
144      [2]=>
145      string(3) "tea"
146    }
147  }
148  ["storedFrenchMealIterator":"EuropeanMeals":private]=>
149  object(FrenchMealIterator)#%d (2) {
150    ["pos":"FrenchMealIterator":private]=>
151    int(0)
152    ["myContent":"FrenchMealIterator":private]=>
153    array(4) {
154      [0]=>
155      string(14) "petit dejeuner"
156      [1]=>
157      string(8) "dejeuner"
158      [2]=>
159      string(6) "gouter"
160      [3]=>
161      string(6) "dinner"
162    }
163  }
164}
165-----( Simple iteration 1: )-----
166--> EuropeanMeals::getIterator
167--> EnglishMealIterator::rewind (0)
168--> EnglishMealIterator::valid (0)
169--> EnglishMealIterator::current (0)
170--> EnglishMealIterator::key (0)
171meal 0 => breakfast
172--> EnglishMealIterator::next (0)
173--> EnglishMealIterator::valid (1)
174--> EnglishMealIterator::current (1)
175--> EnglishMealIterator::key (1)
176meal 1 => dinner
177--> EnglishMealIterator::next (1)
178--> EnglishMealIterator::valid (2)
179--> EnglishMealIterator::current (2)
180--> EnglishMealIterator::key (2)
181meal 2 => tea
182--> EnglishMealIterator::next (2)
183--> EnglishMealIterator::valid (3)
184-----( Simple iteration 2: )-----
185--> EuropeanMeals::getIterator
186--> FrenchMealIterator::rewind (0)
187--> FrenchMealIterator::valid (0)
188--> FrenchMealIterator::current (0)
189--> FrenchMealIterator::key (0)
190meal 0 => petit dejeuner
191--> FrenchMealIterator::next (0)
192--> FrenchMealIterator::valid (1)
193--> FrenchMealIterator::current (1)
194--> FrenchMealIterator::key (1)
195meal 1 => dejeuner
196--> FrenchMealIterator::next (1)
197--> FrenchMealIterator::valid (2)
198--> FrenchMealIterator::current (2)
199--> FrenchMealIterator::key (2)
200meal 2 => gouter
201--> FrenchMealIterator::next (2)
202--> FrenchMealIterator::valid (3)
203--> FrenchMealIterator::current (3)
204--> FrenchMealIterator::key (3)
205meal 3 => dinner
206--> FrenchMealIterator::next (3)
207--> FrenchMealIterator::valid (4)
208
209
210
211-----( Nested iteration: )-----
212 --> EuropeanMeals::getIterator
213 --> EnglishMealIterator::rewind (3)
214 --> EnglishMealIterator::valid (0)
215 --> EnglishMealIterator::current (0)
216 --> EnglishMealIterator::key (0)
217
218Top level 1:
219meal 0 => breakfast
220     --> EuropeanMeals::getIterator
221     --> FrenchMealIterator::rewind (4)
222     --> FrenchMealIterator::valid (0)
223     --> FrenchMealIterator::current (0)
224     --> FrenchMealIterator::key (0)
225     meal 0 => petit dejeuner
226     --> FrenchMealIterator::next (0)
227     --> FrenchMealIterator::valid (1)
228     --> FrenchMealIterator::current (1)
229     --> FrenchMealIterator::key (1)
230     meal 1 => dejeuner
231     --> FrenchMealIterator::next (1)
232     --> FrenchMealIterator::valid (2)
233     --> FrenchMealIterator::current (2)
234     --> FrenchMealIterator::key (2)
235     meal 2 => gouter
236     --> FrenchMealIterator::next (2)
237     --> FrenchMealIterator::valid (3)
238     --> FrenchMealIterator::current (3)
239     --> FrenchMealIterator::key (3)
240     meal 3 => dinner
241     --> FrenchMealIterator::next (3)
242     --> FrenchMealIterator::valid (4)
243 --> EnglishMealIterator::next (0)
244 --> EnglishMealIterator::valid (1)
245 --> EnglishMealIterator::current (1)
246 --> EnglishMealIterator::key (1)
247
248Top level 2:
249meal 1 => dinner
250     --> EuropeanMeals::getIterator
251     --> EnglishMealIterator::rewind (1)
252     --> EnglishMealIterator::valid (0)
253     --> EnglishMealIterator::current (0)
254     --> EnglishMealIterator::key (0)
255     meal 0 => breakfast
256     --> EnglishMealIterator::next (0)
257     --> EnglishMealIterator::valid (1)
258     --> EnglishMealIterator::current (1)
259     --> EnglishMealIterator::key (1)
260     meal 1 => dinner
261     --> EnglishMealIterator::next (1)
262     --> EnglishMealIterator::valid (2)
263     --> EnglishMealIterator::current (2)
264     --> EnglishMealIterator::key (2)
265     meal 2 => tea
266     --> EnglishMealIterator::next (2)
267     --> EnglishMealIterator::valid (3)
268 --> EnglishMealIterator::next (3)
269 --> EnglishMealIterator::valid (4)
270===DONE===
271