@@ -107,6 +107,57 @@ public static function renderDataProvider(): \Generator
107107 . '</ul> ' ,
108108 ];
109109
110+ $ value = new class () implements \IteratorAggregate {
111+ public function getIterator (): \Traversable
112+ {
113+ return new \ArrayIterator ([
114+ 'first ' => 'foo ' ,
115+ 'second ' => 'bar ' ,
116+ ]);
117+ }
118+ };
119+ yield 'iterator total works for non countable traversable ' => [
120+ '<f:for each="{value}" as="item" iteration="iterator">{item}: {iterator.total}, </f:for> ' ,
121+ ['value ' => $ value ],
122+ 'foo: 2, bar: 2, ' ,
123+ ];
124+
125+ yield 'iterator total works for generator ' => [
126+ '<f:for each="{value}" as="item" iteration="iterator">{item}: {iterator.total}, </f:for> ' ,
127+ static function () {
128+ $ value = (static function (): \Generator {
129+ yield 'first ' => 'foo ' ;
130+ yield 'second ' => 'bar ' ;
131+ })();
132+ return ['value ' => $ value ];
133+ },
134+ 'foo: 2, bar: 2, ' ,
135+ ];
136+
137+ yield 'iterator preserves duplicate keys from generator ' => [
138+ '<f:for each="{value}" as="item" key="key" iteration="iterator">{key}: {item} / {iterator.total}, </f:for> ' ,
139+ static function () {
140+ $ value = (static function (): \Generator {
141+ yield 'duplicate ' => 'foo ' ;
142+ yield 'duplicate ' => 'bar ' ;
143+ })();
144+ return ['value ' => $ value ];
145+ },
146+ 'duplicate: foo / 2, duplicate: bar / 2, ' ,
147+ ];
148+
149+ yield 'reverse preserves duplicate keys from generator ' => [
150+ '<f:for each="{value}" as="item" key="key" reverse="true">{key}: {item}, </f:for> ' ,
151+ static function () {
152+ $ value = (static function (): \Generator {
153+ yield 'duplicate ' => 'foo ' ;
154+ yield 'duplicate ' => 'bar ' ;
155+ })();
156+ return ['value ' => $ value ];
157+ },
158+ 'duplicate: bar, duplicate: foo, ' ,
159+ ];
160+
110161 $ value = ['item ' ];
111162 yield 'iterator not available if not requested ' => [
112163 '<f:for each="{value}" as="item">Total: {iterator.total}</f:for> ' ,
@@ -200,16 +251,16 @@ public static function renderDataProvider(): \Generator
200251
201252 #[DataProvider('renderDataProvider ' )]
202253 #[Test]
203- public function render (string $ template , array $ variables , string $ expected ): void
254+ public function render (string $ template , array | callable $ variables , string $ expected ): void
204255 {
205256 $ view = new TemplateView ();
206- $ view ->assignMultiple ($ variables );
257+ $ view ->assignMultiple (is_callable ( $ variables ) ? $ variables () : $ variables );
207258 $ view ->getRenderingContext ()->setCache (self ::$ cache );
208259 $ view ->getRenderingContext ()->getTemplatePaths ()->setTemplateSource ($ template );
209260 self ::assertSame ($ expected , $ view ->render ());
210261
211262 $ view = new TemplateView ();
212- $ view ->assignMultiple ($ variables );
263+ $ view ->assignMultiple (is_callable ( $ variables ) ? $ variables () : $ variables );
213264 $ view ->getRenderingContext ()->setCache (self ::$ cache );
214265 $ view ->getRenderingContext ()->getTemplatePaths ()->setTemplateSource ($ template );
215266 self ::assertSame ($ expected , $ view ->render ());
0 commit comments