Skip to content

Commit

Permalink
Improve CsvReader code and tests.
Browse files Browse the repository at this point in the history
  • Loading branch information
mermshaus committed Sep 7, 2016
1 parent 9089b1e commit dee3233
Show file tree
Hide file tree
Showing 2 changed files with 94 additions and 20 deletions.
28 changes: 18 additions & 10 deletions src/CsvReader.php
Expand Up @@ -103,7 +103,11 @@ public function fetchAllAssoc(array $keys = array())

$data = array();

$rowCounter = 0;

while ($row = $this->getNextRow()) {
$rowCounter++;

if ($headerFlag) {
$headerFlag = false;
$keys = $this->negotiateEncoding($row);
Expand All @@ -112,7 +116,10 @@ public function fetchAllAssoc(array $keys = array())
}

if (count($row) !== $keysCount) {
throw new Exception('Malformed line in CSV input');
throw new Exception(sprintf(
'Malformed row (%s) in CSV input',
$rowCounter
));
}

$data[] = array_combine($keys, $this->negotiateEncoding($row));
Expand All @@ -128,19 +135,17 @@ public function fetch()
{
$row = $this->getNextRow();

if (false === $row) {
// EOF
return false;
if (is_array($row)) {
$row = $this->negotiateEncoding($row);
}

$row = $this->negotiateEncoding($row);

return $row;
}

/**
* @param array $keys
* @return array|bool
* @throws Exception
*/
public function fetchAssoc(array $keys = array())
{
Expand All @@ -165,6 +170,13 @@ public function fetchAssoc(array $keys = array())

$this->fetchRowLineCounter++;

if (count($row) !== count($this->fetchRowKeys)) {
throw new Exception(sprintf(
'Malformed row (%s) in CSV input',
$this->fetchRowLineCounter
));
}

return array_combine($this->fetchRowKeys, $this->negotiateEncoding($row));
}

Expand All @@ -177,10 +189,6 @@ private function getNextRow()

$tmp = fgetcsv($this->stream, 0, $this->delimiter, $this->enclosure, $this->escape);

if ($tmp !== false && !is_array($tmp)) {
throw new LogicException('Unexpected error in fgetcsv call');
}

return $tmp;
}

Expand Down
86 changes: 76 additions & 10 deletions tests/Kaloa/Tests/Filesystem/CsvReaderTest.php
Expand Up @@ -73,7 +73,6 @@ public function testCanReadWithOnlyHeaders()
$expected = array();

$this->assertSame($expected, $data);

}

/**
Expand All @@ -93,6 +92,23 @@ public function testCanReadWithoutHeaders()
$this->assertSame($expected, $data);
}

/**
*
*/
public function testCanReadWithCustomHeaders()
{
$stream = fopen(__DIR__ . '/csv-files/no-headers.csv', 'rb');
$reader = new CsvReader($stream);
$data = $reader->fetchAllAssoc(array('Col a', 'Col b'));
fclose($stream);

$expected = array();
$expected[] = array('Col a' => 'value 1a', 'Col b' => 'value 1b');
$expected[] = array('Col a' => 'value 2a', 'Col b' => 'value 2b');

$this->assertSame($expected, $data);
}

/**
*
*/
Expand Down Expand Up @@ -199,18 +215,68 @@ public function testThrowsExceptionOnInvalidStream()
new CsvReader('invalid');
}

/**
*
*/
public function testThrowsExceptionOnMalformedLine()
{
$csvData = <<<'CSV'
"Col a","Col b"
"value 1a"
"value 2a","value 2b"
CSV;

$dataUri = $this->convertToDataUri($csvData);

$stream = fopen($dataUri, 'rb');

$reader = new CsvReader($stream);

$this->setExpectedException('Exception', 'Malformed row (2) in CSV input');

$reader->fetchAllAssoc();

fclose($stream);
}

/**
*
*/
public function testThrowsExceptionOnMalformedLineInStreamingMode()
{
$csvData = <<<'CSV'
"Col a","Col b"
"value 1a"
"value 2a","value 2b"
CSV;

$dataUri = $this->convertToDataUri($csvData);

$stream = fopen($dataUri, 'rb');

$reader = new CsvReader($stream);

$this->setExpectedException('Exception', 'Malformed row (2) in CSV input');

while ($row = $reader->fetchAssoc()) {
// nop
}

fclose($stream);
}

/**
*
*/
public function testCanConvertCharset()
{
$csvData = <<<CSV
"Thomas Müller","FC Bayern München",Sturm
"Julian Weigl","Borussia Dortmund",Mittelfeld
"Serge Gnabry","Werder Bremen",Sturm
"Gianluigi Buffon",Juventus,Tor
"Shkodran Mustafi",Arsenal,Abwehr
"Mario Gómez","VfL Wolfsburg",Sturm
"Thomas Müller","FC Bayern München",Striker
"Julian Weigl","Borussia Dortmund",Midfield
"Serge Gnabry","Werder Bremen",Striker
"Gianluigi Buffon",Juventus,Keeper
"Shkodran Mustafi",Arsenal,Defender
"Mario Gómez","VfL Wolfsburg",Striker
CSV;

$csvData = mb_convert_encoding($csvData, 'ISO-8859-1', 'UTF-8');
Expand All @@ -232,10 +298,10 @@ public function testCanConvertCharset()

fclose($stream);

$expected = array('name' => 'Thomas Müller', 'team' => 'FC Bayern München', 'position' => 'Sturm');
$expected = array('name' => 'Thomas Müller', 'team' => 'FC Bayern München', 'position' => 'Striker');
$this->assertSame($expected, $data[0]);

$expected = array('name' => 'Mario Gómez', 'team' => 'VfL Wolfsburg', 'position' => 'Sturm');
$expected = array('name' => 'Mario Gómez', 'team' => 'VfL Wolfsburg', 'position' => 'Striker');
$this->assertSame($expected, $data[5]);
}

Expand All @@ -257,7 +323,7 @@ public function testFetchAllAfterEofReturnsEmptyArray()
}

/**
* @param $string
* @param string $string
* @return string
*/
private function convertToDataUri($string)
Expand Down

0 comments on commit dee3233

Please sign in to comment.