diff options
-rw-r--r-- | CHANGELOG.md | 11 | ||||
-rw-r--r-- | src/Validators/ColumnConsistency.php | 123 | ||||
-rw-r--r-- | src/Validators/NullHandling.php | 134 | ||||
-rw-r--r-- | src/Writer.php | 228 | ||||
-rw-r--r-- | test/Validators/ColumnConsistencyTest.php | 78 | ||||
-rw-r--r-- | test/Validators/NullHandlingTest.php | 117 | ||||
-rw-r--r-- | test/WriterTest.php | 128 |
7 files changed, 528 insertions, 291 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md index b36c8f2..7eec613 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,8 +4,14 @@ All Notable changes to `League\Csv` will be documented in this file ## Next - 2015-XX-XX ### Added -- `Writer::NULL_HANDLING_DISABLED` To completely remove null handling when inserting new data. -- `Writer::useValidation` To enable/disabled complete validation when inserting new data. +- `Writer::useValidation` To enable/disabled row validation when inserting new data. +- `Writer::addValidationRule` to add any callable function to the Writer +- `Writer::removeValidationRule` to remove an already registered callable +- `Writer::hasValidationRule` to detect the presence of a validation rule +- `League\Csv\Validators\ColumnConsistency` to validation column consistency when adding new data +- `League\Csv\Validators\NullHandling` to handle `null` value on insertion + +To better manage row validation on insert with the `Writer` class ### Deprecated - Nothing @@ -25,6 +31,7 @@ All Notable changes to `League\Csv` will be documented in this file ### Removed - Setting `ini_set("auto_detect_line_endings", true);` is no longer set in the class constructor. Mac OS X users must explicitly set this ini options in their script. - `Writer` and `Reader` default constructor are removed from public API in favor of the named constructors. +- All `Writer` built in validation methods, properties and constants have been removed from the class to allow for better extensibility. ## 6.3.0 - 2015-01-21 diff --git a/src/Validators/ColumnConsistency.php b/src/Validators/ColumnConsistency.php new file mode 100644 index 0000000..06d0bfd --- /dev/null +++ b/src/Validators/ColumnConsistency.php @@ -0,0 +1,123 @@ +<?php +/** +* This file is part of the League.csv library +* +* @license http://opensource.org/licenses/MIT +* @link https://github.com/thephpleague/csv/ +* @version 7.0.0 +* @package League.csv +* +* For the full copyright and license information, please view the LICENSE +* file that was distributed with this source code. +*/ +namespace League\Csv\Validators; + +use InvalidArgumentException; +use RuntimeException; + +/** + * A class to manage data insertion into a CSV + * + * @package League.csv + * @since 7.0.0 + * + */ +class ColumnConsistency +{ + /** + * The number of column per row + * + * @var int + */ + private $columns_count = -1; + + /** + * should the class detect the column count based the inserted row + * + * @var bool + */ + private $detect_columns_count = false; + + /** + * Set Inserted row column count + * + * @param int $value + * + * @throws \InvalidArgumentException If $value is lesser than -1 + * + * @return static + */ + public function setColumnsCount($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_columns_count = false; + $this->columns_count = $value; + + return $this; + } + + /** + * Column count getter + * + * @return int + */ + public function getColumnsCount() + { + return $this->columns_count; + } + + /** + * The method will set the $columns_count property according to the next inserted row + * and therefore will also validate the next line whatever length it has no matter + * the current $columns_count property value. + * + * @return static + */ + public function autodetectColumnsCount() + { + $this->detect_columns_count = true; + + return $this; + } + + /** + * Is the submitted row valid + * + * @param array $row + * + * @throws \RuntimeException If the given $row does not contain valid column count + * + * @return array + */ + public function __invoke(array $row) + { + if (! $this->isColumnsCountConsistent($row)) { + throw new RuntimeException('Adding '.count($row).' cells on a {$this->columns_count} cells per row CSV.'); + } + + return $row; + } + + /** + * Check column count consistency + * + * @param array $row the row to be added to the CSV + * + * @return bool + */ + private function isColumnsCountConsistent(array $row) + { + if ($this->detect_columns_count) { + $this->columns_count = count($row); + $this->detect_columns_count = false; + + return true; + } elseif (-1 == $this->columns_count) { + return true; + } + + return count($row) == $this->columns_count; + } +} diff --git a/src/Validators/NullHandling.php b/src/Validators/NullHandling.php new file mode 100644 index 0000000..a685d84 --- /dev/null +++ b/src/Validators/NullHandling.php @@ -0,0 +1,134 @@ +<?php +/** +* This file is part of the League.csv library +* +* @license http://opensource.org/licenses/MIT +* @link https://github.com/thephpleague/csv/ +* @version 7.0.0 +* @package League.csv +* +* For the full copyright and license information, please view the LICENSE +* file that was distributed with this source code. +*/ +namespace League\Csv\Validators; + +use InvalidArgumentException; +use OutOfBoundsException; + +/** + * A class to manage data insertion into a CSV + * + * @package League.csv + * @since 7.0.0 + * + */ +class NullHandling +{ + /** + * set null handling mode to throw exception + */ + const NULL_AS_EXCEPTION = 1; + + /** + * set null handling mode to remove cell + */ + const NULL_AS_SKIP_CELL = 2; + + /** + * set null handling mode to convert null into empty string + */ + const NULL_AS_EMPTY = 3; + + /** + * disable null handling + */ + const NULL_HANDLING_DISABLED = 4; + + /** + * the object current null handling mode + * + * @var int + */ + private $null_handling_mode = self::NULL_AS_EXCEPTION; + + /** + * Tell the class how to handle null value + * + * @param int $value a Writer null behavior constant + * + * @throws \OutOfBoundsException If the Integer is not valid + * + * @return static + */ + public function setNullHandlingMode($value) + { + if (! in_array($value, [ + self::NULL_AS_SKIP_CELL, + self::NULL_AS_EXCEPTION, + self::NULL_AS_EMPTY, + self::NULL_HANDLING_DISABLED, + ])) { + throw new OutOfBoundsException('invalid value for null handling'); + } + $this->null_handling_mode = $value; + + return $this; + } + + /** + * null handling getter + * + * @return int + */ + public function getNullHandlingMode() + { + return $this->null_handling_mode; + } + + + /** + * Is the submitted row valid + * + * @param array $row + * + * @throws \InvalidArgumentException If the given $row is not valid + * + * @return array + */ + public function __invoke(array $row) + { + if (self::NULL_HANDLING_DISABLED == $this->null_handling_mode) { + return $row; + } + + array_walk($row, function ($value) { + if (! $this->isConvertibleContent($value)) { + throw new InvalidArgumentException('The values are not convertible into strings'); + } + }); + + if (self::NULL_AS_EMPTY == $this->null_handling_mode) { + return str_replace(null, '', $row); + } + + return array_filter($row, function ($value) { + return ! is_null($value); + }); + } + + /** + * Check if a given value can be added into a CSV cell + * + * The value MUST respect the null handling mode + * The value MUST be convertible into a string + * + * @param string|null $value the value to be added + * + * @return bool + */ + private function isConvertibleContent($value) + { + return (is_null($value) && self::NULL_AS_EXCEPTION != $this->null_handling_mode) + || \League\Csv\Writer::isValidString($value); + } +} diff --git a/src/Writer.php b/src/Writer.php index 9c52374..1e12ab2 100644 --- a/src/Writer.php +++ b/src/Writer.php @@ -13,9 +13,6 @@ namespace League\Csv; use InvalidArgumentException; -use OutOfBoundsException; -use RuntimeException; -use SplFileObject; use Traversable; /** @@ -28,47 +25,6 @@ use Traversable; class Writer extends AbstractCsv { /** - * set null handling mode to throw exception - */ - const NULL_AS_EXCEPTION = 1; - - /** - * set null handling mode to remove cell - */ - const NULL_AS_SKIP_CELL = 2; - - /** - * set null handling mode to convert null into empty string - */ - const NULL_AS_EMPTY = 3; - - /** - * disable null handling - */ - const NULL_HANDLING_DISABLED = 4; - - /** - * the object current null handling mode - * - * @var int - */ - protected $null_handling_mode = self::NULL_AS_EXCEPTION; - - /** - * The number of column per row - * - * @var int - */ - protected $columns_count = -1; - - /** - * should the class detect the column count based the inserted row - * - * @var bool - */ - protected $detect_columns_count = false; - - /** * {@ihneritdoc} */ protected $stream_filter_mode = STREAM_FILTER_WRITE; @@ -81,102 +37,107 @@ class Writer extends AbstractCsv protected $csv; /** + * Callables to filter the iterator + * + * @var callable[] + */ + protected $rules = []; + + /** * should the class validate the input before insertion * * @var boolean */ protected $useValidation = true; + /** - * Tell the class how to handle null value - * - * @param int $value a Writer null behavior constant + * Tells wether the library should check or not the input * - * @throws \OutOfBoundsException If the Integer is not valid + * @param bool $status * * @return static */ - public function setNullHandlingMode($value) + public function useValidation($activate) { - if (! in_array($value, [ - self::NULL_AS_SKIP_CELL, - self::NULL_AS_EXCEPTION, - self::NULL_AS_EMPTY, - self::NULL_HANDLING_DISABLED, - ])) { - throw new OutOfBoundsException('invalid value for null handling'); - } - $this->null_handling_mode = $value; + $this->useValidation = (bool) $activate; return $this; } /** - * null handling getter + * Set an Iterator sorting callable function + * + * @param callable $callable * - * @return int + * @return static */ - public function getNullHandlingMode() + public function addValidationRule(callable $callable) { - return $this->null_handling_mode; + $this->rules[] = $callable; + + return $this; } /** - * Set Inserted row column count + * Remove a callable from the collection * - * @param int $value - * - * @throws \InvalidArgumentException If $value is lesser than -1 + * @param callable $callable * * @return static */ - public function setColumnsCount($value) + public function removeValidationRule(callable $callable) { - 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'); + $res = array_search($callable, $this->rules, true); + if (false !== $res) { + unset($this->rules[$res]); } - $this->detect_columns_count = false; - $this->columns_count = $value; return $this; } /** - * Column count getter + * Detect if the callable is already registered + * + * @param callable $callable * - * @return int + * @return bool */ - public function getColumnsCount() + public function hasValidationRule(callable $callable) { - return $this->columns_count; + return false !== array_search($callable, $this->rules, true); } /** - * The method will set the $columns_count property according to the next inserted row - * and therefore will also validate the next line whatever length it has no matter - * the current $columns_count property value. + * Remove all registered callable * * @return static */ - public function autodetectColumnsCount() + public function clearValidationRules() { - $this->detect_columns_count = true; + $this->rules = []; return $this; } /** - * Tells wether the library should check or not the input - * - * @param bool $status - * - * @return static - */ - public function useValidation($status) + * Filter the Iterator + * + * @param array $row + * + * @return array + */ + protected function applyValidationRules(array $row) { - $this->useValidation = (bool) $status; + if (! $this->useValidation || ! $this->rules) { + return $row; + } - return $this; + foreach ($this->rules as $rule) { + $row = $rule($row); + } + + return $row; } /** @@ -215,9 +176,7 @@ class Writer extends AbstractCsv public function insertOne($row) { $row = $this->formatRow($row); - if ($this->useValidation) { - $row = $this->validateRow($row); - } + $row = $this->applyValidationRules($row); $csv = $this->getCsv(); $csv->fputcsv($row, $this->delimiter, $this->enclosure); if ("\n" !== $this->newline) { @@ -245,91 +204,6 @@ class Writer extends AbstractCsv } /** - * Is the submitted row valid - * - * @param array $row - * - * @throws \InvalidArgumentException If the given $row is not valid - * @throws \RuntimeException If the given $row does not contain valid column count - * - * @return array - */ - protected function validateRow(array $row) - { - if (self::NULL_HANDLING_DISABLED != $this->null_handling_mode) { - array_walk($row, function ($value) { - if (! $this->isConvertibleContent($value)) { - throw new InvalidArgumentException('The values are not convertible into strings'); - } - }); - $row = $this->sanitizeColumnsContent($row); - } - - if (! $this->isColumnsCountConsistent($row)) { - throw new RuntimeException('Adding '.count($row).' cells on a {$this->columns_count} cells per row CSV.'); - } - - return $row; - } - - /** - * Check if a given value can be added into a CSV cell - * - * The value MUST respect the null handling mode - * The value MUST be convertible into a string - * - * @param string|null $value the value to be added - * - * @return bool - */ - protected function isConvertibleContent($value) - { - return (is_null($value) && self::NULL_AS_EXCEPTION != $this->null_handling_mode) - || self::isValidString($value); - } - - /** - * Format the row according to the null handling behavior - * - * @param array $row - * - * @return array - */ - protected function sanitizeColumnsContent(array $row) - { - if (self::NULL_AS_EMPTY == $this->null_handling_mode) { - return str_replace(null, '', $row); - } elseif (self::NULL_AS_SKIP_CELL == $this->null_handling_mode) { - return array_filter($row, function ($value) { - return !is_null($value); - }); - } - - return $row; - } - - /** - * Check column count consistency - * - * @param array $row the row to be added to the CSV - * - * @return bool - */ - protected function isColumnsCountConsistent(array $row) - { - if ($this->detect_columns_count) { - $this->columns_count = count($row); - $this->detect_columns_count = false; - - return true; - } elseif (-1 == $this->columns_count) { - return true; - } - - return count($row) == $this->columns_count; - } - - /** * set the csv container as a SplFileObject instance * insure we use the same object for insertion to * avoid loosing the cursor position diff --git a/test/Validators/ColumnConsistencyTest.php b/test/Validators/ColumnConsistencyTest.php new file mode 100644 index 0000000..2233532 --- /dev/null +++ b/test/Validators/ColumnConsistencyTest.php @@ -0,0 +1,78 @@ +<?php + +namespace League\Csv\Test\Validators; + +use ArrayIterator; +use DateTime; +use League\Csv\Writer; +use League\Csv\Validators\ColumnConsistency; +use LimitIterator; +use PHPUnit_Framework_TestCase; +use SplFileObject; +use SplTempFileObject; + +date_default_timezone_set('UTC'); + +/** + * @group validators + */ +class ColumnConsistencyTest extends PHPUnit_Framework_TestCase +{ + private $csv; + + public function setUp() + { + $this->csv = Writer::createFromFileObject(new SplTempFileObject()); + } + + public function tearDown() + { + $csv = new SplFileObject(__DIR__.'/foo.csv', 'w'); + $csv->setCsvControl(); + $csv->fputcsv(["john", "doe", "john.doe@example.com"], ",", '"'); + $this->csv = null; + } + + /** + * @expectedException InvalidArgumentException + * @expectedExceptionMessage the column count must an integer greater or equals to -1 + */ + public function testColumsCountSetterGetter() + { + $consistency = new ColumnConsistency(); + $this->assertSame(-1, $consistency->getColumnsCount()); + $consistency->setColumnsCount(3); + $this->assertSame(3, $consistency->getColumnsCount()); + $consistency->setColumnsCount('toto'); + } + + /** + * @expectedException RuntimeException + * @expectedExceptionMessageRegexp Adding \d+ cells on a \d+ cells per row CSV + */ + public function testColumsCountConsistency() + { + $consistency = new ColumnConsistency(); + $this->csv->addValidationRule($consistency); + $this->csv->insertOne(['john', 'doe', 'john.doe@example.com']); + $consistency->setColumnsCount(2); + $this->csv->insertOne(['jane', 'jane.doe@example.com']); + $consistency->setColumnsCount(3); + $this->csv->insertOne(['jane', 'jane.doe@example.com']); + } + + /** + * @expectedException RuntimeException + * @expectedExceptionMessageRegexp Adding \d+ cells on a \d+ cells per row CSV + */ + public function testAutoDetectColumnsCount() + { + $consistency = new ColumnConsistency(); + $this->csv->addValidationRule($consistency); + $consistency->autodetectColumnsCount(); + $this->assertSame(-1, $consistency->getColumnsCount()); + $this->csv->insertOne(['john', 'doe', 'john.doe@example.com']); + $this->assertSame(3, $consistency->getColumnsCount()); + $this->csv->insertOne(['jane', 'jane.doe@example.com']); + } +} diff --git a/test/Validators/NullHandlingTest.php b/test/Validators/NullHandlingTest.php new file mode 100644 index 0000000..8132a98 --- /dev/null +++ b/test/Validators/NullHandlingTest.php @@ -0,0 +1,117 @@ +<?php + +namespace League\Csv\Test\Validators; + +use ArrayIterator; +use DateTime; +use League\Csv\Writer; +use League\Csv\Validators\NullHandling; +use LimitIterator; +use PHPUnit_Framework_TestCase; +use SplFileObject; +use SplTempFileObject; + +date_default_timezone_set('UTC'); + +/** + * @group validators + */ +class NullHandlingTest extends PHPUnit_Framework_TestCase +{ + private $csv; + + public function setUp() + { + $this->csv = Writer::createFromFileObject(new SplTempFileObject()); + } + + public function tearDown() + { + $csv = new SplFileObject(__DIR__.'/foo.csv', 'w'); + $csv->setCsvControl(); + $csv->fputcsv(["john", "doe", "john.doe@example.com"], ",", '"'); + $this->csv = null; + } + + /** + * @expectedException OutOfBoundsException + * @expectedExceptionMessage invalid value for null handling + */ + public function testSetterGetterNullBehavior() + { + $plugin = new NullHandling(); + $plugin->setNullHandlingMode(NullHandling::NULL_AS_SKIP_CELL); + $this->assertSame(NullHandling::NULL_AS_SKIP_CELL, $plugin->getNullHandlingMode()); + + $plugin->setNullHandlingMode(23); + } + + + public function testInsertNullToSkipCell() + { + $expected = [ + ['john', 'doe', 'john.doe@example.com'], + 'john,doe,john.doe@example.com', + ['john', null, 'john.doe@example.com'], + ]; + $plugin = new NullHandling(); + $plugin->setNullHandlingMode(NullHandling::NULL_AS_SKIP_CELL); + $this->csv->addValidationRule($plugin); + 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'], + ]; + $plugin = new NullHandling(); + $plugin->setNullHandlingMode(NullHandling::NULL_AS_EMPTY); + $this->csv->addValidationRule($plugin); + 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 testInsertWithoutNullHandlingMode() + { + $expected = [ + ['john', 'doe', 'john.doe@example.com'], + 'john,doe,john.doe@example.com', + ['john', null, 'john.doe@example.com'], + ]; + $plugin = new NullHandling(); + $plugin->setNullHandlingMode(NullHandling::NULL_HANDLING_DISABLED); + $this->csv->addValidationRule($plugin); + $this->csv->insertAll($expected); + + $iterator = new LimitIterator($this->csv->getIterator(), 2, 1); + $iterator->rewind(); + $res = $iterator->getInnerIterator()->current(); + $this->assertSame(['john', '', 'john.doe@example.com'], $res); + } + + /** + * @expectedException InvalidArgumentException + * @expectedExceptionMessage + */ + public function testInsertNullThrowsException() + { + $plugin = new NullHandling(); + $plugin->setNullHandlingMode(NullHandling::NULL_AS_EXCEPTION); + $this->csv->addValidationRule($plugin); + $this->csv->insertOne(['john', null, 'john.doe@example.com']); + } +} diff --git a/test/WriterTest.php b/test/WriterTest.php index 96874de..0d59dc1 100644 --- a/test/WriterTest.php +++ b/test/WriterTest.php @@ -56,18 +56,6 @@ class WriterTest extends PHPUnit_Framework_TestCase } } - /** - * @expectedException OutOfBoundsException - * @expectedExceptionMessage invalid value for null handling - */ - public function testSetterGetterNullBehavior() - { - $this->csv->setNullHandlingMode(Writer::NULL_AS_SKIP_CELL); - $this->assertSame(Writer::NULL_AS_SKIP_CELL, $this->csv->getNullHandlingMode()); - - $this->csv->setNullHandlingMode(23); - } - public function testInsertNormalFile() { $csv = Writer::createFromPath(__DIR__.'/foo.csv', 'a+'); @@ -77,56 +65,6 @@ class WriterTest extends PHPUnit_Framework_TestCase $this->assertSame(['jane', 'doe', 'jane.doe@example.com'], $iterator->getInnerIterator()->current()); } - public function testInsertNullToSkipCell() - { - $expected = [ - ['john', 'doe', 'john.doe@example.com'], - 'john,doe,john.doe@example.com', - ['john', null, 'john.doe@example.com'], - ]; - $this->csv->setNullHandlingMode(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->setNullHandlingMode(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); - } - - public function testInsertWithoutNullHandlingMode() - { - $expected = [ - ['john', 'doe', 'john.doe@example.com'], - 'john,doe,john.doe@example.com', - ['john', null, 'john.doe@example.com'], - ]; - $this->csv->setNullHandlingMode(Writer::NULL_HANDLING_DISABLED); - $this->csv->insertAll($expected); - - $iterator = new LimitIterator($this->csv->getIterator(), 2, 1); - $iterator->rewind(); - $res = $iterator->getInnerIterator()->current(); - $this->assertSame(['john', '', 'john.doe@example.com'], $res); - } - /** * @expectedException PHPUnit_Framework_Error */ @@ -143,54 +81,6 @@ class WriterTest extends PHPUnit_Framework_TestCase } /** - * @expectedException InvalidArgumentException - * @expectedExceptionMessage - */ - public function testInsertNullThrowsException() - { - $this->csv->setNullHandlingMode(Writer::NULL_AS_EXCEPTION); - $this->csv->insertOne(['john', null, 'john.doe@example.com']); - } - - /** - * @expectedException InvalidArgumentException - * @expectedExceptionMessage the column count must an integer greater or equals to -1 - */ - public function testColumsCountSetterGetter() - { - $this->assertSame(-1, $this->csv->getColumnsCount()); - $this->csv->setColumnsCount(3); - $this->assertSame(3, $this->csv->getColumnsCount()); - $this->csv->setColumnsCount('toto'); - } - - /** - * @expectedException RuntimeException - * @expectedExceptionMessageRegexp Adding \d+ cells on a \d+ cells per row CSV - */ - public function testColumsCountConsistency() - { - $this->csv->insertOne(['john', 'doe', 'john.doe@example.com']); - $this->csv->setColumnsCount(2); - $this->csv->insertOne(['jane', 'jane.doe@example.com']); - $this->csv->setColumnsCount(3); - $this->csv->insertOne(['jane', 'jane.doe@example.com']); - } - - /** - * @expectedException RuntimeException - * @expectedExceptionMessageRegexp Adding \d+ cells on a \d+ cells per row CSV - */ - public function testAutoDetectColumnsCount() - { - $this->csv->autodetectColumnsCount(); - $this->assertSame(-1, $this->csv->getColumnsCount()); - $this->csv->insertOne(['john', 'doe', 'john.doe@example.com']); - $this->assertSame(3, $this->csv->getColumnsCount()); - $this->csv->insertOne(['jane', 'jane.doe@example.com']); - } - - /** * @expectedException PHPUnit_Framework_Error */ public function testFailedInsertWithWrongData() @@ -199,8 +89,7 @@ class WriterTest extends PHPUnit_Framework_TestCase } /** - * @expectedException InvalidArgumentException - * @expectedExceptionMessageRegexp Adding \d+ cells on a \d+ cells per row CSV + * @expectedException PHPUnit_Framework_Error */ public function testFailedInsertWithMultiDimensionArray() { @@ -266,4 +155,19 @@ class WriterTest extends PHPUnit_Framework_TestCase $csv = Writer::createFromString($raw, $expected); $this->assertSame($expected, $csv->getNewline()); } + + public function testAddRules() + { + $func = function (array $row) { + return $row; + }; + + $this->csv->addValidationRule($func); + $this->csv->addValidationRule($func); + $this->assertTrue($this->csv->hasValidationRule($func)); + $this->csv->removeValidationRule($func); + $this->assertTrue($this->csv->hasValidationRule($func)); + $this->csv->clearValidationRules(); + $this->assertFalse($this->csv->hasValidationRule($func)); + } } |