From 657cec4b4eeed70e8eb84979786165b8fa40853a Mon Sep 17 00:00:00 2001 From: Susann Sgorzaly Date: Thu, 22 Feb 2018 20:41:03 +0100 Subject: [PATCH 01/10] added enum for sort --- src/Csv.php | 12 +++--------- src/enums/SortEnum.php | 18 ++++++++++++++++++ 2 files changed, 21 insertions(+), 9 deletions(-) create mode 100644 src/enums/SortEnum.php diff --git a/src/Csv.php b/src/Csv.php index 74381e4..f75bb0d 100644 --- a/src/Csv.php +++ b/src/Csv.php @@ -1,6 +1,7 @@ titles = $head; if (!empty($this->sort_by)) { - $sort_type = SORT_REGULAR; - if ($this->sort_type == 'numeric') { - $sort_type = SORT_NUMERIC; - } elseif ($this->sort_type == 'string') { - $sort_type = SORT_STRING; - } - - $this->sort_reverse ? krsort($rows, $sort_type) : ksort($rows, $sort_type); + $this->sort_reverse ? krsort($rows, $this->sort_type) : ksort($rows, $this->sort_type); if ($this->offset !== null || $this->limit !== null) { $rows = array_slice($rows, ($this->offset === null ? 0 : $this->offset), $this->limit, true); diff --git a/src/enums/SortEnum.php b/src/enums/SortEnum.php new file mode 100644 index 0000000..01a37b0 --- /dev/null +++ b/src/enums/SortEnum.php @@ -0,0 +1,18 @@ + Date: Thu, 22 Feb 2018 21:01:06 +0100 Subject: [PATCH 02/10] init implementation of abstract enum class --- src/enums/AbstractEnum.php | 40 ++++++++++++++++++++++++++++++++++++++ src/enums/DatatypeEnum.php | 2 +- src/enums/SortEnum.php | 9 +-------- 3 files changed, 42 insertions(+), 9 deletions(-) create mode 100644 src/enums/AbstractEnum.php diff --git a/src/enums/AbstractEnum.php b/src/enums/AbstractEnum.php new file mode 100644 index 0000000..aae78e1 --- /dev/null +++ b/src/enums/AbstractEnum.php @@ -0,0 +1,40 @@ +isValid($value)) { + throw new \UnexpectedValueException("Value '$value' is not part of the enum " . get_called_class()); + } + $this->value = $value; + } + + public static function getConstants(){ + $class = get_called_class(); + $reflection = new \ReflectionClass($class); + + return $reflection->getConstants(); + } + + /** + * Check if enum value is valid + * + * @param $value + * + * @return bool + */ + public static function isValid($value) + { + return in_array($value, static::getConstants(), true); + } +} diff --git a/src/enums/DatatypeEnum.php b/src/enums/DatatypeEnum.php index 8fea47d..7f490e9 100644 --- a/src/enums/DatatypeEnum.php +++ b/src/enums/DatatypeEnum.php @@ -9,7 +9,7 @@ namespace ParseCsv\enums; * * todo: needs a basic parent enum class for error handling. */ -class DatatypeEnum { +class DatatypeEnum extends AbstractEnum { const __DEFAULT = self::TYPE_STRING; diff --git a/src/enums/SortEnum.php b/src/enums/SortEnum.php index 01a37b0..e5b78f3 100644 --- a/src/enums/SortEnum.php +++ b/src/enums/SortEnum.php @@ -1,15 +1,8 @@ Date: Thu, 22 Feb 2018 21:15:00 +0100 Subject: [PATCH 03/10] added test for sort enums (todo: handle exception on test) --- src/enums/SortEnum.php | 2 ++ tests/properties/PublicPropertiesTest.php | 17 +++++++++++++++++ 2 files changed, 19 insertions(+) diff --git a/src/enums/SortEnum.php b/src/enums/SortEnum.php index e5b78f3..42626ef 100644 --- a/src/enums/SortEnum.php +++ b/src/enums/SortEnum.php @@ -3,6 +3,8 @@ namespace ParseCsv\enums; class SortEnum extends AbstractEnum { + const __DEFAULT = self::SORT_TYPE_REGULAR; + const SORT_TYPE_REGULAR = SORT_REGULAR; const SORT_TYPE_NUMERIC = SORT_NUMERIC; diff --git a/tests/properties/PublicPropertiesTest.php b/tests/properties/PublicPropertiesTest.php index fbf85d5..0510e73 100644 --- a/tests/properties/PublicPropertiesTest.php +++ b/tests/properties/PublicPropertiesTest.php @@ -3,6 +3,7 @@ namespace ParseCsv\tests\properties; use ParseCsv\Csv; +use ParseCsv\enums\SortEnum; use PHPUnit\Framework\TestCase; class PublicPropertiesTest extends TestCase { @@ -145,4 +146,20 @@ class PublicPropertiesTest extends TestCase { $this->assertCount($counter, $this->properties); } + + public function testDefaultSortTypeIsRegular(){ + $this->assertEquals(SortEnum::SORT_TYPE_REGULAR, $this->csv->sort_type); + } + + public function testSetSortType(){ + $this->csv->sort_type = SortEnum::SORT_TYPE_NUMERIC; + $this->assertEquals(SortEnum::SORT_TYPE_NUMERIC, $this->csv->sort_type); + + $this->csv->sort_type = SortEnum::SORT_TYPE_STRING; + $this->assertEquals(SortEnum::SORT_TYPE_STRING, $this->csv->sort_type); + + $this->csv->sort_type = SortEnum::SORT_TYPE_UNKNOWN; + // todo: how to handle this exception? + $this->expectException(InvalidArgumentException::class); + } } From 958af1027e18cda627341f059ddf3f1696ec4722 Mon Sep 17 00:00:00 2001 From: Susann Sgorzaly Date: Thu, 22 Feb 2018 21:34:39 +0100 Subject: [PATCH 04/10] small code improvements --- src/Csv.php | 86 ++++++++++++++++++++++++++++++----------------------- 1 file changed, 49 insertions(+), 37 deletions(-) diff --git a/src/Csv.php b/src/Csv.php index f75bb0d..70bbbcf 100644 --- a/src/Csv.php +++ b/src/Csv.php @@ -332,13 +332,35 @@ class Csv { * Constructor * Class constructor * - * @param string|null $input The CSV string or a direct filepath - * @param integer|null $offset Number of rows to ignore from the beginning of the data - * @param integer|null $limit Limits the number of returned rows to specified amount - * @param string|null $conditions Basic SQL-like conditions for row matching - * @param null|true $keep_file_data Keep raw file data in memory after successful parsing (useful for debugging) + * @param string|null $input The CSV string or a direct filepath + * @param integer|null $offset Number of rows to ignore from the beginning + * of the data + * @param integer|null $limit Limits the number of returned rows to + * specified amount + * @param string|null $conditions Basic SQL-like conditions for row + * matching + * @param null|true $keep_file_data Keep raw file data in memory after + * successful parsing (useful for debugging) */ - public function __construct($input = null, $offset = null, $limit = null, $conditions = null, $keep_file_data = null) { + public function __construct($input = NULL, $offset = NULL, $limit = NULL, $conditions = NULL, $keep_file_data = NULL) { + $this->init($offset, $limit, $conditions, $keep_file_data); + + if (!empty($input)) { + $this->parse($input); + } + } + + /** + * @param integer|null $offset Number of rows to ignore from the beginning + * of the data + * @param integer|null $limit Limits the number of returned rows to + * specified amount + * @param string|null $conditions Basic SQL-like conditions for row + * matching + * @param null|true $keep_file_data Keep raw file data in memory after + * successful parsing (useful for debugging) + */ + public function init($offset = NULL, $limit = NULL, $conditions = NULL, $keep_file_data = NULL) { if (!is_null($offset)) { $this->offset = $offset; } @@ -354,10 +376,6 @@ class Csv { if (!is_null($keep_file_data)) { $this->keep_file_data = $keep_file_data; } - - if (!empty($input)) { - $this->parse($input); - } } // ============================================== @@ -375,37 +393,31 @@ class Csv { * * @return bool True on success */ - public function parse($input = null, $offset = null, $limit = null, $conditions = null) { - if (is_null($input)) { - $input = $this->file; + public function parse($input = NULL, $offset = NULL, $limit = NULL, $conditions = NULL) { + if (!is_null($input)) { + $this->file = $input; } - if (!empty($input)) { - if (!is_null($offset)) { - $this->offset = $offset; - } - - if (!is_null($limit)) { - $this->limit = $limit; - } - - if (!is_null($conditions)) { - $this->conditions = $conditions; - } - - if (strlen($input) <= PHP_MAXPATHLEN && is_readable($input)) { - $this->data = $this->parse_file($input); - } else { - $this->file_data = &$input; - $this->data = $this->parse_string(); - } - - if ($this->data === false) { - return false; - } + if (empty($this->file)) { + // todo: but why true? + return true; + } + + $this->init($offset, $limit, $conditions); + + + if (strlen($this->file) <= PHP_MAXPATHLEN && is_readable($this->file)) { + $this->data = $this->parse_file($this->file); + } + else { + $this->file_data = &$this->file; + $this->data = $this->parse_string(); + } + + if ($this->data === false) { + return false; } - return true; } /** From cf91bf40ffbcdd341e301c6f5c5ec1a66a4c0f46 Mon Sep 17 00:00:00 2001 From: Susann Sgorzaly Date: Fri, 23 Feb 2018 08:11:56 +0100 Subject: [PATCH 05/10] now compatible with old sorting values --- src/Csv.php | 3 ++- src/enums/SortEnum.php | 21 ++++++++++++++++++--- tests/properties/PublicPropertiesTest.php | 16 +++++++++++----- 3 files changed, 31 insertions(+), 9 deletions(-) diff --git a/src/Csv.php b/src/Csv.php index 70bbbcf..7a8c2f9 100644 --- a/src/Csv.php +++ b/src/Csv.php @@ -739,7 +739,8 @@ class Csv { $this->titles = $head; if (!empty($this->sort_by)) { - $this->sort_reverse ? krsort($rows, $this->sort_type) : ksort($rows, $this->sort_type); + $sort_type = SortEnum::getSorting($this->sort_type); + $this->sort_reverse ? krsort($rows, $sort_type) : ksort($rows, $sort_type); if ($this->offset !== null || $this->limit !== null) { $rows = array_slice($rows, ($this->offset === null ? 0 : $this->offset), $this->limit, true); diff --git a/src/enums/SortEnum.php b/src/enums/SortEnum.php index 42626ef..54c3040 100644 --- a/src/enums/SortEnum.php +++ b/src/enums/SortEnum.php @@ -5,9 +5,24 @@ namespace ParseCsv\enums; class SortEnum extends AbstractEnum { const __DEFAULT = self::SORT_TYPE_REGULAR; - const SORT_TYPE_REGULAR = SORT_REGULAR; + const SORT_TYPE_REGULAR = 'regular'; - const SORT_TYPE_NUMERIC = SORT_NUMERIC; + const SORT_TYPE_NUMERIC = 'numeric'; + + const SORT_TYPE_STRING = 'string'; + + private static $sorting = array( + self::SORT_TYPE_REGULAR => SORT_REGULAR, + self::SORT_TYPE_STRING => SORT_STRING, + self::SORT_TYPE_NUMERIC => SORT_NUMERIC + ); + + public static function getSorting($type){ + if (array_key_exists($type, self::$sorting)){ + return self::$sorting[$type]; + } + + return self::$sorting[self::__DEFAULT]; + } - const SORT_TYPE_STRING = SORT_STRING; } diff --git a/tests/properties/PublicPropertiesTest.php b/tests/properties/PublicPropertiesTest.php index 0510e73..ed49354 100644 --- a/tests/properties/PublicPropertiesTest.php +++ b/tests/properties/PublicPropertiesTest.php @@ -152,14 +152,20 @@ class PublicPropertiesTest extends TestCase { } public function testSetSortType(){ - $this->csv->sort_type = SortEnum::SORT_TYPE_NUMERIC; + $this->csv->sort_type = 'numeric'; $this->assertEquals(SortEnum::SORT_TYPE_NUMERIC, $this->csv->sort_type); - $this->csv->sort_type = SortEnum::SORT_TYPE_STRING; + $this->csv->sort_type = 'string'; $this->assertEquals(SortEnum::SORT_TYPE_STRING, $this->csv->sort_type); + } - $this->csv->sort_type = SortEnum::SORT_TYPE_UNKNOWN; - // todo: how to handle this exception? - $this->expectException(InvalidArgumentException::class); + public function testGetSorting(){ + $this->csv->sort_type = 'numeric'; + $sorting = SortEnum::getSorting($this->csv->sort_type); + $this->assertEquals(SORT_NUMERIC, $sorting); + + $this->csv->sort_type = 'string'; + $sorting = SortEnum::getSorting($this->csv->sort_type); + $this->assertEquals(SORT_STRING, $sorting); } } From 343c683077199b56f5fe88aaf8d1bbb89ac5c34e Mon Sep 17 00:00:00 2001 From: Susann Sgorzaly Date: Fri, 23 Feb 2018 10:02:13 +0100 Subject: [PATCH 06/10] corrected test for default sort type. Is set to regular now --- tests/properties/DefaultValuesPropertiesTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/properties/DefaultValuesPropertiesTest.php b/tests/properties/DefaultValuesPropertiesTest.php index 803afcc..364f7cd 100644 --- a/tests/properties/DefaultValuesPropertiesTest.php +++ b/tests/properties/DefaultValuesPropertiesTest.php @@ -57,7 +57,7 @@ class DefaultValuesPropertiesTest extends TestCase { } public function test_sort_type_default() { - $this->assertNull($this->csv->sort_type); + $this->assertEquals('regular', $this->csv->sort_type); } public function test_delimiter_default() { From 249e5a24ac99fdbe6331af1577f87ce5760a1586 Mon Sep 17 00:00:00 2001 From: Susann Sgorzaly Date: Fri, 23 Feb 2018 10:14:01 +0100 Subject: [PATCH 07/10] readded missing return statement in parse-function --- src/Csv.php | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/src/Csv.php b/src/Csv.php index 7a8c2f9..e2160b6 100644 --- a/src/Csv.php +++ b/src/Csv.php @@ -394,11 +394,11 @@ class Csv { * @return bool True on success */ public function parse($input = NULL, $offset = NULL, $limit = NULL, $conditions = NULL) { - if (!is_null($input)) { - $this->file = $input; + if (is_null($input)) { + $input = $this->file; } - if (empty($this->file)) { + if (empty($input)) { // todo: but why true? return true; } @@ -406,11 +406,12 @@ class Csv { $this->init($offset, $limit, $conditions); - if (strlen($this->file) <= PHP_MAXPATHLEN && is_readable($this->file)) { - $this->data = $this->parse_file($this->file); + if (strlen($input) <= PHP_MAXPATHLEN && is_readable($input)) { + $this->file = $input; + $this->data = $this->parse_file($input); } else { - $this->file_data = &$this->file; + $this->file_data = &$input; $this->data = $this->parse_string(); } @@ -418,6 +419,8 @@ class Csv { return false; } + return true; + } /** From 95521cde8747560f447e808e97fd9443ce86434d Mon Sep 17 00:00:00 2001 From: Susann Sgorzaly Date: Fri, 23 Feb 2018 10:17:09 +0100 Subject: [PATCH 08/10] reset file property if input is string --- src/Csv.php | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Csv.php b/src/Csv.php index e2160b6..129fe77 100644 --- a/src/Csv.php +++ b/src/Csv.php @@ -411,6 +411,7 @@ class Csv { $this->data = $this->parse_file($input); } else { + $this->file = null; $this->file_data = &$input; $this->data = $this->parse_string(); } From f8fe4cad033b1bd38b3b1bafeeb4697a855f2167 Mon Sep 17 00:00:00 2001 From: Susann Sgorzaly Date: Fri, 23 Feb 2018 10:37:12 +0100 Subject: [PATCH 09/10] change accessibility of parse_file and parse_string --- src/Csv.php | 6 +++--- tests/methods/ParseTest.php | 21 ++++++++++++++++++++- 2 files changed, 23 insertions(+), 4 deletions(-) diff --git a/src/Csv.php b/src/Csv.php index 129fe77..5fe15be 100644 --- a/src/Csv.php +++ b/src/Csv.php @@ -408,7 +408,7 @@ class Csv { if (strlen($input) <= PHP_MAXPATHLEN && is_readable($input)) { $this->file = $input; - $this->data = $this->parse_file($input); + $this->data = $this->parse_file(); } else { $this->file = null; @@ -569,7 +569,7 @@ class Csv { * * @return array|bool */ - public function parse_file($file = null) { + protected function parse_file($file = null) { if (is_null($file)) { $file = $this->file; } @@ -592,7 +592,7 @@ class Csv { * * @return array|false - 2D array with CSV data, or false on failure */ - public function parse_string($data = null) { + protected function parse_string($data = null) { if (empty($data)) { if ($this->_check_data()) { $data = &$this->file_data; diff --git a/tests/methods/ParseTest.php b/tests/methods/ParseTest.php index 9566499..6bf683c 100644 --- a/tests/methods/ParseTest.php +++ b/tests/methods/ParseTest.php @@ -89,7 +89,8 @@ class ParseTest extends TestCase $this->csv->enclosure = '"'; $sInput = "86545235689,a\r\n34365587654,b\r\n13469874576,\"c\r\nd\""; $expected_data = [86545235689, 34365587654, 13469874576]; - $actual_data = $this->csv->parse_string($sInput); + + $actual_data = $this->invokeMethod($this->csv, 'parse_string', array($sInput)); $actual_column = array_map('reset', $actual_data); $this->assertEquals($expected_data, $actual_column); $this->assertEquals([ @@ -198,4 +199,22 @@ class ParseTest extends TestCase $this->assertArrayHasKey('column1', $csv->data[0], 'Data parsed incorrectly with enclosure ' . $enclosure); $this->assertEquals('value1', $csv->data[0]['column1'], 'Data parsed incorrectly with enclosure ' . $enclosure); } + + /** + * Call protected/private method of a class. + * + * @param object &$object Instantiated object that we will run method on. + * @param string $methodName Method name to call + * @param array $parameters Array of parameters to pass into method. + * + * @return mixed Method return. + */ + private function invokeMethod(&$object, $methodName, array $parameters = array()) + { + $reflection = new \ReflectionClass(get_class($object)); + $method = $reflection->getMethod($methodName); + $method->setAccessible(true); + + return $method->invokeArgs($object, $parameters); + } } From ba4cc0672a9e97038365354ffdebb0cfb350a975 Mon Sep 17 00:00:00 2001 From: Susann Sgorzaly Date: Mon, 26 Feb 2018 06:57:40 +0100 Subject: [PATCH 10/10] reformat code --- src/Csv.php | 63 +++++++++++++++++++++++++++++------------------------ 1 file changed, 35 insertions(+), 28 deletions(-) diff --git a/src/Csv.php b/src/Csv.php index 5fe15be..24c0947 100644 --- a/src/Csv.php +++ b/src/Csv.php @@ -1,4 +1,5 @@ init($offset, $limit, $conditions, $keep_file_data); if (!empty($input)) { @@ -351,16 +352,16 @@ class Csv { } /** - * @param integer|null $offset Number of rows to ignore from the beginning - * of the data - * @param integer|null $limit Limits the number of returned rows to - * specified amount - * @param string|null $conditions Basic SQL-like conditions for row - * matching - * @param null|true $keep_file_data Keep raw file data in memory after - * successful parsing (useful for debugging) + * @param integer|null $offset Number of rows to ignore from the beginning + * of the data + * @param integer|null $limit Limits the number of returned rows to + * specified amount + * @param string|null $conditions Basic SQL-like conditions for row + * matching + * @param null|true $keep_file_data Keep raw file data in memory after + * successful parsing (useful for debugging) */ - public function init($offset = NULL, $limit = NULL, $conditions = NULL, $keep_file_data = NULL) { + public function init($offset = null, $limit = null, $conditions = null, $keep_file_data = null) { if (!is_null($offset)) { $this->offset = $offset; } @@ -393,7 +394,7 @@ class Csv { * * @return bool True on success */ - public function parse($input = NULL, $offset = NULL, $limit = NULL, $conditions = NULL) { + public function parse($input = null, $offset = null, $limit = null, $conditions = null) { if (is_null($input)) { $input = $this->file; } @@ -409,8 +410,7 @@ class Csv { if (strlen($input) <= PHP_MAXPATHLEN && is_readable($input)) { $this->file = $input; $this->data = $this->parse_file(); - } - else { + } else { $this->file = null; $this->file_data = &$input; $this->data = $this->parse_string(); @@ -926,12 +926,19 @@ class Csv { */ protected function _validate_row_condition($row, $condition) { $operators = array( - '=', 'equals', 'is', - '!=', 'is not', - '<', 'is less than', - '>', 'is greater than', - '<=', 'is less than or equals', - '>=', 'is greater than or equals', + '=', + 'equals', + 'is', + '!=', + 'is not', + '<', + 'is less than', + '>', + 'is greater than', + '<=', + 'is less than or equals', + '>=', + 'is greater than or equals', 'contains', 'does not contain', );