diff options
author | ignace nyamagana butera <nyamsprod@gmail.com> | 2014-04-11 13:42:14 +0200 |
---|---|---|
committer | Ignace Nyamagana Butera <nyamsprod@gmail.com> | 2014-04-14 15:11:57 +0200 |
commit | c623d3dbd71bda1c1b109c9e6901e47817fa947b (patch) | |
tree | da84c3ce71a9a4b8851c97833ff92f36adbb9fd4 | |
parent | 3cdd4d14b233b5a0863eb7c13b46fb23978081bc (diff) | |
download | csv-c623d3dbd71bda1c1b109c9e6901e47817fa947b.zip csv-c623d3dbd71bda1c1b109c9e6901e47817fa947b.tar.gz csv-c623d3dbd71bda1c1b109c9e6901e47817fa947b.tar.bz2 |
implementing consistency check in the Writer class #34
-rw-r--r-- | src/Writer.php | 131 | ||||
-rw-r--r-- | test/WriterTest.php | 37 |
2 files changed, 143 insertions, 25 deletions
diff --git a/src/Writer.php b/src/Writer.php index 4db0fd1..8cbfa8c 100644 --- a/src/Writer.php +++ b/src/Writer.php @@ -36,7 +36,6 @@ use Traversable; use InvalidArgumentException; use OutOfBoundsException; -use RuntimeException; /** * A class to manage data insertion into a CSV @@ -70,6 +69,20 @@ class Writer extends AbstractCsv protected $null_handling_mode = self::NULL_AS_EXCEPTION; /** + * The number of column per row + * + * @var integer + */ + protected $column_count = -1; + + /** + * should the class detect the column count based the inserted row + * + * @var boolean + */ + protected $detect_column_count = false; + + /** * Tell the class how to handle null value * * @param integer $value a Writer null behavior constant @@ -99,6 +112,95 @@ class Writer extends AbstractCsv } /** + * Set Inserted row column count + * @param integer $value + * + * @return self + * + * @throws \InvalidArgumentException If $value is lesser than -1 + */ + public function setColumnCount($value) + { + if (false === filter_var($value, FILTER_VALIDATE_INT, ['options' => ['min_range' => -1]])) { + throw new InvalidArgumentException('the column count must an integer greater or equals to -1'); + } + $this->detect_column_count = false; + $this->column_count = $value; + + return $this; + } + + /** + * Column count getter + * + * @return integer + */ + public function getColumnCount() + { + return $this->column_count; + } + + /** + * The method will set the $column_count property according to the next inserted row + * and therefore will also validate the next line whatever length it has no matter + * the current $column_count property value. + * + * @return self + */ + public function autoDetectColumnCount() + { + $this->detect_column_count = true; + + return $this; + } + + /** + * Is the submitted row valid + * + * @param mixed $row + * + * @return array + * + * @throws InvalidArgumentException If the given $row is invalid + */ + private function validateRow($row) + { + if (self::isValidString($row)) { + $row = str_getcsv((string) $row, $this->delimiter, $this->enclosure, $this->escape); + } + if (! is_array($row)) { + throw new InvalidArgumentException( + 'the data provided must be convertible into an array' + ); + } + $check = array_filter($row, function ($value) { + return (is_null($value) && self::NULL_AS_EXCEPTION != $this->null_handling_mode) + || self::isValidString($value); + }); + + if (count($check) != count($row)) { + throw new InvalidArgumentException( + 'the converted array must contain only data that can be converted into string' + ); + } + + $row = $this->formatRow($row); + if ($this->detect_column_count) { + $this->column_count = count($row); + $this->detect_column_count = false; + } + + if (-1 != $this->column_count && count($row) != $this->column_count) { + throw new InvalidArgumentException( + 'You are trying to add '.count($row).' columns to a CSV + that requires '.$this->column_count.' columns.' + ); + } + + return $row; + } + + /** * Format the row according to the null handling behavior * * @param array $row @@ -121,7 +223,7 @@ class Writer extends AbstractCsv } return array_filter($row, function ($value) { - return ! is_null($value); + return !is_null($value); }); } @@ -132,32 +234,13 @@ class Writer extends AbstractCsv * * @return self * - * @throws InvalidArgumentException If the given row format is invalid + * @throws \InvalidArgumentException If the given row is invalid */ public function insertOne($row) { - if (self::isValidString($row)) { - $row = str_getcsv((string) $row, $this->delimiter, $this->enclosure, $this->escape); - } - if (! is_array($row)) { - throw new InvalidArgumentException( - 'the row provided must be an array of a valid string that can be converted into an array' - ); - } - $check = array_filter($row, function ($value) { - return (is_null($value) && self::NULL_AS_EXCEPTION != $this->null_handling_mode) - || self::isValidString($value); - }); - if (count($check) == count($row)) { - $this->csv->fputcsv( - $this->formatRow($row), - $this->delimiter, - $this->enclosure - ); + $this->csv->fputcsv($this->validateRow($row), $this->delimiter, $this->enclosure); - return $this; - } - throw new RuntimeException('the provided data can not be transform into a single CSV data row'); + return $this; } /** diff --git a/test/WriterTest.php b/test/WriterTest.php index ecfcb90..bf922c0 100644 --- a/test/WriterTest.php +++ b/test/WriterTest.php @@ -87,13 +87,48 @@ class WriterTest extends PHPUnit_Framework_TestCase /** * @expectedException InvalidArgumentException */ + public function testColumCountSetterGetter() + { + $this->assertSame(-1, $this->csv->getColumnCount()); + $this->csv->setColumnCount(3); + $this->assertSame(3, $this->csv->getColumnCount()); + $this->csv->setColumnCount('toto'); + } + + /** + * @expectedException InvalidArgumentException + */ + public function testColumCountConsistency() + { + $this->csv->insertOne(['john', 'doe', 'john.doe@example.com']); + $this->csv->setColumnCount(2); + $this->csv->insertOne(['jane', 'jane.doe@example.com']); + $this->csv->setColumnCount(3); + $this->csv->insertOne(['jane', 'jane.doe@example.com']); + } + + /** + * @expectedException InvalidArgumentException + */ + public function testAutoDetectColumnCount() + { + $this->csv->autoDetectColumnCount(); + $this->assertSame(-1, $this->csv->getColumnCount()); + $this->csv->insertOne(['john', 'doe', 'john.doe@example.com']); + $this->assertSame(3, $this->csv->getColumnCount()); + $this->csv->insertOne(['jane', 'jane.doe@example.com']); + } + + /** + * @expectedException InvalidArgumentException + */ public function testFailedInsertWithWrongData() { $this->csv->insertOne(new DateTime); } /** - * @expectedException RuntimeException + * @expectedException InvalidArgumentException */ public function testFailedInsertWithMultiDimensionArray() { |