summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorignace nyamagana butera <nyamsprod@gmail.com>2014-04-11 13:42:14 +0200
committerIgnace Nyamagana Butera <nyamsprod@gmail.com>2014-04-14 15:11:57 +0200
commitc623d3dbd71bda1c1b109c9e6901e47817fa947b (patch)
treeda84c3ce71a9a4b8851c97833ff92f36adbb9fd4
parent3cdd4d14b233b5a0863eb7c13b46fb23978081bc (diff)
downloadcsv-c623d3dbd71bda1c1b109c9e6901e47817fa947b.zip
csv-c623d3dbd71bda1c1b109c9e6901e47817fa947b.tar.gz
csv-c623d3dbd71bda1c1b109c9e6901e47817fa947b.tar.bz2
implementing consistency check in the Writer class #34
-rw-r--r--src/Writer.php131
-rw-r--r--test/WriterTest.php37
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()
{