12 Commits

Author SHA1 Message Date
Christian Bläul
02a8c1995d Semantic versioning: Marked the current state of the repo as 1.0.0-rc.1 2018-02-23 15:03:57 +01:00
Christian Bläul
72a7c29ed6 Updated remaining occurrences for old class/project name. 2018-02-02 17:31:26 +01:00
Christian Bläul
c905c9abfd Updated README.md 2018-02-02 17:26:13 +01:00
Christian Bläul
221c175217 Further improved ChangeLog.txt 2018-02-02 17:22:35 +01:00
Christian Bläul
4376cc8bd6 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-02 14:28:51 +01:00
Christian Bläul
5c157efbc3 output(): Use better mime type for \t separator.
Fixes #79
2018-02-02 13:49:57 +01:00
Christian Bläul
387a0f5761 Renamed class to follow the PHP community guidelines such as:
- https://svn.apache.org/repos/asf/shindig/attic/php/docs/style-guide.html:
  "Acryonyms are treated as normal words."

- https://softwareengineering.stackexchange.com/a/149321/80632
  Overview of class naming conventions of PHP frameworks

- https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-4-autoloader.md
  No .lib allowed: "The class name corresponds to a file name ending in .php"

See issue #50
2018-02-02 13:22:58 +01:00
Christian Bläul
7a9d55dd1e Prepared new release in ChangeLog.txt 2018-02-02 12:27:12 +01:00
Christian Bläul
979e9ed0cd Moved ConditionsTest to properties subfolder 2018-02-02 12:26:06 +01:00
Christian Bläul
adcd258ea2 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-02 12:22:23 +01:00
Christian Bläul
34d28f7435 PHPUnit: Repaired file paths in autoQuotesDataProvider() 2018-02-02 12:10:25 +01:00
Christian Bläul
5cdec32466 Test some conditions 2018-02-02 11:14:41 +01:00
49 changed files with 881 additions and 2761 deletions

View File

@@ -13,9 +13,3 @@ insert_final_newline = true
[composer.json] [composer.json]
indent_size = 4 indent_size = 4
[Makefile]
indent_style = tab
[*.yml,*.yaml]
indent_size = 2

9
.gitattributes vendored
View File

@@ -1,9 +0,0 @@
/.editorconfig export-ignore
/.gitattributes export-ignore
/.gitignore export-ignore
/.travis.yml export-ignore
/ChangeLog.txt export-ignore
/examples export-ignore
/Makefile export-ignore
/ruleset.xml export-ignore
/tests export-ignore

View File

@@ -1,38 +0,0 @@
---
name: CI
on:
push:
jobs:
test:
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
php_version:
- "7.4"
- "7.3"
- "7.2"
- "7.1"
steps:
- uses: actions/checkout@v2
- uses: shivammathur/setup-php@v2
with:
php-version: ${{ matrix.php_version }}
env:
COMPOSER_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Get composer cache directory
id: composer-cache
run: echo "::set-output name=dir::$(composer config cache-files-dir)"
- name: Cache composer dependencies
uses: actions/cache@v2
with:
path: ${{ steps.composer-cache.outputs.dir }}
key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }}
restore-keys: ${{ runner.os }}-composer-
- name: Install dependencies
run: composer update
- name: Validate dependencies
run: composer validate
- name: Run tests
run: vendor/bin/phpunit --configuration tests/phpunit.xml

5
.gitignore vendored
View File

@@ -1,7 +1,6 @@
*.bak *.bak
/.idea /.idea
/composer.lock
/coverage_clover.xml
/phive.xml /phive.xml
/tools /tools
/vendor/ composer.lock
vendor/

18
.travis.yml Normal file
View File

@@ -0,0 +1,18 @@
language: php
php:
- 7.2
- 7.1
- 7.0
- 5.6
- 5.5
- 5.4
script:
- phpunit --configuration tests/phpunit.xml
notifications:
email:
- will.knauss@gmail.com
on_success: never
on_failure: always

View File

@@ -1,415 +1,266 @@
ParseCSV 1.3.1 ParseCsvForPhp 1.0.0-rc.1
----------------------------------- -----------------------------------
Date: 20-Jun-2021 Date: unreleased
Bugfix: - Renamed class from parseCSV to ParseCsvForPhp
- `parseFile()` will now set `$csv->data`.
Until now, the parsed data was only returned. - Added support for MS Excel's "sep=" to detect the
This adds consistency with `$csv->parse()` delimiter (Issue #60).
for the following operations on the object.
- 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
ParseCSV 1.3.0 iconv() (Issue #109)
-----------------------------------
Date: 14-Apr-2021 - A number of minor bug fixes - see GitHub issues
Breaking changes: -----------------------------------
- Passing file paths to parse() or new Csv() is now deprecated
and will be removed in v2.0.0. Use ->parseFile() instead.
parseCSV 0.4.3 beta
WARNING: It will call trigger_error() for now. -----------------------------------
This may still break your application, depending on your Date: 1-July-2008
php.ini config. You can add E_USER_DEPRECATED to the
error_reporting mask to avoid breaking your application: - Issue #4. Added an option for setting sorting
type behavior when sorting data.
Example: Simply set $csv->sort_type to "regular", "numeric",
or "string".
error_reporting = E_ALL & ~E_DEPRECATED & ~E_STRICT & ~E_USER_DEPRECATED
- Issue #6. Raw loaded file data is now cleared from
This change is to avoid security issues: see issue #198. file_data property when it has been successfully
parsed to keep parseCSV's memory footprint to a
Non-breaking deprecations: minimum. Specifically handy when using multiple
- The function load_data() is deprecated. instances of parseCSV to process large files.
Call loadFile() or loadDataString() instead.
- Supplying CSV data (file content) to auto() is deprecated. -----------------------------------
Please use autoDetectionForDataString().
The motivation is to make subtle gotchas less likely: when the parseCSV 0.4.2 beta
file cannot be found or read by PHP (permissions), its file path -----------------------------------
would be treated like CSV data. Date: 31-May-2008
- Currently, there is code to parse .php: <?...?> tags are removed
before the remaining file content is treated like a .csv file. - IMPORTANT! If you're using the output(),
This rarely-used functionality will be removed in v2.0.0. method please note that the first parameter
You are only affected if you use ParseCsv to parse .php files. has been completely removed as it was
technically just useless. Instead, the second
New features: none parameter (filename) doubles as its replacement.
Bug fixes: none Simply put, if filename is not set or null, the
----------------------------------- output() method will not output a downloadable
file. Please update your existing code
when using 0.4.2 and later :)
ParseCSV 1.2.1
----------------------------------- - Small fix to the headers sent by the output()
Date: 25-Apr-2020 method.
Breaking changes: none - Added a download example using the output()
New features: none method to the examples folder.
Bug fixes: none
-----------------------------------
Code quality:
- Switched from PHPUnit 4 to 6 to get rid of
wrappers. This will reduce friction for PhpStorm users, parseCSV 0.4.1 beta
because it gets rid of the "Multiple definitions" error -----------------------------------
See issue #188. Thanks to @SharkMachine for the hint. Date: 29-May-2008
-----------------------------------
- Fixed a small bug in how the output() method
handles input data.
ParseCSV 1.2.0
----------------------------------- -----------------------------------
Date: 07-Jan-2020
Breaking changes: none parseCSV 0.4 beta
-----------------------------------
New features: Date: 11-Apr-2008
- Compatible with PHP 7.4. Thanks to @andreybolonin
@morrislaptop @martijnengler and @fjf2002. - Error reporting for files/data which is corrupt
- unparse() now also understands $use_mb_convert_encoding. or has formatting errors like using double
- Verbal condition operators are now allowed to contain quotes in a field without enclosing quotes. Or
upper case letters, for example: not escaping double quotes with a second one.
$csv->conditions = 'rating IS GREATER THAN 4';
- parse() method does not require input anymore
Bug fixes: if the "$object->file" property has been set.
- All filter condition operators containing "is" or "equals"
were broken. I'm calling this a beta release due to the heavy
modifications to the core parsing logic required
Code quality: for error reporting to work. I have tested the
- Improved test coverage. new code quite extensively, I'm fairly confident
----------------------------------- that it still parses exactly as it always has.
The second reason I'm calling it a beta release
ParseCSV 1.1.1 is cause I'm sure the error reporting code will
----------------------------------- need more refinements and tweaks to detect more
Date: 2-Feb-2019 types of errors, as it's only picking two types
or syntax errors right now. However, it seems
Breaking changes: none these two are the most common errors that you
would be likely to come across.
New features: none
-----------------------------------
Bug fixes:
- Function load_data: check length of input, prevents E_NOTICE
if too long. parseCSV 0.3.2
- Fixed bugs in unparse(). -----------------------------------
Date: 1-Apr-2008
Code quality:
- Improved test coverage. This is primarily a bug-fix release for a critical
----------------------------------- bug which was brought to my attention.
- Fixed a critical bug in conditions parsing which
ParseCSV 1.1.0 would generate corrupt matching patterns causing
----------------------------------- the condition(s) to not work at all in some
Date: 9-Aug-2018 situations.
Breaking changes: - Fixed a small code error which would cause PHP to
- Ignore entirely empty lines at the end of files generate a invalid offset notice when zero length
See https://github.com/parsecsv/parsecsv-for-php/pull/142 values were fed into the unparse() method to
- Dropped support for PHP 5.4. Now, you need at leas PHP 5.5. generate CSV data from an array.
- Fixed parse()'s return value: return true only if $data is useful.
Notice: If you have been using the "parsecsv-stable"
New features: branch as an external in any of your projects,
- Added support for Laravel-style collections via the please use the "stable/parsecsv" branch from this
new getCollection() function - see point on as I will eventually remove the former due
https://github.com/parsecsv/parsecsv-for-php/pull/134 to it's stupid naming.
- New function getTotalDataRowCount() - useful if
$limit is set - see pull request #122. -----------------------------------
- Added requires to keep Composer-free environments working.
Bug fixes: parseCSV 0.3.1
- Better support for streams. -----------------------------------
See https://github.com/parsecsv/parsecsv-for-php/pull/147 Date: 1-Sep-2007
- Fixed output() with custom header.
See https://github.com/parsecsv/parsecsv-for-php/issues/132 - Small change to default output settings to
- Fixed bug on _validate_fields_for_unparse() if titles property conform with RFC 4180 (http://rfc.net/rfc4180.html).
is used instead of fields parameter for changing the titles for Only the LF (line feed) character was used
unparsing. by default to separate rows, rather than
- Fixed bug in unparse() that caused incorrect column order CRLF (carriage return & line feed).
(Issue #41).
-----------------------------------
Code quality:
- Improved test coverage. parseCSV 0.3.0
----------------------------------- -----------------------------------
Date: 9-Aug-2007
ParseCSV 1.0.0 - Changed to the MIT license.
-----------------------------------
Date: 3-March-2018 - Added offset and limit options.
- Renamed class from parseCSV to Csv and added name- - Added SQL-like conditions for quickly
space "ParseCsv" for PSR compliance. filtering out entries. Documentation on the
condition syntax is forthcoming.
- Added support for MS Excel's "sep=" to detect the
delimiter (Issue #60). - Small parsing modification to comply
with some recent changes to the specifications
- Added data type detection - function getDatatypes() outlined on Wikipedia's Comma-separated values
guesses the type of each column. article.
- MIME: output() sends correct MIME type to browser - Minor changes and optimizations, and a few
if the separator is a tab char (Issue #79). spelling corrections. Oops :)
- Added support for mb_convert_encoding() instead of - Included more complex code examples in the
iconv() - see issue #109. parseCSV download.
- A number of minor bug fixes - see GitHub issues. -----------------------------------
- Added many more unit tests.
parseCSV 0.2.1
----------------------------------- -----------------------------------
Date: 8-Aug-2007
parseCSV 0.4.3 beta - Fixed stupid code which caused auto function
----------------------------------- to not work in some situations.
Date: 1-July-2008
-----------------------------------
- Issue #4. Added an option for setting sorting
type behavior when sorting data.
Simply set $csv->sort_type to "regular", "numeric", parseCSV 0.2.0 beta
or "string". -----------------------------------
Date: 2-Jan-2007
- Issue #6. Raw loaded file data is now cleared from
file_data property when it has been successfully - Added auto() function to automatically detect
parsed to keep parseCSV's memory footprint to a delimiter character.
minimum. Specifically handy when using multiple Useful for user upload in case delimiter is
instances of parseCSV to process large files. comma (,), tab, or semi-colon (;). Some
versions of MS Excel for Windows use
----------------------------------- semi-colons instead of commas when saving to
CSV files.
It uses a process of elimination to eliminate
parseCSV 0.4.2 beta characters that can not be the delimiter,
----------------------------------- so it should work on all CSV-structured files
Date: 31-May-2008 almost no matter what the delimiter is.
- IMPORTANT! If you're using the output(), - Generally updated some of the core workings
method please note that the first parameter to increase performance, and offer better
has been completely removed as it was support for large (1MB and up) files.
technically just useless. Instead, the second
parameter (filename) doubles as its replacement. - Added code examples to header comment.
Simply put, if filename is not set or null, the
output() method will not output a downloadable -----------------------------------
file. Please update your existing code
when using 0.4.2 and later :)
parseCSV 0.1.6 beta
- Small fix to the headers sent by the output() -----------------------------------
method. Date: 22-Dec-2006
- Added a download example using the output() - Updated output() function.
method to the examples folder.
-----------------------------------
-----------------------------------
parseCSV 0.1.5 beta
parseCSV 0.4.1 beta -----------------------------------
----------------------------------- Date: 22-Dec-2006
Date: 29-May-2008
- Added output() function for easy output to
- Fixed a small bug in how the output() method browser, for downloading features for example.
handles input data.
-----------------------------------
-----------------------------------
parseCSV 0.1.4 beta
parseCSV 0.4 beta -----------------------------------
----------------------------------- Date: 17-Dec-2006
Date: 11-Apr-2008
- Minor changes and fixes
- Error reporting for files/data which is corrupt
or has formatting errors like using double -----------------------------------
quotes in a field without enclosing quotes. Or
not escaping double quotes with a second one.
parseCSV 0.1.3 beta
- parse() method does not require input anymore -----------------------------------
if the "$object->file" property has been set. Date: 17-Dec-2006
I'm calling this a beta release due to the heavy - Added GPL v2.0 license.
modifications to the core parsing logic required
for error reporting to work. I have tested the -----------------------------------
new code quite extensively, I'm fairly confident
that it still parses exactly as it always has.
parseCSV 0.1.2 beta
The second reason I'm calling it a beta release -----------------------------------
is cause I'm sure the error reporting code will Date: 17-Dec-2006
need more refinements and tweaks to detect more
types of errors, as it's only picking two types - Added encoding() function for easier character
or syntax errors right now. However, it seems encoding configuration.
these two are the most common errors that you
would be likely to come across. -----------------------------------
-----------------------------------
parseCSV 0.1.1 beta
-----------------------------------
parseCSV 0.3.2 Date: 24-Nov-2006
-----------------------------------
Date: 1-Apr-2008 - Added support for a PHP die command on first
line of csv files if they have a .php extension
This is primarily a bug-fix release for a critical to protect secure data from being displayed
bug which was brought to my attention. directly to the browser.
- Fixed a critical bug in conditions parsing which -----------------------------------
would generate corrupt matching patterns causing
the condition(s) to not work at all in some
situations. parseCSV 0.1 beta
-----------------------------------
- Fixed a small code error which would cause PHP to Date: 23-Nov-2006
generate a invalid offset notice when zero length
values were fed into the unparse() method to - Initial release
generate CSV data from an array.
-----------------------------------
Notice: If you have been using the "parsecsv-stable"
branch as an external in any of your projects,
please use the "stable/parsecsv" branch from this
point on as I will eventually remove the former due
to it's stupid naming.
-----------------------------------
parseCSV 0.3.1
-----------------------------------
Date: 1-Sep-2007
- Small change to default output settings to
conform with RFC 4180 (http://rfc.net/rfc4180.html).
Only the LF (line feed) character was used
by default to separate rows, rather than
CRLF (carriage return & line feed).
-----------------------------------
parseCSV 0.3.0
-----------------------------------
Date: 9-Aug-2007
- Changed to the MIT license.
- Added offset and limit options.
- Added SQL-like conditions for quickly
filtering out entries. Documentation on the
condition syntax is forthcoming.
- Small parsing modification to comply
with some recent changes to the specifications
outlined on Wikipedia's Comma-separated values
article.
- Minor changes and optimizations, and a few
spelling corrections. Oops :)
- Included more complex code examples in the
parseCSV download.
-----------------------------------
parseCSV 0.2.1
-----------------------------------
Date: 8-Aug-2007
- Fixed stupid code which caused auto function
to not work in some situations.
-----------------------------------
parseCSV 0.2.0 beta
-----------------------------------
Date: 2-Jan-2007
- Added auto() function to automatically detect
delimiter character.
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
CSV files.
It uses a process of elimination to eliminate
characters that can not be the delimiter,
so it should work on all CSV-structured files
almost no matter what the delimiter is.
- Generally updated some of the core workings
to increase performance, and offer better
support for large (1MB and up) files.
- Added code examples to header comment.
-----------------------------------
parseCSV 0.1.6 beta
-----------------------------------
Date: 22-Dec-2006
- Updated output() function.
-----------------------------------
parseCSV 0.1.5 beta
-----------------------------------
Date: 22-Dec-2006
- Added output() function for easy output to
browser, for downloading features for example.
-----------------------------------
parseCSV 0.1.4 beta
-----------------------------------
Date: 17-Dec-2006
- Minor changes and fixes
-----------------------------------
parseCSV 0.1.3 beta
-----------------------------------
Date: 17-Dec-2006
- Added GPL v2.0 license.
-----------------------------------
parseCSV 0.1.2 beta
-----------------------------------
Date: 17-Dec-2006
- Added encoding() function for easier character
encoding configuration.
-----------------------------------
parseCSV 0.1.1 beta
-----------------------------------
Date: 24-Nov-2006
- Added support for a PHP die command on first
line of csv files if they have a .php extension
to protect secure data from being displayed
directly to the browser.
-----------------------------------
parseCSV 0.1 beta
-----------------------------------
Date: 23-Nov-2006
- Initial release
-----------------------------------

View File

@@ -11,21 +11,5 @@ phpunit-dep:
exit 1 \ exit 1 \
) )
# Requires:
# - Docker: https://docker.com
# - act: https://github.com/nektos/act
local-ci:
ifeq (, $(shell which act))
define ACT_ERROR
Consider running the following to install 'act':
curl https://raw.githubusercontent.com/nektos/act/master/install.sh | sudo bash
The dependency 'act' was not found
endef
$(error ${ACT_ERROR})
endif
act -P ubuntu-latest=shivammathur/node:latest -W .github/workflows/ci.yml
.SILENT: .SILENT:
.PHONY: test phpunit-dep local-ci .PHONY: test phpunit-dep

File diff suppressed because it is too large Load Diff

183
README.md
View File

@@ -1,21 +1,30 @@
# ParseCsv # ParseCsvForPhp
[![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 This 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
[Wikipedia article][CSV] (and thus RFC 4180). It has many advanced features which help make your [Wikipedia article][CSV] (and thus RFC 4180). It has many advanced features which help make your
life easier when dealing with CSV data. 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()`, ``fgetcsv()`` or `fputcsv()` meets your needs. You may not need a library at all: before using ParseCsvForPhp, 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 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. and third-party support for handling CSV data in PHP.
[csv]: http://en.wikipedia.org/wiki/Comma-separated_values [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": "1.0.0"
```
You may also manually include the ParseCsvForPhp.php file
```php
require_once 'ParseCsvForPhp.php';
```
## Features ## Features
* ParseCsv is a complete and fully featured CSV solution for PHP
* Supports enclosed values, enclosed commas, double quotes and new lines. * Supports enclosed values, enclosed commas, double quotes and new lines.
* Automatic delimiter character detection. * Automatic delimiter character detection.
* Sort data by specific fields/columns. * Sort data by specific fields/columns.
@@ -25,112 +34,56 @@ and third-party support for handling CSV data in PHP.
* Error detection for incorrectly formatted input. It attempts to be * Error detection for incorrectly formatted input. It attempts to be
intelligent, but can not be trusted 100% due to the structure of CSV, and intelligent, but can not be trusted 100% due to the structure of CSV, and
how different programs like Excel for example outputs CSV data. how different programs like Excel for example outputs CSV data.
* Support for character encoding conversion using PHP's * Support for character encoding conversion using PHP's
`iconv()` and `mb_convert_encoding()` functions. `iconv()` and `mb_convert_encoding()` functions (requires PHP 5).
* Supports PHP 5.5 and higher. * Supports PHP 5.4 and higher.
It certainly works with PHP 7.2 and all versions in between. 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 ## Example Usage
**Parse a tab-delimited CSV file with encoding conversion** **General**
```php ```php
$csv = new \ParseCsv\Csv(); $csv = new ParseCsvForPhp('data.csv');
$csv->encoding('UTF-16', 'UTF-8');
$csv->delimiter = "\t";
$csv->parseFile('data.tsv');
print_r($csv->data); print_r($csv->data);
``` ```
**Auto-detect field delimiter character** **Tab delimited, and encoding conversion**
```php ```php
$csv = new \ParseCsv\Csv(); $csv = new ParseCsvForPhp();
$csv->encoding('UTF-16', 'UTF-8');
$csv->delimiter = "\t";
$csv->parse('data.tsv');
print_r($csv->data);
```
**Auto-detect delimiter character**
```php
$csv = new ParseCsvForPhp();
$csv->auto('data.csv'); $csv->auto('data.csv');
print_r($csv->data); print_r($csv->data);
``` ```
**Parse data with offset**
* ignoring the first X (e.g. two) rows
```php
$csv = new \ParseCsv\Csv();
$csv->offset = 2;
$csv->parseFile('data.csv');
print_r($csv->data);
```
**Limit the number of returned data rows**
```php
$csv = new \ParseCsv\Csv();
$csv->limit = 5;
$csv->parseFile('data.csv');
print_r($csv->data);
```
**Get total number of data rows without parsing whole data**
* Excluding heading line if present (see $csv->header property)
```php
$csv = new \ParseCsv\Csv();
$csv->loadFile('data.csv');
$count = $csv->getTotalDataRowCount();
print_r($count);
```
**Get most common data type for each column**
```php
$csv = new \ParseCsv\Csv('data.csv');
$csv->getDatatypes();
print_r($csv->data_types);
```
**Modify data in a CSV file** **Modify data in a CSV file**
Change data values:
```php ```php
$csv = new \ParseCsv\Csv(); $csv = new ParseCsvForPhp();
$csv->sort_by = 'id'; $csv->sort_by = 'id';
$csv->parseFile('data.csv'); $csv->parse('data.csv');
# "4" is the value of the "id" column of the CSV row # "4" is the value of the "id" column of the CSV row
$csv->data[4] = array('firstname' => 'John', 'lastname' => 'Doe', 'email' => 'john@doe.com'); $csv->data[4] = array('firstname' => 'John', 'lastname' => 'Doe', 'email' => 'john@doe.com');
$csv->save(); $csv->save();
``` ```
Enclose each data value by quotes:
```php
$csv = new \ParseCsv\Csv();
$csv->parseFile('data.csv');
$csv->enclose_all = true;
$csv->save();
```
**Replace field names or set ones if missing** **Replace field names or set ones if missing**
```php ```php
$csv = new \ParseCsv\Csv(); $csv = new ParseCsvForPhp();
$csv->fields = ['id', 'name', 'category']; $csv->fields = ['id', 'name', 'category']
$csv->parseFile('data.csv'); $csv->parse('data.csv');
``` ```
**Add row/entry to end of CSV file** **Add row/entry to end of CSV file**
@@ -138,47 +91,23 @@ $csv->parseFile('data.csv');
_Only recommended when you know the exact structure of the file._ _Only recommended when you know the exact structure of the file._
```php ```php
$csv = new \ParseCsv\Csv(); $csv = new ParseCsvForPhp();
$csv->save('data.csv', array(array('1986', 'Home', 'Nowhere', '')), /* append */ true); $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** a file and download it**
Your web app users would call this an export.
```php ```php
$csv = new \ParseCsv\Csv(); $csv = new ParseCsvForPhp();
$csv->linefeed = "\n"; $csv->output('movies.csv', $array, array('field 1', 'field 2'), ',');
$header = array('field 1', 'field 2');
$csv->output('movies.csv', $data_array, $header, ',');
``` ```
For more complex examples, see the ``tests`` and `examples` directories. For more complex examples, see the ``tests`` and `examples` directories.
## Test coverage
All tests are located in the `tests` directory. To execute tests, run the following commands:
````bash
composer install
composer run test
````
When pushing code to GitHub, tests will be executed using GitHub Actions. The relevant configuration is in the
file `.github/workflows/ci.yml`. To run the `test` action locally, you can execute the following command:
````bash
make local-ci
````
## Security
If you discover any security related issues, please email ParseCsv@blaeul.de instead of using GitHub issues.
## Credits ## Credits
* ParseCsv is based on the concept of [Ming Hong Ng][ming]'s [CsvFileParser][] * ParseCsvForPhp is based on the concept of [Ming Hong Ng][ming]'s [CsvFileParser][]
class. class.
[ming]: http://minghong.blogspot.com/ [ming]: http://minghong.blogspot.com/
@@ -187,37 +116,11 @@ If you discover any security related issues, please email ParseCsv@blaeul.de ins
## 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
<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
Become a financial contributor and help us sustain our community. [[Contribute](https://opencollective.com/parsecsv/contribute)]
#### Individuals
<a href="https://opencollective.com/parsecsv"><img src="https://opencollective.com/parsecsv/individuals.svg?width=890"></a>
#### Organizations
Support this project with your organization. Your logo will show up here with a link to your website. [[Contribute](https://opencollective.com/parsecsv/contribute)]
<a href="https://opencollective.com/parsecsv/organization/0/website"><img src="https://opencollective.com/parsecsv/organization/0/avatar.svg"></a>
<a href="https://opencollective.com/parsecsv/organization/1/website"><img src="https://opencollective.com/parsecsv/organization/1/avatar.svg"></a>
<a href="https://opencollective.com/parsecsv/organization/2/website"><img src="https://opencollective.com/parsecsv/organization/2/avatar.svg"></a>
<a href="https://opencollective.com/parsecsv/organization/3/website"><img src="https://opencollective.com/parsecsv/organization/3/avatar.svg"></a>
<a href="https://opencollective.com/parsecsv/organization/4/website"><img src="https://opencollective.com/parsecsv/organization/4/avatar.svg"></a>
<a href="https://opencollective.com/parsecsv/organization/5/website"><img src="https://opencollective.com/parsecsv/organization/5/avatar.svg"></a>
<a href="https://opencollective.com/parsecsv/organization/6/website"><img src="https://opencollective.com/parsecsv/organization/6/avatar.svg"></a>
<a href="https://opencollective.com/parsecsv/organization/7/website"><img src="https://opencollective.com/parsecsv/organization/7/avatar.svg"></a>
<a href="https://opencollective.com/parsecsv/organization/8/website"><img src="https://opencollective.com/parsecsv/organization/8/avatar.svg"></a>
<a href="https://opencollective.com/parsecsv/organization/9/website"><img src="https://opencollective.com/parsecsv/organization/9/avatar.svg"></a>
## License ## License
@@ -242,5 +145,3 @@ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 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 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE. SOFTWARE.
[![Build Status](https://travis-ci.org/parsecsv/parsecsv-for-php.svg?branch=master)](https://travis-ci.org/parsecsv/parsecsv-for-php)

View File

@@ -10,48 +10,14 @@
{ {
"name": "William Knauss", "name": "William Knauss",
"email": "will.knauss@gmail.com" "email": "will.knauss@gmail.com"
},
{
"name": "Susann Sgorzaly",
"homepage": "https://github.com/susgo"
},
{
"name": "Christian Bläul",
"homepage": "https://github.com/Fonata"
} }
], ],
"autoload": { "autoload": {
"psr-4": { "classmap": [
"ParseCsv\\": "src" "."
}
},
"autoload-dev": {
"psr-4": {
"ParseCsv\\tests\\": "tests"
}
},
"require": {
"php": ">=5.5"
},
"require-dev": {
"phpunit/phpunit": "^6",
"squizlabs/php_codesniffer": "^3.5"
},
"suggest": {
"illuminate/support": "Fluent array interface for map functions"
},
"extra": {
"branch-alias": {
"dev-master": "1.0.x-dev"
}
},
"scripts": {
"test": [
"vendor/bin/phpunit -c tests tests --disallow-test-output --coverage-clover coverage_clover.xml --whitelist src"
] ]
}, },
"support": { "require-dev": {
"issues": "https://github.com/parsecsv/parsecsv-for-php/issues", "phpunit/phpunit": "4.1.*"
"source": "https://github.com/parsecsv/parsecsv-for-php"
} }
} }

View File

@@ -1,14 +1,13 @@
<pre> <pre>
<?php <?php
# include parseCSV class.
require __DIR__ . '/../vendor/autoload.php';
use ParseCsv\Csv; # include ParseCsvForPhp class.
require_once('../ParseCsvForPhp.php');
# create new parseCSV object. # create new object.
$csv = new Csv(); $csv = new ParseCsvForPhp();
# Parse '_books.csv' using automatic delimiter detection... # Parse '_books.csv' using automatic delimiter detection...
@@ -18,8 +17,8 @@ $csv->auto('_books.csv');
# if its not the default comma... # if its not the default comma...
// $csv->delimiter = "\t"; # tab delimited // $csv->delimiter = "\t"; # tab delimited
# ...and then use the parseFile() function. # ...and then use the parse() function.
// $csv->parseFile('_books.csv'); // $csv->parse('_books.csv');
# Output result. # Output result.
@@ -41,7 +40,7 @@ $csv->auto('_books.csv');
background-color: #FFF; background-color: #FFF;
} }
</style> </style>
<table> <table border="0" cellspacing="1" cellpadding="3">
<tr> <tr>
<?php foreach ($csv->titles as $value): ?> <?php foreach ($csv->titles as $value): ?>
<th><?php echo $value; ?></th> <th><?php echo $value; ?></th>

View File

@@ -2,14 +2,12 @@
<?php <?php
# include parseCSV class. # include ParseCsvForPhp class.
require __DIR__ . '/../vendor/autoload.php'; require_once('../ParseCsvForPhp.php');
use ParseCsv\Csv;
# create new parseCSV object. # create new object.
$csv = new Csv(); $csv = new ParseCsvForPhp();
# Example conditions: # Example conditions:
@@ -17,7 +15,6 @@ $csv = new Csv();
$csv->conditions = 'author does not contain dan brown'; $csv->conditions = 'author does not contain dan brown';
// $csv->conditions = 'rating < 4 OR author is John Twelve Hawks'; // $csv->conditions = 'rating < 4 OR author is John Twelve Hawks';
// $csv->conditions = 'rating > 4 AND author is Dan Brown'; // $csv->conditions = 'rating > 4 AND author is Dan Brown';
// $csv->conditions = 'rating is greater than 4';
# Parse '_books.csv' using automatic delimiter detection. # Parse '_books.csv' using automatic delimiter detection.
@@ -43,7 +40,7 @@ $csv->auto('_books.csv');
background-color: #FFF; background-color: #FFF;
} }
</style> </style>
<table> <table border="0" cellspacing="1" cellpadding="3">
<tr> <tr>
<?php foreach ($csv->titles as $value): ?> <?php foreach ($csv->titles as $value): ?>
<th><?php echo $value; ?></th> <th><?php echo $value; ?></th>

View File

@@ -1,14 +1,12 @@
<?php <?php
# include parseCSV class. # include ParseCsvForPhp class.
require __DIR__ . '/../vendor/autoload.php'; require_once('../ParseCsvForPhp.php');
use ParseCsv\Csv;
# create new parseCSV object. # create new object.
$csv = new Csv(); $csv = new ParseCsvForPhp();
# Parse '_books.csv' using automatic delimiter detection... # Parse '_books.csv' using automatic delimiter detection...
@@ -32,3 +30,5 @@ $csv->output('books.csv');
# data to download the output as a CSV file. if it's not set # data to download the output as a CSV file. if it's not set
# or is set to null, output will only return the generated CSV # or is set to null, output will only return the generated CSV
# output data, and will not output to the browser itself. # output data, and will not output to the browser itself.
?>

View File

@@ -2,14 +2,12 @@
<?php <?php
# include parseCSV class. # include class.
require __DIR__ . '/../vendor/autoload.php'; require_once('../ParseCsvForPhp.php');
use ParseCsv\Csv;
# create new parseCSV object. # create new object.
$csv = new Csv(); $csv = new ParseCsvForPhp();
# if sorting is enabled, the whole CSV file # if sorting is enabled, the whole CSV file
@@ -55,7 +53,7 @@ $csv->auto('_books.csv');
background-color: #FFF; background-color: #FFF;
} }
</style> </style>
<table> <table border="0" cellspacing="1" cellpadding="3">
<tr> <tr>
<?php foreach ($csv->titles as $value): ?> <?php foreach ($csv->titles as $value): ?>
<th><?php echo $value; ?></th> <th><?php echo $value; ?></th>

View File

@@ -1,27 +0,0 @@
<?php
# include parseCSV class.
require __DIR__ . '/../vendor/autoload.php';
use ParseCsv\Csv;
# Create new parseCSV object.
$csv = new Csv();
# When saving, don't write the header row:
$csv->heading = false;
# Specify which columns to write, and in which order.
# We won't output the 'Awesome' column this time.
$csv->titles = ['Age', 'Name'];
# Data to write:
$csv->data = [
0 => ['Name' => 'Anne', 'Age' => 45, 'Awesome' => true],
1 => ['Name' => 'John', 'Age' => 44, 'Awesome' => false],
];
# Then we save the file to the file system:
$csv->save('people.csv');

View File

@@ -1,24 +0,0 @@
<?php
// This file should not be used at all! Instead, please use Composer's autoload.
// It purely exists to reduce the maintenance burden for existing code using
// this repository.
// Check if people used Composer to include this project in theirs
if (!file_exists(__DIR__ . '/vendor/autoload.php')) {
require __DIR__ . '/src/enums/AbstractEnum.php';
require __DIR__ . '/src/enums/DatatypeEnum.php';
require __DIR__ . '/src/enums/FileProcessingModeEnum.php';
require __DIR__ . '/src/enums/SortEnum.php';
require __DIR__ . '/src/extensions/DatatypeTrait.php';
require __DIR__ . '/src/Csv.php';
} else {
require __DIR__ . '/vendor/autoload.php';
}
// This wrapper class should not be used by new projects. Please look at the
// examples to find the up-to-date way of using this repo.
class parseCSV extends ParseCsv\Csv {
}

View File

@@ -1,3 +0,0 @@
<?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

@@ -1,38 +0,0 @@
<?php
namespace ParseCsv\enums;
abstract class AbstractEnum {
/**
* Creates a new value of some type
*
* @param mixed $value
*
* @throws \UnexpectedValueException if incompatible type is given.
*/
public function __construct($value) {
if (!$this->isValid($value)) {
throw new \UnexpectedValueException("Value '$value' is not part of the enum " . get_called_class());
}
$this->value = $value;
}
public static function getConstants() {
$class = get_called_class();
$reflection = new \ReflectionClass($class);
return $reflection->getConstants();
}
/**
* Check if enum value is valid
*
* @param $value
*
* @return bool
*/
public static function isValid($value) {
return in_array($value, static::getConstants(), true);
}
}

View File

@@ -1,120 +0,0 @@
<?php
namespace ParseCsv\enums;
/**
* Class DatatypeEnum
*
* @package ParseCsv\enums
*
* todo: needs a basic parent enum class for error handling.
*/
class DatatypeEnum extends AbstractEnum {
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

@@ -1,28 +0,0 @@
<?php
namespace ParseCsv\enums;
/**
* Class FileProcessingEnum
*
* @package ParseCsv\enums
*
* todo extends a basic enum class after merging #121
*/
class FileProcessingModeEnum {
const __default = self::MODE_FILE_OVERWRITE;
const MODE_FILE_APPEND = true;
const MODE_FILE_OVERWRITE = false;
public static function getAppendMode($mode) {
if ($mode == self::MODE_FILE_APPEND) {
return 'ab';
}
return 'wb';
}
}

View File

@@ -1,29 +0,0 @@
<?php
namespace ParseCsv\enums;
class SortEnum extends AbstractEnum {
const __DEFAULT = self::SORT_TYPE_REGULAR;
const SORT_TYPE_REGULAR = 'regular';
const SORT_TYPE_NUMERIC = 'numeric';
const SORT_TYPE_STRING = 'string';
private static $sorting = array(
self::SORT_TYPE_REGULAR => SORT_REGULAR,
self::SORT_TYPE_STRING => SORT_STRING,
self::SORT_TYPE_NUMERIC => SORT_NUMERIC,
);
public static function getSorting($type) {
if (array_key_exists($type, self::$sorting)) {
return self::$sorting[$type];
}
return self::$sorting[self::__DEFAULT];
}
}

View File

@@ -1,102 +0,0 @@
<?php
namespace ParseCsv\extensions;
use ParseCsv\enums\DatatypeEnum;
trait DatatypeTrait {
/**
* Data Types
* Data types of CSV data-columns, keyed by the column name. Possible values
* are string, float, integer, boolean, date. See DatatypeEnum.
*
* @var array
*/
public $data_types = [];
/**
* Check data type for one column.
* Check for most commonly data type for one column.
*
* @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
*
* @uses DatatypeEnum::getValidTypeFromSample
*
* @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(DatatypeEnum::class . '::getValidTypeFromSample', $column);
$result[$cName] = $this->getMostFrequentDatatypeForColumn($cDatatypes);
}
$this->data_types = $result;
return !empty($this->data_types) ? $this->data_types : [];
}
/**
* Check data type of titles / first row for auto detecting if this could be
* a heading line.
*
* Requires PHP >= 5.5
*
* @uses DatatypeEnum::getValidTypeFromSample
*
* @return bool
*/
public function autoDetectFileHasHeading() {
if (empty($this->data)) {
throw new \UnexpectedValueException('No data set yet.');
}
if ($this->heading) {
$firstRow = $this->titles;
} else {
$firstRow = $this->data[0];
}
$firstRow = array_filter($firstRow);
if (empty($firstRow)) {
return false;
}
$firstRowDatatype = array_map(DatatypeEnum::class . '::getValidTypeFromSample', $firstRow);
return $this->getMostFrequentDatatypeForColumn($firstRowDatatype) === DatatypeEnum::TYPE_STRING;
}
}

View File

@@ -1,8 +1,13 @@
<?php <?php
chdir(__DIR__ . '/..'); $dir = realpath(__DIR__);
if (!file_exists('vendor/autoload.php')) { defined('BASE') OR define('BASE', dirname($dir) . '/');
`composer dump-autoload`;
require_once BASE . 'ParseCsvForPhp.php';
if (!class_exists('PHPUnit\Framework\TestCase')) {
// we run on an older PHPUnit version without namespaces.
require_once __DIR__ . '/PHPUnit_Framework_TestCase.inc.php';
} }
require __DIR__ . '/../vendor/autoload.php'; require_once BASE . 'tests/properties/BaseClass.php';

View File

@@ -0,0 +1,11 @@
<?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

@@ -1,22 +0,0 @@
ID,dID,createdAt,else1,else2,else3,else4,else5,user,else6,else7,else8,else9,else10,else11,else12,else13,else14,else15,else16,else17,else18,else19,else20,else21,else22,else23,else24,else25,else26,else27,else28,else29,else30,else31,else32,else33,else34,else35,else36,else37,else38
418,0,2017-05-16,,,2018-01-22,22.01.2018 10:00:09,,admin,Ja,,10001,Abweichung,,10001,v1,1,ddd,100,1000,,HH,,v1,0,401,1,2,H1,,-1,10,1,111,Ja,2017-01-01,,12,0,11109,HH-100,default
419,0,2017-05-16,,,2017-05-16,14.07.2017 09:58:09,,admin,Ja,,,Abweichung,,10002,v2,1,ddd,200,500,DD,DD,,v2,1,402,2,4,H2,,-2,100,1,1111,Ja,2017-01-01,1,13,1,11109,DD-200,default
438,0,2017-05-16,,,2017-05-16,14.07.2017 09:58:29,,admin,Ja,,10021,Abweichung,,10021,v3,4,ddd,300,400,DD,DD,,v3,0,421,1,,H3,,-1,106,1,111,Ja,2017-05-08,,2,1,11109,DD-300,default
440,0,2017-05-16,,,,14.07.2017 09:58:53,,admin,Ja,,,Alt,,10023,v4,3,,400,500,BE,DD,,v4,1,423,3,,H4,,-3,143,1,1111,Ja,2017-01-01,1,33,1,11108,BE-400,default
441,0,2017-05-16,,,,14.07.2017 09:59:19,,admin,Ja,,,Fehlt,,10024,v5,3,,500,,BE,,,v5,2,424,4,,H5,,0,1435,0,111,Ja,2017-01-01,,12,1,0,BE-500,default
442,0,2017-05-16,,,,14.07.2017 10:00:46,,admin,Ja,,,Neu,,10025,v6,3,,100,,DD,,,v6,435,425,1,,H6,,0,10,0,1111,Ja,2017-01-01,,102,1,0,DD-100,default
443,0,2017-05-16,,,2017-07-04,14.07.2017 10:01:12,,admin,Ja,,,OK,,10026,v7,3,,200,200,DD,DD,,v7,32,426,2,2,H7,,0,100,0,111,Ja,2017-01-01,,77,1,0,DD-200,default
444,0,2017-05-16,,,,14.07.2017 10:02:13,,admin,Ja,,,Fehlt,,10027,v8,3,,300,,BE,,,v8,45,427,3,,H8,,0,200,0,1111,Ja,2017-01-01,,44,3,0,BE-300,default
445,0,2017-05-16,,,,14.07.2017 10:02:38,,admin,Ja,,,Fehlt,,10028,v9,3,,100,,BE,,,v9,45,428,4,,H9,,0,400,0,111,Ja,2017-01-01,,44,1,0,BE-100,default
446,0,2017-05-16,,,,14.07.2017 10:03:01,,admin,Ja,,,Fehlt,,10029,v10,3,,,400,,DD,,v10,45,429,,,H10,,0,1124,0,1111,Ja,2017-01-01,,89,1,0,,default
1 ID dID createdAt else1 else2 else3 else4 else5 user else6 else7 else8 else9 else10 else11 else12 else13 else14 else15 else16 else17 else18 else19 else20 else21 else22 else23 else24 else25 else26 else27 else28 else29 else30 else31 else32 else33 else34 else35 else36 else37 else38
2 418 0 2017-05-16 2018-01-22 22.01.2018 10:00:09 admin Ja 10001 Abweichung 10001 v1 1 ddd 100 1000 HH v1 0 401 1 2 H1 -1 10 1 111 Ja 2017-01-01 12 0 11109 HH-100 default
3 419 0 2017-05-16 2017-05-16 14.07.2017 09:58:09 admin Ja Abweichung 10002 v2 1 ddd 200 500 DD DD v2 1 402 2 4 H2 -2 100 1 1111 Ja 2017-01-01 1 13 1 11109 DD-200 default
4 438 0 2017-05-16 2017-05-16 14.07.2017 09:58:29 admin Ja 10021 Abweichung 10021 v3 4 ddd 300 400 DD DD v3 0 421 1 H3 -1 106 1 111 Ja 2017-05-08 2 1 11109 DD-300 default
5 440 0 2017-05-16 14.07.2017 09:58:53 admin Ja Alt 10023 v4 3 400 500 BE DD v4 1 423 3 H4 -3 143 1 1111 Ja 2017-01-01 1 33 1 11108 BE-400 default
6 441 0 2017-05-16 14.07.2017 09:59:19 admin Ja Fehlt 10024 v5 3 500 BE v5 2 424 4 H5 0 1435 0 111 Ja 2017-01-01 12 1 0 BE-500 default
7 442 0 2017-05-16 14.07.2017 10:00:46 admin Ja Neu 10025 v6 3 100 DD v6 435 425 1 H6 0 10 0 1111 Ja 2017-01-01 102 1 0 DD-100 default
8 443 0 2017-05-16 2017-07-04 14.07.2017 10:01:12 admin Ja OK 10026 v7 3 200 200 DD DD v7 32 426 2 2 H7 0 100 0 111 Ja 2017-01-01 77 1 0 DD-200 default
9 444 0 2017-05-16 14.07.2017 10:02:13 admin Ja Fehlt 10027 v8 3 300 BE v8 45 427 3 H8 0 200 0 1111 Ja 2017-01-01 44 3 0 BE-300 default
10 445 0 2017-05-16 14.07.2017 10:02:38 admin Ja Fehlt 10028 v9 3 100 BE v9 45 428 4 H9 0 400 0 111 Ja 2017-01-01 44 1 0 BE-100 default
11 446 0 2017-05-16 14.07.2017 10:03:01 admin Ja Fehlt 10029 v10 3 400 DD v10 45 429 H10 0 1124 0 1111 Ja 2017-01-01 89 1 0 default

View File

@@ -1 +0,0 @@
C1,C2,C3
1 C1 C2 C3

View File

@@ -1,6 +0,0 @@
keyword
liability waiver
release of liability form
release of liability
sample waiver
sample waiver form
1 keyword
2 liability waiver
3 release of liability form
4 release of liability
5 sample waiver
6 sample waiver form

View File

@@ -1,70 +1,45 @@
<?php <?php
namespace ParseCsv\tests\methods; class ConstructTest extends PHPUnit\Framework\TestCase {
use ParseCsv\Csv;
use PHPUnit\Framework\TestCase;
class ConstructTest extends TestCase {
/** /**
* @var Csv object * @access protected
* @var ParseCsvForPhp object
*/ */
protected $csv = null; protected $csv = null;
public function test_offset_param() { public function test_offset_param() {
$offset = 10; $offset = 10;
$this->csv = new Csv(null, $offset); $this->csv = new ParseCsvForPhp(null, $offset);
$this->assertTrue(is_numeric($this->csv->offset)); $this->assertTrue(is_numeric($this->csv->offset));
$this->assertEquals($offset, $this->csv->offset); $this->assertEquals($offset, $this->csv->offset);
} }
public function test_limit_param() { public function test_limit_param() {
$limit = 10; $limit = 10;
$this->csv = new Csv(null, null, $limit); $this->csv = new ParseCsvForPhp(null, null, $limit);
$this->assertTrue(is_numeric($this->csv->limit)); $this->assertTrue(is_numeric($this->csv->limit));
$this->assertEquals($limit, $this->csv->limit); $this->assertEquals($limit, $this->csv->limit);
} }
public function test_conditions_param() { public function test_conditions_param() {
$conditions = 'some column NOT value'; $conditions = 'some column NOT value';
$this->csv = new Csv(null, null, null, $conditions); $this->csv = new ParseCsvForPhp(null, null, null, $conditions);
$this->assertTrue(is_string($this->csv->conditions)); $this->assertTrue(is_string($this->csv->conditions));
$this->assertEquals($conditions, $this->csv->conditions); $this->assertEquals($conditions, $this->csv->conditions);
} }
public function test_keep_file_data_param() { public function test_keep_file_data_param() {
$keep = true; $keep = true;
$this->csv = new Csv(null, null, null, null, $keep); $this->csv = new ParseCsvForPhp(null, null, null, null, $keep);
$this->assertTrue(is_bool($this->csv->keep_file_data)); $this->assertTrue(is_bool($this->csv->keep_file_data));
$this->assertEquals($keep, $this->csv->keep_file_data); $this->assertEquals($keep, $this->csv->keep_file_data);
} }
public function test_input_param() { public function test_input_param() {
$csv = "col1,col2,col3\r\nval1,val2,val3\r\nval1A,val2A,val3A\r\n"; $csv = "col1,col2,col3\r\nval1,val2,val3\r\nval1A,val2A,val3A\r\n";
$this->csv = new Csv($csv, null, null, null, true); $this->csv = new ParseCsvForPhp($csv, null, null, null, true);
$this->assertTrue(is_string($this->csv->file_data)); $this->assertTrue(is_string($this->csv->file_data));
$this->assertEquals($csv, $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;
$ob_get_clean = ob_get_clean();
$verb = strtok($script_file, '_.');
if (!in_array($verb, ['download', 'save'], true)) {
$this->assertContains('<td>', $ob_get_clean);
}
}
chdir('..');
}
} }

View File

@@ -1,80 +0,0 @@
<?php
namespace ParseCsv\tests\methods;
use ParseCsv\Csv;
use PHPUnit\Framework\TestCase;
class DataRowCountTest extends TestCase {
/**
* CSV
* The CSV object
*
* @access protected
* @var Csv
*/
protected $csv;
protected function setUp(): void {
$this->csv = new Csv();
}
public function countRowsProvider() {
return [
'auto-double-enclosure' => [
'auto-double-enclosure.csv',
2,
],
'auto-single-enclosure' => [
'auto-single-enclosure.csv',
2,
],
'UTF-8_sep_row' => [
'datatype.csv',
3,
],
];
}
/**
* @dataProvider countRowsProvider
*
* @param string $file
* @param int $expectedRows
*/
public function testGetTotalRowCountFromFile($file, $expectedRows) {
$this->csv->heading = true;
$this->csv->load_data(__DIR__ . '/fixtures/' . $file);
self::assertEquals($expectedRows, $this->csv->getTotalDataRowCount());
}
public function testGetTotalRowCountMissingEndingLineBreak() {
$this->csv->heading = false;
$this->csv->enclosure = '"';
$sInput = "86545235689,a\r\n34365587654,b\r\n13469874576,\"c\r\nd\"";
$this->csv->loadDataString($sInput);
self::assertEquals(3, $this->csv->getTotalDataRowCount());
}
public function testGetTotalRowCountSingleEnclosure() {
$this->csv->heading = false;
$this->csv->enclosure = "'";
$sInput = "86545235689,a\r\n34365587654,b\r\n13469874576,\'c\r\nd\'";
$this->csv->loadDataString($sInput);
$this->assertEquals(3, $this->csv->getTotalDataRowCount());
}
public function testGetTotalRowCountSingleRow() {
$this->csv->heading = false;
$this->csv->enclosure = "'";
$sInput = "86545235689";
$this->csv->loadDataString($sInput);
$this->assertEquals(1, $this->csv->getTotalDataRowCount());
}
public function testGetTotalRowCountNoData() {
self::assertFalse($this->csv->getTotalDataRowCount());
}
}

View File

@@ -1,69 +0,0 @@
<?php
/**
* Created by PhpStorm.
* User: sgorzaly
* Date: 19.02.18
* Time: 20:52
*/
namespace ParseCsv\tests\methods;
use ParseCsv\enums\DatatypeEnum;
use PHPUnit\Framework\TestCase;
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

@@ -1,100 +0,0 @@
<?php
namespace ParseCsv\tests\methods;
/**
* This is a very simple implementation of a stream wrapper. All URLs are mapped
* to just one buffer. It exists to prove that ParseCsv can read and write
* streams.
*
* @see https://www.php.net/manual/en/class.streamwrapper.php
*/
class ExampleStream {
private static $position = 0;
private static $stream_content;
public function stream_open($uri, $mode) {
if (strpos($mode, 'a') === false) {
self::$position = 0;
}
if (strpos($mode, 'w') !== false) {
self::$stream_content = '';
}
return true;
}
public function stream_read($count) {
$ret = substr(self::$stream_content, self::$position, $count);
self::$position += strlen($ret);
return $ret;
}
public function stream_write($data) {
$left = substr(self::$stream_content, 0, self::$position);
$right = substr(self::$stream_content, self::$position + strlen($data));
self::$stream_content = $left . $data . $right;
self::$position += strlen($data);
return strlen($data);
}
public function stream_stat() {
return ['size' => strlen(self::$stream_content)];
}
public function stream_tell() {
return self::$position;
}
public function stream_eof() {
return self::$position >= strlen(self::$stream_content);
}
public function url_stat() {
return ['size' => strlen(self::$stream_content)];
}
public function stream_seek($offset, $whence) {
switch ($whence) {
case SEEK_SET:
if ($offset < strlen(self::$stream_content) && $offset >= 0) {
self::$position = $offset;
return true;
} else {
return false;
}
break;
case SEEK_CUR:
if ($offset >= 0) {
self::$position += $offset;
return true;
} else {
return false;
}
break;
case SEEK_END:
if (strlen(self::$stream_content) + $offset >= 0) {
self::$position = strlen(self::$stream_content) + $offset;
return true;
} else {
return false;
}
break;
default:
return false;
}
}
public function stream_lock($operation) {
return true;
}
public function stream_metadata() {
return false;
}
}

View File

@@ -1,13 +0,0 @@
<?php
namespace ParseCsv\tests\methods;
/**
* Class HasToString is just a helper to test if cells can be objects.
*/
class ObjectThatHasToStringMethod {
public function __toString() {
return 'some value';
}
}

View File

@@ -1,43 +0,0 @@
<?php
namespace ParseCsv\tests\methods;
use PHPUnit\Framework\TestCase;
/**
* This test checks for backwards compatibility: Does it work to
* - require the old "parsecsv.lib.php" instead of composer autoloading?
* - use the old class name "parseCSV"?
*/
class OldRequireTest extends TestCase {
protected function setUp(): void {
rename('vendor/autoload.php', '__autoload');
}
protected function tearDown(): void {
rename('__autoload', 'vendor/autoload.php');
}
/**
* @runInSeparateProcess so that disabled autoloading has an effect
*/
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);
}
/**
* @runInSeparateProcess so that disabled autoloading has an effect
*/
public function testOldLibWithOldClassName() {
file_put_contents('__eval.php', '<?php require "parsecsv.lib.php"; new parseCSV;');
exec("php __eval.php", $output, $return_var);
unlink('__eval.php');
$this->assertEquals($output, []);
$this->assertEquals(0, $return_var);
}
}

View File

@@ -1,23 +0,0 @@
<?php
namespace ParseCsv\tests\methods;
use ParseCsv\Csv;
use PHPUnit\Framework\TestCase;
class OutputTest extends TestCase {
/**
* @runInSeparateProcess because download.php uses header()
*/
public function testOutputWithFourParameters() {
$csv = new Csv();
$data = [0 => ['a', 'b', 'c'], 1 => ['d', 'e', 'f']];
$fields = ['col1', 'col2', 'col3'];
ob_start();
$output = $csv->output('test.csv', $data, $fields, ',');
$expected = "col1,col2,col3\ra,b,c\rd,e,f\r";
self::assertEquals($expected, ob_get_clean());
self::assertEquals($expected, $output);
}
}

View File

@@ -1,15 +1,10 @@
<?php <?php
namespace ParseCsv\tests\methods; class ParseTest extends PHPUnit\Framework\TestCase {
use ParseCsv\Csv;
use PHPUnit\Framework\TestCase;
use ReflectionClass;
class ParseTest extends TestCase {
/** /**
* @var Csv object * @access protected
* @var ParseCsvForPhp
*/ */
protected $csv; protected $csv;
@@ -19,76 +14,49 @@ class ParseTest extends TestCase {
* *
* @access public * @access public
*/ */
protected function setUp(): void { public function setUp() {
$this->csv = new Csv(); $this->csv = new ParseCsvForPhp();
} }
public function testParse() { public function test_parse() {
// can we trick 'is_readable' into whining? See #67. // can we trick 'is_readable' into whining? See #67.
$this->parseRepetitiveString('c:/looks/like/a/path'); $this->parse_repetitive_string('c:/looks/like/a/path');
$this->parseRepetitiveString('http://looks/like/an/url'); $this->parse_repetitive_string('http://looks/like/an/url');
} }
/** private function parse_repetitive_string($content) {
* @param string $content
*/
private function parseRepetitiveString($content) {
$this->csv->delimiter = ';'; $this->csv->delimiter = ';';
$this->csv->heading = false; $this->csv->heading = false;
$success = $this->csv->parse(str_repeat($content . ';', 500)); $success = $this->csv->parse(str_repeat($content . ';', 500));
self::assertEquals(true, $success); $this->assertEquals(true, $success);
$row = array_pop($this->csv->data); $row = array_pop($this->csv->data);
$expected_data = array_fill(0, 500, $content); $expected_data = array_fill(0, 500, $content);
$expected_data[] = ''; $expected_data [] = '';
self::assertEquals($expected_data, $row); $this->assertEquals($expected_data, $row);
} }
/** public function test_sep_row_auto_detection_UTF8_no_BOM() {
* @depends testParse $this->_autoparse_magazine_file(
* __DIR__ . '/../example_files/UTF-8_sep_row_but_no_BOM.csv');
* @dataProvider autoDetectionProvider
*
* @param string $file
*/
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);
self::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'],
'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() { public function testSingleColumnWithZeros() {
$this->csv->delimiter = null; $this->csv->delimiter = null;
$this->csv->parse( $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");
"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'];
self::assertEquals($expected_data, $row); $this->assertEquals($expected_data, $row);
} }
public function testAllNumericalCsv() { public function testAllNumericalCsv() {
$this->csv->heading = false; $this->csv->heading = false;
$sInput = "86545235689\r\n34365587654\r\n13469874576"; $sInput = "86545235689\r\n34365587654\r\n13469874576";
self::assertEquals(false, $this->csv->autoDetectionForDataString($sInput)); $this->assertEquals(false, $this->csv->auto($sInput));
self::assertEquals(null, $this->csv->delimiter); $this->assertEquals(null, $this->csv->delimiter);
$expected_data = explode("\r\n", $sInput); $expected_data = explode("\r\n", $sInput);
$actual_data = array_map('reset', $this->csv->data); $actual_data = array_map('reset', $this->csv->data);
self::assertEquals($expected_data, $actual_data); $this->assertEquals($expected_data, $actual_data);
} }
public function testMissingEndingLineBreak() { public function testMissingEndingLineBreak() {
@@ -96,21 +64,36 @@ class ParseTest extends TestCase {
$this->csv->enclosure = '"'; $this->csv->enclosure = '"';
$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->csv->parse_string($sInput);
$actual_data = $this->invokeMethod($this->csv, '_parse_string', [$sInput]);
$actual_column = array_map('reset', $actual_data); $actual_column = array_map('reset', $actual_data);
self::assertEquals($expected_data, $actual_column); $this->assertEquals($expected_data, $actual_column);
self::assertEquals( $this->assertEquals([
[ 'a',
'a', 'b',
'b', "c\r\nd",
"c\r\nd", ], array_map('next', $actual_data));
],
array_map('next', $actual_data)
);
} }
public function testSingleColumn() { 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'); $this->csv->auto(__DIR__ . '/../example_files/single_column.csv');
$expected = [ $expected = [
['SMS' => '0444'], ['SMS' => '0444'],
@@ -118,153 +101,32 @@ class ParseTest extends TestCase {
['SMS' => '6606'], ['SMS' => '6606'],
['SMS' => '7777'], ['SMS' => '7777'],
]; ];
self::assertEquals($expected, $this->csv->data); $this->assertEquals($expected, $this->csv->data);
} }
public function testSingleRow() { public function test_Piwik_data() {
$this->csv->auto(__DIR__ . '/../example_files/single_row.csv'); if (!function_exists('array_column')) {
self::assertEquals([], $this->csv->data, 'Single row is detected as header'); // function only available in PHP >= 5.5
$this->csv->heading = false; return;
$this->csv->auto(__DIR__ . '/../example_files/single_row.csv'); }
$expected = [['C1', 'C2', 'C3']];
self::assertEquals($expected, $this->csv->data);
}
public function testMatomoData() {
// Matomo (Piwik) export cannot be read with
$this->csv->use_mb_convert_encoding = true; $this->csv->use_mb_convert_encoding = true;
$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)');
self::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');
self::assertEquals( $this->assertEquals([
[ 'São Paulo',
'São Paulo', 'Johannesburg',
'Johannesburg', '',
'', ], $aCity);
],
$aCity
);
} }
/**
* Tests if we can handle BOMs in string data, in contrast to loading files.
*/
public function testStringWithLeadingBOM() {
$string_with_bom = strtr(
file_get_contents(__DIR__ . '/../example_files/UTF-8_with_BOM_and_sep_row.csv'),
["sep=;\n" => '']
);
// Is the BOM still there?
self::assertSame(0xEF, ord($string_with_bom));
$this->csv->output_encoding = 'UTF-8';
$this->csv->delimiter = ';';
self::assertTrue($this->csv->loadDataString($string_with_bom));
self::assertTrue($this->csv->parse($this->csv->file_data));
// This also tests if ::load_data removed the BOM from the data;
// otherwise the 'title' column would have 3 extra bytes.
$this->assertEquals(
[
'title',
'isbn',
'publishedAt',
],
array_keys(reset($this->csv->data)));
$titles = array_column($this->csv->data, 'title');
$this->assertEquals(
[
'Красивая кулинария',
'The Wine Connoisseurs',
'Weißwein',
],
$titles);
}
public function testWithMultipleNewlines() {
$this->csv->auto(__DIR__ . '/../example_files/multiple_empty_lines.csv');
$aElse9 = array_column($this->csv->data, 'else9');
/** @noinspection SpellCheckingInspection */
$this->assertEquals(
[
'Abweichung',
'Abweichung',
'Abweichung',
'Alt',
'Fehlt',
'Neu',
'OK',
'Fehlt',
'Fehlt',
'Fehlt',
],
$aElse9);
}
/**
* @depends testSepRowAutoDetection
*/
public function testGetColumnDatatypes() {
$this->csv->auto(__DIR__ . '/fixtures/datatype.csv');
$this->csv->getDatatypes();
$expected = [
'title' => 'string',
'isbn' => 'string',
'publishedAt' => 'date',
'published' => 'boolean',
'count' => 'integer',
'price' => 'float',
];
self::assertEquals($expected, $this->csv->data_types);
}
/**
* @depends testSepRowAutoDetection
*/
public function testAutoDetectFileHasHeading() {
$this->csv->auto(__DIR__ . '/fixtures/datatype.csv');
self::assertTrue($this->csv->autoDetectFileHasHeading());
$this->csv->heading = false;
$this->csv->auto(__DIR__ . '/fixtures/datatype.csv');
self::assertTrue($this->csv->autoDetectFileHasHeading());
$this->csv->heading = false;
$sInput = "86545235689\r\n34365587654\r\n13469874576";
$this->csv->autoDetectionForDataString($sInput);
self::assertFalse($this->csv->autoDetectFileHasHeading());
$this->csv->heading = true;
$sInput = "86545235689\r\n34365587654\r\n13469874576";
$this->csv->autoDetectionForDataString($sInput);
self::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() { protected function _get_magazines_data() {
return [ return [
[ [
@@ -285,10 +147,7 @@ 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', "'"),
@@ -296,60 +155,15 @@ class ParseTest extends TestCase {
} }
/** /**
* @depends testSepRowAutoDetection
*
* @dataProvider autoQuotesDataProvider * @dataProvider autoQuotesDataProvider
* *
* @param string $file * @param string $file
* @param string $enclosure * @param string $enclosure
*/ */
public function testAutoQuotes($file, $enclosure) { public function testAutoQuotes($file, $enclosure) {
$csv = new Csv(); $csv = new ParseCsvForPhp();
$csv->auto(__DIR__ . '/fixtures/' . $file, true, null, null, $enclosure); $csv->auto(__DIR__ . '/../example_files/' . $file, true, null, null, $enclosure);
self::assertArrayHasKey('column1', $csv->data[0], 'Data parsed incorrectly with enclosure ' . $enclosure); $this->assertArrayHasKey('column1', $csv->data[0], 'Data parsed incorrectly with enclosure ' . $enclosure);
self::assertEquals('value1', $csv->data[0]['column1'], 'Data parsed incorrectly with enclosure ' . $enclosure); $this->assertEquals('value1', $csv->data[0]['column1'], 'Data parsed incorrectly with enclosure ' . $enclosure);
}
/**
* 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.
*
* @return mixed Method return.
*/
private function invokeMethod($object, $methodName, $parameters = []) {
$reflection = new ReflectionClass(get_class($object));
$method = $reflection->getMethod($methodName);
$method->setAccessible(true);
return $method->invokeArgs($object, $parameters);
}
public function testWaiverFieldSeparator() {
self::assertFalse($this->csv->auto(__DIR__ . '/../example_files/waiver_field_separator.csv'));
$expected = [
'liability waiver',
'release of liability form',
'release of liability',
'sample waiver',
'sample waiver form',
];
$actual = array_column($this->csv->data, 'keyword');
self::assertSame($expected, $actual);
}
public function testEmptyInput() {
self::assertFalse($this->csv->parse(''));
self::assertFalse($this->csv->parse(null));
self::assertFalse($this->csv->parseFile(''));
self::assertFalse($this->csv->parseFile(null));
}
public function testParseFile() {
$data = $this->csv->parseFile(__DIR__ . '/fixtures/auto-double-enclosure.csv');
self::assertCount(2, $data);
self::assertEquals($data, $this->csv->data);
} }
} }

View File

@@ -1,13 +1,8 @@
<?php <?php
namespace ParseCsv\tests\methods; class SaveTest extends PHPUnit\Framework\TestCase {
use ParseCsv\Csv; /** @var ParseCsvForPhp */
use PHPUnit\Framework\TestCase;
class SaveTest extends TestCase {
/** @var Csv */
private $csv; private $csv;
private $temp_filename; private $temp_filename;
@@ -15,8 +10,8 @@ class SaveTest extends TestCase {
/** /**
* Setup our test environment objects; will be called before each test. * Setup our test environment objects; will be called before each test.
*/ */
protected function setUp(): void { public function setUp() {
$this->csv = new Csv(); $this->csv = new ParseCsvForPhp();
$this->csv->auto(__DIR__ . '/../example_files/single_column.csv'); $this->csv->auto(__DIR__ . '/../example_files/single_column.csv');
// Remove last 2 lines to simplify comparison // Remove last 2 lines to simplify comparison
@@ -49,13 +44,6 @@ class SaveTest extends TestCase {
$this->saveAndCompare($expected); $this->saveAndCompare($expected);
} }
public function testSaveWithNewHeader() {
$this->csv->linefeed = "\n";
$this->csv->titles = array("NewTitle");
$expected = "NewTitle\n0444\n5555\n";
$this->saveAndCompare($expected);
}
public function testSaveWithoutHeader() { public function testSaveWithoutHeader() {
$this->csv->linefeed = "\n"; $this->csv->linefeed = "\n";
$this->csv->heading = false; $this->csv->heading = false;

View File

@@ -1,71 +0,0 @@
<?php
namespace ParseCsv\tests\methods;
use ParseCsv\Csv;
use PHPUnit\Framework\TestCase;
/**
* Writes roughly 1 MB of data. This is useful because of a limit of 8 KB
* encountered with stream operations in certain PHP versions.
*/
class StreamTest extends TestCase {
protected function setUp(): void {
static $done;
if ($done) {
// Make sure we register the stream just once - or PHP will scream.
return;
}
stream_wrapper_register("example", ExampleStream::class)
or die("Failed to register protocol");
$done = 1;
}
public function testReadStream() {
$csv = new Csv();
// Write data to our stream:
$filename = 'example://tmp';
copy(__DIR__ . '/fixtures/datatype.csv', $filename);
$many_dots = str_repeat('.', 1000 * 1000) . ";;;;;\n";
file_put_contents($filename, $many_dots, FILE_APPEND);
self::assertSame(';', $csv->auto(file_get_contents($filename)));
self::assertCount(4, $csv->data);
self::assertCount(6, reset($csv->data));
}
public function testWriteStream() {
$csv = new Csv();
$csv->linefeed = "\n";
$many_dots = str_repeat('.', 1000 * 1000);
$csv->data = [
[
'Name' => 'Rudolf',
'Question' => 'Which color is his nose?',
],
[
'Name' => 'Sponge Bob',
'Question' => 'Which shape are his pants?',
],
[
'Name' => $many_dots,
'Question' => 'Can you count one million dots?',
],
];
// Just export the first column, but with a new name
$csv->titles = ['Name' => 'Character'];
// Write data to our stream:
$filename = 'example://data';
copy(__DIR__ . '/fixtures/datatype.csv', $filename);
self::assertSame(true, $csv->save($filename));
$expected = "Character\nRudolf\nSponge Bob\n";
$expected .= $many_dots . "\n";
self::assertSame($expected, file_get_contents($filename));
}
}

View File

@@ -1,107 +0,0 @@
<?php
namespace ParseCsv\tests\methods;
use ParseCsv\Csv;
use PHPUnit\Framework\TestCase;
class UnparseTest extends Testcase {
/** @var Csv */
private $csv;
/**
* Setup our test environment objects; will be called before each test.
*/
protected function setUp(): void {
$this->csv = new Csv();
$this->csv->auto(__DIR__ . '/fixtures/auto-double-enclosure.csv');
}
public function testUnparseWithParameters() {
$fields = array('a' => 'AA', 'b' => 'BB');
$data = [['a' => 'value1', 'b' => 'value2']];
$csv_object = new Csv();
$csv_string = $csv_object->unparse($data, $fields);
$this->assertEquals("AA,BB\rvalue1,value2\r", $csv_string);
$csv_object = new Csv();
$csv_object->linefeed = "\n";
$csv_string = $csv_object->unparse([[55, 66]]);
$this->assertEquals("55,66\n", $csv_string);
$csv_object = new Csv();
$data2 = [['a' => "multi\rline", 'b' => 'value2']];
$csv_object->enclosure = "'";
$csv_string = $csv_object->unparse($data2, $fields);
$this->assertEquals("AA,BB\r'multi\rline',value2\r", $csv_string);
}
public function testUnparseDefault() {
$expected = "column1,column2\rvalue1,value2\rvalue3,value4\r";
$this->unparseAndCompare($expected);
}
public function testUnparseDefaultWithoutHeading() {
$this->csv->heading = false;
$this->csv->auto(__DIR__ . '/fixtures/auto-double-enclosure.csv');
$expected = "column1,column2\rvalue1,value2\rvalue3,value4\r";
$this->unparseAndCompare($expected);
}
public function testUnparseRenameFields() {
$expected = "C1,C2\rvalue1,value2\rvalue3,value4\r";
$this->unparseAndCompare($expected, array("C1", "C2"));
}
public function testReorderFields() {
$expected = "column2,column1\rvalue2,value1\rvalue4,value3\r";
$this->unparseAndCompare($expected, array("column2", "column1"));
}
public function testSubsetFields() {
$expected = "column1\rvalue1\rvalue3\r";
$this->unparseAndCompare($expected, array("column1"));
}
public function testReorderAndRenameFields() {
$fields = array(
'column2' => 'C2',
'column1' => 'C1',
);
$expected = "C2,C1\rvalue2,value1\rvalue4,value3\r";
$this->unparseAndCompare($expected, $fields);
}
public function testUnparseDefaultFirstRowMissing() {
unset($this->csv->data[0]);
$expected = "column1,column2\rvalue3,value4\r";
$this->unparseAndCompare($expected);
}
public function testUnparseDefaultWithoutData() {
unset($this->csv->data[0]);
unset($this->csv->data[1]);
$expected = "column1,column2\r";
$this->unparseAndCompare($expected);
}
public function testObjectCells() {
$this->csv->data = [
[
'column1' => new ObjectThatHasToStringMethod(),
'column2' => 'boring',
],
];
$this->csv->linefeed = "\n";
$expected = "column1,column2\nsome value,boring\n";
$this->unparseAndCompare($expected);
}
private function unparseAndCompare($expected, $fields = array()) {
$str = $this->csv->unparse($this->csv->data, $fields);
$this->assertEquals($expected, $str);
}
}

View File

@@ -1,5 +0,0 @@
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

@@ -10,7 +10,7 @@
stopOnIncomplete="true" stopOnIncomplete="true"
stopOnSkipped="false"> stopOnSkipped="false">
<testsuites> <testsuites>
<testsuite name="parseCSV Test Suite"> <testsuite name="ParseCsvForPhp Test Suite">
<directory suffix="est.php">properties/</directory> <directory suffix="est.php">properties/</directory>
<directory suffix="est.php">methods/</directory> <directory suffix="est.php">methods/</directory>
</testsuite> </testsuite>

View File

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

View File

@@ -1,7 +1,5 @@
<?php <?php
namespace ParseCsv\tests\properties;
class ConditionsTest extends BaseClass { class ConditionsTest extends BaseClass {
public function testNotDanBrown() { public function testNotDanBrown() {
@@ -21,93 +19,21 @@ class ConditionsTest extends BaseClass {
]); ]);
} }
public function testRatingEquals() { public function testRating() {
$rating_of_3 = [ $this->csv->conditions = 'rating < 3';
'The Last Templar', $this->_compareWithExpected([
'The Broker (Paperback)',
'Without Blood (Paperback)',
];
$this->csv->conditions = 'rating = 3';
$this->_compareWithExpected($rating_of_3);
$this->csv->conditions = 'rating is 3';
$this->_compareWithExpected($rating_of_3);
$this->csv->conditions = 'rating equals 3';
$this->_compareWithExpected($rating_of_3);
}
public function testRatingNotEquals() {
$rating_not_4 = [
'The Killing Kind', 'The Killing Kind',
'The Third Secret', 'The Third Secret',
'The Last Templar', ]);
'The Traveller',
'Prey',
'The Broker (Paperback)',
'Without Blood (Paperback)',
'State of Fear (Paperback)',
'Digital Fortress : A Thriller (Mass Market Paperback)',
'Angels & Demons (Mass Market Paperback)',
];
// $this->csv->conditions = 'rating != 4';
// $this->_compareWithExpected($rating_not_4);
$this->csv->conditions = 'rating is not 4';
$this->_compareWithExpected($rating_not_4);
// $this->csv->conditions = 'rating does not contain 4';
// $this->_compareWithExpected($rating_not_4);
}
public function testRatingLessThan() { $this->csv->conditions = 'rating >= 5';
$less_than_1 = [ $this->_compareWithExpected([
'The Killing Kind',
'The Third Secret',
];
$this->csv->conditions = 'rating < 1';
$this->_compareWithExpected($less_than_1);
$this->csv->conditions = 'rating is less than 1';
$this->_compareWithExpected($less_than_1);
}
public function testRatingLessOrEquals() {
$less_or_equals_1 = [
'The Killing Kind',
'The Third Secret',
];
$this->csv->conditions = 'rating <= 1';
$this->_compareWithExpected($less_or_equals_1);
$this->csv->conditions = 'rating is less than or equals 1';
$this->_compareWithExpected($less_or_equals_1);
}
public function testRatingGreaterThan() {
$greater_4 = [
'The Traveller', 'The Traveller',
'Prey', 'Prey',
'State of Fear (Paperback)', 'State of Fear (Paperback)',
'Digital Fortress : A Thriller (Mass Market Paperback)', 'Digital Fortress : A Thriller (Mass Market Paperback)',
'Angels & Demons (Mass Market Paperback)', 'Angels & Demons (Mass Market Paperback)',
]; ]);
$this->csv->conditions = 'rating > 4';
$this->_compareWithExpected($greater_4);
$this->csv->conditions = 'rating is greater than 4';
$this->_compareWithExpected($greater_4);
}
public function testRatingGreaterOrEquals() {
$greater_or_equal_4 = [
'The Traveller',
'Crisis Four',
'Prey',
'State of Fear (Paperback)',
'The Rule of Four (Paperback)',
'Deception Point (Paperback)',
'Digital Fortress : A Thriller (Mass Market Paperback)',
'Angels & Demons (Mass Market Paperback)',
'The Da Vinci Code (Hardcover)',
];
$this->csv->conditions = 'rating >= 4';
$this->_compareWithExpected($greater_or_equal_4);
$this->csv->conditions = 'rating is greater than or equals 4';
$this->_compareWithExpected($greater_or_equal_4);
} }
public function testTitleContainsSecretOrCode() { public function testTitleContainsSecretOrCode() {

View File

@@ -1,150 +0,0 @@
<?php
namespace ParseCsv\tests\properties;
use ParseCsv\Csv;
use PHPUnit\Framework\TestCase;
class DefaultValuesPropertiesTest extends TestCase {
/**
* CSV
* The parseCSV object
*
* @access protected
* @var Csv
*/
protected $csv = null;
protected function setUp(): void {
$this->csv = new Csv();
}
public function test_heading_default() {
self::assertTrue(is_bool($this->csv->heading));
self::assertTrue($this->csv->heading);
}
public function test_fields_default() {
self::assertTrue(is_array($this->csv->fields));
self::assertCount(0, $this->csv->fields);
}
public function test_sort_by_default() {
self::assertNull($this->csv->sort_by);
}
public function test_sort_reverse_default() {
self::assertTrue(is_bool($this->csv->sort_reverse));
self::assertFalse($this->csv->sort_reverse);
}
public function test_sort_type_default() {
self::assertEquals('regular', $this->csv->sort_type);
}
public function test_delimiter_default() {
self::assertTrue(is_string($this->csv->delimiter));
self::assertEquals(',', $this->csv->delimiter);
}
public function test_enclosure_default() {
self::assertTrue(is_string($this->csv->enclosure));
self::assertEquals('"', $this->csv->enclosure);
}
public function test_enclose_all_default() {
self::assertTrue(is_bool($this->csv->enclose_all));
self::assertFalse($this->csv->enclose_all);
}
public function test_conditions_default() {
self::assertNull($this->csv->conditions);
}
public function test_offset_default() {
self::assertNull($this->csv->offset);
}
public function test_limit_default() {
self::assertNull($this->csv->limit);
}
public function test_auto_depth_default() {
self::assertTrue(is_numeric($this->csv->auto_depth));
self::assertEquals(15, $this->csv->auto_depth);
}
public function test_auto_non_chars_default() {
self::assertTrue(is_string($this->csv->auto_non_chars));
self::assertEquals("a-zA-Z0-9\n\r", $this->csv->auto_non_chars);
}
public function test_auto_preferred_default() {
self::assertTrue(is_string($this->csv->auto_preferred));
self::assertEquals(",;\t.:|", $this->csv->auto_preferred);
}
public function test_convert_encoding_default() {
self::assertTrue(is_bool($this->csv->convert_encoding));
self::assertFalse($this->csv->convert_encoding);
}
public function test_input_encoding_default() {
self::assertTrue(is_string($this->csv->input_encoding));
self::assertEquals('ISO-8859-1', $this->csv->input_encoding);
}
public function test_output_encoding_default() {
self::assertTrue(is_string($this->csv->output_encoding));
self::assertEquals('ISO-8859-1', $this->csv->output_encoding);
}
public function test_linefeed_default() {
self::assertTrue(is_string($this->csv->linefeed));
self::assertEquals("\r", $this->csv->linefeed);
}
public function test_output_delimiter_default() {
self::assertTrue(is_string($this->csv->output_delimiter));
self::assertEquals(',', $this->csv->output_delimiter);
}
public function test_output_filename_default() {
self::assertTrue(is_string($this->csv->output_filename));
self::assertEquals('data.csv', $this->csv->output_filename);
}
public function test_keep_file_data_default() {
self::assertTrue(is_bool($this->csv->keep_file_data));
self::assertFalse($this->csv->keep_file_data);
}
public function test_file_default() {
self::assertNull($this->csv->file);
}
public function test_file_data_default() {
self::assertNull($this->csv->file_data);
}
public function test_error_default() {
self::assertTrue(is_numeric($this->csv->error));
self::assertEquals(0, $this->csv->error);
}
public function test_error_info_default() {
self::assertTrue(is_array($this->csv->error_info));
self::assertCount(0, $this->csv->error_info);
}
public function test_titles_default() {
self::assertTrue(is_array($this->csv->titles));
self::assertCount(0, $this->csv->titles);
}
public function test_data_default() {
self::assertTrue(is_array($this->csv->data));
self::assertCount(0, $this->csv->data);
}
}

View File

@@ -1,79 +0,0 @@
<?php
namespace ParseCsv\tests\properties;
/**
* Tests related to the $offset property
*/
class OffsetTest extends BaseClass {
public function testOffsetOfOne() {
$this->csv->offset = 1;
$this->csv->auto(__DIR__ . '/../methods/fixtures/datatype.csv');
$this->assertCount(3, $this->csv->data);
if (!function_exists('array_column')) {
// function only available in PHP >= 5.5
return;
}
$expected = [
'Красивая кулинария',
'The Wine Connoisseurs',
'Weißwein',
];
$actual = array_column($this->csv->data, 'title');
$this->assertEquals($expected, $actual);
}
public function numberRangeZeroToFourProvider() {
return array_map(function ($number) {
return [$number];
}, range(0, 4));
}
/**
* @dataProvider numberRangeZeroToFourProvider
*
* @param int $offset
*/
public function testOffsetOfOneNoHeader($offset) {
$this->csv->offset = $offset;
$this->csv->heading = false;
$this->csv->auto(__DIR__ . '/../methods/fixtures/datatype.csv');
$this->assertCount(4 - $offset, $this->csv->data);
}
public function testDataArrayKeysWhenSettingOffsetWithHeading() {
$this->csv->offset = 2;
$this->csv->auto(__DIR__ . '/../methods/fixtures/datatype.csv');
$expected = [
[
'title' => 'The Wine Connoisseurs',
'isbn' => '2547-8548-2541',
'publishedAt' => '12.12.2011',
'published' => 'TRUE',
'count' => '',
'price' => 20.33,
],
[
'title' => 'Weißwein',
'isbn' => '1313-4545-8875',
'publishedAt' => '23.02.2012',
'published' => 'false',
'count' => 10,
'price' => 10,
],
];
$this->assertEquals($expected, $this->csv->data);
}
public function testDataArrayKeysWhenSettingOffsetWithoutHeading() {
$this->csv->heading = false;
$this->csv->offset = 2;
$this->csv->auto(__DIR__ . '/../methods/fixtures/datatype.csv');
$expected = range(0, 5, 1);
$this->assertEquals($expected, array_keys($this->csv->data[0]));
}
}

View File

@@ -1,7 +1,5 @@
<?php <?php
namespace ParseCsv\tests\properties;
class SortByTest extends BaseClass { class SortByTest extends BaseClass {
public function testSortByRating() { public function testSortByRating() {

View File

@@ -0,0 +1,149 @@
<?php
class default_values_properties_Test extends PHPUnit\Framework\TestCase {
/**
* @access protected
* @var ParseCsvForPhp object
*/
protected $csv = null;
/**
* Setup
* Setup our test environment objects
*
* @access public
*/
public function setUp() {
//setup parse CSV
$this->csv = new ParseCsvForPhp();
}
public function test_heading_default() {
$this->assertTrue(is_bool($this->csv->heading));
$this->assertTrue($this->csv->heading);
}
public function test_fields_default() {
$this->assertTrue(is_array($this->csv->fields));
$this->assertCount(0, $this->csv->fields);
}
public function test_sort_by_default() {
$this->assertNull($this->csv->sort_by);
}
public function test_sort_reverse_default() {
$this->assertTrue(is_bool($this->csv->sort_reverse));
$this->assertFalse($this->csv->sort_reverse);
}
public function test_sort_type_default() {
$this->assertNull($this->csv->sort_type);
}
public function test_delimiter_default() {
$this->assertTrue(is_string($this->csv->delimiter));
$this->assertEquals(',', $this->csv->delimiter);
}
public function test_enclosure_default() {
$this->assertTrue(is_string($this->csv->enclosure));
$this->assertEquals('"', $this->csv->enclosure);
}
public function test_enclose_all_default() {
$this->assertTrue(is_bool($this->csv->enclose_all));
$this->assertFalse($this->csv->enclose_all);
}
public function test_conditions_default() {
$this->assertNull($this->csv->conditions);
}
public function test_offset_default() {
$this->assertNull($this->csv->offset);
}
public function test_limit_default() {
$this->assertNull($this->csv->limit);
}
public function test_auto_depth_default() {
$this->assertTrue(is_numeric($this->csv->auto_depth));
$this->assertEquals(15, $this->csv->auto_depth);
}
public function test_auto_non_chars_default() {
$this->assertTrue(is_string($this->csv->auto_non_chars));
$this->assertEquals("a-zA-Z0-9\n\r", $this->csv->auto_non_chars);
}
public function test_auto_preferred_default() {
$this->assertTrue(is_string($this->csv->auto_preferred));
$this->assertEquals(",;\t.:|", $this->csv->auto_preferred);
}
public function test_convert_encoding_default() {
$this->assertTrue(is_bool($this->csv->convert_encoding));
$this->assertFalse($this->csv->convert_encoding);
}
public function test_input_encoding_default() {
$this->assertTrue(is_string($this->csv->input_encoding));
$this->assertEquals('ISO-8859-1', $this->csv->input_encoding);
}
public function test_output_encoding_default() {
$this->assertTrue(is_string($this->csv->output_encoding));
$this->assertEquals('ISO-8859-1', $this->csv->output_encoding);
}
public function test_linefeed_default() {
$this->assertTrue(is_string($this->csv->linefeed));
$this->assertEquals("\r", $this->csv->linefeed);
}
public function test_output_delimiter_default() {
$this->assertTrue(is_string($this->csv->output_delimiter));
$this->assertEquals(',', $this->csv->output_delimiter);
}
public function test_output_filename_default() {
$this->assertTrue(is_string($this->csv->output_filename));
$this->assertEquals('data.csv', $this->csv->output_filename);
}
public function test_keep_file_data_default() {
$this->assertTrue(is_bool($this->csv->keep_file_data));
$this->assertFalse($this->csv->keep_file_data);
}
public function test_file_default() {
$this->assertNull($this->csv->file);
}
public function test_file_data_default() {
$this->assertNull($this->csv->file_data);
}
public function test_error_default() {
$this->assertTrue(is_numeric($this->csv->error));
$this->assertEquals(0, $this->csv->error);
}
public function test_error_info_default() {
$this->assertTrue(is_array($this->csv->error_info));
$this->assertCount(0, $this->csv->error_info);
}
public function test_titles_default() {
$this->assertTrue(is_array($this->csv->titles));
$this->assertCount(0, $this->csv->titles);
}
public function test_data_default() {
$this->assertTrue(is_array($this->csv->data));
$this->assertCount(0, $this->csv->data);
}
}

View File

@@ -1,19 +1,10 @@
<?php <?php
namespace ParseCsv\tests\properties; class worthless_properties_Test extends PHPUnit\Framework\TestCase {
use ParseCsv\Csv;
use ParseCsv\enums\SortEnum;
use PHPUnit\Framework\TestCase;
class PublicPropertiesTest extends TestCase {
/** /**
* CSV
* The parseCSV object
*
* @access protected * @access protected
* @var Csv * @var ParseCsvForPhp
*/ */
protected $csv = null; protected $csv = null;
@@ -22,7 +13,7 @@ class PublicPropertiesTest extends TestCase {
* The reflection class object * The reflection class object
* *
* @access protected * @access protected
* @var \ReflectionClass * @var ReflectionClass
*/ */
protected $reflection = null; protected $reflection = null;
@@ -30,8 +21,8 @@ class PublicPropertiesTest extends TestCase {
* Reflection Properties * Reflection Properties
* The reflected class properties * The reflected class properties
* *
* @var \ReflectionProperty[]
* @access protected * @access protected
* @var ReflectionProperty[]
*/ */
protected $properties = null; protected $properties = null;
@@ -41,12 +32,12 @@ class PublicPropertiesTest extends TestCase {
* *
* @access public * @access public
*/ */
protected function setUp(): void { public function setUp() {
//setup parse CSV //setup parse CSV
$this->csv = new Csv(); $this->csv = new ParseCsvForPhp();
//setup the reflection class //setup the reflection class
$this->reflection = new \ReflectionClass($this->csv); $this->reflection = new ReflectionClass($this->csv);
//setup the reflected class properties //setup the reflected class properties
$this->properties = $this->reflection->getProperties(); $this->properties = $this->reflection->getProperties();
@@ -58,7 +49,7 @@ class PublicPropertiesTest extends TestCase {
* *
* @access public * @access public
*/ */
protected function tearDown(): void { public function tearDown() {
$this->csv = null; $this->csv = null;
$this->reflection = null; $this->reflection = null;
$this->properties = null; $this->properties = null;
@@ -72,7 +63,7 @@ class PublicPropertiesTest extends TestCase {
* @access public * @access public
*/ */
public function test_propertiesCount() { public function test_propertiesCount() {
$this->assertCount(29, $this->properties); $this->assertCount(28, $this->properties);
} }
/** /**
@@ -115,11 +106,10 @@ class PublicPropertiesTest extends TestCase {
'error_info', 'error_info',
'titles', 'titles',
'data', 'data',
'data_types',
); );
// Find our real properties // Find our real properties
$real_properties = array_map(function (\ReflectionProperty $property) { $real_properties = array_map(function (ReflectionProperty $property) {
return $property->getName(); return $property->getName();
}, $this->properties); }, $this->properties);
@@ -137,8 +127,7 @@ class PublicPropertiesTest extends TestCase {
public function test_count_public_properties() { public function test_count_public_properties() {
$counter = 0; $counter = 0;
$propertiesCount = count($this->properties); for ($a = count($this->properties) - 1; $a >= 0; $a--) {
for ($a = 0; $a < $propertiesCount; $a++) {
if ($this->properties[$a]->isPublic() === true) { if ($this->properties[$a]->isPublic() === true) {
$counter++; $counter++;
} }
@@ -146,26 +135,4 @@ class PublicPropertiesTest extends TestCase {
$this->assertCount($counter, $this->properties); $this->assertCount($counter, $this->properties);
} }
public function testDefaultSortTypeIsRegular() {
$this->assertEquals(SortEnum::SORT_TYPE_REGULAR, $this->csv->sort_type);
}
public function testSetSortType() {
$this->csv->sort_type = 'numeric';
$this->assertEquals(SortEnum::SORT_TYPE_NUMERIC, $this->csv->sort_type);
$this->csv->sort_type = 'string';
$this->assertEquals(SortEnum::SORT_TYPE_STRING, $this->csv->sort_type);
}
public function testGetSorting() {
$this->csv->sort_type = 'numeric';
$sorting = SortEnum::getSorting($this->csv->sort_type);
$this->assertEquals(SORT_NUMERIC, $sorting);
$this->csv->sort_type = 'string';
$sorting = SortEnum::getSorting($this->csv->sort_type);
$this->assertEquals(SORT_STRING, $sorting);
}
} }