4 Commits
1.2.0 ... 1.2.1

Author SHA1 Message Date
Fonata
947b1c0866 Removed PHPUnit <6 compat wrapper 2020-04-25 19:17:04 +02:00
Petri Haikonen
a3981edb84 Added some annotations to tests 2020-04-25 19:17:04 +02:00
Petri Haikonen
b4e4c14b42 PHPUnit 6 instead of 4, to get rid of wrapper
The TestCase wrapper caused PhpStorm to show warnings about
multiple implementations

Fixes #188

Improved some type hints in DocBlocks
2020-04-25 19:17:04 +02:00
Fonata
89429ebd60 Cleaned up README 2020-04-25 19:17:04 +02:00
10 changed files with 116 additions and 87 deletions

View File

@@ -8,8 +8,6 @@ php:
- '7.2' - '7.2'
- '7.1' - '7.1'
- '7.0' - '7.0'
- '5.6'
- '5.5'
before_install: before_install:
- composer update - composer update

View File

@@ -1,3 +1,19 @@
ParseCSV 1.2.1
-----------------------------------
Date: 25-Apr-2020
Breaking changes: none
New features: none
Bug fixes: none
Code quality:
- Switched from PHPUnit 4 to 6 to get rid of
wrappers. This will reduce friction for PhpStorm users,
because it gets rid of the "Multiple definitions" error
See issue #188. Thanks to @SharkMachine for the hint.
-----------------------------------
ParseCSV 1.2.0 ParseCSV 1.2.0
----------------------------------- -----------------------------------
Date: 07-Jan-2020 Date: 07-Jan-2020

View File

@@ -1,5 +1,5 @@
# ParseCsv # ParseCsv
[![Financial Contributors on Open Collective](https://opencollective.com/parsecsv/all/badge.svg?label=financial+contributors)](https://opencollective.com/parsecsv) [![Financial Contributors on Open Collective](https://opencollective.com/parsecsv/all/badge.svg?label=financial+contributors)](https://opencollective.com/parsecsv)
ParseCsv is an easy-to-use PHP class that reads and writes CSV data properly. It ParseCsv is an easy-to-use PHP class that reads and writes CSV data properly. It
fully conforms to the specifications outlined on the on the fully conforms to the specifications outlined on the on the
@@ -104,7 +104,7 @@ $count = $csv->getTotalDataRowCount();
print_r($count); print_r($count);
``` ```
**Get most common data type for each column (Requires PHP >= 5.5)** **Get most common data type for each column**
```php ```php
$csv = new ParseCsv\Csv('data.csv'); $csv = new ParseCsv\Csv('data.csv');
@@ -146,7 +146,7 @@ _Only recommended when you know the exact structure of the file._
```php ```php
$csv = new ParseCsv\Csv(); $csv = new ParseCsv\Csv();
$csv->save('data.csv', array(array('1986', 'Home', 'Nowhere', '')), true); $csv->save('data.csv', array(array('1986', 'Home', 'Nowhere', '')), /* append */ true);
``` ```
**Convert 2D array to CSV data and send headers to browser to treat output as **Convert 2D array to CSV data and send headers to browser to treat output as
@@ -157,7 +157,7 @@ $csv = new ParseCsv\Csv();
$csv->output('movies.csv', $array, array('field 1', 'field 2'), ','); $csv->output('movies.csv', $array, array('field 1', 'field 2'), ',');
``` ```
For more complex examples, see the ``tests`` and `examples` directories. For more complex examples, see the ``tests`` and `examples` directories.
## Credits ## Credits
@@ -170,17 +170,13 @@ For more complex examples, see the ``tests`` and `examples` directories.
## Contributors ## Contributors
### Code Contributors
This project exists thanks to all the people who contribute.
Please find a complete list on the project's [contributors][] page. Please find a complete list on the project's [contributors][] page.
[contributors]: https://github.com/parsecsv/parsecsv-for-php/graphs/contributors [contributors]: https://github.com/parsecsv/parsecsv-for-php/graphs/contributors
## Contributors
### Code Contributors
This project exists thanks to all the people who contribute. [[Contribute](CONTRIBUTING.md)].
<a href="https://github.com/parsecsv/parsecsv-for-php/graphs/contributors"><img src="https://opencollective.com/parsecsv/contributors.svg?width=890&button=false" /></a> <a href="https://github.com/parsecsv/parsecsv-for-php/graphs/contributors"><img src="https://opencollective.com/parsecsv/contributors.svg?width=890&button=false" /></a>
### Financial Contributors ### Financial Contributors

View File

@@ -34,7 +34,8 @@
"php": ">=5.5" "php": ">=5.5"
}, },
"require-dev": { "require-dev": {
"phpunit/phpunit": "4.1.*" "phpunit/phpunit": "^6",
"squizlabs/php_codesniffer": "^3.5"
}, },
"suggest": { "suggest": {
"illuminate/support": "Fluent array interface for map functions" "illuminate/support": "Fluent array interface for map functions"

3
ruleset.xml Normal file
View File

@@ -0,0 +1,3 @@
<?xml version="1.0"?>
<ruleset xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" name="ParseCSV" xsi:noNamespaceSchemaLocation="https://raw.githubusercontent.com/squizlabs/PHP_CodeSniffer/master/phpcs.xsd">
</ruleset>

View File

@@ -311,16 +311,16 @@ class Csv {
* Constructor * Constructor
* Class constructor * Class constructor
* *
* @param string|null $input The CSV string or a direct file path * @param string|null $input The CSV string or a direct file path
* @param integer|null $offset Number of rows to ignore from the * @param int|null $offset Number of rows to ignore from the
* beginning of the data * beginning of the data
* @param integer|null $limit Limits the number of returned rows * @param int|null $limit Limits the number of returned rows
* to specified amount * to specified amount
* @param string|null $conditions Basic SQL-like conditions for row * @param string|null $conditions Basic SQL-like conditions for row
* matching * matching
* @param null|true $keep_file_data Keep raw file data in memory after * @param null|true $keep_file_data Keep raw file data in memory after
* successful parsing * successful parsing
* (useful for debugging) * (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); $this->init($offset, $limit, $conditions, $keep_file_data);
@@ -331,13 +331,13 @@ class Csv {
} }
/** /**
* @param integer|null $offset Number of rows to ignore from the * @param int|null $offset Number of rows to ignore from the
* beginning of the data * beginning of the data
* @param integer|null $limit Limits the number of returned rows * @param int|null $limit Limits the number of returned rows
* to specified amount * to specified amount
* @param string|null $conditions Basic SQL-like conditions for row * @param string|null $conditions Basic SQL-like conditions for row
* matching * matching
* @param null|true $keep_file_data Keep raw file data in memory after * @param null|true $keep_file_data Keep raw file data in memory after
* successful parsing * successful parsing
* (useful for debugging) * (useful for debugging)
*/ */
@@ -368,11 +368,11 @@ class Csv {
* Parse a CSV file or string * Parse a CSV file or string
* *
* @param string|null $input The CSV string or a direct file path * @param string|null $input The CSV string or a direct file path
* @param integer $offset Number of rows to ignore from the * @param int|null $offset Number of rows to ignore from the
* beginning of the data * beginning of the data
* @param integer $limit Limits the number of returned rows to * @param int|null $limit Limits the number of returned rows to
* specified amount * specified amount
* @param string $conditions Basic SQL-like conditions for row * @param string|null $conditions Basic SQL-like conditions for row
* matching * matching
* *
* @return bool True on success * @return bool True on success
@@ -474,8 +474,10 @@ class Csv {
* Encoding * Encoding
* Convert character encoding * Convert character encoding
* *
* @param string $input Input character encoding, uses default if left blank * @param string|null $input Input character encoding, uses default if left blank
* @param string $output Output character encoding, uses default if left blank * @param string|null $output Output character encoding, uses default if left blank
*
* @return void
*/ */
public function encoding($input = null, $output = null) { public function encoding($input = null, $output = null) {
$this->convert_encoding = true; $this->convert_encoding = true;
@@ -495,11 +497,11 @@ class Csv {
* *
* @param string|null $file Local CSV file * @param string|null $file Local CSV file
* @param bool $parse True/false parse file directly * @param bool $parse True/false parse file directly
* @param int $search_depth Number of rows to analyze * @param int|null $search_depth Number of rows to analyze
* @param string $preferred Preferred delimiter characters * @param string|null $preferred Preferred delimiter characters
* @param string|null $enclosure Enclosure character, default is double quote ("). * @param string|null $enclosure Enclosure character, default is double quote (").
* *
* @return string The detected field delimiter * @return string|false The detected field delimiter
*/ */
public function auto($file = null, $parse = true, $search_depth = null, $preferred = null, $enclosure = null) { public function auto($file = null, $parse = true, $search_depth = null, $preferred = null, $enclosure = null) {
if (is_null($file)) { if (is_null($file)) {
@@ -572,12 +574,10 @@ class Csv {
$headingRow = $this->heading ? 1 : 0; $headingRow = $this->heading ? 1 : 0;
$count = substr_count($data, "\r") return substr_count($data, "\r")
+ substr_count($data, "\n") + substr_count($data, "\n")
- substr_count($data, "\r\n") - substr_count($data, "\r\n")
- $headingRow; - $headingRow;
return $count;
} }
// ============================================== // ==============================================
@@ -613,7 +613,7 @@ class Csv {
* *
* To detect field separators, please use auto() instead. * To detect field separators, please use auto() instead.
* *
* @param string $data CSV data * @param string|null $data CSV data
* *
* @return array|false - 2D array with CSV data, or false on failure * @return array|false - 2D array with CSV data, or false on failure
*/ */
@@ -861,7 +861,12 @@ class Csv {
return $string; return $string;
} }
private function _validate_fields_for_unparse($fields) { /**
* @param array $fields
*
* @return array|false
*/
private function _validate_fields_for_unparse(array $fields) {
if (empty($fields)) { if (empty($fields)) {
$fields = $this->titles; $fields = $this->titles;
} }
@@ -1298,7 +1303,6 @@ class Csv {
} }
// remove delimiter and its line-end (the data param is by-ref!) // remove delimiter and its line-end (the data param is by-ref!)
/** @noinspection CallableParameterUseCaseInTypeContextInspection */
$data_string = substr($data_string, $pos); $data_string = substr($data_string, $pos);
return true; return true;
} }
@@ -1309,7 +1313,7 @@ class Csv {
* @param string $enclosure Enclosure character, default is double quote * @param string $enclosure Enclosure character, default is double quote
* @param string $data The file content * @param string $data The file content
*/ */
protected function _guess_delimiter($search_depth, $preferred, $enclosure, &$data) { protected function _guess_delimiter($search_depth, $preferred, $enclosure, $data) {
$chars = []; $chars = [];
$strlen = strlen($data); $strlen = strlen($data);
$enclosed = false; $enclosed = false;

View File

@@ -26,5 +26,4 @@ class SortEnum extends AbstractEnum {
return self::$sorting[self::__DEFAULT]; return self::$sorting[self::__DEFAULT];
} }
} }

View File

@@ -5,9 +5,3 @@ if (!file_exists('vendor/autoload.php')) {
} }
require __DIR__ . '/../vendor/autoload.php'; require __DIR__ . '/../vendor/autoload.php';
if (!class_exists('PHPUnit\Framework\TestCase') && class_exists('PHPUnit_Framework_TestCase')) {
// we run on an older PHPUnit version without namespaces.
require_once __DIR__ . '/PHPUnit_Framework_TestCase.inc.php';
}

View File

@@ -1,11 +0,0 @@
<?php
namespace PHPUnit\Framework;
// Only needed to keep unit test code compatible with older PHPUnit versions
/** @noinspection PhpUndefinedClassInspection */
/** @noinspection AutoloadingIssuesInspection */
class TestCase extends \PHPUnit_Framework_TestCase {
}

View File

@@ -4,6 +4,7 @@ namespace ParseCsv\tests\methods;
use ParseCsv\Csv; use ParseCsv\Csv;
use PHPUnit\Framework\TestCase; use PHPUnit\Framework\TestCase;
use ReflectionClass;
class ParseTest extends TestCase { class ParseTest extends TestCase {
@@ -28,6 +29,9 @@ class ParseTest extends TestCase {
$this->parseRepetitiveString('http://looks/like/an/url'); $this->parseRepetitiveString('http://looks/like/an/url');
} }
/**
* @param string $content
*/
private function parseRepetitiveString($content) { private function parseRepetitiveString($content) {
$this->csv->delimiter = ';'; $this->csv->delimiter = ';';
$this->csv->heading = false; $this->csv->heading = false;
@@ -56,6 +60,9 @@ class ParseTest extends TestCase {
$this->assertEquals($this->_get_magazines_data(), $this->csv->data); $this->assertEquals($this->_get_magazines_data(), $this->csv->data);
} }
/**
* @return array
*/
public function autoDetectionProvider() { public function autoDetectionProvider() {
return [ return [
'UTF8_no_BOM' => [__DIR__ . '/../example_files/UTF-8_sep_row_but_no_BOM.csv'], 'UTF8_no_BOM' => [__DIR__ . '/../example_files/UTF-8_sep_row_but_no_BOM.csv'],
@@ -66,7 +73,9 @@ class ParseTest extends TestCase {
public function testSingleColumnWithZeros() { public function testSingleColumnWithZeros() {
$this->csv->delimiter = null; $this->csv->delimiter = null;
$this->csv->parse("URL\nhttp://www.amazon.com/ROX-Ice-Ball-Maker-Original/dp/B00MX59NMQ/ref=sr_1_1?ie=UTF8&qid=1435604374&sr=8-1&keywords=rox,+ice+molds"); $this->csv->parse(
"URL\nhttp://www.amazon.com/ROX-Ice-Ball-Maker-Original/dp/B00MX59NMQ/ref=sr_1_1?ie=UTF8&qid=1435604374&sr=8-1&keywords=rox,+ice+molds"
);
$row = array_pop($this->csv->data); $row = array_pop($this->csv->data);
$expected_data = ['URL' => 'http://www.amazon.com/ROX-Ice-Ball-Maker-Original/dp/B00MX59NMQ/ref=sr_1_1?ie=UTF8&qid=1435604374&sr=8-1&keywords=rox,+ice+molds']; $expected_data = ['URL' => 'http://www.amazon.com/ROX-Ice-Ball-Maker-Original/dp/B00MX59NMQ/ref=sr_1_1?ie=UTF8&qid=1435604374&sr=8-1&keywords=rox,+ice+molds'];
$this->assertEquals($expected_data, $row); $this->assertEquals($expected_data, $row);
@@ -88,14 +97,17 @@ class ParseTest extends TestCase {
$sInput = "86545235689,a\r\n34365587654,b\r\n13469874576,\"c\r\nd\""; $sInput = "86545235689,a\r\n34365587654,b\r\n13469874576,\"c\r\nd\"";
$expected_data = [86545235689, 34365587654, 13469874576]; $expected_data = [86545235689, 34365587654, 13469874576];
$actual_data = $this->invokeMethod($this->csv, '_parse_string', array($sInput)); $actual_data = $this->invokeMethod($this->csv, '_parse_string', [$sInput]);
$actual_column = array_map('reset', $actual_data); $actual_column = array_map('reset', $actual_data);
$this->assertEquals($expected_data, $actual_column); $this->assertEquals($expected_data, $actual_column);
$this->assertEquals([ $this->assertEquals(
'a', [
'b', 'a',
"c\r\nd", 'b',
], array_map('next', $actual_data)); "c\r\nd",
],
array_map('next', $actual_data)
);
} }
public function testSingleColumn() { public function testSingleColumn() {
@@ -115,18 +127,24 @@ class ParseTest extends TestCase {
$this->csv->output_encoding = 'UTF-8'; $this->csv->output_encoding = 'UTF-8';
$this->csv->auto(__DIR__ . '/../example_files/Piwik_API_download.csv'); $this->csv->auto(__DIR__ . '/../example_files/Piwik_API_download.csv');
$aAction27 = array_column($this->csv->data, 'url (actionDetails 27)'); $aAction27 = array_column($this->csv->data, 'url (actionDetails 27)');
$this->assertEquals([ $this->assertEquals(
'http://application/_Main/_GraphicMeanSTD_MDI/btnConfBandOptions', [
'', 'http://application/_Main/_GraphicMeanSTD_MDI/btnConfBandOptions',
'', '',
], $aAction27); '',
],
$aAction27
);
$aCity = array_column($this->csv->data, 'city'); $aCity = array_column($this->csv->data, 'city');
$this->assertEquals([ $this->assertEquals(
'São Paulo', [
'Johannesburg', 'São Paulo',
'', 'Johannesburg',
], $aCity); '',
],
$aCity
);
} }
/** /**
@@ -135,7 +153,8 @@ class ParseTest extends TestCase {
public function testStringWithLeadingBOM() { public function testStringWithLeadingBOM() {
$string_with_bom = strtr( $string_with_bom = strtr(
file_get_contents(__DIR__ . '/../example_files/UTF-8_with_BOM_and_sep_row.csv'), file_get_contents(__DIR__ . '/../example_files/UTF-8_with_BOM_and_sep_row.csv'),
["sep=;\n" => '']); ["sep=;\n" => '']
);
// Is the BOM still there? // Is the BOM still there?
self::assertSame(0xEF, ord($string_with_bom)); self::assertSame(0xEF, ord($string_with_bom));
@@ -220,11 +239,17 @@ class ParseTest extends TestCase {
$this->assertFalse($this->csv->autoDetectFileHasHeading()); $this->assertFalse($this->csv->autoDetectFileHasHeading());
} }
/**
* @doesNotPerformAssertions
*/
public function testVeryLongNonExistingFile() { public function testVeryLongNonExistingFile() {
$this->csv->parse(str_repeat('long_string', PHP_MAXPATHLEN)); $this->csv->parse(str_repeat('long_string', PHP_MAXPATHLEN));
$this->csv->auto(str_repeat('long_string', PHP_MAXPATHLEN)); $this->csv->auto(str_repeat('long_string', PHP_MAXPATHLEN));
} }
/**
* @return array
*/
protected function _get_magazines_data() { protected function _get_magazines_data() {
return [ return [
[ [
@@ -245,7 +270,11 @@ class ParseTest extends TestCase {
]; ];
} }
public function autoQuotesDataProvider() { /**
* @return array
*/
public function autoQuotesDataProvider(): array
{
return array( return array(
array('auto-double-enclosure.csv', '"'), array('auto-double-enclosure.csv', '"'),
array('auto-single-enclosure.csv', "'"), array('auto-single-enclosure.csv', "'"),
@@ -270,14 +299,14 @@ class ParseTest extends TestCase {
/** /**
* Call protected/private method of a class. * Call protected/private method of a class.
* *
* @param object &$object Instantiated object that we will run method on. * @param object $object Instantiated object that we will run method on.
* @param string $methodName Method name to call * @param string $methodName Method name to call
* @param array $parameters Array of parameters to pass into method. * @param array $parameters Array of parameters to pass into method.
* *
* @return mixed Method return. * @return mixed Method return.
*/ */
private function invokeMethod(&$object, $methodName, array $parameters = array()) { private function invokeMethod($object, $methodName, $parameters = []) {
$reflection = new \ReflectionClass(get_class($object)); $reflection = new ReflectionClass(get_class($object));
$method = $reflection->getMethod($methodName); $method = $reflection->getMethod($methodName);
$method->setAccessible(true); $method->setAccessible(true);
@@ -285,7 +314,7 @@ class ParseTest extends TestCase {
} }
public function testWaiverFieldSeparator() { public function testWaiverFieldSeparator() {
$this->assertSame(false, $this->csv->auto(__DIR__ . '/../example_files/waiver_field_separator.csv')); $this->assertFalse($this->csv->auto(__DIR__ . '/../example_files/waiver_field_separator.csv'));
$expected = [ $expected = [
'liability waiver', 'liability waiver',
'release of liability form', 'release of liability form',