mirror of
https://github.com/parsecsv/parsecsv-for-php.git
synced 2026-02-19 08:36:39 +00:00
Compare commits
4 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
947b1c0866 | ||
|
|
a3981edb84 | ||
|
|
b4e4c14b42 | ||
|
|
89429ebd60 |
@@ -8,8 +8,6 @@ php:
|
||||
- '7.2'
|
||||
- '7.1'
|
||||
- '7.0'
|
||||
- '5.6'
|
||||
- '5.5'
|
||||
|
||||
before_install:
|
||||
- composer update
|
||||
|
||||
@@ -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
|
||||
|
||||
20
README.md
20
README.md
@@ -1,5 +1,5 @@
|
||||
# ParseCsv
|
||||
[](https://opencollective.com/parsecsv)
|
||||
[](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
|
||||
|
||||
@@ -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
3
ruleset.xml
Normal 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>
|
||||
62
src/Csv.php
62
src/Csv.php
@@ -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;
|
||||
|
||||
@@ -26,5 +26,4 @@ class SortEnum extends AbstractEnum {
|
||||
|
||||
return self::$sorting[self::__DEFAULT];
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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';
|
||||
}
|
||||
|
||||
|
||||
@@ -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 {
|
||||
|
||||
}
|
||||
@@ -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',
|
||||
|
||||
Reference in New Issue
Block a user