From eeabfc49922a73814f8f953b894abae79d8fd300 Mon Sep 17 00:00:00 2001 From: Leandro Ross Date: Wed, 31 Jan 2018 15:52:10 -0200 Subject: [PATCH 1/3] Multiple updates - Update composer.json - Upgrade to PSR-4 - add parameter newline, delimiter, enclosure, and escape to export csv - When converting a XML to an array, convert @attributes to _attribute_ - add parameter encoding and formated to export xml - JSON parse fix (Instead of only converting the first level to array, use the associative array parameter with true, so all levels will be decoded to array structure) - Add support for laravel 5 - add package discovery for laravel 5 --- composer.json | 68 +++--- readme.md | 12 ++ src/ArrayHelpers.php | 27 +++ src/Formatter.php | 93 +++++++++ src/FormatterServiceProvider.php | 63 ++++++ src/Parsers/ArrayParser.php | 29 +++ src/Parsers/CsvParser.php | 47 +++++ src/Parsers/JsonParser.php | 18 ++ src/Parsers/Parser.php | 194 ++++++++++++++++++ src/Parsers/XmlParser.php | 45 ++++ .../Formatter => }/Parsers/YamlParser.php | 0 src/SoapBox/Formatter/ArrayHelpers.php | 23 --- src/SoapBox/Formatter/Formatter.php | 81 -------- .../Formatter/FormatterServiceProvider.php | 43 ---- src/SoapBox/Formatter/Parsers/ArrayParser.php | 26 --- src/SoapBox/Formatter/Parsers/CsvParser.php | 44 ---- src/SoapBox/Formatter/Parsers/JsonParser.php | 15 -- src/SoapBox/Formatter/Parsers/Parser.php | 167 --------------- src/SoapBox/Formatter/Parsers/XmlParser.php | 36 ---- tests/Bootstrap.php | 2 +- tests/TestCase.php | 25 ++- tests/unit/ParserTest.php | 146 ++++++------- 22 files changed, 658 insertions(+), 546 deletions(-) create mode 100644 src/ArrayHelpers.php create mode 100644 src/Formatter.php create mode 100644 src/FormatterServiceProvider.php create mode 100644 src/Parsers/ArrayParser.php create mode 100644 src/Parsers/CsvParser.php create mode 100644 src/Parsers/JsonParser.php create mode 100644 src/Parsers/Parser.php create mode 100644 src/Parsers/XmlParser.php rename src/{SoapBox/Formatter => }/Parsers/YamlParser.php (100%) delete mode 100644 src/SoapBox/Formatter/ArrayHelpers.php delete mode 100644 src/SoapBox/Formatter/Formatter.php delete mode 100644 src/SoapBox/Formatter/FormatterServiceProvider.php delete mode 100644 src/SoapBox/Formatter/Parsers/ArrayParser.php delete mode 100644 src/SoapBox/Formatter/Parsers/CsvParser.php delete mode 100644 src/SoapBox/Formatter/Parsers/JsonParser.php delete mode 100644 src/SoapBox/Formatter/Parsers/Parser.php delete mode 100644 src/SoapBox/Formatter/Parsers/XmlParser.php diff --git a/composer.json b/composer.json index 36d7598..a71a691 100644 --- a/composer.json +++ b/composer.json @@ -1,33 +1,43 @@ { - "name": "soapbox/laravel-formatter", - "type": "library", - "description": "A formatting library that converts data output between XML, CSV, JSON, TXT, YAML and a few others.", - "keywords": ["laravel", "formatter", "data", "convert", "csv", "xml", "yaml"], + "name": "soapbox/laravel-formatter", + "type": "library", + "description": "A formatting library that converts data output between XML, CSV, JSON, TXT, YAML and a few others.", + "keywords": ["laravel", "formatter", "data", "convert", "csv", "xml", "yaml"], "homepage": "http://github.com/SoapBox/laravel-formatter", "license": "MIT", - "version": "2.0", - "authors": [ - { - "name": "Graham McCarthy", - "email": "graham@soapboxhq.com", - "homepage": "http://grahammccarthy.com" - }, - { - "name": "Jaspaul Bola", - "email": "jaspaul.b@gamil.com", - "homepage": "http://jaspaulbola.com" - } - ], - "require": { - "php": ">=5.4.0", - "league/csv": "~6.0", - "mustangostang/spyc": "0.5.*@dev", - "illuminate/support": ">=4.0" - }, - "autoload": { - "psr-0": { - "SoapBox\\Formatter": "src/" - } - }, - "minimum-stability": "dev" + "version": "3.0", + "authors": [ + { + "name": "Graham McCarthy", + "email": "graham@soapboxhq.com", + "homepage": "http://grahammccarthy.com" + }, + { + "name": "Jaspaul Bola", + "email": "jaspaul.b@gamil.com", + "homepage": "http://jaspaulbola.com" + } + ], + "require": { + "php" : ">=7.0.10", + "league/csv": "~9.0", + "mustangostang/spyc": "~0.6", + "illuminate/support": "5.5.x" + }, + "require-dev": { + "phpunit/phpunit": "^5.7 || ^6.5" + }, + "autoload": { + "psr-4": { + "SoapBox\\Formatter\\": "src/" + } + }, + "extra": { + "laravel": { + "aliases": { + "Formatter": "SoapBox\\Formatter" + } + } + }, + "minimum-stability": "stable" } diff --git a/readme.md b/readme.md index a1dfc9f..01741fc 100644 --- a/readme.md +++ b/readme.md @@ -1,3 +1,15 @@ +Changelog +================ + +- Update composer.json +- Upgrade to PSR-4 +- add parameter newline, delimiter, enclosure, and escape to export csv +- When converting a XML to an array, convert @attributes to _attribute_ +- add parameter encoding and formated to export xml +- JSON parse fix (Instead of only converting the first level to array, use the associative array parameter with true, so all levels will be decoded to array structure) +- Add support for laravel 5 +- add package discovery for laravel 5 + Formatter Bundle ================ diff --git a/src/ArrayHelpers.php b/src/ArrayHelpers.php new file mode 100644 index 0000000..d6a9d09 --- /dev/null +++ b/src/ArrayHelpers.php @@ -0,0 +1,27 @@ +parser = $parser; + } + + public function toJson() + { + return $this->parser->toJson(); + } + + public function toArray() + { + return $this->parser->toArray(); + } + + public function toYaml() + { + return $this->parser->toYaml(); + } + + public function toXml($baseNode = 'xml', $encoding = 'utf-8', $formated = false) + { + return $this->parser->toXml($baseNode, $encoding, $formated); + } + + public function toCsv($newline = "\n", $delimiter = ",", $enclosure = '"', $escape = "\\") + { + return $this->parser->toCsv($newline, $delimiter, $enclosure, $escape); + } +} diff --git a/src/FormatterServiceProvider.php b/src/FormatterServiceProvider.php new file mode 100644 index 0000000..dc8702a --- /dev/null +++ b/src/FormatterServiceProvider.php @@ -0,0 +1,63 @@ +package('soapbox/laravel-formatter'); + } + + /** + * Register the service provider. + * + * @return void + */ + public function register() + { + $this->app['formatter'] = $this->app->share(function ($app) { + return new Formatter; + }); + } + + /** + * Get the services provided by the provider. + * + * @return array + */ + public function provides() + { + return ['formatter']; + } + +} diff --git a/src/Parsers/ArrayParser.php b/src/Parsers/ArrayParser.php new file mode 100644 index 0000000..4950957 --- /dev/null +++ b/src/Parsers/ArrayParser.php @@ -0,0 +1,29 @@ +array = (array) $data; + } else { + throw new InvalidArgumentException( + 'ArrayParser only accepts (optionally serialized) [object, array] for $data.' + ); + } + } + + public function toArray() + { + return $this->array; + } +} diff --git a/src/Parsers/CsvParser.php b/src/Parsers/CsvParser.php new file mode 100644 index 0000000..40248c1 --- /dev/null +++ b/src/Parsers/CsvParser.php @@ -0,0 +1,47 @@ +csv = Reader::createFromString($data); + } else { + throw new InvalidArgumentException( + 'CsvParser only accepts (string) [csv] for $data.' + ); + } + } + + public function toArray() + { + $temp = $this->csv->jsonSerialize(); + + $headings = $temp[0]; + $result = $headings; + + if (count($temp) > 1) { + $result = []; + for ($i = 1; $i < count($temp); ++$i) { + $row = []; + for ($j = 0; $j < count($headings); ++$j) { + $row[$headings[$j]] = $temp[$i][$j]; + } + $expanded = []; + foreach ($row as $key => $value) { + ArrayHelpers::set($expanded, $key, $value); + } + $result[] = $expanded; + } + } + + return $result; + } +} diff --git a/src/Parsers/JsonParser.php b/src/Parsers/JsonParser.php new file mode 100644 index 0000000..a83b70e --- /dev/null +++ b/src/Parsers/JsonParser.php @@ -0,0 +1,18 @@ +json = json_decode(trim($data), true); + } + + public function toArray() + { + return $this->json; + } + +} diff --git a/src/Parsers/Parser.php b/src/Parsers/Parser.php new file mode 100644 index 0000000..190ab48 --- /dev/null +++ b/src/Parsers/Parser.php @@ -0,0 +1,194 @@ +toArray()); + } + + /** + * Return a yaml representation of the data stored in the parser + * + * @return string A yaml string representing the encapsulated data + */ + public function toYaml() + { + return Spyc::YAMLDump($this->toArray()); + } + + /** + * To XML conversion + * + * @param mixed $data + * @param null $structure + * @param null|string $basenode + * @param null|string $encoding + * @return string + */ + private function xmlify($data, $structure = null, $basenode = 'xml', $encoding = 'utf-8', $formatted = false) + { + // turn off compatibility mode as simple xml throws a wobbly if you don't. + if (ini_get('zend.ze1_compatibility_mode') == 1) { + ini_set('zend.ze1_compatibility_mode', 0); + } + + if ($structure == null) { + $structure = simplexml_load_string("<$basenode />"); + } + + // Force it to be something useful + if (!is_array($data) && !is_object($data)) { + $data = (array) $data; + } + + foreach ($data as $key => $value) { + // checking for xml tag having attributes + if ($key === '@attributes') { + //STRICT IS NECESSARY because if key is numeric @attributes will be cast to integer and 0 == 0! + foreach ($data[$key] as $attrName => $attrValue) { + $structure->addAttribute($attrName, $attrValue); + } + } else { + // convert our booleans to 0/1 integer values so they are + // not converted to blanks. + if (is_bool($value)) { + $value = (int) $value; + } + + // no numeric keys in our xml please! + if (is_numeric($key)) { + // make string key... + if (isset($value['@name']) && is_string($value['@name'])) { + $key = $value['@name']; + } else { + $key = (Str::singular($basenode) != $basenode) ? Str::singular($basenode) : 'item'; + } + + unset($value['@name']); + } + + // replace anything not alpha numeric AND '@' because of '@attributes' + $key = preg_replace('/[^a-z_@\-0-9]/i', '', $key); + + // if there is another array found recursively call this function + if (is_array($value) or is_object($value)) { + $node = $structure->addChild($key); + + // recursive call if value is not empty + if (!empty($value)) { + $this->xmlify($value, $node, $key); + } + } else { + // add single node. + $value = htmlspecialchars(html_entity_decode($value, ENT_QUOTES, 'UTF-8'), ENT_QUOTES, "UTF-8"); + $structure->addChild($key, $value); + } + } + } + + // return formatted xml + if ($formatted) { + $dom = dom_import_simplexml($structure)->ownerDocument; + $dom->formatOutput = true; + return $dom->saveXML(); + } + + // pass back as string. or simple xml object if you want! + return $structure->asXML(); + } + + /** + * Return an xml representation of the data stored in the parser + * + * @param string $baseNode + * @param string $encoding + * @param bool $formatted + * @return string An xml string representing the encapsulated data + */ + public function toXml($baseNode = 'xml', $encoding = 'utf-8', $formatted = false) + { + return $this->xmlify($this->toArray(), null, $baseNode, $encoding, $formatted); + } + + private function csvify($data) + { + $results = []; + foreach ($data as $row) { + $results[] = array_values(ArrayHelpers::dot($row)); + } + return $results; + } + + /** + * Ported from laravel-formatter + * https://github.com/SoapBox/laravel-formatter + * + * Return a csv representation of the data stored in the parser + * @author Daniel Berry + * @license MIT License (see LICENSE.readme included in the bundle) + * + * @return string An csv string representing the encapsulated data + */ + public function toCsv($newline = "\n", $delimiter = ",", $enclosure = '"', $escape = "\\") + { + $data = $this->toArray(); + + if (ArrayHelpers::isAssociative($data) || !is_array($data[0])) { + $data = [$data]; + } + + $escaper = function ($items) use ($enclosure, $escape) { + return array_map(function ($item) use ($enclosure, $escape) { + return str_replace($enclosure, $escape . $enclosure, $item); + }, $items); + }; + + $headings = ArrayHelpers::dotKeys($data[0]); + $result = []; + + foreach ($data as $row) { + $result[] = array_values(ArrayHelpers::dot($row)); + } + + $data = $result; + + $output = $enclosure . implode($enclosure . $delimiter . $enclosure, $escaper($headings)) . $enclosure . $newline; + + foreach ($data as $row) { + $output .= $enclosure . implode($enclosure . $delimiter . $enclosure, $escaper((array) $row)) . $enclosure . $newline; + } + + return rtrim($output, $newline); + } +} diff --git a/src/Parsers/XmlParser.php b/src/Parsers/XmlParser.php new file mode 100644 index 0000000..973d555 --- /dev/null +++ b/src/Parsers/XmlParser.php @@ -0,0 +1,45 @@ + + * @license MIT License (see LICENSE.readme included in the bundle) + */ + private function objectify($value) + { + $temp = is_string($value) ? + simplexml_load_string($value, 'SimpleXMLElement', LIBXML_NOCDATA) : + $value; + + $result = []; + + foreach ((array) $temp as $key => $value) { + if ($key === "@attributes") { + $result['_' . key($value)] = $value[key($value)]; + } elseif (count($value) < 1) { + $result[$key] = ''; + } else { + $result[$key] = (is_array($value) or is_object($value)) ? $this->objectify($value) : $value; + } + } + + return $result; + } + + public function __construct($data) + { + $this->xml = $this->objectify($data); + } + + public function toArray() + { + return (array) $this->xml; + } +} diff --git a/src/SoapBox/Formatter/Parsers/YamlParser.php b/src/Parsers/YamlParser.php similarity index 100% rename from src/SoapBox/Formatter/Parsers/YamlParser.php rename to src/Parsers/YamlParser.php diff --git a/src/SoapBox/Formatter/ArrayHelpers.php b/src/SoapBox/Formatter/ArrayHelpers.php deleted file mode 100644 index 42ec4e3..0000000 --- a/src/SoapBox/Formatter/ArrayHelpers.php +++ /dev/null @@ -1,23 +0,0 @@ -parser = $parser; - } - - public function toJson() { - return $this->parser->toJson(); - } - - public function toArray() { - return $this->parser->toArray(); - } - - public function toYaml() { - return $this->parser->toYaml(); - } - - public function toXml($baseNode = 'xml') { - return $this->parser->toXml($baseNode); - } - - public function toCsv() { - return $this->parser->toCsv(); - } -} diff --git a/src/SoapBox/Formatter/FormatterServiceProvider.php b/src/SoapBox/Formatter/FormatterServiceProvider.php deleted file mode 100644 index 903ee2e..0000000 --- a/src/SoapBox/Formatter/FormatterServiceProvider.php +++ /dev/null @@ -1,43 +0,0 @@ -package('soapbox/laravel-formatter'); - } - - /** - * Register the service provider. - * - * @return void - */ - public function register() { - } - - /** - * Get the services provided by the provider. - * - * @return array - */ - public function provides() { - return array(); - } - -} diff --git a/src/SoapBox/Formatter/Parsers/ArrayParser.php b/src/SoapBox/Formatter/Parsers/ArrayParser.php deleted file mode 100644 index aa569cb..0000000 --- a/src/SoapBox/Formatter/Parsers/ArrayParser.php +++ /dev/null @@ -1,26 +0,0 @@ -array = (array) $data; - } else { - throw new InvalidArgumentException( - 'ArrayParser only accepts (optionally serialized) [object, array] for $data.' - ); - } - } - - public function toArray() { - return $this->array; - } -} diff --git a/src/SoapBox/Formatter/Parsers/CsvParser.php b/src/SoapBox/Formatter/Parsers/CsvParser.php deleted file mode 100644 index 5f57fb6..0000000 --- a/src/SoapBox/Formatter/Parsers/CsvParser.php +++ /dev/null @@ -1,44 +0,0 @@ -csv = Reader::createFromString($data); - } else { - throw new InvalidArgumentException( - 'CsvParser only accepts (string) [csv] for $data.' - ); - } - } - - public function toArray() { - $temp = $this->csv->jsonSerialize(); - - $headings = $temp[0]; - $result = $headings; - - if (count($temp) > 1) { - $result = []; - for ($i = 1; $i < count($temp); ++$i) { - $row = []; - for ($j = 0; $j < count($headings); ++$j) { - $row[$headings[$j]] = $temp[$i][$j]; - } - $expanded = []; - foreach ($row as $key => $value) { - ArrayHelpers::set($expanded, $key, $value); - } - $result[] = $expanded; - } - } - - return $result; - } -} diff --git a/src/SoapBox/Formatter/Parsers/JsonParser.php b/src/SoapBox/Formatter/Parsers/JsonParser.php deleted file mode 100644 index 372ec68..0000000 --- a/src/SoapBox/Formatter/Parsers/JsonParser.php +++ /dev/null @@ -1,15 +0,0 @@ -json = json_decode(trim($data)); - } - - public function toArray() { - return (array) $this->json; - } - -} diff --git a/src/SoapBox/Formatter/Parsers/Parser.php b/src/SoapBox/Formatter/Parsers/Parser.php deleted file mode 100644 index 83eebe5..0000000 --- a/src/SoapBox/Formatter/Parsers/Parser.php +++ /dev/null @@ -1,167 +0,0 @@ -toArray()); - } - - /** - * Return a yaml representation of the data stored in the parser - * - * @return string A yaml string representing the encapsulated data - */ - public function toYaml() { - return Spyc::YAMLDump($this->toArray()); - } - - /** - * To XML conversion - * - * @param mixed $data - * @param null $structure - * @param null|string $basenode - * @return string - */ - private function xmlify($data, $structure = null, $basenode = 'xml') { - // turn off compatibility mode as simple xml throws a wobbly if you don't. - if (ini_get('zend.ze1_compatibility_mode') == 1) { - ini_set('zend.ze1_compatibility_mode', 0); - } - - if ($structure == null) { - $structure = simplexml_load_string("<$basenode />"); - } - - // Force it to be something useful - if (!is_array($data) && !is_object($data)) { - $data = (array) $data; - } - - foreach ($data as $key => $value) { - // convert our booleans to 0/1 integer values so they are - // not converted to blanks. - if (is_bool($value)) { - $value = (int) $value; - } - - // no numeric keys in our xml please! - if (is_numeric($key)) { - // make string key... - $key = (Str::singular($basenode) != $basenode) ? Str::singular($basenode) : 'item'; - } - - // replace anything not alpha numeric - $key = preg_replace('/[^a-z_\-0-9]/i', '', $key); - - // if there is another array found recrusively call this function - if (is_array($value) or is_object($value)) { - $node = $structure->addChild($key); - - // recursive call if value is not empty - if (!empty($value)) { - $this->xmlify($value, $node, $key); - } - } else { - // add single node. - $value = htmlspecialchars(html_entity_decode($value, ENT_QUOTES, 'UTF-8'), ENT_QUOTES, "UTF-8"); - - $structure->addChild($key, $value); - } - } - - // pass back as string. or simple xml object if you want! - return $structure->asXML(); - } - - /** - * Return an xml representation of the data stored in the parser - * - * @param string $baseNode - * - * @return string An xml string representing the encapsulated data - */ - public function toXml($baseNode = 'xml') { - return $this->xmlify($this->toArray(), null, $baseNode); - } - - private function csvify($data) { - $results = []; - foreach ($data as $row) { - $results[] = array_values(ArrayHelpers::dot($row)); - } - return $results; - } - - /** - * Ported from laravel-formatter - * https://github.com/SoapBox/laravel-formatter - * - * @author Daniel Berry - * @license MIT License (see LICENSE.readme included in the bundle) - * - * Return a csv representation of the data stored in the parser - * - * @return string An csv string representing the encapsulated data - */ - public function toCsv($newline = "\n", $delimiter = ",", $enclosure = '"', $escape = "\\") { - $data = $this->toArray(); - - if (ArrayHelpers::isAssociative($data) || !is_array($data[0])) { - $data = [$data]; - } - - $escaper = function($items) use($enclosure, $escape) { - return array_map(function($item) use($enclosure, $escape) { - return str_replace($enclosure, $escape.$enclosure, $item); - }, $items); - }; - - $headings = ArrayHelpers::dotKeys($data[0]); - $result = []; - - foreach ($data as $row) { - $result[] = array_values(ArrayHelpers::dot($row)); - } - - $data = $result; - - $output = $enclosure.implode($enclosure.$delimiter.$enclosure, $escaper($headings)).$enclosure.$newline; - - foreach ($data as $row) - { - $output .= $enclosure.implode($enclosure.$delimiter.$enclosure, $escaper((array) $row)).$enclosure.$newline; - } - - return rtrim($output, $newline); - } -} diff --git a/src/SoapBox/Formatter/Parsers/XmlParser.php b/src/SoapBox/Formatter/Parsers/XmlParser.php deleted file mode 100644 index 100786d..0000000 --- a/src/SoapBox/Formatter/Parsers/XmlParser.php +++ /dev/null @@ -1,36 +0,0 @@ - - * @license MIT License (see LICENSE.readme included in the bundle) - * - */ - private function objectify($value) { - $temp = is_string($value) ? - simplexml_load_string($value, 'SimpleXMLElement', LIBXML_NOCDATA) : - $value; - - $result = []; - - foreach ((array) $temp as $key => $value) { - $result[$key] = (is_array($value) or is_object($value)) ? $this->objectify($value) : $value; - } - - return $result; - } - - public function __construct($data) { - $this->xml = $this->objectify($data); - } - - public function toArray() { - return (array) $this->xml; - } -} diff --git a/tests/Bootstrap.php b/tests/Bootstrap.php index 728f2cb..f81daa6 100644 --- a/tests/Bootstrap.php +++ b/tests/Bootstrap.php @@ -1,5 +1,5 @@ toArray(); - $expected = ['foo'=>'bar', 'bar'=>'foo']; - - $this->assertEquals($expected, $actual); - } - - /** - * A basic functional test for Array to JSON conversion - * - * @return void - */ - public function testArrayToJson() { - $data = ['foo'=>'bar', 'bar'=>'foo']; - - $actual = Formatter::make($data, Formatter::ARR)->toJson(); - $expected = '{"foo":"bar","bar":"foo"}'; - - $this->assertEquals($expected, $actual); - } - - /** - * A basic functional test for CSV data to array - * - * @return void - */ - public function testCSVToArray() { - $data = 'foo,bar,bing,bam,boom'; - - $actual = Formatter::make($data, Formatter::CSV)->toArray(); - $expected = array('foo','bar','bing','bam','boom'); - - $this->assertEquals($expected, $actual); - } - - /** - * A basic functional test for testJSONToXMLToArrayToJsonToArray data to array - * - * @return void - */ - public function testJSONToXMLToArrayToJsonToArray() { - $data = '{"foo":"bar","bar":"foo"}'; - - $result = Formatter::make($data, Formatter::JSON)->toXml(); - $result = Formatter::make($result, Formatter::XML)->toArray(); - $result = Formatter::make($result, Formatter::ARR)->toJson(); - $actual = Formatter::make($result, Formatter::JSON)->toArray(); - - $expected = ['foo'=>'bar', 'bar'=>'foo']; - - $this->assertEquals($expected, $actual); - } - - public function testMultiDimensionalArrayFromJsonToCsv() { - $expected = "\"simple\",\"date\",\"time\",\"duration_onset\",\"devicename\",\"calc_data.0.0\",\"calc_data.0.1\",\"calc_data.0.2\",\"calc_data.0.3\",\"calc_data.0.4\",\"calc_data.0.5\",\"calc_data.1.0\",\"calc_data.1.1\",\"calc_data.1.2\",\"calc_data.1.3\",\"calc_data.1.4\",\"calc_data.1.5\"\n\"118\",\"2014-05-20 21:03:59.333\",\"4067\",\"\",\"My Device\",\"1400609039\",\"0\",\"37\",\"0\",\"0\",\"1\",\"1400609039\",\"0\",\"37\",\"0\",\"0\",\"1\""; - - $json = -'{ +class ParserTest extends TestCase +{ + + /** + * A basic functional test for JSON to Array conversion + * + * @return void + */ + public function testJsonToArray() + { + $data = '{"foo":"bar","bar":"foo"}'; + + $actual = Formatter::make($data, Formatter::JSON)->toArray(); + $expected = ['foo' => 'bar', 'bar' => 'foo']; + + $this->assertEquals($expected, $actual); + } + + /** + * A basic functional test for Array to JSON conversion + * + * @return void + */ + public function testArrayToJson() + { + $data = ['foo' => 'bar', 'bar' => 'foo']; + + $actual = Formatter::make($data, Formatter::ARR)->toJson(); + $expected = '{"foo":"bar","bar":"foo"}'; + + $this->assertEquals($expected, $actual); + } + + /** + * A basic functional test for CSV data to array + * + * @return void + */ + public function testCSVToArray() + { + $data = 'foo,bar,bing,bam,boom'; + + $actual = Formatter::make($data, Formatter::CSV)->toArray(); + $expected = ['foo', 'bar', 'bing', 'bam', 'boom']; + + $this->assertEquals($expected, $actual); + } + + /** + * A basic functional test for testJSONToXMLToArrayToJsonToArray data to array + * + * @return void + */ + public function testJSONToXMLToArrayToJsonToArray() + { + $data = '{"foo":"bar","bar":"foo"}'; + + $result = Formatter::make($data, Formatter::JSON)->toXml(); + $result = Formatter::make($result, Formatter::XML)->toArray(); + $result = Formatter::make($result, Formatter::ARR)->toJson(); + $actual = Formatter::make($result, Formatter::JSON)->toArray(); + + $expected = ['foo' => 'bar', 'bar' => 'foo']; + + $this->assertEquals($expected, $actual); + } + + public function testMultiDimensionalArrayFromJsonToCsv() + { + $expected = "\"simple\",\"date\",\"time\",\"duration_onset\",\"devicename\",\"calc_data.0.0\",\"calc_data.0.1\",\"calc_data.0.2\",\"calc_data.0.3\",\"calc_data.0.4\",\"calc_data.0.5\",\"calc_data.1.0\",\"calc_data.1.1\",\"calc_data.1.2\",\"calc_data.1.3\",\"calc_data.1.4\",\"calc_data.1.5\"\n\"118\",\"2014-05-20 21:03:59.333\",\"4067\",\"\",\"My Device\",\"1400609039\",\"0\",\"37\",\"0\",\"0\",\"1\",\"1400609039\",\"0\",\"37\",\"0\",\"0\",\"1\""; + + $json = + '{ "simple":"118", "date":"2014-05-20 21:03:59.333", "time":"4067", @@ -93,9 +99,9 @@ public function testMultiDimensionalArrayFromJsonToCsv() { ] ] }'; - $jsonParser = Formatter::make($json, Formatter::JSON); + $jsonParser = Formatter::make($json, Formatter::JSON); - $this->assertEquals($expected, $jsonParser->toCsv()); - } + $this->assertEquals($expected, $jsonParser->toCsv()); + } } From 572429ac0b87f23a90f7d89014f7c8cba20b436d Mon Sep 17 00:00:00 2001 From: Leandro Ross Date: Wed, 31 Jan 2018 15:58:24 -0200 Subject: [PATCH 2/3] update travis --- .travis.yml | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/.travis.yml b/.travis.yml index c08b8d6..2c5f8b6 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,13 +1,17 @@ language: php php: - - 5.4 - - 5.5 - - 5.6 + - 7.0 + - 7.1 + - 7.2 -before_script: - - curl -s http://getcomposer.org/installer | php - - php composer.phar install --dev +matrix: + allow_failures: + - php: 7.2 -script: phpunit +before_script: + - composer self-update + - composer install --no-interaction +script: + - vendor/bin/phpunit \ No newline at end of file From 9b497e00873afb3f4536c1715832401d32b88e88 Mon Sep 17 00:00:00 2001 From: Leandro Ross Date: Wed, 31 Jan 2018 16:19:34 -0200 Subject: [PATCH 3/3] Added delimiter to CSV --- readme.md | 1 + src/Formatter.php | 9 +- src/Parsers/CsvParser.php | 7 +- tests/unit/FormatterTest.php | 76 +++++++------ tests/unit/Parsers/ArrayParserTest.php | 101 ++++++++++-------- tests/unit/Parsers/CsvParserDelemiterTest.php | 41 +++++++ tests/unit/Parsers/CsvParserTest.php | 51 +++++---- tests/unit/Parsers/JsonParserTest.php | 49 +++++---- tests/unit/Parsers/XmlParserTest.php | 36 ++++--- tests/unit/Parsers/YamlParserTest.php | 29 ++--- 10 files changed, 240 insertions(+), 160 deletions(-) create mode 100644 tests/unit/Parsers/CsvParserDelemiterTest.php diff --git a/readme.md b/readme.md index 01741fc..3d13aeb 100644 --- a/readme.md +++ b/readme.md @@ -9,6 +9,7 @@ Changelog - JSON parse fix (Instead of only converting the first level to array, use the associative array parameter with true, so all levels will be decoded to array structure) - Add support for laravel 5 - add package discovery for laravel 5 +- add support delimiter to a csv Formatter Bundle ================ diff --git a/src/Formatter.php b/src/Formatter.php index 5e47b79..d28210c 100644 --- a/src/Formatter.php +++ b/src/Formatter.php @@ -29,17 +29,18 @@ class Formatter /** * Make: Returns an instance of formatter initialized with data and type * - * @param mixed $data The data that formatter should parse - * @param string $type The type of data formatter is expected to parse + * @param mixed $data The data that formatter should parse + * @param string $type The type of data formatter is expected to parse + * @param string $delimiter The delimitation of data formatter to csv * @return Formatter */ - public static function make($data, $type) + public static function make($data, $type, $delimiter = null) { if (in_array($type, self::$supportedTypes)) { $parser = null; switch ($type) { case self::CSV: - $parser = new CsvParser($data); + $parser = new CsvParser($data, $delimiter); break; case self::JSON: $parser = new JsonParser($data); diff --git a/src/Parsers/CsvParser.php b/src/Parsers/CsvParser.php index 40248c1..3dbd236 100644 --- a/src/Parsers/CsvParser.php +++ b/src/Parsers/CsvParser.php @@ -6,13 +6,16 @@ class CsvParser extends Parser { - private $csv; - public function __construct($data) + public function __construct($data, $delimiter = null) { if (is_string($data)) { $this->csv = Reader::createFromString($data); + if ($delimiter) { + $this->csv->setDelimiter($delimiter); + } + $this->csv->setEnclosure('|'); } else { throw new InvalidArgumentException( 'CsvParser only accepts (string) [csv] for $data.' diff --git a/tests/unit/FormatterTest.php b/tests/unit/FormatterTest.php index d1e96a5..88e5948 100644 --- a/tests/unit/FormatterTest.php +++ b/tests/unit/FormatterTest.php @@ -2,53 +2,61 @@ use SoapBox\Formatter\Formatter; -class FormatterTest extends TestCase { +class FormatterTest extends TestCase +{ - public function testFormatterProvidesCsvConstant() { - $expected = 'csv'; - $actual = Formatter::CSV; + public function testFormatterProvidesCsvConstant() + { + $expected = 'csv'; + $actual = Formatter::CSV; - $this->assertEquals($expected, $actual); - } + $this->assertEquals($expected, $actual); + } - public function testFormatterProvidesJsonConstant() { - $expected = 'json'; - $actual = Formatter::JSON; + public function testFormatterProvidesJsonConstant() + { + $expected = 'json'; + $actual = Formatter::JSON; - $this->assertEquals($expected, $actual); - } + $this->assertEquals($expected, $actual); + } - public function testFormatterProvidesXmlConstant() { - $expected = 'xml'; - $actual = Formatter::XML; + public function testFormatterProvidesXmlConstant() + { + $expected = 'xml'; + $actual = Formatter::XML; - $this->assertEquals($expected, $actual); - } + $this->assertEquals($expected, $actual); + } - public function testFormatterProvidesArrayConstant() { - $expected = 'array'; - $actual = Formatter::ARR; + public function testFormatterProvidesArrayConstant() + { + $expected = 'array'; + $actual = Formatter::ARR; - $this->assertEquals($expected, $actual); - } + $this->assertEquals($expected, $actual); + } - public function testFormatterProvidesYamlConstant() { - $expected = 'yaml'; - $actual = Formatter::YAML; + public function testFormatterProvidesYamlConstant() + { + $expected = 'yaml'; + $actual = Formatter::YAML; - $this->assertEquals($expected, $actual); - } + $this->assertEquals($expected, $actual); + } /** * @expectedException InvalidArgumentException */ - public function testFormatterMakeThrowsInvalidTypeException() { - $formatter = Formatter::make('', 'blue'); - } - - public function testFormatterMakeReturnsInstanceOfFormatter() { - $formatter = Formatter::make('', Formatter::CSV); - $this->assertTrue($formatter instanceof Formatter); - } + public function testFormatterMakeThrowsInvalidTypeException() + { + $formatter = Formatter::make('', 'blue'); + } + + public function testFormatterMakeReturnsInstanceOfFormatter() + { + $formatter = Formatter::make('', Formatter::CSV); + $this->assertTrue($formatter instanceof Formatter); + } } diff --git a/tests/unit/Parsers/ArrayParserTest.php b/tests/unit/Parsers/ArrayParserTest.php index d18c0b3..ebe609e 100644 --- a/tests/unit/Parsers/ArrayParserTest.php +++ b/tests/unit/Parsers/ArrayParserTest.php @@ -1,58 +1,67 @@ assertTrue($parser instanceof Parser); - } + public function testArrayParserIsInstanceOfParserInterface() + { + $parser = new ArrayParser(new \stdClass); + $this->assertTrue($parser instanceof Parser); + } - public function testConstructorAcceptsSerializedArray() { - $expected = [0, 1, 2]; - $parser = new ArrayParser(serialize($expected)); - $this->assertEquals($expected, $parser->toArray()); - } + public function testConstructorAcceptsSerializedArray() + { + $expected = [0, 1, 2]; + $parser = new ArrayParser(serialize($expected)); + $this->assertEquals($expected, $parser->toArray()); + } - public function testConstructorAcceptsObject() { - $expected = ['foo' => 'bar']; - $input = new stdClass; - $input->foo = 'bar'; - $parser = new ArrayParser($input); - $this->assertEquals($expected, $parser->toArray()); - } + public function testConstructorAcceptsObject() + { + $expected = ['foo' => 'bar']; + $input = new stdClass; + $input->foo = 'bar'; + $parser = new ArrayParser($input); + $this->assertEquals($expected, $parser->toArray()); + } /** * @expectedException InvalidArgumentException */ - public function testArrayParserThrowsExceptionWithInvalidInputOfEmptyString() { - $parser = new ArrayParser(''); - } - - public function testtoArrayReturnsArray() { - $parser = new ArrayParser(serialize([0, 1, 2])); - $this->assertTrue(is_array($parser->toArray())); - } - - public function testtoJsonReturnsJsonRepresentationOfArray() { - $expected = '[0,1,2]'; - $parser = new ArrayParser([0, 1, 2]); - $this->assertEquals($expected, $parser->toJson()); - } - - public function testtoJsonReturnsJsonRepresentationOfNamedArray() { - $expected = '{"foo":"bar"}'; - $parser = new ArrayParser(['foo' => 'bar']); - $this->assertEquals($expected, $parser->toJson()); - } - - public function testtoCSVFromArrayContainingContentWithCommasWorks() { - $expected = "\"0\",\"1\",\"2\",\"3\"\n\"a\",\"b\",\"c,e\",\"d\""; - $parser = new ArrayParser(['a','b','c,e','d']); - $this->assertEquals($expected, $parser->toCsv()); - } + public function testArrayParserThrowsExceptionWithInvalidInputOfEmptyString() + { + $parser = new ArrayParser(''); + } + + public function testtoArrayReturnsArray() + { + $parser = new ArrayParser(serialize([0, 1, 2])); + $this->assertTrue(is_array($parser->toArray())); + } + + public function testtoJsonReturnsJsonRepresentationOfArray() + { + $expected = '[0,1,2]'; + $parser = new ArrayParser([0, 1, 2]); + $this->assertEquals($expected, $parser->toJson()); + } + + public function testtoJsonReturnsJsonRepresentationOfNamedArray() + { + $expected = '{"foo":"bar"}'; + $parser = new ArrayParser(['foo' => 'bar']); + $this->assertEquals($expected, $parser->toJson()); + } + + public function testtoCSVFromArrayContainingContentWithCommasWorks() + { + $expected = "\"0\",\"1\",\"2\",\"3\"\n\"a\",\"b\",\"c,e\",\"d\""; + $parser = new ArrayParser(['a', 'b', 'c,e', 'd']); + $this->assertEquals($expected, $parser->toCsv()); + } } diff --git a/tests/unit/Parsers/CsvParserDelemiterTest.php b/tests/unit/Parsers/CsvParserDelemiterTest.php new file mode 100644 index 0000000..87d11bd --- /dev/null +++ b/tests/unit/Parsers/CsvParserDelemiterTest.php @@ -0,0 +1,41 @@ +assertTrue($parser instanceof Parser); + } + + /** + * @expectedException InvalidArgumentException + */ + public function testConstructorThrowsInvalidExecptionWhenArrayDataIsProvided() + { + $parser = new CsvParser([0, 1, 3], ';'); + } + + public function testtoArrayReturnsCsvArrayRepresentation() + { + $expected = [['foo' => 'bar', 'boo' => 'far']]; + $parser = new CsvParser($this->simpleCsv, ';'); + $this->assertEquals($expected, $parser->toArray()); + } + + public function testtoJsonReturnsJsonRepresentationOfNamedArray() + { + $expected = '[{"foo":"bar","boo":"far"}]'; + $parser = new CsvParser($this->simpleCsv, ';'); + $this->assertEquals($expected, $parser->toJson()); + } + +} diff --git a/tests/unit/Parsers/CsvParserTest.php b/tests/unit/Parsers/CsvParserTest.php index 39547c0..246416e 100644 --- a/tests/unit/Parsers/CsvParserTest.php +++ b/tests/unit/Parsers/CsvParserTest.php @@ -1,36 +1,41 @@ assertTrue($parser instanceof Parser); - } + public function testCsvParserIsInstanceOfParserInterface() + { + $parser = new CsvParser(''); + $this->assertTrue($parser instanceof Parser); + } /** * @expectedException InvalidArgumentException */ - public function testConstructorThrowsInvalidExecptionWhenArrayDataIsProvided() { - $parser = new CsvParser([0, 1, 3]); - } - - public function testtoArrayReturnsCsvArrayRepresentation() { - $expected = [['foo' => 'bar', 'boo' => 'far']]; - $parser = new CsvParser($this->simpleCsv); - $this->assertEquals($expected, $parser->toArray()); - } - - public function testtoJsonReturnsJsonRepresentationOfNamedArray() { - $expected = '[{"foo":"bar","boo":"far"}]'; - $parser = new CsvParser($this->simpleCsv); - $this->assertEquals($expected, $parser->toJson()); - } + public function testConstructorThrowsInvalidExecptionWhenArrayDataIsProvided() + { + $parser = new CsvParser([0, 1, 3]); + } + + public function testtoArrayReturnsCsvArrayRepresentation() + { + $expected = [['foo' => 'bar', 'boo' => 'far']]; + $parser = new CsvParser($this->simpleCsv); + $this->assertEquals($expected, $parser->toArray()); + } + + public function testtoJsonReturnsJsonRepresentationOfNamedArray() + { + $expected = '[{"foo":"bar","boo":"far"}]'; + $parser = new CsvParser($this->simpleCsv); + $this->assertEquals($expected, $parser->toJson()); + } } diff --git a/tests/unit/Parsers/JsonParserTest.php b/tests/unit/Parsers/JsonParserTest.php index 9bca418..17ebba7 100644 --- a/tests/unit/Parsers/JsonParserTest.php +++ b/tests/unit/Parsers/JsonParserTest.php @@ -1,31 +1,36 @@ assertTrue($parser instanceof Parser); - } + public function testJsonParserIsInstanceOfParserInterface() + { + $parser = new JsonParser(''); + $this->assertTrue($parser instanceof Parser); + } - public function testtoArrayReturnsArrayRepresentationOfJsonObject() { - $expected = ['foo' => 'bar']; - $parser = new JsonParser('{"foo": "bar"}'); - $this->assertEquals($expected, $parser->toArray()); - } + public function testtoArrayReturnsArrayRepresentationOfJsonObject() + { + $expected = ['foo' => 'bar']; + $parser = new JsonParser('{"foo": "bar"}'); + $this->assertEquals($expected, $parser->toArray()); + } - public function testtoJsonReturnsArrayRepresentationOfArray() { - $expected = '[0,1,2]'; - $parser = new JsonParser($expected); - $this->assertEquals($expected, $parser->toJson()); - } + public function testtoJsonReturnsArrayRepresentationOfArray() + { + $expected = '[0,1,2]'; + $parser = new JsonParser($expected); + $this->assertEquals($expected, $parser->toJson()); + } - public function testtoJsonReturnsJsonRepresentationOfNamedArray() { - $expected = '{"foo":"bar"}'; - $parser = new JsonParser($expected); - $this->assertEquals($expected, $parser->toJson()); - } + public function testtoJsonReturnsJsonRepresentationOfNamedArray() + { + $expected = '{"foo":"bar"}'; + $parser = new JsonParser($expected); + $this->assertEquals($expected, $parser->toJson()); + } } diff --git a/tests/unit/Parsers/XmlParserTest.php b/tests/unit/Parsers/XmlParserTest.php index 614be06..7f1b93b 100644 --- a/tests/unit/Parsers/XmlParserTest.php +++ b/tests/unit/Parsers/XmlParserTest.php @@ -1,25 +1,29 @@ assertTrue($parser instanceof Parser); - } + public function testXmlParserIsInstanceOfParserInterface() + { + $parser = new XmlParser(''); + $this->assertTrue($parser instanceof Parser); + } - public function testtoArrayReturnsArrayRepresenationOfXmlObject() { - $expected = ['foo' => 'bar']; - $parser = new XmlParser('bar'); - $this->assertEquals($expected, $parser->toArray()); - } + public function testtoArrayReturnsArrayRepresenationOfXmlObject() + { + $expected = ['foo' => 'bar']; + $parser = new XmlParser('bar'); + $this->assertEquals($expected, $parser->toArray()); + } - public function testtoJsonReturnsJsonRepresentationOfXmlObject() { - $expected = '{"foo":"bar"}'; - $parser = new XmlParser('bar'); - $this->assertEquals($expected, $parser->toJson()); - } + public function testtoJsonReturnsJsonRepresentationOfXmlObject() + { + $expected = '{"foo":"bar"}'; + $parser = new XmlParser('bar'); + $this->assertEquals($expected, $parser->toJson()); + } } diff --git a/tests/unit/Parsers/YamlParserTest.php b/tests/unit/Parsers/YamlParserTest.php index bf0edac..e25c53c 100644 --- a/tests/unit/Parsers/YamlParserTest.php +++ b/tests/unit/Parsers/YamlParserTest.php @@ -1,22 +1,25 @@ assertTrue($parser instanceof Parser); - } + public function testYamlParserIsInstanceOfParserInterface() + { + $parser = new YamlParser(''); + $this->assertTrue($parser instanceof Parser); + } - public function testtoArrayReturnsArrayRepresenationOfYamlObject() { - $expected = ['foo' => 'bar']; - $parser = new XmlParser('bar'); - $x = new YamlParser($parser->toYaml()); - $this->assertEquals($expected, $x->toArray()); - } + public function testtoArrayReturnsArrayRepresenationOfYamlObject() + { + $expected = ['foo' => 'bar']; + $parser = new XmlParser('bar'); + $x = new YamlParser($parser->toYaml()); + $this->assertEquals($expected, $x->toArray()); + } }