Skip to content

Commit

Permalink
Catch array_combine errors and skip items with warning (cherry pick 1…
Browse files Browse the repository at this point in the history
  • Loading branch information
yann-eugone authored Sep 27, 2021
1 parent d1932f7 commit 0ef37ea
Show file tree
Hide file tree
Showing 3 changed files with 76 additions and 1 deletion.
31 changes: 30 additions & 1 deletion src/batch-box-spout/src/FlatFileReader.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
use Yokai\Batch\Job\Item\ItemReaderInterface;
use Yokai\Batch\Job\JobExecutionAwareInterface;
use Yokai\Batch\Job\JobExecutionAwareTrait;
use Yokai\Batch\Warning;

final class FlatFileReader implements
ItemReaderInterface,
Expand Down Expand Up @@ -110,7 +111,35 @@ public function read(): iterable
}

if (is_array($headers)) {
$row = array_combine($headers, $row);
try {
/** @var array<string, mixed>|false $combined */
$combined = @array_combine($headers, $row);
if ($combined === false) {
// @codeCoverageIgnoreStart
// Prior to PHP 8.0 array_combine only trigger a warning
// Now it is throwing a ValueError
throw new \ValueError(
'array_combine(): Argument #1 ($keys) and argument #2 ($values) ' .
'must have the same number of elements'
);
// @codeCoverageIgnoreEnd
}
} catch (\ValueError $exception) {
$this->jobExecution->addWarning(
new Warning(
'Expecting row {row} to have exactly {expected} columns(s), but got {actual}.',
[
'{row}' => (string)$rowIndex,
'{expected}' => (string)count($headers),
'{actual}' => (string)count($row),
],
['headers' => $headers, 'row' => $row]
)
);
continue;
}

$row = $combined;
}

yield $row;
Expand Down
42 changes: 42 additions & 0 deletions src/batch-box-spout/tests/FlatFileReaderTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,48 @@ public function testMissingFileToRead(string $type)
iterator_to_array($reader->read());
}

public function testReadWrongLineSize(): void
{
$file = __DIR__ . '/fixtures/wrong-line-size.csv';
$jobExecution = JobExecution::createRoot('123456789', 'parent');
$reader = new FlatFileReader(
'csv',
[],
FlatFileReader::HEADERS_MODE_COMBINE,
null,
$file
);
$reader->setJobExecution($jobExecution);

/** @var \Iterator $result */
$result = $reader->read();
self::assertInstanceOf(\Iterator::class, $result);
self::assertSame(
[
['firstName' => 'John', 'lastName' => 'Doe'],
['firstName' => 'Jack', 'lastName' => 'Doe'],
],
iterator_to_array($result)
);

self::assertSame(
'Expecting row {row} to have exactly {expected} columns(s), but got {actual}.',
$jobExecution->getWarnings()[0]->getMessage()
);
self::assertSame(
[
'{row}' => '3',
'{expected}' => '2',
'{actual}' => '3',
],
$jobExecution->getWarnings()[0]->getParameters()
);
self::assertSame(
['headers' => ['firstName', 'lastName'], 'row' => ['Jane', 'Doe', 'too much data']],
$jobExecution->getWarnings()[0]->getContext()
);
}

public function types()
{
foreach ([Type::CSV, Type::XLSX, Type::ODS] as $type) {
Expand Down
4 changes: 4 additions & 0 deletions src/batch-box-spout/tests/fixtures/wrong-line-size.csv
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
firstName,lastName
John,Doe
Jane,Doe,too much data
Jack,Doe

0 comments on commit 0ef37ea

Please sign in to comment.