57 Commits
1.1.0 ... 1.2.1

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

Fixes #188

Improved some type hints in DocBlocks
2020-04-25 19:17:04 +02:00
Fonata
89429ebd60 Cleaned up README 2020-04-25 19:17:04 +02:00
Fonata
548a9fe551 ChangeLog: Added release date 2020-01-07 09:32:12 +01:00
susgo
5336800ec6 Merge pull request #186 from parsecsv/bu-object-test
Added test for the case of objects as cells
2020-01-06 19:35:23 +01:00
susgo
6bd53940c5 Merge pull request #185 from parsecsv/release-1.2.0
Release candidate 1.2.0
2020-01-06 19:32:41 +01:00
Fonata
a9297449b9 Autoloading: No need to explicitly mention ParseCsv\extensions
It is a sub-directory of src anyway.
2020-01-06 19:04:58 +01:00
Fonata
c12b6ba671 Added test for the case of objects as cells
I encountered this in Drupal 8, where cells implemented the
MarkupInterface. It was objects that, when cast to a string,
returned the translated string.

Before 5ca540daa7, this new test
would fail.
2020-01-06 18:12:37 +01:00
Fonata
b792a6cc7b Code quality: Removed superfluous brackets; should not change anything 2020-01-06 18:04:45 +01:00
Fonata
af442cdd0e PHP closing tags are no longer common practise 2019-12-25 15:09:31 +01:00
Fonata
95810ec2fa Updated ChangeLog.txt 2019-12-25 15:08:37 +01:00
Fonata
d79160f40a Examples: Removed deprecated HTTML attributes from <table> tag 2019-12-25 15:06:18 +01:00
Fonata
7ba2f9b296 Added an example for a verbal comparison 2019-12-25 15:04:07 +01:00
Fonata
d7ba892d38 Bug fix for $csv->conditions = 'rating is LESS than 4'
The $op was wrong because of upper case
2019-12-25 14:54:50 +01:00
Jess
38e9fff285 Added financial contributors to the README 2019-12-25 07:57:32 -05:00
Fonata
174d2e6070 Merge branch 'andreybolonin-patch-1' 2019-12-25 13:49:08 +01:00
Andrey Bolonin
d93036ca87 Update .travis.yml 2019-12-25 13:47:59 +01:00
Craig Morris
62fc367c14 Run https://gist.github.com/theodorejb/763b83a43522b0fc1755a537663b1863 2019-12-25 07:45:00 -05:00
susgo
044122efb9 Merge pull request #180 from parsecsv/more-conditions-bu
Bugfix for verbal conditions
2019-11-04 21:20:58 +01:00
susgo
18cbc3ab87 Merge pull request #174 from parsecsv/code-quality-and-documentation
Code quality and documentation
2019-11-04 21:19:35 +01:00
Fonata
af75206e86 Travis dist implicitly switched to Ubuntu Xenial, which didn't have PHP 5.5 2019-11-03 23:19:51 +01:00
Fonata
e45eb18213 Bugfix: All operators containing "is" or "equals" were broken
Fixes #179
2019-11-03 23:09:23 +01:00
Fonata
5340ab9584 New feature: Verbal condition operators don't have to be lower case 2019-11-03 23:08:08 +01:00
Fonata
f3601dbfb5 PHP 5.5 was not available; attempt to use Ubuntu Trusty 2019-09-14 09:01:10 +02:00
Fonata
67c8a0167c Added test for 1 MB stream data 2019-09-14 04:17:58 +02:00
Fonata
8b583daa08 Improved documentation comments 2019-09-14 04:10:58 +02:00
Fonata
b6dccf5fa6 Use in_array() to make code more readable 2019-09-14 03:56:00 +02:00
Fonata
5ca540daa7 Avoid PhpStorm inspection for $value{0} on empty string (prevent E_NOTICE)
Here, $value is not empty, but the PhpStorm inspection doesn't get that.
I want to have zero warnings for this library.
2019-09-14 01:19:40 +02:00
Fonata
f89ed5978d Simplified RegEx: {1} is the default and can be dropped 2019-09-14 01:17:09 +02:00
Fonata
f053cdde80 New feature: unparse now also understands $use_mb_convert_encoding 2019-09-14 01:14:41 +02:00
Fonata
62ae4e5fc3 Formated code using PhpStorm 2019.2.1 - only DocBlocks changed 2019-09-14 01:05:21 +02:00
susgo
a286556c16 Merge pull request #171 from parsecsv/travis-conf-bu
Travis conf didn't match schema
2019-07-27 12:11:55 +02:00
Fonata
7326262304 Travis conf didn't match schema
- PHP versions need to be strings
- https://docs.travis-ci.com/user/notifications/#configuring-email-notifications

Also: tell editors like PhpStorm how the YAML needs to be formatted.
2019-07-26 21:55:06 +02:00
susgo
b746ea1de0 Merge pull request #166 from parsecsv/parse_string_internal
End users should not be tempted to call parse_string.
2019-05-11 14:19:52 +02:00
Fonata
ef5e81f837 Added test for our code example in issue #165
Closes #165
2019-03-22 08:17:55 +01:00
Fonata
637f79c2e6 Improved documentation and parameter declaration
No functional changes.
2019-03-22 08:17:55 +01:00
Fonata
e3105d4003 Renamed protected functions: no end user should be tempted to call them 2019-03-22 08:17:55 +01:00
susgo
5874b768b9 Merge pull request #164 from parsecsv/composer-validate
Quality improvement, but no bug fixes or new features
2019-02-24 05:47:39 +01:00
Fonata
5d766adc17 PHPUnit versions newer than 8 don't like our setUp function
See https://travis-ci.org/parsecsv/parsecsv-for-php/jobs/497446669
2019-02-23 13:21:54 +01:00
Fonata
67ed765eff Added PHP 7.3 to test coverage 2019-02-23 13:09:09 +01:00
Fonata
a7be07cc02 PHP 7.2.15 doesn't seem to like public setUp functions 2019-02-23 13:06:28 +01:00
Fonata
b4cef37bb5 Simplyfied BaseClass.php: @access annotations are not needed 2019-02-23 13:05:55 +01:00
Fonata
f97f03a088 Only improved code formatting 2019-02-23 12:57:48 +01:00
Fonata
2e94f4ad41 Add composer validation to CI;
Also: add branch alias for `dev-master`

Fix #159
2019-02-23 12:53:58 +01:00
Fonata
d03f8a2f09 Simplified code; shouldn't change results 2019-02-23 12:48:52 +01:00
Fonata
14c9254ed4 Removed @access annotations because they don't add value
I believe they come from the time when PHP didn't universally
support the language keywords. phpDocumentor doesn't need the
@access annotations.
2019-02-23 12:45:28 +01:00
Fonata
78c288db8c Improved documentation comment 2019-02-23 12:45:07 +01:00
Fonata
531ac26e11 Improved spelling in comments 2019-02-23 12:44:31 +01:00
susgo
65566adcd3 Merge pull request #162 from parsecsv/add-save-example
Added example for writing CSV files to better document heading property
2019-02-02 20:40:45 +01:00
Fonata
2d428ffa93 Updated test: no output in save_to_file_without_header_row.php
Thus, effectively, we just test for valid PHP syntax.
2019-02-02 18:47:55 +01:00
Fonata
bc9207de09 Added example for writing CSV files to better document heading property
Fixes #161
2019-02-02 18:39:21 +01:00
susgo
ace09c3c11 Update README.md
Update examples for #155
2018-11-14 18:30:03 +01:00
Susann Sgorzaly
52ad56c66a fixes unparse bug if no data for unparsing remain (comments #150) 2018-11-14 08:26:39 +01:00
Susann Sgorzaly
ab9e8a0af9 fixes unparse bug if array ids doesn't begin on zero (comments#149) 2018-11-14 08:26:39 +01:00
Fonata
8aa61914f7 Function load_data: check length of input, prevents E_NOTICE if too long
Fixes #151
2018-09-25 00:35:03 +02:00
Fonata
3b74f7ce57 Added PHPUnit test to make sure very long text doesn't cause E_NOTICE 2018-09-25 00:27:04 +02:00
30 changed files with 757 additions and 219 deletions

View File

@@ -13,3 +13,6 @@ insert_final_newline = true
[composer.json] [composer.json]
indent_size = 4 indent_size = 4
[.travis.yml]
indent_size = 2

View File

@@ -1,18 +1,25 @@
dist: trusty
language: php language: php
dist: trusty
php: php:
- 7.2 - '7.4'
- 7.1 - '7.3'
- 7.0 - '7.2'
- 5.6 - '7.1'
- 5.5 - '7.0'
before_install:
- composer update
script: script:
- phpunit --version - composer validate
- phpunit --configuration tests/phpunit.xml - vendor/bin/phpunit --version
- vendor/bin/phpunit --configuration tests/phpunit.xml
notifications: notifications:
email: email:
- will.knauss@gmail.com recipients:
on_success: never - will.knauss@gmail.com
on_failure: always on_success: never
on_failure: always

View File

@@ -1,16 +1,92 @@
ParseCSV dev-master ParseCSV 1.2.1
----------------------------------- -----------------------------------
Date: unreleased Date: 25-Apr-2020
- New function getTotalDataRowCount() - useful if Breaking changes: none
$limit is set - see pull request #122. New features: none
Bug fixes: none
- Dropped support for PHP 5.4 Code quality:
- Switched from PHPUnit 4 to 6 to get rid of
wrappers. This will reduce friction for PhpStorm users,
because it gets rid of the "Multiple definitions" error
See issue #188. Thanks to @SharkMachine for the hint.
-----------------------------------
ParseCSV 1.2.0
-----------------------------------
Date: 07-Jan-2020
Breaking changes: none
New features:
- Compatible with PHP 7.4. Thanks to @andreybolonin
@morrislaptop @martijnengler and @fjf2002.
- unparse() now also understands $use_mb_convert_encoding.
- Verbal condition operators are now allowed to contain
upper case letters, for example:
$csv->conditions = 'rating IS GREATER THAN 4';
Bug fixes:
- All filter condition operators containing "is" or "equals"
were broken.
Code quality:
- Improved test coverage.
-----------------------------------
ParseCSV 1.1.1
-----------------------------------
Date: 2-Feb-2019
Breaking changes: none
New features: none
Bug fixes:
- Function load_data: check length of input, prevents E_NOTICE
if too long.
- Fixed bugs in unparse().
Code quality:
- Improved test coverage.
-----------------------------------
ParseCSV 1.1.0
-----------------------------------
Date: 9-Aug-2018
Breaking changes:
- Ignore entirely empty lines at the end of files
See https://github.com/parsecsv/parsecsv-for-php/pull/142
- Dropped support for PHP 5.4. Now, you need at leas PHP 5.5.
- Fixed parse()'s return value: return true only if $data is useful.
New features:
- Added support for Laravel-style collections via the - Added support for Laravel-style collections via the
new getCollection() function - see new getCollection() function - see
https://github.com/parsecsv/parsecsv-for-php/pull/134 https://github.com/parsecsv/parsecsv-for-php/pull/134
- New function getTotalDataRowCount() - useful if
$limit is set - see pull request #122.
- Added requires to keep Composer-free environments working.
Bug fixes:
- Better support for streams.
See https://github.com/parsecsv/parsecsv-for-php/pull/147
- Fixed output() with custom header.
See https://github.com/parsecsv/parsecsv-for-php/issues/132
- Fixed bug on _validate_fields_for_unparse() if titles property
is used instead of fields parameter for changing the titles for
unparsing.
- Fixed bug in unparse() that caused incorrect column order
(Issue #41).
Code quality:
- Improved test coverage.
----------------------------------- -----------------------------------

View File

@@ -1,4 +1,5 @@
# ParseCsv # ParseCsv
[![Financial Contributors on Open Collective](https://opencollective.com/parsecsv/all/badge.svg?label=financial+contributors)](https://opencollective.com/parsecsv)
ParseCsv is an easy-to-use PHP class that reads and writes CSV data properly. It ParseCsv is an easy-to-use PHP class that reads and writes CSV data properly. It
fully conforms to the specifications outlined on the on the fully conforms to the specifications outlined on the on the
@@ -103,7 +104,7 @@ $count = $csv->getTotalDataRowCount();
print_r($count); print_r($count);
``` ```
**Get most common data type for each column (Requires PHP >= 5.5)** **Get most common data type for each column**
```php ```php
$csv = new ParseCsv\Csv('data.csv'); $csv = new ParseCsv\Csv('data.csv');
@@ -113,6 +114,7 @@ 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 ParseCsv\Csv();
$csv->sort_by = 'id'; $csv->sort_by = 'id';
@@ -122,6 +124,14 @@ $csv->data[4] = array('firstname' => 'John', 'lastname' => 'Doe', 'email' => 'jo
$csv->save(); $csv->save();
``` ```
Enclose each data value by quotes:
```php
$csv = new ParseCsv\Csv();
$csv->parse('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
@@ -136,7 +146,7 @@ _Only recommended when you know the exact structure of the file._
```php ```php
$csv = new ParseCsv\Csv(); $csv = new ParseCsv\Csv();
$csv->save('data.csv', array(array('1986', 'Home', 'Nowhere', '')), true); $csv->save('data.csv', array(array('1986', 'Home', 'Nowhere', '')), /* append */ true);
``` ```
**Convert 2D array to CSV data and send headers to browser to treat output as **Convert 2D array to CSV data and send headers to browser to treat output as
@@ -147,7 +157,7 @@ $csv = new ParseCsv\Csv();
$csv->output('movies.csv', $array, array('field 1', 'field 2'), ','); $csv->output('movies.csv', $array, array('field 1', 'field 2'), ',');
``` ```
For more complex examples, see the ``tests`` and `examples` directories. For more complex examples, see the ``tests`` and `examples` directories.
## Credits ## Credits
@@ -160,11 +170,37 @@ For more complex examples, see the ``tests`` and `examples` directories.
## Contributors ## Contributors
### Code Contributors
This project exists thanks to all the people who contribute.
Please find a complete list on the project's [contributors][] page. Please find a complete list on the project's [contributors][] page.
[contributors]: https://github.com/parsecsv/parsecsv-for-php/graphs/contributors [contributors]: https://github.com/parsecsv/parsecsv-for-php/graphs/contributors
<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

View File

@@ -20,14 +20,13 @@
"homepage": "https://github.com/Fonata" "homepage": "https://github.com/Fonata"
} }
], ],
"autoload":{ "autoload": {
"psr-4":{ "psr-4": {
"ParseCsv\\": "src", "ParseCsv\\": "src"
"ParseCsv\\extensions\\": "src\\extensions"
} }
}, },
"autoload-dev":{ "autoload-dev": {
"psr-4":{ "psr-4": {
"ParseCsv\\tests\\": "tests" "ParseCsv\\tests\\": "tests"
} }
}, },
@@ -35,11 +34,17 @@
"php": ">=5.5" "php": ">=5.5"
}, },
"require-dev": { "require-dev": {
"phpunit/phpunit": "4.1.*" "phpunit/phpunit": "^6",
"squizlabs/php_codesniffer": "^3.5"
}, },
"suggest": { "suggest": {
"illuminate/support": "Fluent array interface for map functions" "illuminate/support": "Fluent array interface for map functions"
}, },
"extra": {
"branch-alias": {
"dev-master": "1.0.x-dev"
}
},
"support": { "support": {
"issues": "https://github.com/parsecsv/parsecsv-for-php/issues", "issues": "https://github.com/parsecsv/parsecsv-for-php/issues",
"source": "https://github.com/parsecsv/parsecsv-for-php" "source": "https://github.com/parsecsv/parsecsv-for-php"

View File

@@ -3,6 +3,7 @@
# include parseCSV class. # include parseCSV class.
require __DIR__ . '/../vendor/autoload.php'; require __DIR__ . '/../vendor/autoload.php';
use ParseCsv\Csv; use ParseCsv\Csv;
@@ -40,7 +41,7 @@ $csv->auto('_books.csv');
background-color: #FFF; background-color: #FFF;
} }
</style> </style>
<table border="0" cellspacing="1" cellpadding="3"> <table>
<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

@@ -4,6 +4,7 @@
# include parseCSV class. # include parseCSV class.
require __DIR__ . '/../vendor/autoload.php'; require __DIR__ . '/../vendor/autoload.php';
use ParseCsv\Csv; use ParseCsv\Csv;
@@ -16,6 +17,7 @@ $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.
@@ -41,7 +43,7 @@ $csv->auto('_books.csv');
background-color: #FFF; background-color: #FFF;
} }
</style> </style>
<table border="0" cellspacing="1" cellpadding="3"> <table>
<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

@@ -3,6 +3,7 @@
# include parseCSV class. # include parseCSV class.
require __DIR__ . '/../vendor/autoload.php'; require __DIR__ . '/../vendor/autoload.php';
use ParseCsv\Csv; use ParseCsv\Csv;
@@ -31,5 +32,3 @@ $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

@@ -4,6 +4,7 @@
# include parseCSV class. # include parseCSV class.
require __DIR__ . '/../vendor/autoload.php'; require __DIR__ . '/../vendor/autoload.php';
use ParseCsv\Csv; use ParseCsv\Csv;
@@ -54,7 +55,7 @@ $csv->auto('_books.csv');
background-color: #FFF; background-color: #FFF;
} }
</style> </style>
<table border="0" cellspacing="1" cellpadding="3"> <table>
<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

@@ -0,0 +1,27 @@
<?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');

3
ruleset.xml Normal file
View File

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

View File

@@ -151,7 +151,7 @@ class Csv {
public $auto_depth = 15; public $auto_depth = 15;
/** /**
* Auto Non Charts * Auto Non Chars
* Characters that should be ignored when attempting to auto-detect delimiter * Characters that should be ignored when attempting to auto-detect delimiter
* *
* @var string * @var string
@@ -169,7 +169,7 @@ class Csv {
/** /**
* Convert Encoding * Convert Encoding
* Should we convert the csv encoding? * Should we convert the CSV character encoding?
* *
* @var bool * @var bool
*/ */
@@ -278,8 +278,20 @@ class Csv {
public $error_info = array(); public $error_info = array();
/** /**
* Titles * $titles has 4 distinct tasks:
* CSV titles if they exists * 1. After reading in CSV data, $titles will contain the column headers
* present in the data.
*
* 2. It defines which fields from the $data array to write e.g. when
* calling unparse(), and in which order. This lets you skip columns you
* don't want in your output, but are present in $data.
* See examples/save_to_file_without_header_row.php.
*
* 3. It lets you rename columns. See StreamTest::testWriteStream for an
* example.
*
* 4. When writing data and $header is true, then $titles is also used for
* the first row.
* *
* @var array * @var array
*/ */
@@ -287,7 +299,7 @@ class Csv {
/** /**
* Data * Data
* Two dimensional array of CSV data * Two-dimensional array of CSV data
* *
* @var array * @var array
*/ */
@@ -299,16 +311,16 @@ class Csv {
* Constructor * Constructor
* Class constructor * Class constructor
* *
* @param string|null $input The CSV string or a direct filepath * @param string|null $input The CSV string or a direct file path
* @param integer|null $offset Number of rows to ignore from the * @param int|null $offset Number of rows to ignore from the
* beginning of the data * beginning of the data
* @param integer|null $limit Limits the number of returned rows * @param int|null $limit Limits the number of returned rows
* to specified amount * to specified amount
* @param string|null $conditions Basic SQL-like conditions for row * @param string|null $conditions Basic SQL-like conditions for row
* matching * matching
* @param null|true $keep_file_data Keep raw file data in memory after * @param null|true $keep_file_data Keep raw file data in memory after
* successful parsing * successful parsing
* (useful for debugging) * (useful for debugging)
*/ */
public function __construct($input = null, $offset = null, $limit = null, $conditions = null, $keep_file_data = null) { public function __construct($input = null, $offset = null, $limit = null, $conditions = null, $keep_file_data = null) {
$this->init($offset, $limit, $conditions, $keep_file_data); $this->init($offset, $limit, $conditions, $keep_file_data);
@@ -319,13 +331,13 @@ class Csv {
} }
/** /**
* @param integer|null $offset Number of rows to ignore from the * @param int|null $offset Number of rows to ignore from the
* beginning of the data * beginning of the data
* @param integer|null $limit Limits the number of returned rows * @param int|null $limit Limits the number of returned rows
* to specified amount * to specified amount
* @param string|null $conditions Basic SQL-like conditions for row * @param string|null $conditions Basic SQL-like conditions for row
* matching * matching
* @param null|true $keep_file_data Keep raw file data in memory after * @param null|true $keep_file_data Keep raw file data in memory after
* successful parsing * successful parsing
* (useful for debugging) * (useful for debugging)
*/ */
@@ -355,12 +367,12 @@ class Csv {
* Parse * Parse
* Parse a CSV file or string * Parse a CSV file or string
* *
* @param string|null $input The CSV string or a direct filepath * @param string|null $input The CSV string or a direct file path
* @param integer $offset Number of rows to ignore from the * @param int|null $offset Number of rows to ignore from the
* beginning of the data * beginning of the data
* @param integer $limit Limits the number of returned rows to * @param int|null $limit Limits the number of returned rows to
* specified amount * specified amount
* @param string $conditions Basic SQL-like conditions for row * @param string|null $conditions Basic SQL-like conditions for row
* matching * matching
* *
* @return bool True on success * @return bool True on success
@@ -378,11 +390,11 @@ class Csv {
if (strlen($input) <= PHP_MAXPATHLEN && is_readable($input)) { if (strlen($input) <= PHP_MAXPATHLEN && is_readable($input)) {
$this->file = $input; $this->file = $input;
$this->data = $this->parse_file(); $this->data = $this->_parse_file();
} else { } else {
$this->file = null; $this->file = null;
$this->file_data = &$input; $this->file_data = &$input;
$this->data = $this->parse_string(); $this->data = $this->_parse_string();
} }
return $this->data !== false; return $this->data !== false;
@@ -392,14 +404,15 @@ class Csv {
* Save * Save
* Save changes, or write a new file and/or data * Save changes, or write a new file and/or data
* *
* @param string $file File location to save to * @param string $file File location to save to
* @param array $data 2D array of data * @param array $data 2D array of data
* @param bool $append Append current data to end of target CSV, if file * @param bool $append Append current data to end of target CSV, if file
* exists * exists
* @param array $fields Field names. Sets the header. If it is not set * @param array $fields Field names. Sets the header. If it is not set
* $this->titles would be used instead. * $this->titles would be used instead.
* *
* @return bool * @return bool
* True on success
*/ */
public function save($file = '', $data = array(), $append = FileProcessingModeEnum::MODE_FILE_OVERWRITE, $fields = array()) { public function save($file = '', $data = array(), $append = FileProcessingModeEnum::MODE_FILE_OVERWRITE, $fields = array()) {
if (empty($file)) { if (empty($file)) {
@@ -416,16 +429,16 @@ class Csv {
* Output * Output
* Generate a CSV based string for output. * Generate a CSV based string for output.
* *
* @param string|null $filename If a filename is specified here or in the * @param string|null $filename If a filename is specified here or in the
* object, headers and data will be output * object, headers and data will be output
* directly to browser as a downloadable * directly to browser as a downloadable
* file. This file doesn't have to exist on * file. This file doesn't have to exist on
* the server; the parameter only affects * the server; the parameter only affects
* how the download is called to the * how the download is called to the
* browser. * browser.
* @param array[] $data 2D array with data * @param array[] $data 2D array with data
* @param array $fields Field names * @param array $fields Field names
* @param string|null $delimiter character used to separate data * @param string|null $delimiter character used to separate data
* *
* @return string The resulting CSV string * @return string The resulting CSV string
*/ */
@@ -461,8 +474,10 @@ class Csv {
* Encoding * Encoding
* Convert character encoding * Convert character encoding
* *
* @param string $input Input character encoding, uses default if left blank * @param string|null $input Input character encoding, uses default if left blank
* @param string $output Output character encoding, uses default if left blank * @param string|null $output Output character encoding, uses default if left blank
*
* @return void
*/ */
public function encoding($input = null, $output = null) { public function encoding($input = null, $output = null) {
$this->convert_encoding = true; $this->convert_encoding = true;
@@ -480,13 +495,13 @@ class Csv {
* Auto-Detect Delimiter: Find delimiter by analyzing a specific number of * Auto-Detect Delimiter: Find delimiter by analyzing a specific number of
* rows to determine most probable delimiter character * rows to determine most probable delimiter character
* *
* @param string|null $file Local CSV file * @param string|null $file Local CSV file
* @param bool $parse True/false parse file directly * @param bool $parse True/false parse file directly
* @param int $search_depth Number of rows to analyze * @param int|null $search_depth Number of rows to analyze
* @param string $preferred Preferred delimiter characters * @param string|null $preferred Preferred delimiter characters
* @param string|null $enclosure Enclosure character, default is double quote ("). * @param string|null $enclosure Enclosure character, default is double quote (").
* *
* @return string The detected field delimiter * @return string|false The detected field delimiter
*/ */
public function auto($file = null, $parse = true, $search_depth = null, $preferred = null, $enclosure = null) { public function auto($file = null, $parse = true, $search_depth = null, $preferred = null, $enclosure = null) {
if (is_null($file)) { if (is_null($file)) {
@@ -523,7 +538,7 @@ class Csv {
// parse data // parse data
if ($parse) { if ($parse) {
$this->data = $this->parse_string(); $this->data = $this->_parse_string();
} }
return $this->delimiter; return $this->delimiter;
@@ -559,12 +574,10 @@ class Csv {
$headingRow = $this->heading ? 1 : 0; $headingRow = $this->heading ? 1 : 0;
$count = substr_count($data, "\r") return substr_count($data, "\r")
+ substr_count($data, "\n") + substr_count($data, "\n")
- substr_count($data, "\r\n") - substr_count($data, "\r\n")
- $headingRow; - $headingRow;
return $count;
} }
// ============================================== // ==============================================
@@ -573,13 +586,13 @@ class Csv {
/** /**
* Parse File * Parse File
* Read file to string and call parse_string() * Read file to string and call _parse_string()
* *
* @param string|null $file Local CSV file * @param string|null $file Local CSV file
* *
* @return array|bool * @return array|bool
*/ */
protected function parse_file($file = null) { protected function _parse_file($file = null) {
if (is_null($file)) { if (is_null($file)) {
$file = $this->file; $file = $this->file;
} }
@@ -588,21 +601,23 @@ class Csv {
$this->load_data($file); $this->load_data($file);
} }
return !empty($this->file_data) ? $this->parse_string() : false; return !empty($this->file_data) ? $this->_parse_string() : false;
} }
/** /**
* Parse CSV strings to arrays. If you need BOM detection or character * Internal function to parse CSV strings to arrays.
* encoding conversion, please call load_data() first, followed by a call to *
* parse_string() with no parameters. * If you need BOM detection or character encoding conversion, please call
* $csv->load_data($your_data_string) first, followed by a call to
* $csv->parse($csv->file_data).
* *
* To detect field separators, please use auto() instead. * To detect field separators, please use auto() instead.
* *
* @param string $data CSV data * @param string|null $data CSV data
* *
* @return array|false - 2D array with CSV data, or false on failure * @return array|false - 2D array with CSV data, or false on failure
*/ */
protected function parse_string($data = null) { protected function _parse_string($data = null) {
if (empty($data)) { if (empty($data)) {
if ($this->_check_data()) { if ($this->_check_data()) {
$data = &$this->file_data; $data = &$this->file_data;
@@ -625,7 +640,7 @@ class Csv {
// force the parser to process end of data as a character (false) when // force the parser to process end of data as a character (false) when
// data does not end with a line feed or carriage return character. // data does not end with a line feed or carriage return character.
$lch = $data{$strlen - 1}; $lch = $data[$strlen - 1];
if ($lch != "\n" && $lch != "\r") { if ($lch != "\n" && $lch != "\r") {
$data .= "\n"; $data .= "\n";
$strlen++; $strlen++;
@@ -633,8 +648,8 @@ class Csv {
// walk through each character // walk through each character
for ($i = 0; $i < $strlen; $i++) { for ($i = 0; $i < $strlen; $i++) {
$ch = isset($data{$i}) ? $data{$i} : false; $ch = isset($data[$i]) ? $data[$i] : false;
$nch = isset($data{$i + 1}) ? $data{$i + 1} : false; $nch = isset($data[$i + 1]) ? $data[$i + 1] : false;
// open/close quotes, and inline quotes // open/close quotes, and inline quotes
if ($ch == $this->enclosure) { if ($ch == $this->enclosure) {
@@ -664,10 +679,10 @@ class Csv {
$i++; $i++;
} elseif ($nch != $this->delimiter && $nch != "\r" && $nch != "\n") { } elseif ($nch != $this->delimiter && $nch != "\r" && $nch != "\n") {
$x = $i + 1; $x = $i + 1;
while (isset($data{$x}) && ltrim($data{$x}, $white_spaces) == '') { while (isset($data[$x]) && ltrim($data[$x], $white_spaces) == '') {
$x++; $x++;
} }
if ($data{$x} == $this->delimiter) { if ($data[$x] == $this->delimiter) {
$enclosed = false; $enclosed = false;
$i = $x; $i = $x;
} else { } else {
@@ -707,7 +722,7 @@ class Csv {
$col++; $col++;
// end of row // end of row
if ($ch == "\n" || $ch == "\r" || $ch === false) { if (in_array($ch, ["\n", "\r", false], true)) {
if ($this->_validate_offset($row_count) && $this->_validate_row_conditions($row, $this->conditions)) { if ($this->_validate_offset($row_count) && $this->_validate_row_conditions($row, $this->conditions)) {
if ($this->heading && empty($head)) { if ($this->heading && empty($head)) {
$head = $row; $head = $row;
@@ -830,13 +845,28 @@ class Csv {
} }
if ($this->convert_encoding) { if ($this->convert_encoding) {
$string = iconv($this->input_encoding, $this->output_encoding, $string); /** @noinspection PhpComposerExtensionStubsInspection
*
* If you receive an error at the following 3 lines, you must enable
* the following PHP extension:
*
* - if $use_mb_convert_encoding is true: mbstring
* - if $use_mb_convert_encoding is false: iconv
*/
$string = $this->use_mb_convert_encoding ?
mb_convert_encoding($string, $this->output_encoding, $this->input_encoding) :
iconv($this->input_encoding, $this->output_encoding, $string);
} }
return $string; return $string;
} }
private function _validate_fields_for_unparse($fields) { /**
* @param array $fields
*
* @return array|false
*/
private function _validate_fields_for_unparse(array $fields) {
if (empty($fields)) { if (empty($fields)) {
$fields = $this->titles; $fields = $this->titles;
} }
@@ -846,10 +876,10 @@ class Csv {
} }
// this is needed because sometime titles property is overwritten instead of using fields parameter! // this is needed because sometime titles property is overwritten instead of using fields parameter!
$titlesOnParse = !empty($this->data) ? array_keys($this->data[0]) : array(); $titlesOnParse = !empty($this->data) ? array_keys(reset($this->data)) : array();
// both are identical, also in ordering // both are identical, also in ordering OR we have no data (only titles)
if (array_values($fields) === array_values($titlesOnParse)) { if (empty($titlesOnParse) || array_values($fields) === array_values($titlesOnParse)) {
return array_combine($fields, $fields); return array_combine($fields, $fields);
} }
@@ -877,11 +907,16 @@ class Csv {
} }
/** /**
* Load local file or string * Load local file or string.
* *
* @param string|null $input local CSV file * Only use this function if auto() and parse() don't handle your data well.
* *
* @return true or false * This function load_data() is able to handle BOMs and encodings. The data
* is stored within the $this->file_data class field.
*
* @param string|null $input local CSV file or CSV data as a string
*
* @return bool True on success
*/ */
public function load_data($input = null) { public function load_data($input = null) {
$data = null; $data = null;
@@ -889,9 +924,10 @@ class Csv {
if (is_null($input)) { if (is_null($input)) {
$file = $this->file; $file = $this->file;
} elseif (file_exists($input)) { } elseif (\strlen($input) <= PHP_MAXPATHLEN && file_exists($input)) {
$file = $input; $file = $input;
} else { } else {
// It is CSV data as a string.
$data = $input; $data = $input;
} }
@@ -919,6 +955,14 @@ class Csv {
} }
if ($this->convert_encoding && $this->input_encoding !== $this->output_encoding) { if ($this->convert_encoding && $this->input_encoding !== $this->output_encoding) {
/** @noinspection PhpComposerExtensionStubsInspection
*
* If you receive an error at the following 3 lines, you must enable
* the following PHP extension:
*
* - if $use_mb_convert_encoding is true: mbstring
* - if $use_mb_convert_encoding is false: iconv
*/
$data = $this->use_mb_convert_encoding ? $data = $this->use_mb_convert_encoding ?
mb_convert_encoding($data, $this->output_encoding, $this->input_encoding) : mb_convert_encoding($data, $this->output_encoding, $this->input_encoding) :
iconv($this->input_encoding, $this->output_encoding, $data); iconv($this->input_encoding, $this->output_encoding, $data);
@@ -1015,10 +1059,22 @@ class Csv {
if (preg_match('/^(.+) (' . $operators_regex . ') (.+)$/i', trim($condition), $capture)) { if (preg_match('/^(.+) (' . $operators_regex . ') (.+)$/i', trim($condition), $capture)) {
$field = $capture[1]; $field = $capture[1];
$op = $capture[2]; $op = strtolower($capture[2]);
$value = $capture[3]; $value = $capture[3];
if ($op == 'equals' && preg_match('/^(.+) is (less|greater) than or$/i', $field, $m)) {
$field = $m[1];
$op = strtolower($m[2]) == 'less' ? '<=' : '>=';
}
if ($op == 'is' && preg_match('/^(less|greater) than (.+)$/i', $value, $m)) {
$value = $m[2];
$op = strtolower($m[1]) == 'less' ? '<' : '>';
}
if ($op == 'is' && preg_match('/^not (.+)$/i', $value, $m)) {
$value = $m[1];
$op = '!=';
}
if (preg_match('/^([\'\"]{1})(.*)([\'\"]{1})$/', $value, $capture) && $capture[1] == $capture[3]) { if (preg_match('/^([\'"])(.*)([\'"])$/', $value, $capture) && $capture[1] == $capture[3]) {
$value = strtr($capture[2], array( $value = strtr($capture[2], array(
"\\n" => "\n", "\\n" => "\n",
"\\r" => "\r", "\\r" => "\r",
@@ -1029,7 +1085,8 @@ class Csv {
} }
if (array_key_exists($field, $row)) { if (array_key_exists($field, $row)) {
if (($op == '=' || $op == 'equals' || $op == 'is') && $row[$field] == $value) { $op_equals = in_array($op, ['=', 'equals', 'is'], true);
if ($op_equals && $row[$field] == $value) {
return '1'; return '1';
} elseif (($op == '!=' || $op == 'is not') && $row[$field] != $value) { } elseif (($op == '!=' || $op == 'is not') && $row[$field] != $value) {
return '1'; return '1';
@@ -1073,19 +1130,19 @@ class Csv {
* Enclose values if needed * Enclose values if needed
* - only used by unparse() * - only used by unparse()
* *
* @param string $value Cell value to process * @param string|null $value Cell value to process
* @param string $delimiter Character to put between cells on the same row * @param string $delimiter Character to put between cells on the same row
* *
* @return string Processed value * @return string Processed value
*/ */
protected function _enclose_value($value = null, $delimiter) { protected function _enclose_value($value, $delimiter) {
if ($value !== null && $value != '') { if ($value !== null && $value != '') {
$delimiter_quoted = $delimiter ? $delimiter_quoted = $delimiter ?
preg_quote($delimiter, '/') . "|" preg_quote($delimiter, '/') . "|"
: ''; : '';
$enclosure_quoted = preg_quote($this->enclosure, '/'); $enclosure_quoted = preg_quote($this->enclosure, '/');
$pattern = "/" . $delimiter_quoted . $enclosure_quoted . "|\n|\r/i"; $pattern = "/" . $delimiter_quoted . $enclosure_quoted . "|\n|\r/i";
if ($this->enclose_all || preg_match($pattern, $value) || ($value{0} == ' ' || substr($value, -1) == ' ')) { if ($this->enclose_all || preg_match($pattern, $value) || strpos($value, ' ') === 0 || substr($value, -1) == ' ') {
$value = str_replace($this->enclosure, $this->enclosure . $this->enclosure, $value); $value = str_replace($this->enclosure, $this->enclosure . $this->enclosure, $value);
$value = $this->enclosure . $value . $this->enclosure; $value = $this->enclosure . $value . $this->enclosure;
} }
@@ -1097,7 +1154,7 @@ class Csv {
/** /**
* Check file data * Check file data
* *
* @param string|null $file local filename * @param string|null $file local filename
* *
* @return bool * @return bool
*/ */
@@ -1117,10 +1174,10 @@ class Csv {
* Check if passed info might be delimiter * Check if passed info might be delimiter
* Only used by find_delimiter * Only used by find_delimiter
* *
* @param string $char Potential field separating character * @param string $char Potential field separating character
* @param array $array Frequency * @param array $array Frequency
* @param int $depth Number of analyzed rows * @param int $depth Number of analyzed rows
* @param string $preferred Preferred delimiter characters * @param string $preferred Preferred delimiter characters
* *
* @return string|false special string used for delimiter selection, or false * @return string|false special string used for delimiter selection, or false
*/ */
@@ -1177,12 +1234,14 @@ class Csv {
/** /**
* Write to local file * Write to local file
* *
* @param string $file local filename * @param string $file local filename
* @param string $content data to write to file * @param string $content data to write to file
* @param string $mode fopen() mode * @param string $mode fopen() mode
* @param int $lock flock() mode * @param int $lock flock() mode
*
* @return bool
* True on success
* *
* @return true or false
*/ */
protected function _wfile($file, $content = '', $mode = 'wb', $lock = LOCK_EX) { protected function _wfile($file, $content = '', $mode = 'wb', $lock = LOCK_EX) {
if ($fp = fopen($file, $mode)) { if ($fp = fopen($file, $mode)) {
@@ -1244,7 +1303,6 @@ class Csv {
} }
// remove delimiter and its line-end (the data param is by-ref!) // remove delimiter and its line-end (the data param is by-ref!)
/** @noinspection CallableParameterUseCaseInTypeContextInspection */
$data_string = substr($data_string, $pos); $data_string = substr($data_string, $pos);
return true; return true;
} }
@@ -1255,7 +1313,7 @@ class Csv {
* @param string $enclosure Enclosure character, default is double quote * @param string $enclosure Enclosure character, default is double quote
* @param string $data The file content * @param string $data The file content
*/ */
protected function _guess_delimiter($search_depth, $preferred, $enclosure, &$data) { protected function _guess_delimiter($search_depth, $preferred, $enclosure, $data) {
$chars = []; $chars = [];
$strlen = strlen($data); $strlen = strlen($data);
$enclosed = false; $enclosed = false;
@@ -1270,9 +1328,9 @@ class Csv {
// walk specific depth finding possible delimiter characters // walk specific depth finding possible delimiter characters
for ($i = 0; $i < $strlen; $i++) { for ($i = 0; $i < $strlen; $i++) {
$ch = $data{$i}; $ch = $data[$i];
$nch = isset($data{$i + 1}) ? $data{$i + 1} : false; $nch = isset($data[$i + 1]) ? $data[$i + 1] : false;
$pch = isset($data{$i - 1}) ? $data{$i - 1} : false; $pch = isset($data[$i - 1]) ? $data[$i - 1] : false;
// open and closing quotes // open and closing quotes
$is_newline = ($ch == "\n" && $pch != "\r") || $ch == "\r"; $is_newline = ($ch == "\n" && $pch != "\r") || $ch == "\r";

View File

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

View File

@@ -19,7 +19,7 @@ class FileProcessingModeEnum {
const MODE_FILE_OVERWRITE = false; const MODE_FILE_OVERWRITE = false;
public static function getAppendMode($mode) { public static function getAppendMode($mode) {
if ($mode == self::MODE_FILE_APPEND){ if ($mode == self::MODE_FILE_APPEND) {
return 'ab'; return 'ab';
} }

View File

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

View File

@@ -7,10 +7,10 @@ use ParseCsv\enums\DatatypeEnum;
trait DatatypeTrait { trait DatatypeTrait {
/** /**
* Datatypes * Data Types
* Datatypes of CSV data-columns * Data types of CSV data-columns, keyed by the column name. Possible values
* are string, float, integer, boolean, date. See DatatypeEnum.
* *
* @access public
* @var array * @var array
*/ */
public $data_types = []; public $data_types = [];
@@ -19,8 +19,6 @@ trait DatatypeTrait {
* Check data type for one column. * Check data type for one column.
* Check for most commonly data type for one column. * Check for most commonly data type for one column.
* *
* @access private
*
* @param array $datatypes * @param array $datatypes
* *
* @return string|false * @return string|false
@@ -47,15 +45,13 @@ trait DatatypeTrait {
* *
* Requires PHP >= 5.5 * Requires PHP >= 5.5
* *
* @access public
*
* @uses DatatypeEnum::getValidTypeFromSample * @uses DatatypeEnum::getValidTypeFromSample
* *
* @return array|bool * @return array|bool
*/ */
public function getDatatypes() { public function getDatatypes() {
if (empty($this->data)) { if (empty($this->data)) {
$this->data = $this->parse_string(); $this->data = $this->_parse_string();
} }
if (!is_array($this->data)) { if (!is_array($this->data)) {
throw new \UnexpectedValueException('No data set yet.'); throw new \UnexpectedValueException('No data set yet.');
@@ -80,34 +76,28 @@ trait DatatypeTrait {
* *
* Requires PHP >= 5.5 * Requires PHP >= 5.5
* *
* @access public
*
* @uses DatatypeEnum::getValidTypeFromSample * @uses DatatypeEnum::getValidTypeFromSample
* *
* @return bool * @return bool
*/ */
public function autoDetectFileHasHeading(){ public function autoDetectFileHasHeading() {
if (empty($this->data)){ if (empty($this->data)) {
throw new \UnexpectedValueException('No data set yet.'); throw new \UnexpectedValueException('No data set yet.');
} }
if ($this->heading){ if ($this->heading) {
$firstRow = $this->titles; $firstRow = $this->titles;
} else { } else {
$firstRow = $this->data[0]; $firstRow = $this->data[0];
} }
$firstRow = array_filter($firstRow); $firstRow = array_filter($firstRow);
if (empty($firstRow)){ if (empty($firstRow)) {
return false; return false;
} }
$firstRowDatatype = array_map(DatatypeEnum::class . '::getValidTypeFromSample', $firstRow); $firstRowDatatype = array_map(DatatypeEnum::class . '::getValidTypeFromSample', $firstRow);
if ($this->getMostFrequentDatatypeForColumn($firstRowDatatype) !== DatatypeEnum::TYPE_STRING){ return $this->getMostFrequentDatatypeForColumn($firstRowDatatype) === DatatypeEnum::TYPE_STRING;
return false;
}
return true;
} }
} }

View File

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

View File

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

View File

@@ -59,7 +59,9 @@ class ConstructTest extends TestCase {
/** @noinspection PhpIncludeInspection */ /** @noinspection PhpIncludeInspection */
require $script_file; require $script_file;
$ob_get_clean = ob_get_clean(); $ob_get_clean = ob_get_clean();
if ($script_file != 'download.php') { $verb = strtok($script_file, '_.');
if (!in_array($verb, ['download', 'save'], true)) {
$this->assertContains('<td>', $ob_get_clean); $this->assertContains('<td>', $ob_get_clean);
} }
} }

View File

@@ -8,12 +8,12 @@
namespace ParseCsv\tests\methods; namespace ParseCsv\tests\methods;
use PHPUnit\Framework\TestCase;
use ParseCsv\enums\DatatypeEnum; use ParseCsv\enums\DatatypeEnum;
use PHPUnit\Framework\TestCase;
class DatatypeTest extends TestCase class DatatypeTest extends TestCase {
{
public function testSampleIsValidInteger(){ 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->assertEquals(DatatypeEnum::TYPE_INT, DatatypeEnum::getValidTypeFromSample('+1'));
$this->assertEquals(DatatypeEnum::TYPE_INT, DatatypeEnum::getValidTypeFromSample('-1')); $this->assertEquals(DatatypeEnum::TYPE_INT, DatatypeEnum::getValidTypeFromSample('-1'));
@@ -27,7 +27,7 @@ class DatatypeTest extends TestCase
$this->assertNotEquals(DatatypeEnum::TYPE_INT, DatatypeEnum::getValidTypeFromSample('2018-02-19')); $this->assertNotEquals(DatatypeEnum::TYPE_INT, DatatypeEnum::getValidTypeFromSample('2018-02-19'));
} }
public function testSampleIsValidBool(){ 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('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'));
@@ -39,7 +39,7 @@ class DatatypeTest extends TestCase
$this->assertNotEquals(DatatypeEnum::TYPE_BOOL, DatatypeEnum::getValidTypeFromSample('0.1')); $this->assertNotEquals(DatatypeEnum::TYPE_BOOL, DatatypeEnum::getValidTypeFromSample('0.1'));
} }
public function testSampleIsValidFloat(){ public function testSampleIsValidFloat() {
$this->assertEquals(DatatypeEnum::TYPE_FLOAT, DatatypeEnum::getValidTypeFromSample('1.0')); $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'));
@@ -54,7 +54,7 @@ class DatatypeTest extends TestCase
$this->assertNotEquals(DatatypeEnum::TYPE_FLOAT, DatatypeEnum::getValidTypeFromSample('2018-02-19')); $this->assertNotEquals(DatatypeEnum::TYPE_FLOAT, DatatypeEnum::getValidTypeFromSample('2018-02-19'));
} }
public function testSampleIsValidDate(){ public function testSampleIsValidDate() {
$this->assertEquals(DatatypeEnum::TYPE_DATE, DatatypeEnum::getValidTypeFromSample('2018-02-19')); $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('18-2-19'));
$this->assertEquals(DatatypeEnum::TYPE_DATE, DatatypeEnum::getValidTypeFromSample('01.02.2018')); $this->assertEquals(DatatypeEnum::TYPE_DATE, DatatypeEnum::getValidTypeFromSample('01.02.2018'));

View File

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

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

@@ -4,6 +4,7 @@ namespace ParseCsv\tests\methods;
use ParseCsv\Csv; use ParseCsv\Csv;
use PHPUnit\Framework\TestCase; use PHPUnit\Framework\TestCase;
use ReflectionClass;
class ParseTest extends TestCase { class ParseTest extends TestCase {
@@ -28,6 +29,9 @@ class ParseTest extends TestCase {
$this->parseRepetitiveString('http://looks/like/an/url'); $this->parseRepetitiveString('http://looks/like/an/url');
} }
/**
* @param string $content
*/
private function parseRepetitiveString($content) { private function parseRepetitiveString($content) {
$this->csv->delimiter = ';'; $this->csv->delimiter = ';';
$this->csv->heading = false; $this->csv->heading = false;
@@ -56,6 +60,9 @@ class ParseTest extends TestCase {
$this->assertEquals($this->_get_magazines_data(), $this->csv->data); $this->assertEquals($this->_get_magazines_data(), $this->csv->data);
} }
/**
* @return array
*/
public function autoDetectionProvider() { public function autoDetectionProvider() {
return [ return [
'UTF8_no_BOM' => [__DIR__ . '/../example_files/UTF-8_sep_row_but_no_BOM.csv'], 'UTF8_no_BOM' => [__DIR__ . '/../example_files/UTF-8_sep_row_but_no_BOM.csv'],
@@ -66,7 +73,9 @@ class ParseTest extends TestCase {
public function testSingleColumnWithZeros() { public function testSingleColumnWithZeros() {
$this->csv->delimiter = null; $this->csv->delimiter = null;
$this->csv->parse("URL\nhttp://www.amazon.com/ROX-Ice-Ball-Maker-Original/dp/B00MX59NMQ/ref=sr_1_1?ie=UTF8&qid=1435604374&sr=8-1&keywords=rox,+ice+molds"); $this->csv->parse(
"URL\nhttp://www.amazon.com/ROX-Ice-Ball-Maker-Original/dp/B00MX59NMQ/ref=sr_1_1?ie=UTF8&qid=1435604374&sr=8-1&keywords=rox,+ice+molds"
);
$row = array_pop($this->csv->data); $row = array_pop($this->csv->data);
$expected_data = ['URL' => 'http://www.amazon.com/ROX-Ice-Ball-Maker-Original/dp/B00MX59NMQ/ref=sr_1_1?ie=UTF8&qid=1435604374&sr=8-1&keywords=rox,+ice+molds']; $expected_data = ['URL' => 'http://www.amazon.com/ROX-Ice-Ball-Maker-Original/dp/B00MX59NMQ/ref=sr_1_1?ie=UTF8&qid=1435604374&sr=8-1&keywords=rox,+ice+molds'];
$this->assertEquals($expected_data, $row); $this->assertEquals($expected_data, $row);
@@ -88,14 +97,17 @@ class ParseTest extends TestCase {
$sInput = "86545235689,a\r\n34365587654,b\r\n13469874576,\"c\r\nd\""; $sInput = "86545235689,a\r\n34365587654,b\r\n13469874576,\"c\r\nd\"";
$expected_data = [86545235689, 34365587654, 13469874576]; $expected_data = [86545235689, 34365587654, 13469874576];
$actual_data = $this->invokeMethod($this->csv, 'parse_string', array($sInput)); $actual_data = $this->invokeMethod($this->csv, '_parse_string', [$sInput]);
$actual_column = array_map('reset', $actual_data); $actual_column = array_map('reset', $actual_data);
$this->assertEquals($expected_data, $actual_column); $this->assertEquals($expected_data, $actual_column);
$this->assertEquals([ $this->assertEquals(
'a', [
'b', 'a',
"c\r\nd", 'b',
], array_map('next', $actual_data)); "c\r\nd",
],
array_map('next', $actual_data)
);
} }
public function testSingleColumn() { public function testSingleColumn() {
@@ -115,18 +127,57 @@ class ParseTest extends TestCase {
$this->csv->output_encoding = 'UTF-8'; $this->csv->output_encoding = 'UTF-8';
$this->csv->auto(__DIR__ . '/../example_files/Piwik_API_download.csv'); $this->csv->auto(__DIR__ . '/../example_files/Piwik_API_download.csv');
$aAction27 = array_column($this->csv->data, 'url (actionDetails 27)'); $aAction27 = array_column($this->csv->data, 'url (actionDetails 27)');
$this->assertEquals([ $this->assertEquals(
'http://application/_Main/_GraphicMeanSTD_MDI/btnConfBandOptions', [
'', 'http://application/_Main/_GraphicMeanSTD_MDI/btnConfBandOptions',
'', '',
], $aAction27); '',
],
$aAction27
);
$aCity = array_column($this->csv->data, 'city'); $aCity = array_column($this->csv->data, 'city');
$this->assertEquals(
[
'São Paulo',
'Johannesburg',
'',
],
$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->load_data($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([ $this->assertEquals([
'São Paulo', 'title',
'Johannesburg', 'isbn',
'', 'publishedAt',
], $aCity); ], array_keys(reset($this->csv->data)));
$titles = array_column($this->csv->data, 'title');
$this->assertEquals([
'Красивая кулинария',
'The Wine Connoisseurs',
'Weißwein',
], $titles);
} }
public function testWithMultipleNewlines() { public function testWithMultipleNewlines() {
@@ -188,6 +239,17 @@ class ParseTest extends TestCase {
$this->assertFalse($this->csv->autoDetectFileHasHeading()); $this->assertFalse($this->csv->autoDetectFileHasHeading());
} }
/**
* @doesNotPerformAssertions
*/
public function testVeryLongNonExistingFile() {
$this->csv->parse(str_repeat('long_string', PHP_MAXPATHLEN));
$this->csv->auto(str_repeat('long_string', PHP_MAXPATHLEN));
}
/**
* @return array
*/
protected function _get_magazines_data() { protected function _get_magazines_data() {
return [ return [
[ [
@@ -208,7 +270,11 @@ class ParseTest extends TestCase {
]; ];
} }
public function autoQuotesDataProvider() { /**
* @return array
*/
public function autoQuotesDataProvider(): array
{
return array( return array(
array('auto-double-enclosure.csv', '"'), array('auto-double-enclosure.csv', '"'),
array('auto-single-enclosure.csv', "'"), array('auto-single-enclosure.csv', "'"),
@@ -233,14 +299,14 @@ class ParseTest extends TestCase {
/** /**
* Call protected/private method of a class. * Call protected/private method of a class.
* *
* @param object &$object Instantiated object that we will run method on. * @param object $object Instantiated object that we will run method on.
* @param string $methodName Method name to call * @param string $methodName Method name to call
* @param array $parameters Array of parameters to pass into method. * @param array $parameters Array of parameters to pass into method.
* *
* @return mixed Method return. * @return mixed Method return.
*/ */
private function invokeMethod(&$object, $methodName, array $parameters = array()) { private function invokeMethod($object, $methodName, $parameters = []) {
$reflection = new \ReflectionClass(get_class($object)); $reflection = new ReflectionClass(get_class($object));
$method = $reflection->getMethod($methodName); $method = $reflection->getMethod($methodName);
$method->setAccessible(true); $method->setAccessible(true);
@@ -248,7 +314,7 @@ class ParseTest extends TestCase {
} }
public function testWaiverFieldSeparator() { public function testWaiverFieldSeparator() {
$this->assertSame(false, $this->csv->auto(__DIR__ . '/../example_files/waiver_field_separator.csv')); $this->assertFalse($this->csv->auto(__DIR__ . '/../example_files/waiver_field_separator.csv'));
$expected = [ $expected = [
'liability waiver', 'liability waiver',
'release of liability form', 'release of liability form',

View File

@@ -1,11 +1,11 @@
<?php <?php
namespace ParseCsv\tests\methods; namespace ParseCsv\tests\methods;
use ParseCsv\Csv; use ParseCsv\Csv;
use PHPUnit\Framework\TestCase; use PHPUnit\Framework\TestCase;
class SaveTest extends TestCase class SaveTest extends TestCase {
{
/** @var Csv */ /** @var Csv */
private $csv; private $csv;

View File

@@ -0,0 +1,71 @@
<?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 {
public function setUp() {
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

@@ -75,6 +75,31 @@ class UnparseTest extends Testcase {
$this->unparseAndCompare($expected, $fields); $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()) { private function unparseAndCompare($expected, $fields = array()) {
$str = $this->csv->unparse($this->csv->data, $fields); $str = $this->csv->unparse($this->csv->data, $fields);
$this->assertEquals($expected, $str); $this->assertEquals($expected, $str);

View File

@@ -11,7 +11,6 @@ class BaseClass extends TestCase {
* CSV * CSV
* The parseCSV object * The parseCSV object
* *
* @access protected
* @var Csv * @var Csv
*/ */
protected $csv; protected $csv;
@@ -19,10 +18,8 @@ class BaseClass extends TestCase {
/** /**
* Setup * Setup
* Setup our test environment objects * Setup our test environment objects
*
* @access public
*/ */
public function setUp() { protected function setUp() {
$this->csv = new Csv(); $this->csv = new Csv();
} }

View File

@@ -21,21 +21,93 @@ class ConditionsTest extends BaseClass {
]); ]);
} }
public function testRating() { public function testRatingEquals() {
$this->csv->conditions = 'rating < 3'; $rating_of_3 = [
$this->_compareWithExpected([ 'The Last Templar',
'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);
}
$this->csv->conditions = 'rating >= 5'; public function testRatingLessThan() {
$this->_compareWithExpected([ $less_than_1 = [
'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

@@ -6,6 +6,7 @@ namespace ParseCsv\tests\properties;
* Tests related to the $offset property * Tests related to the $offset property
*/ */
class OffsetTest extends BaseClass { class OffsetTest extends BaseClass {
public function testOffsetOfOne() { public function testOffsetOfOne() {
$this->csv->offset = 1; $this->csv->offset = 1;
$this->csv->auto(__DIR__ . '/../methods/fixtures/datatype.csv'); $this->csv->auto(__DIR__ . '/../methods/fixtures/datatype.csv');

View File

@@ -147,25 +147,25 @@ class PublicPropertiesTest extends TestCase {
$this->assertCount($counter, $this->properties); $this->assertCount($counter, $this->properties);
} }
public function testDefaultSortTypeIsRegular(){ public function testDefaultSortTypeIsRegular() {
$this->assertEquals(SortEnum::SORT_TYPE_REGULAR, $this->csv->sort_type); $this->assertEquals(SortEnum::SORT_TYPE_REGULAR, $this->csv->sort_type);
} }
public function testSetSortType(){ public function testSetSortType() {
$this->csv->sort_type = 'numeric'; $this->csv->sort_type = 'numeric';
$this->assertEquals(SortEnum::SORT_TYPE_NUMERIC, $this->csv->sort_type); $this->assertEquals(SortEnum::SORT_TYPE_NUMERIC, $this->csv->sort_type);
$this->csv->sort_type = 'string'; $this->csv->sort_type = 'string';
$this->assertEquals(SortEnum::SORT_TYPE_STRING, $this->csv->sort_type); $this->assertEquals(SortEnum::SORT_TYPE_STRING, $this->csv->sort_type);
} }
public function testGetSorting(){ public function testGetSorting() {
$this->csv->sort_type = 'numeric'; $this->csv->sort_type = 'numeric';
$sorting = SortEnum::getSorting($this->csv->sort_type); $sorting = SortEnum::getSorting($this->csv->sort_type);
$this->assertEquals(SORT_NUMERIC, $sorting); $this->assertEquals(SORT_NUMERIC, $sorting);
$this->csv->sort_type = 'string'; $this->csv->sort_type = 'string';
$sorting = SortEnum::getSorting($this->csv->sort_type); $sorting = SortEnum::getSorting($this->csv->sort_type);
$this->assertEquals(SORT_STRING, $sorting); $this->assertEquals(SORT_STRING, $sorting);
} }
} }