Skip to content

Commit 0ef37ea

Browse files
authored
Catch array_combine errors and skip items with warning (cherry pick 16f6ca8) (#42)
1 parent d1932f7 commit 0ef37ea

File tree

3 files changed

+76
-1
lines changed

3 files changed

+76
-1
lines changed

src/batch-box-spout/src/FlatFileReader.php

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
use Yokai\Batch\Job\Item\ItemReaderInterface;
1515
use Yokai\Batch\Job\JobExecutionAwareInterface;
1616
use Yokai\Batch\Job\JobExecutionAwareTrait;
17+
use Yokai\Batch\Warning;
1718

1819
final class FlatFileReader implements
1920
ItemReaderInterface,
@@ -110,7 +111,35 @@ public function read(): iterable
110111
}
111112

112113
if (is_array($headers)) {
113-
$row = array_combine($headers, $row);
114+
try {
115+
/** @var array<string, mixed>|false $combined */
116+
$combined = @array_combine($headers, $row);
117+
if ($combined === false) {
118+
// @codeCoverageIgnoreStart
119+
// Prior to PHP 8.0 array_combine only trigger a warning
120+
// Now it is throwing a ValueError
121+
throw new \ValueError(
122+
'array_combine(): Argument #1 ($keys) and argument #2 ($values) ' .
123+
'must have the same number of elements'
124+
);
125+
// @codeCoverageIgnoreEnd
126+
}
127+
} catch (\ValueError $exception) {
128+
$this->jobExecution->addWarning(
129+
new Warning(
130+
'Expecting row {row} to have exactly {expected} columns(s), but got {actual}.',
131+
[
132+
'{row}' => (string)$rowIndex,
133+
'{expected}' => (string)count($headers),
134+
'{actual}' => (string)count($row),
135+
],
136+
['headers' => $headers, 'row' => $row]
137+
)
138+
);
139+
continue;
140+
}
141+
142+
$row = $combined;
114143
}
115144

116145
yield $row;

src/batch-box-spout/tests/FlatFileReaderTest.php

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,48 @@ public function testMissingFileToRead(string $type)
5757
iterator_to_array($reader->read());
5858
}
5959

60+
public function testReadWrongLineSize(): void
61+
{
62+
$file = __DIR__ . '/fixtures/wrong-line-size.csv';
63+
$jobExecution = JobExecution::createRoot('123456789', 'parent');
64+
$reader = new FlatFileReader(
65+
'csv',
66+
[],
67+
FlatFileReader::HEADERS_MODE_COMBINE,
68+
null,
69+
$file
70+
);
71+
$reader->setJobExecution($jobExecution);
72+
73+
/** @var \Iterator $result */
74+
$result = $reader->read();
75+
self::assertInstanceOf(\Iterator::class, $result);
76+
self::assertSame(
77+
[
78+
['firstName' => 'John', 'lastName' => 'Doe'],
79+
['firstName' => 'Jack', 'lastName' => 'Doe'],
80+
],
81+
iterator_to_array($result)
82+
);
83+
84+
self::assertSame(
85+
'Expecting row {row} to have exactly {expected} columns(s), but got {actual}.',
86+
$jobExecution->getWarnings()[0]->getMessage()
87+
);
88+
self::assertSame(
89+
[
90+
'{row}' => '3',
91+
'{expected}' => '2',
92+
'{actual}' => '3',
93+
],
94+
$jobExecution->getWarnings()[0]->getParameters()
95+
);
96+
self::assertSame(
97+
['headers' => ['firstName', 'lastName'], 'row' => ['Jane', 'Doe', 'too much data']],
98+
$jobExecution->getWarnings()[0]->getContext()
99+
);
100+
}
101+
60102
public function types()
61103
{
62104
foreach ([Type::CSV, Type::XLSX, Type::ODS] as $type) {
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
firstName,lastName
2+
John,Doe
3+
Jane,Doe,too much data
4+
Jack,Doe

0 commit comments

Comments
 (0)