summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/Writer.php72
-rw-r--r--test/WriterTest.php46
2 files changed, 116 insertions, 2 deletions
diff --git a/src/Writer.php b/src/Writer.php
index 41c5609..9318f23 100644
--- a/src/Writer.php
+++ b/src/Writer.php
@@ -32,8 +32,9 @@
*/
namespace League\Csv;
-use InvalidArgumentException;
use Traversable;
+use InvalidArgumentException;
+use OutOfBoundsException;
/**
* A class to manage data insertion into a CSV
@@ -44,6 +45,15 @@ use Traversable;
*/
class Writer extends AbstractCsv
{
+
+ const NULL_AS_EXCEPTION = 1;
+
+ const NULL_AS_SKIP_CELL = 2;
+
+ const NULL_AS_EMPTY = 3;
+
+ private $null_handling = self::NULL_AS_EXCEPTION;
+
/**
* The constructor
*
@@ -56,6 +66,62 @@ class Writer extends AbstractCsv
}
/**
+ * Tell the class how to handle null value
+ *
+ * @param integer $value a Writer null behavior constant
+ *
+ * @return self
+ *
+ * @throws OutOfBoundsException If the Integer is not valid
+ */
+ public function setNullHandling($value)
+ {
+ if (!in_array($value, [self::NULL_AS_SKIP_CELL, self::NULL_AS_EXCEPTION, self::NULL_AS_EMPTY])) {
+ throw new OutOfBoundsException(
+ 'invalid value for null behavior'
+ );
+ }
+ $this->null_handling = $value;
+
+ return $this;
+ }
+
+ /**
+ * null handling getter
+ *
+ * @return integer
+ */
+ public function getNullHandling()
+ {
+ return $this->null_handling;
+ }
+
+ /**
+ * Format the row according to the null handling behavior
+ *
+ * @param array $row
+ *
+ * @return array
+ */
+ private function formatRow(array $row)
+ {
+ if (self::NULL_AS_EMPTY == $this->null_handling) {
+ foreach ($row as &$value) {
+ if (is_null($value)) {
+ $value = '';
+ }
+ }
+ unset($value);
+
+ return $row;
+ }
+
+ return array_filter($row, function ($value) {
+ return ! is_null($value);
+ });
+ }
+
+ /**
* Add a new CSV row to the generated CSV
*
* @param mixed $row a string, an array or an object implementing to '__toString' method
@@ -75,9 +141,11 @@ class Writer extends AbstractCsv
);
}
$check = array_filter($row, function ($value) {
- return self::isValidString($value);
+ return (is_null($value) && self::NULL_AS_EXCEPTION != $this->null_handling)
+ || self::isValidString($value);
});
if (count($check) == count($row)) {
+ $row = $this->formatRow($row);
$this->csv->fputcsv($row, $this->delimiter, $this->enclosure);
return $this;
diff --git a/test/WriterTest.php b/test/WriterTest.php
index e22cd9a..2e87c91 100644
--- a/test/WriterTest.php
+++ b/test/WriterTest.php
@@ -4,6 +4,7 @@ namespace League\Csv\Test;
use SplTempFileObject;
use ArrayIterator;
+use LimitIterator;
use PHPUnit_Framework_TestCase;
use DateTime;
use League\Csv\Writer;
@@ -39,6 +40,51 @@ class WriterTest extends PHPUnit_Framework_TestCase
}
/**
+ * @expectedException OutOfBoundsException
+ */
+ public function testSetterGetterNullBehavior()
+ {
+ $this->csv->setNullHandling(Writer::NULL_AS_SKIP_CELL);
+ $this->assertSame(Writer::NULL_AS_SKIP_CELL, $this->csv->getNullHandling());
+
+ $this->csv->setNullHandling(23);
+ }
+
+ public function testInsertNullToSkipCell()
+ {
+ $expected = [
+ ['john', 'doe', 'john.doe@example.com'],
+ 'john,doe,john.doe@example.com',
+ ['john', null, 'john.doe@example.com'],
+ ];
+ $this->csv->setNullHandling(Writer::NULL_AS_SKIP_CELL);
+ foreach ($expected as $row) {
+ $this->csv->insertOne($row);
+ }
+ $iterator = new LimitIterator($this->csv->getIterator(), 2, 1);
+ $iterator->rewind();
+ $res = $iterator->getInnerIterator()->current();
+ $this->assertSame(['john', 'john.doe@example.com'], $res);
+ }
+
+ public function testInsertNullToEmpty()
+ {
+ $expected = [
+ ['john', 'doe', 'john.doe@example.com'],
+ 'john,doe,john.doe@example.com',
+ ['john', null, 'john.doe@example.com'],
+ ];
+ $this->csv->setNullHandling(Writer::NULL_AS_EMPTY);
+ foreach ($expected as $row) {
+ $this->csv->insertOne($row);
+ }
+ $iterator = new LimitIterator($this->csv->getIterator(), 2, 1);
+ $iterator->rewind();
+ $res = $iterator->getInnerIterator()->current();
+ $this->assertSame(['john', '', 'john.doe@example.com'], $res);
+ }
+
+ /**
* @expectedException InvalidArgumentException
*/
public function testFailedInsertWithWrongData()