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.1'
- '7.0'
- '5.6'
- '5.5'
before_install:
- 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
-----------------------------------
Date: 07-Jan-2020

View File

@@ -1,5 +1,5 @@
# 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
fully conforms to the specifications outlined on the on the
@@ -104,7 +104,7 @@ $count = $csv->getTotalDataRowCount();
print_r($count);
```
**Get most common data type for each column (Requires PHP >= 5.5)**
**Get most common data type for each column**
```php
$csv = new ParseCsv\Csv('data.csv');
@@ -146,7 +146,7 @@ _Only recommended when you know the exact structure of the file._
```php
$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
@@ -157,7 +157,7 @@ $csv = new ParseCsv\Csv();
$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
@@ -170,17 +170,13 @@ For more complex examples, see the ``tests`` and `examples` directories.
## Contributors
### Code Contributors
This project exists thanks to all the people who contribute.
Please find a complete list on the project's [contributors][] page.
[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>
### Financial Contributors

View File

@@ -34,7 +34,8 @@
"php": ">=5.5"
},
"require-dev": {
"phpunit/phpunit": "4.1.*"
"phpunit/phpunit": "^6",
"squizlabs/php_codesniffer": "^3.5"
},
"suggest": {
"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
* Class constructor
*
* @param string|null $input The CSV string or a direct file path
* @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 file path
* @param int|null $offset Number of rows to ignore from the
* beginning of the data
* @param int|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) {
$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
* @param integer|null $limit Limits the number of returned rows
* @param int|null $limit Limits the number of returned rows
* to specified amount
* @param string|null $conditions Basic SQL-like conditions for row
* @param string|null $conditions Basic SQL-like conditions for row
* 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
* (useful for debugging)
*/
@@ -368,11 +368,11 @@ class Csv {
* Parse a CSV file or string
*
* @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
* @param integer $limit Limits the number of returned rows to
* @param int|null $limit Limits the number of returned rows to
* specified amount
* @param string $conditions Basic SQL-like conditions for row
* @param string|null $conditions Basic SQL-like conditions for row
* matching
*
* @return bool True on success
@@ -474,8 +474,10 @@ class Csv {
* Encoding
* Convert character encoding
*
* @param string $input Input character encoding, uses default if left blank
* @param string $output Output character encoding, uses default if left blank
* @param string|null $input Input 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) {
$this->convert_encoding = true;
@@ -495,11 +497,11 @@ class Csv {
*
* @param string|null $file Local CSV file
* @param bool $parse True/false parse file directly
* @param int $search_depth Number of rows to analyze
* @param string $preferred Preferred delimiter characters
* @param int|null $search_depth Number of rows to analyze
* @param string|null $preferred Preferred delimiter characters
* @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) {
if (is_null($file)) {
@@ -572,12 +574,10 @@ class Csv {
$headingRow = $this->heading ? 1 : 0;
$count = substr_count($data, "\r")
return substr_count($data, "\r")
+ substr_count($data, "\n")
- substr_count($data, "\r\n")
- $headingRow;
return $count;
}
// ==============================================
@@ -613,7 +613,7 @@ class Csv {
*
* 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
*/
@@ -861,7 +861,12 @@ class Csv {
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)) {
$fields = $this->titles;
}
@@ -1298,7 +1303,6 @@ class Csv {
}
// remove delimiter and its line-end (the data param is by-ref!)
/** @noinspection CallableParameterUseCaseInTypeContextInspection */
$data_string = substr($data_string, $pos);
return true;
}
@@ -1309,7 +1313,7 @@ class Csv {
* @param string $enclosure Enclosure character, default is double quote
* @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 = [];
$strlen = strlen($data);
$enclosed = false;

View File

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

View File

@@ -5,9 +5,3 @@ if (!file_exists('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 PHPUnit\Framework\TestCase;
use ReflectionClass;
class ParseTest extends TestCase {
@@ -28,6 +29,9 @@ class ParseTest extends TestCase {
$this->parseRepetitiveString('http://looks/like/an/url');
}
/**
* @param string $content
*/
private function parseRepetitiveString($content) {
$this->csv->delimiter = ';';
$this->csv->heading = false;
@@ -56,6 +60,9 @@ class ParseTest extends TestCase {
$this->assertEquals($this->_get_magazines_data(), $this->csv->data);
}
/**
* @return array
*/
public function autoDetectionProvider() {
return [
'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() {
$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);
$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);
@@ -88,14 +97,17 @@ class ParseTest extends TestCase {
$sInput = "86545235689,a\r\n34365587654,b\r\n13469874576,\"c\r\nd\"";
$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);
$this->assertEquals($expected_data, $actual_column);
$this->assertEquals([
'a',
'b',
"c\r\nd",
], array_map('next', $actual_data));
$this->assertEquals(
[
'a',
'b',
"c\r\nd",
],
array_map('next', $actual_data)
);
}
public function testSingleColumn() {
@@ -115,18 +127,24 @@ class ParseTest extends TestCase {
$this->csv->output_encoding = 'UTF-8';
$this->csv->auto(__DIR__ . '/../example_files/Piwik_API_download.csv');
$aAction27 = array_column($this->csv->data, 'url (actionDetails 27)');
$this->assertEquals([
'http://application/_Main/_GraphicMeanSTD_MDI/btnConfBandOptions',
'',
'',
], $aAction27);
$this->assertEquals(
[
'http://application/_Main/_GraphicMeanSTD_MDI/btnConfBandOptions',
'',
'',
],
$aAction27
);
$aCity = array_column($this->csv->data, 'city');
$this->assertEquals([
'São Paulo',
'Johannesburg',
'',
], $aCity);
$this->assertEquals(
[
'São Paulo',
'Johannesburg',
'',
],
$aCity
);
}
/**
@@ -135,7 +153,8 @@ class ParseTest extends TestCase {
public function testStringWithLeadingBOM() {
$string_with_bom = strtr(
file_get_contents(__DIR__ . '/../example_files/UTF-8_with_BOM_and_sep_row.csv'),
["sep=;\n" => '']);
["sep=;\n" => '']
);
// Is the BOM still there?
self::assertSame(0xEF, ord($string_with_bom));
@@ -220,11 +239,17 @@ class ParseTest extends TestCase {
$this->assertFalse($this->csv->autoDetectFileHasHeading());
}
/**
* @doesNotPerformAssertions
*/
public function testVeryLongNonExistingFile() {
$this->csv->parse(str_repeat('long_string', PHP_MAXPATHLEN));
$this->csv->auto(str_repeat('long_string', PHP_MAXPATHLEN));
}
/**
* @return array
*/
protected function _get_magazines_data() {
return [
[
@@ -245,7 +270,11 @@ class ParseTest extends TestCase {
];
}
public function autoQuotesDataProvider() {
/**
* @return array
*/
public function autoQuotesDataProvider(): array
{
return array(
array('auto-double-enclosure.csv', '"'),
array('auto-single-enclosure.csv', "'"),
@@ -270,14 +299,14 @@ class ParseTest extends TestCase {
/**
* 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.
* @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));
private function invokeMethod($object, $methodName, $parameters = []) {
$reflection = new ReflectionClass(get_class($object));
$method = $reflection->getMethod($methodName);
$method->setAccessible(true);
@@ -285,7 +314,7 @@ class ParseTest extends TestCase {
}
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 = [
'liability waiver',
'release of liability form',