Skip to content

Commit

Permalink
implementing detectDelimiter with Exceptions #16
Browse files Browse the repository at this point in the history
  • Loading branch information
nyamsprod committed Mar 7, 2014
1 parent 5a46f7d commit 987c48c
Show file tree
Hide file tree
Showing 2 changed files with 52 additions and 23 deletions.
37 changes: 23 additions & 14 deletions src/AbstractCsv.php
Original file line number Diff line number Diff line change
Expand Up @@ -215,34 +215,43 @@ public function getDelimiter()
* Detect the CSV file delimiter
*
* @param integer $nbRows
* @param array $additionals additional delimiters
* @param array $delimiters additional delimiters
*
* @return string
*
* @throws \InvalidArgumentException If $nbRows value is invalid
* @throws \RuntimeException If too many delimiters are found
*/
public function detectDelimiter($nbRows = 1, array $additionals = [])
public function detectDelimiter($nbRows = 1, array $delimiters = [])
{
$nbRows = filter_var($nbRows, FILTER_VALIDATE_INT, ['options' => ['min_range' => 1]]);
if (! $nbRows) {
throw new InvalidArgumentException('`$nbRows` must be a valid positive integer');
}
$additionals = array_filter($additionals, function ($str) {
$delimiters = array_filter($delimiters, function ($str) {
return 1 == mb_strlen($str);
});
$delimiters = [',', ';', "\t"];
$delim = array_unique(array_merge($delimiters, $additionals));
$iterator = new CallbackFilterIterator(new LimitIterator($this->csv, 0, $nbRows), function ($row) {
return is_array($row) && count($row) > 1;
});
$origDelimiter = $this->getDelimiter();
$res = array_fill_keys($delimiters, null);
$delimiters = array_merge([',', ';', "\t"], $delimiters);
$delimiters = array_unique($delimiters);
$iterator = new CallbackFilterIterator(
new LimitIterator($this->csv, 0, $nbRows),
function ($row) {
return is_array($row) && count($row) > 1;
}
);
$res = [];
foreach ($delimiters as $delim) {
$iterator->setCsvControl($delim);
$iterator->setCsvControl($delim, $this->enclosure, $this->escape);
$res[$delim] = count(iterator_to_array($iterator, false));
}
$this->setDelimiter($origDelimiter);
arsort($res, SORT_NUMERIC);

return array_keys(array_filter($res));
$res = array_keys(array_filter($res));
if (! $res) {
return null;
} elseif (count($res) == 1) {
return $res[0];
}
throw new RuntimeException('too many delimiters were found: `'.implode('`,`', $res).'`');
}

/**
Expand Down
38 changes: 29 additions & 9 deletions test/CsvTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -84,23 +84,43 @@ public function testDelimeter()
$this->csv->setDelimiter('foo');
}

public function testDetectDelimiter()
{
$this->assertSame($this->csv->detectDelimiter(), ',');
}

/**
* @expectedException InvalidArgumentException
*/
public function testDetectDelimiter()
public function testDetectDelimiterWithInvalidRowLimit()
{
$this->assertSame($this->csv->detectDelimiter(), [',']);
$this->csv->detectDelimiter(-4);
}

public function testDetectDelimiterWithNoCSV()
{
$file = new SplTempFileObject;
$file->fwrite("How are you today ?\nI'm doing fine thanks!");
$csv = new Writer($file);
$this->assertNull($csv->detectDelimiter(5, ['toto', '|']));
}

/**
* @expectedException RuntimeException
*/
public function testDetectDelimiterWithInconsistentCSV()
{
$csv = new Writer(new SplTempFileObject);
$csv->setDelimiter(';');
$csv->insertOne(['toto', 'tata', 'tutu']);
$csv->setDelimiter(',');
$csv->insertOne(['toto', 'tata', 'tutu']);
$csv->insertOne(['toto', 'tata', 'tutu']);
$csv->insertOne(['toto', 'tata', 'tutu']);

$this->assertSame($csv->detectDelimiter(5, ['toto', '|']), [',', ';']);
$csv->detectDelimiter(-4);
$csv->setDelimiter('|');
$csv->insertAll([
['toto', 'tata', 'tutu'],
['toto', 'tata', 'tutu'],
['toto', 'tata', 'tutu']
]);

$csv->detectDelimiter(5, ['toto', '|']);
}

/**
Expand Down

0 comments on commit 987c48c

Please sign in to comment.