Skip to content

Commit 2d86f81

Browse files
Merge branch '7.2' into 7.3
* 7.2: Fix: prevent "Cannot traverse an already closed generator" error by materializing Traversable input [HttpFoundation] Fix: Encode path in X-Accel-Redirect header
2 parents 74e0e56 + 33734cd commit 2d86f81

File tree

2 files changed

+28
-0
lines changed

2 files changed

+28
-0
lines changed

Encoder/CsvEncoder.php

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,10 @@ public function encode(mixed $data, string $format, array $context = []): string
7272
} elseif (!$data) {
7373
$data = [[]];
7474
} else {
75+
if ($data instanceof \Traversable) {
76+
// Generators can only be iterated once — convert to array to allow multiple traversals
77+
$data = iterator_to_array($data);
78+
}
7579
// Sequential arrays of arrays are considered as collections
7680
$i = 0;
7781
foreach ($data as $key => $value) {

Tests/Encoder/CsvEncoderTest.php

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -708,6 +708,30 @@ public function testEndOfLinePassedInConstructor()
708708
$this->assertSame("foo,bar\r\nhello,test\r\n", $encoder->encode($value, 'csv'));
709709
}
710710

711+
/** @dataProvider provideIterable */
712+
public function testIterable(mixed $data)
713+
{
714+
$this->assertEquals(<<<'CSV'
715+
foo,bar
716+
hello,"hey ho"
717+
hi,"let's go"
718+
719+
CSV, $this->encoder->encode($data, 'csv'));
720+
}
721+
722+
public static function provideIterable()
723+
{
724+
$data = [
725+
['foo' => 'hello', 'bar' => 'hey ho'],
726+
['foo' => 'hi', 'bar' => 'let\'s go'],
727+
];
728+
729+
yield 'array' => [$data];
730+
yield 'array iterator' => [new \ArrayIterator($data)];
731+
yield 'iterator aggregate' => [new \IteratorIterator(new \ArrayIterator($data))];
732+
yield 'generator' => [(fn (): \Generator => yield from $data)()];
733+
}
734+
711735
/**
712736
* @group legacy
713737
*/

0 commit comments

Comments
 (0)