75 Commits

Author SHA1 Message Date
Christian Bläul
9c14bc2f30 Updated ChangeLog.txt with new features 2018-03-03 12:01:45 +01:00
Christian Bläul
4b6b7ee0b8 Removed -rc.2 from version, as it is officially released now 2018-03-03 11:55:57 +01:00
Christian Bläul
a80a6f1862 Moved features section up because library selection comes before install 2018-03-03 11:55:06 +01:00
Christian Bläul
da70838698 Only improved ChangeLog to include the output() change 2018-03-02 17:52:26 +01:00
Christian Bläul
abecaf1b5d Only re-formated source code slightly 2018-03-02 17:25:38 +01:00
Christian Bläul
3af94399e6 Semantic versioning: Marked the current state of the repo as 1.0.0-rc.2 2018-03-02 17:15:31 +01:00
Christian Bläul
499088b3b2 Slightly improved README.md 2018-03-02 17:15:31 +01:00
Christian Bläul
fd63ff4a26 Removed examples from class file as they are also in the README.md 2018-03-02 17:15:31 +01:00
Christian Bläul
d250c9034b Further improved ChangeLog.txt and README.txt 2018-03-02 17:15:31 +01:00
Christian Bläul
bfc2c0901b Improved installation section of README.md; added Travid badge. 2018-03-02 17:15:31 +01:00
Christian Bläul
a0336f02ee Prepared new release in ChangeLog.txt 2018-03-02 17:15:31 +01:00
Christian Bläul
ea78f38e26 ConstructTest: undo directory change to be on the safe side. 2018-03-02 17:15:31 +01:00
Christian Bläul
c9e7997643 Don't break people's code just because they don't have Composer 2018-03-02 17:15:31 +01:00
Christian Bläul
68239d6859 No code changes, just cleaned up comments a bit 2018-03-02 17:15:31 +01:00
Christian Bläul
d05577d303 output(): Use better mime type for \t separator.
Fixes #79
2018-03-02 17:13:45 +01:00
Fonata
eedbffc375 Merge pull request #125 from itexia/42-Heading-and-offset
Fixed issue 42: heading and offset; added tests
2018-03-02 17:06:22 +01:00
Susann Sgorzaly
11b20a3144 fixes #42. If csv has heading and offset is set, first row will always be parsed 2018-02-27 15:10:55 +01:00
Susann Sgorzaly
7766bf7c3b added two tests for reproducing the heading and offset bug. test with heading fails at the moment. if this one is green, bug would be solved 2018-02-27 15:00:14 +01:00
susgo
ef44ea3989 Merge pull request #7 from parsecsv/master
update
2018-02-22 14:55:40 +01:00
Christian Bläul
2ac9f450f1 Check if output contains HTML table cells
They should if the _books.csv file is found
2018-02-21 19:25:39 +01:00
Christian Bläul
3968659b9f Make sure the code examples run without syntax or runtime errors. 2018-02-21 19:22:45 +01:00
Christian Bläul
d3a084d973 Added namespace support for further tests 2018-02-21 19:04:00 +01:00
Christian Bläul
b0355be96a Re-added the parsecsv.lib.php file for compatibility 2018-02-21 19:00:41 +01:00
Christian Bläul
b753d9c694 Repaired examples: there was a require missing. 2018-02-21 18:45:50 +01:00
Christian Bläul
2b95ec5aa1 Merge remote-tracking branch 'origin/Tests-for-sort-and-cond' into pull-test
# Conflicts:
#	tests/Bootstrap.php
#	tests/methods/ParseTest.php
#	tests/properties/worthless_test.php
2018-02-21 18:41:45 +01:00
Susann Sgorzaly
3f595dfd3b only renamed variable 2018-02-21 12:55:26 +01:00
susgo
081949339b Merge pull request #6 from parsecsv/itexia-fixed-remaining-test
Fixed remaining test
2018-02-21 08:36:24 +01:00
Christian Bläul
a60aae47a4 getDatatypes: Documented the need for PHP 5.5 or higher 2018-02-20 22:16:49 +01:00
Christian Bläul
4cba97ad51 Allow PhpStorm to understand the code better
(I followed suggestions from PhpStorm's inspections)
2018-02-20 22:07:08 +01:00
Christian Bläul
2206ec1e7c only reformatted source code to match the rest of the project 2018-02-20 22:06:06 +01:00
Christian Bläul
d188921ab6 composer.json: Only allow to load tests in dev environment 2018-02-20 21:50:52 +01:00
Christian Bläul
85cc0d9cfc Updated README.md to new name & namespace 2018-02-20 21:50:45 +01:00
Christian Bläul
a7f2bbb7bc Throw more specific exception 2018-02-20 21:40:48 +01:00
Christian Bläul
d484f3e9e3 The workaround for array_count_values was wrong and unnecessary. 2018-02-20 21:37:39 +01:00
Christian Bläul
f8b2fe274a Added missing letter in function name 2018-02-20 21:35:21 +01:00
susgo
17bfd9496a Merge pull request #5 from parsecsv/itexia-repair-tests
Repair tests (somewhat)
2018-02-20 08:22:59 +01:00
Christian Bläul
ec7b1c1d55 PHPUnit: Better class names with modern naming scheme 2018-02-19 23:01:31 +01:00
Christian Bläul
ba9eae17d4 Bootstrap: Improved the conditions under which the test wrapper loads 2018-02-19 23:00:57 +01:00
Christian Bläul
8f26ce6ea3 Force Travis to output which PHPUnit version it uses 2018-02-19 22:49:43 +01:00
Christian Bläul
913dc94e2c Keep sorting keys compatible: Moved array_values call to PHPUnit.
This commit partially reverts adcd258ea2.
2018-02-19 22:08:59 +01:00
Christian Bläul
5ced1f4212 Added conditions to SortByTest because otherwise different PHP versions...
yielded different sort orders (that's sort of ok, as rating is ambiguous).

See https://travis-ci.org/parsecsv/parsecsv-for-php/jobs/336540118
2018-02-19 22:08:59 +01:00
Christian Bläul
ca84469950 Moved ConditionsTest to properties subfolder 2018-02-19 22:08:59 +01:00
Christian Bläul
75902f4a22 Added PHPUnit test for sorting; I could not get the rows in the right...
order without calling array_values - maybe this helps just PHPUnit. I
consider the risk of breaking library users' code unlikely.
2018-02-19 22:08:59 +01:00
Christian Bläul
7470d2b804 PHPUnit: Repaired file paths in autoQuotesDataProvider() 2018-02-19 22:08:59 +01:00
Christian Bläul
01f0891cfb Test some conditions 2018-02-19 22:08:59 +01:00
Susann Sgorzaly
52a9b61b97 added DatatypeEnum tests; repaired the other test for local execution; small bug fixes 2018-02-19 21:36:31 +01:00
susgo
5660be3373 Merge pull request #1 from itexia/introduce-namespaces
init introduce namespaces and enums
2018-02-19 14:22:46 +01:00
Susann Sgorzaly
70b6fe4bd8 Merge branch 'introduce-namespaces' of https://github.com/itexia/parsecsv-for-php into introduce-namespaces 2018-02-19 14:10:10 +01:00
Susann Sgorzaly
f1a89127c2 regex updated according to merge conflict 2018-02-19 14:09:30 +01:00
susgo
31dba0411e Merge pull request #4 from parsecsv/test-helper-for-itexia-with-namespaces
Test helper for ITEXIA fork with namespaces
2018-02-19 14:05:14 +01:00
susgo
6da0537197 Merge branch 'introduce-namespaces' into test-helper-for-itexia-with-namespaces 2018-02-19 14:04:37 +01:00
susgo
91091ac933 Merge pull request #2 from itexia/new-enom-datatype
init enum for data type
2018-02-19 12:08:38 +01:00
susgo
2c7c552515 Update DatatypeTrait.php 2018-02-19 12:07:32 +01:00
Susann Sgorzaly
52e87953a4 corrected datatype count 2018-02-19 12:02:48 +01:00
Christian Bläul
2b6e38734c Merge remote-tracking branch 'origin/test-helper-for-itexia-master' into delete_this_branch 2018-02-18 19:41:38 +01:00
Christian Bläul
af7368378c Changed tests to work now that we have a namespace 2018-02-18 19:40:21 +01:00
Christian Bläul
f2fb7c81bd Absolute path in require do stop PhpStorm from nagging
(PhpStorm couldn't find the file)
2018-02-18 19:34:32 +01:00
Christian Bläul
92653c99c5 Force predictable working dir; create autoloader file if it doesn't exist 2018-02-18 19:32:39 +01:00
Christian Bläul
d4f9c9f020 Updated worthless_test to allow for more fields 2018-02-18 19:04:16 +01:00
Christian Bläul
2b17f01a0a Removed additional column to make expected data fit to fixture 2018-02-18 19:03:23 +01:00
Christian Bläul
9551862a95 Allow current working dir to be different when running tests
...By using an absolute path
2018-02-18 19:02:37 +01:00
Christian Bläul
736bc489e6 getDatatypes: throw more meaningful exception if no data is present 2018-02-18 19:01:47 +01:00
Christian Bläul
f702ca93fe Float regex: Don't allow double dot; do allow 'e' for exponentials 2018-02-18 19:00:24 +01:00
Susann Sgorzaly
48cec20f4f namespace change 2018-02-18 12:45:33 +01:00
Susann Sgorzaly
c266ef9fbc Merge branch 'introduce-namespaces' of https://github.com/itexia/parsecsv-for-php into new-enom-datatype 2018-02-18 12:43:45 +01:00
Susann Sgorzaly
76a0406eff updated examples for using new classname 2018-02-18 12:43:19 +01:00
Susann Sgorzaly
17ac1dee1a renamed namespace 2018-02-18 12:42:53 +01:00
Susann Sgorzaly
f6bd414ae7 init enum for data type 2018-02-18 00:09:22 +01:00
Susann Sgorzaly
a7a0bc34a4 init introduce namespaces 2018-02-17 23:41:03 +01:00
Susann Sgorzaly
0e5afb209e test for method getDatatypes added 2018-02-17 22:24:50 +01:00
Susann Sgorzaly
f8c68a6cd7 test improvements 2018-02-17 22:24:19 +01:00
Susann Sgorzaly
5babb55879 review changes 2018-02-14 14:03:00 +01:00
Susann Sgorzaly
8ec87126dc load files from extensions folder for tests; added new property in worthless_test 2018-02-14 12:12:53 +01:00
Susann Sgorzaly
d788135bbe exclude datatype detection in its own trait 2018-02-14 12:12:01 +01:00
Susann Sgorzaly
301f6da3e6 init new functionality to identify datatypes of columns 2018-02-13 17:18:01 +01:00
26 changed files with 1915 additions and 1364 deletions

View File

@@ -9,6 +9,7 @@ php:
- 5.4
script:
- phpunit --version
- phpunit --configuration tests/phpunit.xml
notifications:

View File

@@ -1,3 +1,29 @@
ParseCSV 1.0.0
-----------------------------------
Date: 3-March-2018
- Renamed class from parseCSV to Csv and added name-
space "ParseCsv" for PSR compliance.
- Added support for MS Excel's "sep=" to detect the
delimiter (Issue #60).
- Added data type detection - function getDatatypes()
guesses the type of each column.
- MIME: output() sends correct MIME type to browser
if the separator is a tab tab (Issue #79).
- Added support for mb_convert_encoding() instead of
iconv() - see issue #109.
- A number of minor bug fixes - see GitHub issues.
- Added many more unit tests.
-----------------------------------
parseCSV 0.4.3 beta
-----------------------------------
Date: 1-July-2008
@@ -159,7 +185,7 @@ Date: 2-Jan-2007
- Added auto() function to automatically detect
delimiter character.
Useful for user upload incase delimiter is
Useful for user upload in case delimiter is
comma (,), tab, or semi-colon (;). Some
versions of MS Excel for Windows use
semi-colons instead of commas when saving to
@@ -170,7 +196,7 @@ Date: 2-Jan-2007
almost no matter what the delimiter is.
- Generally updated some of the core workings
to increase performance, and offer better
to increase performance, and offer better
support for large (1MB and up) files.
- Added code examples to header comment.

View File

@@ -1,32 +1,20 @@
# parseCSV
# 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
[Wikipedia article][CSV] (and thus RFC 4180). It has many advanced features which help make your
life easier when dealing with CSV data.
You may not need a library at all: before using parseCSV, please make sure if PHP's own `str_getcsv()`, ``fgetcvs()`` or `fputcsv()` meets your needs.
You may not need a library at all: before using ParseCsv, please make sure if PHP's own `str_getcsv()`, ``fgetcvs()`` or `fputcsv()` meets your needs.
This library was originally created in early 2007 by [jimeh](https://github.com/jimeh) due to the lack of built-in
and third-party support for handling CSV data in PHP.
[csv]: http://en.wikipedia.org/wiki/Comma-separated_values
## Installation
Installation is easy using Composer. Include the following in your composer.json
```
"parsecsv/php-parsecsv": "0.4.5"
```
You may also manually include the parsecsv.lib.php file
```php
require_once 'parsecsv.lib.php';
```
## Features
* parseCSV is the only complete and fully featured CSV solution for PHP (as
far as I know).
* ParseCsv is a complete and fully featured CSV solution for PHP
* Supports enclosed values, enclosed commas, double quotes and new lines.
* Automatic delimiter character detection.
* Sort data by specific fields/columns.
@@ -36,24 +24,45 @@ require_once 'parsecsv.lib.php';
* Error detection for incorrectly formatted input. It attempts to be
intelligent, but can not be trusted 100% due to the structure of CSV, and
how different programs like Excel for example outputs CSV data.
* Support for character encoding conversion using PHP's _iconv_ function
(requires PHP 5).
* Supports PHP 5.4 and higher. It certainly works with PHP 7.2
* Support for character encoding conversion using PHP's
`iconv()` and `mb_convert_encoding()` functions.
* Supports PHP 5.4 and higher.
It certainly works with PHP 7.2 and all versions in between.
## Installation
Installation is easy using Composer. Just run the following on the
command line:
```
composer require parsecsv/php-parsecsv
```
If you don't use a framework such as Drupal, Laravel, Symfony, Yii etc.,
you may have to manually include Composer's autoloader file in your PHP
script:
```php
require_once __DIR__ . '/vendor/autoload.php';
```
#### Without composer
Not recommended, but technically possible: you can also clone the
repository or extract the
[ZIP](https://github.com/parsecsv/parsecsv-for-php/archive/master.zip).
To use ParseCSV, you then have to add a `require 'parsecsv.lib.php';` line.
## Example Usage
**General**
```php
$csv = new parseCSV('data.csv');
$csv = new ParseCsv\Csv('data.csv');
print_r($csv->data);
```
**Tab delimited, and encoding conversion**
```php
$csv = new parseCSV();
$csv = new ParseCsv\Csv();
$csv->encoding('UTF-16', 'UTF-8');
$csv->delimiter = "\t";
$csv->parse('data.tsv');
@@ -63,7 +72,7 @@ print_r($csv->data);
**Auto-detect delimiter character**
```php
$csv = new parseCSV();
$csv = new ParseCsv\Csv();
$csv->auto('data.csv');
print_r($csv->data);
```
@@ -71,7 +80,7 @@ print_r($csv->data);
**Modify data in a CSV file**
```php
$csv = new parseCSV();
$csv = new ParseCsv\Csv();
$csv->sort_by = 'id';
$csv->parse('data.csv');
# "4" is the value of the "id" column of the CSV row
@@ -82,7 +91,7 @@ $csv->save();
**Replace field names or set ones if missing**
```php
$csv = new parseCSV();
$csv = new ParseCsv\Csv();
$csv->fields = ['id', 'name', 'category']
$csv->parse('data.csv');
```
@@ -92,15 +101,15 @@ $csv->parse('data.csv');
_Only recommended when you know the exact structure of the file._
```php
$csv = new parseCSV();
$csv = new ParseCsv\Csv();
$csv->save('data.csv', array(array('1986', 'Home', 'Nowhere', '')), 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
a file and download it**
```php
$csv = new parseCSV();
$csv = new ParseCsv\Csv();
$csv->output('movies.csv', $array, array('field 1', 'field 2'), ',');
```
@@ -108,7 +117,7 @@ For more complex examples, see the ``tests`` and `examples` directories.
## Credits
* parseCSV is based on the concept of [Ming Hong Ng][ming]'s [CsvFileParser][]
* ParseCsv is based on the concept of [Ming Hong Ng][ming]'s [CsvFileParser][]
class.
[ming]: http://minghong.blogspot.com/
@@ -146,3 +155,5 @@ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
[![Build Status](https://travis-ci.org/parsecsv/parsecsv-for-php.svg?branch=master)](https://travis-ci.org/parsecsv/parsecsv-for-php)

View File

@@ -12,10 +12,17 @@
"email": "will.knauss@gmail.com"
}
],
"autoload": {
"classmap": [
"."
]
"autoload":{
"psr-4":{
"ParseCsv\\": "src",
"ParseCsv\\extensions\\": "src\\extensions",
"ParseCsv\\tests\\": "tests"
}
},
"autoload-dev":{
"psr-4":{
"ParseCsv\\tests\\": "tests"
}
},
"require-dev": {
"phpunit/phpunit": "4.1.*"

View File

@@ -1,13 +1,13 @@
<pre>
<?php
# include parseCSV class.
require_once('../parsecsv.lib.php');
require __DIR__ . '/../vendor/autoload.php';
use ParseCsv\Csv;
# create new parseCSV object.
$csv = new parseCSV();
$csv = new Csv();
# Parse '_books.csv' using automatic delimiter detection...

View File

@@ -3,11 +3,12 @@
# include parseCSV class.
require_once('../parsecsv.lib.php');
require __DIR__ . '/../vendor/autoload.php';
use ParseCsv\Csv;
# create new parseCSV object.
$csv = new parseCSV();
$csv = new Csv();
# Example conditions:

View File

@@ -2,11 +2,12 @@
# include parseCSV class.
require_once('../parsecsv.lib.php');
require __DIR__ . '/../vendor/autoload.php';
use ParseCsv\Csv;
# create new parseCSV object.
$csv = new parseCSV();
$csv = new Csv();
# Parse '_books.csv' using automatic delimiter detection...
@@ -31,4 +32,4 @@ $csv->output('books.csv');
# or is set to null, output will only return the generated CSV
# output data, and will not output to the browser itself.
?>
?>

View File

@@ -3,11 +3,12 @@
# include parseCSV class.
require_once('../parsecsv.lib.php');
require __DIR__ . '/../vendor/autoload.php';
use ParseCsv\Csv;
# create new parseCSV object.
$csv = new parseCSV();
$csv = new Csv();
# if sorting is enabled, the whole CSV file

File diff suppressed because it is too large Load Diff

1212
src/Csv.php Normal file

File diff suppressed because it is too large Load Diff

120
src/enums/DatatypeEnum.php Normal file
View File

@@ -0,0 +1,120 @@
<?php
namespace ParseCsv\enums;
/**
* Class DatatypeEnum
*
* @package ParseCsv\enums
*
* todo: needs a basic parent enum class for error handling.
*/
class DatatypeEnum {
const __DEFAULT = self::TYPE_STRING;
const TYPE_STRING = 'string';
const TYPE_FLOAT = 'float';
const TYPE_INT = 'integer';
const TYPE_BOOL = 'boolean';
const TYPE_DATE = 'date';
const REGEX_FLOAT = '/(^[+-]?$)|(^[+-]?[0-9]+([,.][0-9])?[0-9]*(e[+-]?[0-9]+)?$)/';
const REGEX_INT = '/^[-+]?[0-9]\d*$/';
const REGEX_BOOL = '/^(?i:true|false)$/';
/**
* Define validator functions here.
*
* @var array
*
* @uses isValidFloat
* @uses isValidInteger
* @uses isValidBoolean
* @uses isValidDate
*/
private static $validators = array(
self::TYPE_STRING => null,
self::TYPE_INT => 'isValidInteger',
self::TYPE_BOOL => 'isValidBoolean',
self::TYPE_FLOAT => 'isValidFloat',
self::TYPE_DATE => 'isValidDate',
);
/**
* Checks data type for given string.
*
* @param string $value
*
* @return bool|string
*/
public static function getValidTypeFromSample($value) {
$value = trim((string) $value);
if (empty($value)) {
return false;
}
foreach (self::$validators as $type => $validator) {
if ($validator === null) {
continue;
}
if (method_exists(__CLASS__, $validator) && self::$validator($value)) {
return $type;
}
}
return self::__DEFAULT;
}
/**
* Check if string is float value.
*
* @param string $value
*
* @return bool
*/
private static function isValidFloat($value) {
return (bool) preg_match(self::REGEX_FLOAT, $value);
}
/**
* Check if string is integer value.
*
* @param string $value
*
* @return bool
*/
private static function isValidInteger($value) {
return (bool) preg_match(self::REGEX_INT, $value);
}
/**
* Check if string is boolean.
*
* @param string $value
*
* @return bool
*/
private static function isValidBoolean($value) {
return (bool) preg_match(self::REGEX_BOOL, $value);
}
/**
* Check if string is date.
*
* @param string $value
*
* @return bool
*/
private static function isValidDate($value) {
return (bool) strtotime($value);
}
}

View File

@@ -0,0 +1,74 @@
<?php
namespace ParseCsv\extensions;
trait DatatypeTrait {
/**
* Datatypes
* Datatypes of CSV data-columns
*
* @access public
* @var array
*/
public $data_types = [];
/**
* Check data type for one column.
* Check for most commonly data type for one column.
*
* @access private
*
* @param array $datatypes
*
* @return string|false
*/
private function getMostFrequentDatatypeForColumn($datatypes) {
// remove 'false' from array (can happen if CSV cell is empty)
$typesFiltered = array_filter($datatypes);
if (empty($typesFiltered)) {
return false;
}
$typesFreq = array_count_values($typesFiltered);
arsort($typesFreq);
reset($typesFreq);
return key($typesFreq);
}
/**
* Check data type foreach Column
* Check data type for each column and returns the most commonly.
*
* Requires PHP >= 5.5
*
* @access public
*
* @uses getDatatypeFromString
*
* @return array|bool
*/
public function getDatatypes() {
if (empty($this->data)) {
$this->data = $this->parse_string();
}
if (!is_array($this->data)) {
throw new \UnexpectedValueException('No data set yet.');
}
$result = [];
foreach ($this->titles as $cName) {
$column = array_column($this->data, $cName);
$cDatatypes = array_map('ParseCsv\enums\DatatypeEnum::getValidTypeFromSample', $column);
$result[$cName] = $this->getMostFrequentDatatypeForColumn($cDatatypes);
}
$this->data_types = $result;
return !empty($this->data_types) ? $this->data_types : [];
}
}

View File

@@ -1,11 +1,13 @@
<?php
chdir(__DIR__ . '/..');
if (!file_exists('vendor/autoload.php')) {
`composer dump-autoload`;
}
$dir = realpath(__DIR__);
defined('BASE') OR define('BASE', dirname($dir) . '/');
require __DIR__ . '/../vendor/autoload.php';
require_once BASE . 'parsecsv.lib.php';
if (!class_exists('PHPUnit\Framework\TestCase')) {
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,69 +1,67 @@
<?php
class ConstructTest extends PHPUnit\Framework\TestCase {
namespace ParseCsv\tests\methods;
use ParseCsv\Csv;
use PHPUnit\Framework\TestCase;
class ConstructTest extends TestCase {
/**
* CSV
* The parseCSV object
*
* @access protected
* @var [parseCSV]
* @var Csv object
*/
protected $csv = null;
/**
* Setup
* Setup our test environment objects
*
* @access public
*/
public function setUp() {
//setup parse CSV
#$this->csv = new parseCSV();
}
/**
* Tear down
* Tear down our test environment objects
*
* @access public
*/
public function tearDown() {
$this->csv = null;
}
public function test_offset_param() {
$offset = 10;
$this->csv = new parseCSV(null, $offset);
$this->csv = new Csv(null, $offset);
$this->assertTrue(is_numeric($this->csv->offset));
$this->assertEquals($offset, $this->csv->offset);
}
public function test_limit_param() {
$limit = 10;
$this->csv = new parseCSV(null, null, $limit);
$this->csv = new Csv(null, null, $limit);
$this->assertTrue(is_numeric($this->csv->limit));
$this->assertEquals($limit, $this->csv->limit);
}
public function test_conditions_param() {
$conditions = 'some column NOT value';
$this->csv = new parseCSV(null, null, null, $conditions);
$this->csv = new Csv(null, null, null, $conditions);
$this->assertTrue(is_string($this->csv->conditions));
$this->assertEquals($conditions, $this->csv->conditions);
}
public function test_keep_file_data_param() {
$keep = true;
$this->csv = new parseCSV(null, null, null, null, $keep);
$this->csv = new Csv(null, null, null, null, $keep);
$this->assertTrue(is_bool($this->csv->keep_file_data));
$this->assertEquals($keep, $this->csv->keep_file_data);
}
public function test_input_param() {
$csv = "col1,col2,col3\r\nval1,val2,val3\r\nval1A,val2A,val3A\r\n";
$this->csv = new parseCSV($csv, null, null, null, true);
$this->csv = new Csv($csv, null, null, null, true);
$this->assertTrue(is_string($this->csv->file_data));
$this->assertEquals($csv, $this->csv->file_data);
}
/**
* @runInSeparateProcess because download.php uses header()
*
* @see https://github.com/sebastianbergmann/phpunit/issues/720#issuecomment-10421092
*/
public function testCodeExamples() {
chdir('examples');
foreach (glob('*.php') as $script_file) {
ob_start();
/** @noinspection PhpIncludeInspection */
require $script_file;
if ($script_file != 'download.php') {
$this->assertContains('<td>', ob_get_clean());
}
}
chdir('..');
}
}

View File

@@ -0,0 +1,69 @@
<?php
/**
* Created by PhpStorm.
* User: sgorzaly
* Date: 19.02.18
* Time: 20:52
*/
namespace ParseCsv\tests\methods;
use PHPUnit\Framework\TestCase;
use ParseCsv\enums\DatatypeEnum;
class DatatypeTest extends TestCase
{
public function testSampleIsValidInteger(){
$this->assertEquals(DatatypeEnum::TYPE_INT, DatatypeEnum::getValidTypeFromSample('1'));
$this->assertEquals(DatatypeEnum::TYPE_INT, DatatypeEnum::getValidTypeFromSample('+1'));
$this->assertEquals(DatatypeEnum::TYPE_INT, DatatypeEnum::getValidTypeFromSample('-1'));
$this->assertNotEquals(DatatypeEnum::TYPE_INT, DatatypeEnum::getValidTypeFromSample('--1'));
$this->assertNotEquals(DatatypeEnum::TYPE_INT, DatatypeEnum::getValidTypeFromSample('test'));
$this->assertNotEquals(DatatypeEnum::TYPE_INT, DatatypeEnum::getValidTypeFromSample('1.0'));
$this->assertNotEquals(DatatypeEnum::TYPE_INT, DatatypeEnum::getValidTypeFromSample('1,0'));
$this->assertNotEquals(DatatypeEnum::TYPE_INT, DatatypeEnum::getValidTypeFromSample('1,1'));
$this->assertNotEquals(DatatypeEnum::TYPE_INT, DatatypeEnum::getValidTypeFromSample('0.1'));
$this->assertNotEquals(DatatypeEnum::TYPE_INT, DatatypeEnum::getValidTypeFromSample('true'));
$this->assertNotEquals(DatatypeEnum::TYPE_INT, DatatypeEnum::getValidTypeFromSample('2018-02-19'));
}
public function testSampleIsValidBool(){
$this->assertEquals(DatatypeEnum::TYPE_BOOL, DatatypeEnum::getValidTypeFromSample('true'));
$this->assertEquals(DatatypeEnum::TYPE_BOOL, DatatypeEnum::getValidTypeFromSample('TRUE'));
$this->assertEquals(DatatypeEnum::TYPE_BOOL, DatatypeEnum::getValidTypeFromSample('false'));
$this->assertEquals(DatatypeEnum::TYPE_BOOL, DatatypeEnum::getValidTypeFromSample('FALSE'));
$this->assertNotEquals(DatatypeEnum::TYPE_BOOL, DatatypeEnum::getValidTypeFromSample('FALS'));
$this->assertNotEquals(DatatypeEnum::TYPE_BOOL, DatatypeEnum::getValidTypeFromSample('test'));
$this->assertNotEquals(DatatypeEnum::TYPE_BOOL, DatatypeEnum::getValidTypeFromSample('0'));
$this->assertNotEquals(DatatypeEnum::TYPE_BOOL, DatatypeEnum::getValidTypeFromSample('1'));
$this->assertNotEquals(DatatypeEnum::TYPE_BOOL, DatatypeEnum::getValidTypeFromSample('0.1'));
}
public function testSampleIsValidFloat(){
$this->assertEquals(DatatypeEnum::TYPE_FLOAT, DatatypeEnum::getValidTypeFromSample('1.0'));
$this->assertEquals(DatatypeEnum::TYPE_FLOAT, DatatypeEnum::getValidTypeFromSample('-1.1'));
$this->assertEquals(DatatypeEnum::TYPE_FLOAT, DatatypeEnum::getValidTypeFromSample('+1,1'));
$this->assertEquals(DatatypeEnum::TYPE_FLOAT, DatatypeEnum::getValidTypeFromSample('1,1'));
$this->assertEquals(DatatypeEnum::TYPE_FLOAT, DatatypeEnum::getValidTypeFromSample('1,1'));
$this->assertEquals(DatatypeEnum::TYPE_FLOAT, DatatypeEnum::getValidTypeFromSample('1e-03'));
$this->assertEquals(DatatypeEnum::TYPE_FLOAT, DatatypeEnum::getValidTypeFromSample('1e+03'));
$this->assertNotEquals(DatatypeEnum::TYPE_FLOAT, DatatypeEnum::getValidTypeFromSample('1'));
$this->assertNotEquals(DatatypeEnum::TYPE_FLOAT, DatatypeEnum::getValidTypeFromSample('test'));
$this->assertNotEquals(DatatypeEnum::TYPE_FLOAT, DatatypeEnum::getValidTypeFromSample('1,,1'));
$this->assertNotEquals(DatatypeEnum::TYPE_FLOAT, DatatypeEnum::getValidTypeFromSample('1..1'));
$this->assertNotEquals(DatatypeEnum::TYPE_FLOAT, DatatypeEnum::getValidTypeFromSample('2018-02-19'));
}
public function testSampleIsValidDate(){
$this->assertEquals(DatatypeEnum::TYPE_DATE, DatatypeEnum::getValidTypeFromSample('2018-02-19'));
$this->assertEquals(DatatypeEnum::TYPE_DATE, DatatypeEnum::getValidTypeFromSample('18-2-19'));
$this->assertEquals(DatatypeEnum::TYPE_DATE, DatatypeEnum::getValidTypeFromSample('01.02.2018'));
$this->assertEquals(DatatypeEnum::TYPE_DATE, DatatypeEnum::getValidTypeFromSample('1.2.18'));
$this->assertEquals(DatatypeEnum::TYPE_DATE, DatatypeEnum::getValidTypeFromSample('07/31/2018'));
$this->assertNotEquals(DatatypeEnum::TYPE_DATE, DatatypeEnum::getValidTypeFromSample('31/07/2018'));
$this->assertNotEquals(DatatypeEnum::TYPE_DATE, DatatypeEnum::getValidTypeFromSample('1-2'));
$this->assertEquals(DatatypeEnum::TYPE_DATE, DatatypeEnum::getValidTypeFromSample('1.2.'));
$this->assertNotEquals(DatatypeEnum::TYPE_DATE, DatatypeEnum::getValidTypeFromSample('test'));
}
}

View File

@@ -0,0 +1,28 @@
<?php
namespace ParseCsv\tests\methods;
use PHPUnit\Framework\TestCase;
class OldRequireTest extends TestCase {
protected function setUp() {
rename('vendor/autoload.php', '__autoload');
}
protected function tearDown() {
rename('__autoload', 'vendor/autoload.php');
}
/**
* @runInSeparateProcess because download.php uses header()
*/
public function testOldLibWithoutComposer() {
file_put_contents('__eval.php', '<?php require "parsecsv.lib.php"; new \ParseCsv\Csv;');
exec("php __eval.php", $output, $return_var);
unlink('__eval.php');
$this->assertEquals($output, []);
$this->assertEquals(0, $return_var);
}
}

View File

@@ -1,13 +1,14 @@
<?php
class ParseTest extends PHPUnit\Framework\TestCase {
namespace ParseCsv\tests\methods;
use ParseCsv\Csv;
use PHPUnit\Framework\TestCase;
class ParseTest extends TestCase {
/**
* CSV
* The parseCSV object
*
* @access protected
* @var parseCSV
* @var Csv object
*/
protected $csv;
@@ -18,7 +19,7 @@ class ParseTest extends PHPUnit\Framework\TestCase {
* @access public
*/
public function setUp() {
$this->csv = new parseCSV();
$this->csv = new Csv();
}
public function test_parse() {
@@ -39,9 +40,26 @@ class ParseTest extends PHPUnit\Framework\TestCase {
$this->assertEquals($expected_data, $row);
}
public function test_sep_row_auto_detection_UTF8_no_BOM() {
$this->_autoparse_magazine_file(
__DIR__ . '/../example_files/UTF-8_sep_row_but_no_BOM.csv');
/**
* @depends test_parse
*
* @dataProvider autoDetectionProvider
*/
public function testSepRowAutoDetection($file) {
// This file (parse_test.php) is encoded in UTF-8, hence comparison will
// fail unless we to this:
$this->csv->output_encoding = 'UTF-8';
$this->csv->auto($file);
$this->assertEquals($this->_get_magazines_data(), $this->csv->data);
}
public function autoDetectionProvider() {
return [
'UTF8_no_BOM' => [__DIR__ . '/../example_files/UTF-8_sep_row_but_no_BOM.csv'],
'UTF8' => [__DIR__ . '/../example_files/UTF-8_with_BOM_and_sep_row.csv'],
'UTF16' => [__DIR__ . '/../example_files/UTF-16LE_with_BOM_and_sep_row.csv'],
];
}
public function testSingleColumnWithZeros() {
@@ -77,25 +95,6 @@ class ParseTest extends PHPUnit\Framework\TestCase {
], array_map('next', $actual_data));
}
public function test_sep_row_auto_detection_UTF8() {
$this->_autoparse_magazine_file(
__DIR__ . '/../example_files/UTF-8_with_BOM_and_sep_row.csv');
}
public function test_sep_row_auto_detection_UTF16() {
$this->_autoparse_magazine_file(
__DIR__ . '/../example_files/UTF-16LE_with_BOM_and_sep_row.csv');
}
protected function _autoparse_magazine_file($file) {
// This file (parse_test.php) is encoded in UTF-8, hence comparison will
// fail unless we to this:
$this->csv->output_encoding = 'UTF-8';
$this->csv->auto($file);
$this->assertEquals($this->_get_magazines_data(), $this->csv->data);
}
public function test_single_column() {
$this->csv->auto(__DIR__ . '/../example_files/single_column.csv');
$expected = [
@@ -130,6 +129,55 @@ class ParseTest extends PHPUnit\Framework\TestCase {
], $aCity);
}
/**
* @depends testSepRowAutoDetection
*/
public function testGetColumnDatatypes() {
if (!function_exists('array_column')) {
// getDatatypes requires array_column, but that
// function is only available in PHP >= 5.5
return;
}
$this->csv->auto(__DIR__ . '/fixtures/datatype.csv');
$this->csv->getDatatypes();
$expected = [
'title' => 'string',
'isbn' => 'string',
'publishedAt' => 'date',
'published' => 'boolean',
'count' => 'integer',
'price' => 'float',
];
$this->assertEquals($expected, $this->csv->data_types);
}
public function testDataArrayKeysWhenSettingOffsetWithHeading() {
$this->csv->offset = 2;
$this->csv->auto(__DIR__ . '/fixtures/datatype.csv');
$expected = [
'title',
'isbn',
'publishedAt',
'published',
'count',
'price'
];
$this->assertEquals($expected, array_keys($this->csv->data[0]));
}
public function testDataArrayKeysWhenSettingOffsetWithoutHeading() {
$this->csv->heading = false;
$this->csv->offset = 2;
$this->csv->auto(__DIR__ . '/fixtures/datatype.csv');
$expected = range(0, 5, 1);
$this->assertEquals($expected, array_keys($this->csv->data[0]));
}
protected function _get_magazines_data() {
return [
[
@@ -152,20 +200,22 @@ class ParseTest extends PHPUnit\Framework\TestCase {
public function autoQuotesDataProvider() {
return array(
array('tests/methods/fixtures/auto-double-enclosure.csv', '"'),
array('tests/methods/fixtures/auto-single-enclosure.csv', "'"),
array('auto-double-enclosure.csv', '"'),
array('auto-single-enclosure.csv', "'"),
);
}
/**
* @depends testSepRowAutoDetection
*
* @dataProvider autoQuotesDataProvider
*
* @param string $file
* @param string $enclosure
*/
public function testAutoQuotes($file, $enclosure) {
$csv = new parseCSV();
$csv->auto($file, true, null, null, $enclosure);
$csv = new Csv();
$csv->auto(__DIR__ . '/fixtures/' . $file, true, null, null, $enclosure);
$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);
}

View File

@@ -1,8 +1,13 @@
<?php
namespace ParseCsv\tests\methods;
class SaveTest extends PHPUnit\Framework\TestCase {
use ParseCsv\Csv;
use PHPUnit\Framework\TestCase;
/** @var parseCSV */
class SaveTest extends TestCase
{
/** @var Csv */
private $csv;
private $temp_filename;
@@ -11,7 +16,7 @@ class SaveTest extends PHPUnit\Framework\TestCase {
* Setup our test environment objects; will be called before each test.
*/
public function setUp() {
$this->csv = new parseCSV();
$this->csv = new Csv();
$this->csv->auto(__DIR__ . '/../example_files/single_column.csv');
// Remove last 2 lines to simplify comparison

View File

@@ -0,0 +1,5 @@
sep=;
title;isbn;publishedAt;published;count;price
Красивая кулинария;5454-5587-3210;21.05.2011;true;1;10.99
The Wine Connoisseurs;2547-8548-2541;12.12.2011;TRUE;;20.33
Weißwein;1313-4545-8875;23.02.2012;false;10;10
1 sep=;
2 title;isbn;publishedAt;published;count;price
3 Красивая кулинария;5454-5587-3210;21.05.2011;true;1;10.99
4 The Wine Connoisseurs;2547-8548-2541;12.12.2011;TRUE;;20.33
5 Weißwein;1313-4545-8875;23.02.2012;false;10;10

View File

@@ -0,0 +1,36 @@
<?php
namespace ParseCsv\tests\properties;
use ParseCsv\Csv;
use PHPUnit\Framework\TestCase;
class BaseClass extends TestCase {
/**
* CSV
* The parseCSV object
*
* @access protected
* @var Csv
*/
protected $csv;
/**
* Setup
* Setup our test environment objects
*
* @access public
*/
public function setUp() {
$this->csv = new Csv();
}
protected function _compareWithExpected($expected) {
$this->csv->auto(__DIR__ . '/../../examples/_books.csv');
$actual = array_map(function ($row) {
return $row['title'];
}, $this->csv->data);
$this->assertEquals($expected, array_values($actual));
}
}

View File

@@ -0,0 +1,49 @@
<?php
namespace ParseCsv\tests\properties;
class ConditionsTest extends BaseClass {
public function testNotDanBrown() {
$this->csv->conditions = 'author does not contain dan brown';
$this->_compareWithExpected([
'The Killing Kind',
'The Third Secret',
'The Last Templar',
'The Traveller',
'Crisis Four',
'Prey',
'The Broker (Paperback)',
'Without Blood (Paperback)',
'State of Fear (Paperback)',
'The Rule of Four (Paperback)',
]);
}
public function testRating() {
$this->csv->conditions = 'rating < 3';
$this->_compareWithExpected([
'The Killing Kind',
'The Third Secret',
]);
$this->csv->conditions = 'rating >= 5';
$this->_compareWithExpected([
'The Traveller',
'Prey',
'State of Fear (Paperback)',
'Digital Fortress : A Thriller (Mass Market Paperback)',
'Angels & Demons (Mass Market Paperback)',
]);
}
public function testTitleContainsSecretOrCode() {
$this->csv->conditions = 'title contains code OR title contains SECRET';
$this->_compareWithExpected([
'The Third Secret',
'The Da Vinci Code (Hardcover)',
]);
}
}

View File

@@ -1,13 +1,18 @@
<?php
class default_values_properties_Test extends PHPUnit\Framework\TestCase {
namespace ParseCsv\tests\properties;
use ParseCsv\Csv;
use PHPUnit\Framework\TestCase;
class DefaultValuesPropertiesTest extends TestCase {
/**
* CSV
* The parseCSV object
*
* @access protected
* @var [parseCSV]
* @var Csv
*/
protected $csv = null;
@@ -19,7 +24,7 @@ class default_values_properties_Test extends PHPUnit\Framework\TestCase {
*/
public function setUp() {
//setup parse CSV
$this->csv = new parseCSV();
$this->csv = new Csv();
}
/**

View File

@@ -1,13 +1,18 @@
<?php
class worthless_properties_Test extends PHPUnit\Framework\TestCase {
namespace ParseCsv\tests\properties;
use ParseCsv\Csv;
use PHPUnit\Framework\TestCase;
class PublicPropertiesTest extends TestCase {
/**
* CSV
* The parseCSV object
*
* @access protected
* @var [parseCSV]
* @var Csv
*/
protected $csv = null;
@@ -16,7 +21,7 @@ class worthless_properties_Test extends PHPUnit\Framework\TestCase {
* The reflection class object
*
* @access protected
* @var [ReflectionClass]
* @var \ReflectionClass
*/
protected $reflection = null;
@@ -24,6 +29,7 @@ class worthless_properties_Test extends PHPUnit\Framework\TestCase {
* Reflection Properties
* The reflected class properties
*
* @var \ReflectionProperty[]
* @access protected
*/
protected $properties = null;
@@ -36,10 +42,10 @@ class worthless_properties_Test extends PHPUnit\Framework\TestCase {
*/
public function setUp() {
//setup parse CSV
$this->csv = new parseCSV();
$this->csv = new Csv();
//setup the reflection class
$this->reflection = new ReflectionClass($this->csv);
$this->reflection = new \ReflectionClass($this->csv);
//setup the reflected class properties
$this->properties = $this->reflection->getProperties();
@@ -65,7 +71,7 @@ class worthless_properties_Test extends PHPUnit\Framework\TestCase {
* @access public
*/
public function test_propertiesCount() {
$this->assertCount(28, $this->properties);
$this->assertCount(29, $this->properties);
}
/**
@@ -107,11 +113,12 @@ class worthless_properties_Test extends PHPUnit\Framework\TestCase {
'error',
'error_info',
'titles',
'data'
'data',
'data_types',
);
// Find our real properties
$real_properties = array_map(function (ReflectionProperty $property) {
$real_properties = array_map(function (\ReflectionProperty $property) {
return $property->getName();
}, $this->properties);
@@ -129,7 +136,8 @@ class worthless_properties_Test extends PHPUnit\Framework\TestCase {
public function test_count_public_properties() {
$counter = 0;
for ($a = 0; $a < count($this->properties); $a++) {
$propertiesCount = count($this->properties);
for ($a = 0; $a < $propertiesCount; $a++) {
if ($this->properties[$a]->isPublic() === true) {
$counter++;
}

View File

@@ -0,0 +1,60 @@
<?php
namespace ParseCsv\tests\properties;
class SortByTest extends BaseClass {
public function testSortByRating() {
$this->csv->sort_by = 'rating';
$this->csv->conditions = 'title does not contain Blood';
$this->_compareWithExpected([
// Rating 0
'The Killing Kind',
'The Third Secret',
// Rating 3
'The Last Templar',
'The Broker (Paperback)',
// Rating 4
'Deception Point (Paperback)',
'The Rule of Four (Paperback)',
'The Da Vinci Code (Hardcover)',
// Rating 5
'State of Fear (Paperback)',
'Prey',
'Digital Fortress : A Thriller (Mass Market Paperback)',
'Angels & Demons (Mass Market Paperback)',
]);
}
public function testReverseSortByRating() {
$this->csv->sort_by = 'rating';
$this->csv->conditions =
'title does not contain Prey AND ' .
'title does not contain Fortress AND ' .
'title does not contain Blood AND ' .
'title does not contain Fear';
$this->csv->sort_reverse = true;
$this->_compareWithExpected([
// Rating 5
'Angels & Demons (Mass Market Paperback)',
'The Traveller',
// Rating 4
'The Da Vinci Code (Hardcover)',
'The Rule of Four (Paperback)',
'Deception Point (Paperback)',
// Rating 3
'The Broker (Paperback)',
'The Last Templar',
// Rating 0
'The Third Secret',
'The Killing Kind',
]);
}
}