453 Commits
0.4.0 ... 1.3.2

Author SHA1 Message Date
Fonata
2d6236cae0 docs(changelog): add version 1.3.2 2021-11-07 15:15:46 +01:00
Fonata
f2b0aecd12 docs: remove Travis from README; make running act locally easier 2021-11-07 13:36:38 +01:00
Fonata
5d4643b201 Allow _guess_delimiter to work with a single row of data
Fix #206
2021-11-07 13:36:38 +01:00
d5606f8b2a ci(travis): remove .travis.yml config file
If we're switching to GitHub Actions, there's no need to keep the
Travis-CI config file around.
2021-11-07 13:36:38 +01:00
8cebcbd9bb ci(github): add GitHub Actions CI workflow
Can be tested locally via the local-ci make target, which requires
Docker and act (https://github.com/nektos/act).
2021-11-07 13:36:38 +01:00
518f5081fb chore: improve editorconfig for YAML and Makefile 2021-11-07 13:36:38 +01:00
Fonata
a28fc6ab0a refactor: simplify code without changing behavior 2021-11-07 13:36:38 +01:00
Fonata
009820d190 Explicit email address for security problems 2021-06-20 23:25:35 +02:00
Fonata
facdf1c06c Set release date 2021-06-20 23:25:26 +02:00
Fonata
ee13c17157 Apply PhpStorm source code formatting 2021-06-20 23:21:46 +02:00
Fonata
99daaa7235 Bugfix: $csv->parseFile now sets $this->data
This adds consistency because $csv->parse() does the same.

Fix #200
Fix #201
2021-06-20 23:21:46 +02:00
Fonata
05826c2bbf Make return value of parseFile() explicit as false if parsing failed
In practise this changes nothing because $this->file_data would typically be empty.
The only exception is if the object was reused from a previous parsing operation.
2021-06-20 23:21:46 +02:00
Fonata
731900effe DocBlock types: Use Psalm notation for 2-dimensional array 2021-06-20 23:21:46 +02:00
Fonata
913c3b1b94 Source code comments: add more information to DocBlocks 2021-06-20 23:21:46 +02:00
Fonata
96b2784d3c Source code comments: don’t repeat the field we are describing
The motivation for this change is how the PhpStorm IDE displays help texts.
Because the enter is shown as a space in the tooltips/help hovers, the
previous version was harder to read than after this commit.
2021-06-20 23:21:46 +02:00
Fonata
be01bc9ae4 README.md: Fix incorrect constructor usage 2021-05-03 21:26:56 +02:00
Fonata
b444afae2f Specify release date 2021-04-14 20:14:01 +02:00
Fonata
bd6befe01e Remove low-value comment 2021-04-14 20:12:43 +02:00
Fonata
05ed8ec667 Rename parameter to reduce confusion 2021-04-14 20:12:43 +02:00
Fonata
d21233c0f8 Remove Travis tests for PHP 7.0
It said:
> TypeError: Return value of ParseCsv\tests\properties\BaseClass::setUp() must be an instance of void, none returned
2021-04-14 20:12:43 +02:00
Fonata
7a066f9d5e Add test for empty first parameter 2021-04-14 20:12:43 +02:00
Fonata
2425c1bbda Deprecation: Stronger language in PHP DocBlock 2021-04-14 20:12:43 +02:00
Fonata
eb502f9dad PHP DocBlock: use more common type name 2021-04-14 20:12:43 +02:00
Fonata
0af6e98670 Tests should not produce output - capture it 2021-04-14 20:12:43 +02:00
Fonata
b38d0de800 Add test for getTotalDataRowCount without loading data 2021-04-14 20:12:43 +02:00
Fonata
e15d144e27 Adjust call to static function 2021-04-14 20:12:43 +02:00
Fonata
4518e944c4 Adjust function signatures for newer PHPUnit versions
Will make an update to PHPUnit 8 or 9 easier.
2021-04-14 20:12:43 +02:00
Fonata
3ce6a82052 Make deprecation clearer 2021-04-14 20:12:43 +02:00
Fonata
abae91a1a2 Make condition easier to read; no change in logic 2021-04-14 20:12:43 +02:00
Fonata
45f079b5dd Code comment for future me: I was afraid the code would surprise users 2021-04-14 20:12:43 +02:00
Fonata
fba67b84ff More consistent formatting 2021-04-14 20:12:43 +02:00
Fonata
2a154869b4 Fix PHP DocBlock: some tools thought the function always returns true
(Also, there was a spelling mistake)
2021-04-14 20:12:43 +02:00
Fonata
d1186fcafa Deprecate support for file paths in __construct() and parse()
See https://github.com/parsecsv/parsecsv-for-php/issues/198
2021-04-14 20:12:43 +02:00
Fonata
9c5eee23f6 Fix examples in README.md: add missing semicolons 2021-04-14 20:12:43 +02:00
Fonata
6a54a6a509 Move parsing of .php files (sic!) to _rfile for easier refactoring
Note that this arcane code comes from v0.2.0 beta:
5f0e6b03d4
2021-04-14 20:12:43 +02:00
Fonata
8277b9682d Ignore files on the root directory only 2021-04-14 20:12:43 +02:00
Fonata
0e54a2b9fa Make testing easier 2021-04-14 20:12:43 +02:00
Fonata
9c35237b1b README: make sure examples can be used in namespaced files 2020-12-15 16:20:14 +01:00
Fonata
1528a1f6ae README.md: fix the function name fix from my last commit 2020-12-07 18:13:09 +01:00
Fonata
aadb654edf Fix incorrect function name in README.md
Closes #195
2020-11-12 06:40:58 +01:00
Sergei Morozov
8069409c73 Add .gitattributes 2020-05-10 14:57:29 +02:00
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
Fonata
c7375dea8e Added authors and web links to source and issues 2018-08-09 13:48:06 +02:00
Fonata
6ce4550eed Merge pull request #147 from parsecsv/file_get_contents
Replace fread with file_get_contents to avoid the 8192 byte limit
2018-08-08 21:02:26 +02:00
Fonata
55890da647 Replace fread with file_get_contents to avoid the 8192 byte limit
This can happen when using streams.

Specific problem occurred with a file uploaded with Drupal's ``managed_file``
Form API element.

See https://secure.php.net/manual/en/function.fread.php
2018-07-31 21:59:04 +02:00
Fonata
21953ab6be Merge pull request #146 from parsecsv/waiver-test
Added test for issue 145, couldn't reproduce it
2018-05-22 09:01:01 +02:00
Fonata
1d8e6808bc Added test for issue #145, couldn't reproduce it 2018-05-21 21:56:54 +02:00
Fonata
063a812732 Merge pull request #142 from parsecsv/issue-141-multiple-empty-lines
Ignore entirely empty lines at the end of files
2018-05-11 09:03:36 +02:00
Fonata
4504f4b158 Converted function names to camelCase for PSR karma points 2018-04-29 11:21:00 +02:00
Fonata
b82ad03bd5 Ignore entirely empty lines at the end of files
Closes #141
2018-04-29 11:08:40 +02:00
Fonata
23a1b0a4b3 Merge pull request #138 from geminorum/master
min php on composer.json
2018-04-11 08:47:06 +02:00
Fonata
51d878a9a1 Merge pull request #137 from parsecsv/new-unparse-test
Added new test for unparse with parameters
2018-04-11 08:31:33 +02:00
Fonata
7d39b80fca Merge pull request #140 from susgo/patch-1
Update README.md: corrected function name getTotalDataRowCount()
2018-04-11 08:30:21 +02:00
susgo
8c7eba6815 Update README.md 2018-04-05 16:32:44 +02:00
Nasser Rafie
c41c559ac2 min php on composer.json 2018-04-02 18:36:16 +04:30
Fonata
e1ecf9302e Advertised getCollection in ChangeLog.txt 2018-04-02 15:11:17 +02:00
Fonata
de8e792ef4 Merge branch 'feature-datacollections'
Conflicts:
	src/Csv.php
2018-04-02 14:40:32 +02:00
Fonata
60d6458080 PHPUnit: prevent output from download.php to leak 2018-04-02 14:38:03 +02:00
William Knauss
406e1e415f added getCollection method that returns a Illuminate\Support\Collection object - useful for using the mapping functions 2018-04-02 14:32:17 +02:00
Fonata
2e40a2eb1c Added new test for unparse with parameters 2018-03-28 15:45:44 +02:00
Fonata
927e785891 Merge pull request #133 from parsecsv/fixing-132-output-with-fields
Bug fix: calling ->output() with $fields parameter set
2018-03-28 13:25:05 +02:00
Fonata
e6ba24b47a Dropping PHP 5.4 support (#131)
Also removed special treatment of PHP 5.4, as we don't support it anymore
2018-03-20 11:12:22 +01:00
Fonata
f24e5bf3a3 Merge branch 'offset-comment-and-tests' 2018-03-17 12:44:02 +01:00
Fonata
bdd4e5ef25 Merge branch 'master' into offset-comment-and-tests
Conflicts:
	tests/methods/ParseTest.php
2018-03-17 12:42:18 +01:00
Fonata
42b5d30d66 Improved OldRequireTest: explanation and new test added (#128) 2018-03-17 12:37:54 +01:00
Fonata
93f177a396 Merged two ifs in _validate_row_condition to prevent
This is to a sane count of zero PhpStorm inspections. In particular,
this is NestedPositiveIfStatementsInspection from EA Extended.
2018-03-17 12:17:25 +01:00
Fonata
f5ff7332a4 Set $data field on unparse. This fixes issue #132. 2018-03-17 12:16:39 +01:00
Fonata
07846d33c1 Added OutputTest to verify issue #132 is a bug. 2018-03-17 12:07:12 +01:00
Fonata
4b60d38fb0 Tell PhpStorm not to complain about reference mismatch
http://blog.jpauli.tech/2014/06/27/references-mismatch.html#what-is-a-reference-mismatch
2018-03-17 12:05:01 +01:00
Fonata
c8d15557cb Fixed parse()'s return value: return true only if $data is useful 2018-03-17 12:05:01 +01:00
Fonata
10895788c8 Slightly simplified getTotalDataRowCount, added test
The brackets () in the pattern were not needed, as only
$matches[0] was accessed, not $matches[1].

The @var is useful for PhpStorm's Php Inspections (EA Extended).
More details here: https://github.com/kalessil/phpinspectionsea/blob/master/docs/types-compatibility.md#foreach-source-to-iterate-over
2018-03-17 12:05:01 +01:00
Fonata
ffed7ffdc0 Only improved PHPDoc blocks, including sentance for output() 2018-03-17 12:05:01 +01:00
Fonata
7498a963ac _validate_fields_for_unparse: more info in UnexpectedValueException 2018-03-17 11:42:44 +01:00
Fonata
49728a74bb Only reformatted the source code 2018-03-17 10:31:09 +01:00
susgo
e4c9fed6cf Update README.md for old and new functions (#129)
* Update README.md
2018-03-12 08:28:25 +01:00
Susann Sgorzaly
5bc6d09b5e fixes bug on _validate_fields_for_unparse() if titles property is used instead of fields parameter for changing the titles for unparsing 2018-03-12 08:25:42 +01:00
susgo
b7f2075efc Fix #41: output order and subset (#126)
* init unparse tests for ordering and subseting by fields
* added one test for heading=false
* implements functionality of this issue
2018-03-11 11:14:53 +01:00
Christian Bläul
3cc20fbb47 Merge remote-tracking branch 'itexia/auto-detect-file-has-heading'
# Conflicts:
#	tests/methods/ParseTest.php
2018-03-10 12:46:36 +01:00
Christian Bläul
086cd15b44 Added requires to keep Composer-free environments working 2018-03-07 09:51:50 +01:00
Christian Bläul
03bc946b98 Sorted uses alphabetically, removed version
The repo is no longer on version 1.0.0. The ChangeLog.txt file is a
more obvious place for people to see which version includes what.
2018-03-07 09:45:48 +01:00
Christian Bläul
8f431aa7a4 Merge remote-tracking branch 'itexia/refactoring-constants' 2018-03-07 09:43:22 +01:00
Christian Bläul
7168cb15e3 ChangeLog.txt: Added new feature 2018-03-07 09:40:43 +01:00
Fonata
1142ef2611 Merge pull request #124 from itexia/new-enums-for-docu
New Enum class for file processing (save + unparse) + Documentation
2018-03-07 09:35:01 +01:00
Fonata
80a4954a3a Merge pull request #122 from itexia/get-total-row-count
New feature: get total row count - useful if $limit is set.
2018-03-07 09:30:36 +01:00
Christian Bläul
9c14bc2f30 Updated ChangeLog.txt with new features 2018-03-03 12:01:45 +01:00
Christian Bläul
4b6b7ee0b8 Removed -rc.2 from version, as it is officially released now 2018-03-03 11:55:57 +01:00
Christian Bläul
a80a6f1862 Moved features section up because library selection comes before install 2018-03-03 11:55:06 +01:00
Christian Bläul
da70838698 Only improved ChangeLog to include the output() change 2018-03-02 17:52:26 +01:00
Christian Bläul
9d7ccab20f Improved comment and test data to show how the offset is counted. 2018-03-02 17:50:01 +01:00
Christian Bläul
abecaf1b5d Only re-formated source code slightly 2018-03-02 17:25:38 +01:00
Christian Bläul
3af94399e6 Semantic versioning: Marked the current state of the repo as 1.0.0-rc.2 2018-03-02 17:15:31 +01:00
Christian Bläul
499088b3b2 Slightly improved README.md 2018-03-02 17:15:31 +01:00
Christian Bläul
fd63ff4a26 Removed examples from class file as they are also in the README.md 2018-03-02 17:15:31 +01:00
Christian Bläul
d250c9034b Further improved ChangeLog.txt and README.txt 2018-03-02 17:15:31 +01:00
Christian Bläul
bfc2c0901b Improved installation section of README.md; added Travid badge. 2018-03-02 17:15:31 +01:00
Christian Bläul
a0336f02ee Prepared new release in ChangeLog.txt 2018-03-02 17:15:31 +01:00
Christian Bläul
ea78f38e26 ConstructTest: undo directory change to be on the safe side. 2018-03-02 17:15:31 +01:00
Christian Bläul
c9e7997643 Don't break people's code just because they don't have Composer 2018-03-02 17:15:31 +01:00
Christian Bläul
68239d6859 No code changes, just cleaned up comments a bit 2018-03-02 17:15:31 +01:00
Christian Bläul
d05577d303 output(): Use better mime type for \t separator.
Fixes #79
2018-03-02 17:13:45 +01:00
Fonata
eedbffc375 Merge pull request #125 from itexia/42-Heading-and-offset
Fixed issue 42: heading and offset; added tests
2018-03-02 17:06:22 +01:00
Susann Sgorzaly
fb9325884d small code improvement 2018-02-28 13:47:38 +01:00
Susann Sgorzaly
11b20a3144 fixes #42. If csv has heading and offset is set, first row will always be parsed 2018-02-27 15:10:55 +01:00
Susann Sgorzaly
7766bf7c3b added two tests for reproducing the heading and offset bug. test with heading fails at the moment. if this one is green, bug would be solved 2018-02-27 15:00:14 +01:00
Susann Sgorzaly
5daa422aca new test for setting new headers before save (comments #82) 2018-02-27 14:33:26 +01:00
Susann Sgorzaly
48a3cdbc5c new enum for file processing mode. extended documentation (comments #112) 2018-02-27 14:18:00 +01:00
Susann Sgorzaly
fbe5263bca only code improvements 2018-02-27 13:22:11 +01:00
Susann Sgorzaly
5b1002a677 test correction 2018-02-26 10:06:59 +01:00
Susann Sgorzaly
4bbc928f09 added dependency for test 2018-02-26 10:00:52 +01:00
Susann Sgorzaly
951fc68886 new feature: auto detect if parsed file has heading 2018-02-26 09:46:44 +01:00
Susann Sgorzaly
68b849a37b corrected regex to fit all given enclosures. Added test for single enclosure 2018-02-26 08:55:51 +01:00
Susann Sgorzaly
aaefe2a480 introduces new local variable that holds the data 2018-02-26 08:50:35 +01:00
Susann Sgorzaly
611b1a92e8 use strpos instead of preg_match 2018-02-26 08:46:41 +01:00
Susann Sgorzaly
e5eccf1fc1 put tests into new file 2018-02-26 08:38:08 +01:00
Susann Sgorzaly
9e5c97328d renamed function to getTotalDataRowCount 2018-02-26 08:33:09 +01:00
Susann Sgorzaly
b6247c367c reformat code; only extended comment for new function 2018-02-26 08:31:46 +01:00
Susann Sgorzaly
ba4cc0672a reformat code 2018-02-26 06:57:40 +01:00
Susann Sgorzaly
c9cc9697ef new feature: getting total data row count without parsing all data 2018-02-24 16:55:45 +01:00
Susann Sgorzaly
f8fe4cad03 change accessibility of parse_file and parse_string 2018-02-23 10:37:12 +01:00
Susann Sgorzaly
95521cde87 reset file property if input is string 2018-02-23 10:17:09 +01:00
Susann Sgorzaly
249e5a24ac readded missing return statement in parse-function 2018-02-23 10:14:01 +01:00
Susann Sgorzaly
343c683077 corrected test for default sort type. Is set to regular now 2018-02-23 10:02:13 +01:00
Susann Sgorzaly
cf91bf40ff now compatible with old sorting values 2018-02-23 08:11:56 +01:00
Susann Sgorzaly
958af1027e small code improvements 2018-02-22 21:34:39 +01:00
Susann Sgorzaly
7a3120dd28 added test for sort enums (todo: handle exception on test) 2018-02-22 21:15:00 +01:00
Susann Sgorzaly
a74736d4da init implementation of abstract enum class 2018-02-22 21:01:06 +01:00
Susann Sgorzaly
657cec4b4e added enum for sort 2018-02-22 20:41:03 +01:00
susgo
ef44ea3989 Merge pull request #7 from parsecsv/master
update
2018-02-22 14:55:40 +01:00
Christian Bläul
2ac9f450f1 Check if output contains HTML table cells
They should if the _books.csv file is found
2018-02-21 19:25:39 +01:00
Christian Bläul
3968659b9f Make sure the code examples run without syntax or runtime errors. 2018-02-21 19:22:45 +01:00
Christian Bläul
d3a084d973 Added namespace support for further tests 2018-02-21 19:04:00 +01:00
Christian Bläul
b0355be96a Re-added the parsecsv.lib.php file for compatibility 2018-02-21 19:00:41 +01:00
Christian Bläul
b753d9c694 Repaired examples: there was a require missing. 2018-02-21 18:45:50 +01:00
Christian Bläul
2b95ec5aa1 Merge remote-tracking branch 'origin/Tests-for-sort-and-cond' into pull-test
# Conflicts:
#	tests/Bootstrap.php
#	tests/methods/ParseTest.php
#	tests/properties/worthless_test.php
2018-02-21 18:41:45 +01:00
Susann Sgorzaly
3f595dfd3b only renamed variable 2018-02-21 12:55:26 +01:00
susgo
081949339b Merge pull request #6 from parsecsv/itexia-fixed-remaining-test
Fixed remaining test
2018-02-21 08:36:24 +01:00
Christian Bläul
a60aae47a4 getDatatypes: Documented the need for PHP 5.5 or higher 2018-02-20 22:16:49 +01:00
Christian Bläul
4cba97ad51 Allow PhpStorm to understand the code better
(I followed suggestions from PhpStorm's inspections)
2018-02-20 22:07:08 +01:00
Christian Bläul
2206ec1e7c only reformatted source code to match the rest of the project 2018-02-20 22:06:06 +01:00
Christian Bläul
d188921ab6 composer.json: Only allow to load tests in dev environment 2018-02-20 21:50:52 +01:00
Christian Bläul
85cc0d9cfc Updated README.md to new name & namespace 2018-02-20 21:50:45 +01:00
Christian Bläul
a7f2bbb7bc Throw more specific exception 2018-02-20 21:40:48 +01:00
Christian Bläul
d484f3e9e3 The workaround for array_count_values was wrong and unnecessary. 2018-02-20 21:37:39 +01:00
Christian Bläul
f8b2fe274a Added missing letter in function name 2018-02-20 21:35:21 +01:00
susgo
17bfd9496a Merge pull request #5 from parsecsv/itexia-repair-tests
Repair tests (somewhat)
2018-02-20 08:22:59 +01:00
Christian Bläul
ec7b1c1d55 PHPUnit: Better class names with modern naming scheme 2018-02-19 23:01:31 +01:00
Christian Bläul
ba9eae17d4 Bootstrap: Improved the conditions under which the test wrapper loads 2018-02-19 23:00:57 +01:00
Christian Bläul
8f26ce6ea3 Force Travis to output which PHPUnit version it uses 2018-02-19 22:49:43 +01:00
Christian Bläul
913dc94e2c Keep sorting keys compatible: Moved array_values call to PHPUnit.
This commit partially reverts adcd258ea2.
2018-02-19 22:08:59 +01:00
Christian Bläul
5ced1f4212 Added conditions to SortByTest because otherwise different PHP versions...
yielded different sort orders (that's sort of ok, as rating is ambiguous).

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

Fixes #55.
Also see #61
2018-02-02 11:13:49 +01:00
Christian Bläul
47f691ce33 Added new testSingleColumnWithZeros.
Proves that issue #61 is indeed fixed.
2018-02-02 11:13:49 +01:00
Christian Bläul
ab6b3d19e0 Added line to send people to the other examples within the repo. 2018-02-02 11:13:49 +01:00
Christian Bläul
2d7ab4b2f0 Added documentation to parse_string()
Fixes #76
2018-02-02 11:13:49 +01:00
Christian Bläul
2bf4a2d0cd Added reference to RFC 4180 to make the goal of this project a little clearer.
Fixes #64
2018-02-02 11:13:49 +01:00
Christian Bläul
f41a18b1c0 Added support for DOS double line endings
Fixed GitHub issue #75
2018-02-02 11:13:49 +01:00
Christian Bläul
003e98e8ff Added SaveTest for coverage of writing files 2018-02-02 11:13:49 +01:00
Christian Bläul
d8aefa792e Made PhpStorm inspections happy:
- avoid empty for-loop bodies as they are unusual and look a bit like
  forgotten implementations
- removed 'i' modifier from regular expressions that contain no letters
- replaced consecutive 'str_replace' calls by single 'strtr' call
- introduced new variable $is_newline to make the intend of a complex
  'if' more obvious and get rid of the operator precedence inspection
2018-02-02 11:13:49 +01:00
Christian Bläul
a92506d078 Prevent quoting of sinlge-column file. Needed because auto() with...
...single-column file will not set field delimiter. This commit is a bug fix.

For a test see testSaveWithDefaultSettings.
2018-02-02 11:13:49 +01:00
Christian Bläul
54e846ee30 Construct array key just once instead for better readability 2018-02-02 11:13:49 +01:00
Christian Bläul
63932f67a4 ParseTest: skip 'test_Piwik_data' in PHP 5.4 2018-02-02 11:13:49 +01:00
Christian Bläul
44ff705a23 Improved README.md: spelling, mention native PHP functions 2018-02-02 11:13:49 +01:00
Christian Bläul
6432ba2ced Added test for new field 'use_mb_convert_encoding' 2018-02-02 11:13:49 +01:00
Christian Bläul
8ae09c604b Added support for mb_convert_encoding() instead of iconv()
See issue #109 at GitHub
2018-02-02 11:13:49 +01:00
Christian Bläul
5ea1d95f31 Also run test files ending with Test.php (capital letter) 2018-02-02 11:13:49 +01:00
Christian Bläul
af549dc47e Updated .travis.yml to test with PHP 7.2 2018-02-02 11:13:49 +01:00
Christian Bläul
12aec86bf7 Merge branch 'alex-vlasov-single_quote_auto_detection'
See #74
2018-01-21 21:48:13 +01:00
Christian Bläul
38944ba221 Moved testAutoQuotes into existing test infrastructure 2018-01-21 21:47:28 +01:00
Alexander Vlasov
5a9a10aeed Incorrect parsing with single quote during auto-detection delimiter. 2018-01-21 21:43:42 +01:00
Christian Bläul
631fae5191 Improved PHPDoc of _check_count; Refactored vars in _guess_delimiter
This commit does not contain functional changes.
2018-01-21 01:15:56 +01:00
Christian Bläul
18ddde98c0 Comparison in _enclose_value: put least expensive condition first 2018-01-21 01:15:56 +01:00
Christian Bläul
a07de14bba Slightly more meaningful variable names in 'unparse' function 2018-01-21 01:15:56 +01:00
Christian Bläul
e87a5ae0e6 Improved source code formatting (no functional change) 2018-01-21 01:15:56 +01:00
Christian Bläul
c04fc89c43 Removed @access PHPDoc because it doesn't add value.
Today's phpDocumentor detects visiblity from the PHP keywords.
2018-01-21 01:15:56 +01:00
Christian Bläul
cc908fd096 _detect_and_remove_sep_row_from_data: improved comments to make it more ...
obvious that $data given is changed.
2018-01-21 01:15:56 +01:00
Christian Bläul
155c50ad7a Slightly improved code quality, no functionality changes
E.g.:
- Improved PHPDoc to reflect/include actual types
- Removed unnecessary brackets in ternary statements
- _check_count: Added return statement (code smell)
- added type-safe comparison where it doesn't change results
2018-01-21 01:15:56 +01:00
Christian Bläul
98edcbfec3 Ignore *.bak files that WinMerge leaves behind
I don't want to accidentally add them to the repo.
2018-01-21 01:15:56 +01:00
Christian Bläul
378353eb79 Added PHIVE files to .gitignore 2018-01-21 01:15:56 +01:00
Christian Bläul
e4ca0062f6 Added .idea folder to .gitignore; if you want my PHPStorm settings, go ...
...to GitHub issue #101: https://github.com/parsecsv/parsecsv-for-php/issues/101
2018-01-21 01:15:56 +01:00
Christian Bläul
e419663679 Improved name of files and classes within tests/methods folder
This follows PHP best practices for classes.
2018-01-21 01:15:56 +01:00
Christian Bläul
0ecaa80222 Added .editorconfig to tell others about spaces and tabs
Also:
- formated source code according to these rules;
- added spaces after commas in test code

See GitHub issue #101
2017-12-21 09:33:23 +01:00
Christian Bläul
0ac5064d58 Only call iconv if input and output encoding differ.
This saves some headache if characters are invalid according to iconv.
2017-12-21 09:33:23 +01:00
Christian Bläul
4d011827f5 When we find a BOM, we know the input encoding. Let's use it!
Also: UTF tests not failing anymore because we are specifying
the output encoding now.
2017-12-21 09:33:23 +01:00
Christian Bläul
c818fff81a Only improved spelling in source code comments 2017-12-21 09:33:23 +01:00
Matthew de Marillac
ccad5c8360 Remove BOM from UTF files.
Implementation similar to suggestion from, and thus closes #83
2017-12-21 09:33:23 +01:00
Christian Bläul
b082849b17 Added tests for files starting with a byte order mark (BOM) 2017-12-21 09:33:23 +01:00
Christian Bläul
7536d55f27 PHPUnit: Prevent 'Cannot redeclare class' error
The Travis environments of PHP 5.4 and 5.6 contained both the
namespaced and the global version of the TestCase class :-/
2017-12-06 02:25:54 +01:00
Christian Bläul
db1e242d07 PHPUnit: made compatible with v6, which is now namespaced. 2017-12-06 02:25:54 +01:00
Christian Bläul
fd5fb96bce PHPUnit: simplified Bootstrap.php without changing functionality.
Notes:
- Using / on Windows is safe.
- __DIR__ is identical to dirname(__FILE)
2017-12-06 02:25:54 +01:00
Christian Bläul
4f08cbb561 PHPUnit: added test for UTF-8 and sep= row
Thanks to https://github.com/blaubaer! Some things in the CSV file
originate from java-kata-1 by Gregor Noczinski
2017-12-06 02:25:54 +01:00
Christian Bläul
0d14ca01be Improved sep= detection and added it to auto() 2017-12-06 02:25:54 +01:00
Christian Bläul
a4a0dfa2fd Extracted the long detection algorithm from 'auto()' into new function.
Also removed unnecessary brackets () in ternary on the way.
2017-12-06 02:25:54 +01:00
Christian Bläul
95ad7c315a PHPUnit: told Travis to also run tests on PHP 7 2017-12-06 02:25:54 +01:00
Christian Bläul
0e50aec3b9 Renamed example file 'single_row', as it containes a single column. 2017-12-06 02:25:54 +01:00
Christian Bläul
f5851ba9ac Only improved comments in source code 2017-12-06 02:25:54 +01:00
Jan Piskvor Martinec
fad5ebcdc8 Added function to detect delimiter using sep= file header 2017-12-06 02:25:54 +01:00
Christian Bläul
bd2031582d Added 'single_row' test data for issue #99
Took example documented in #100. Thanks, @tunecino!
2017-11-16 15:29:17 +01:00
Christian Bläul
1db4b02e9e ChangeLog: corrected spelling mistake 2017-11-16 15:29:17 +01:00
Christian Bläul
07f2306a9c Travis configuration: removed hhvm and PHP 5.3
They seem unsupported by GitHub at this point.
2017-11-16 15:29:17 +01:00
Christian Bläul
7eb6daa6fb Added file parse_test.php to check for 'is_readable' warning
As documented in pull request #67
2017-11-16 15:29:17 +01:00
Christian Bläul
240fa0ce23 construct_test.php: only reformatted the code 2017-11-16 15:29:17 +01:00
Salem Ouerdani
1321c3b693 Should fix #99 (zeros breaking lines)
see https://github.com/parsecsv/parsecsv-for-php/issues/99
2017-11-03 21:35:58 +01:00
Christian Bläul
b9cf7cb0c1 Improved PHPDoc blocks
Added missing parameters, wrapped at 80 characters, added types.
2017-11-03 20:25:56 +01:00
Christian Bläul
4bae0d2bcf Re-added the code to grap object-level filename in output()
Follow-up on pull request #88: No breaking compatibality with
older parsecsv versions.

If no output to browser is desired, set $output_filename to null,
or use unparse() function.
2017-11-03 20:23:12 +01:00
Jan Piskvor Martinec
189746405f Do not force filename if not set explicitly
Per docblock, the function output() is supposed to output to browser
    only if filename is passed into it.
    If not, it should return the CSV as a string, not auto-set filename.
2017-11-03 11:30:55 -06:00
Fonata
2ae35c26ff Merge pull request #78 from lbajsarowicz/patch-1
Documentation: added example usage of fields variable
2017-11-03 11:13:47 -06:00
Fonata
2d1b7cebde Merge pull request #67 from BreyndotEchse/patch-1
Suppress file name too long warning
2017-11-02 15:09:33 -06:00
Lukasz Bajsarowicz
b33cc6c667 Example usage of field variable 2016-02-08 00:08:17 +01:00
Marvin Feldmann
fa5aea7631 Suppress file name too long warning
Suppress Warning: "File name is longer than the maximum allowed path length on this platform (4096)"
2015-09-14 17:15:10 +02:00
William Knauss
4f144f2662 Addresses #62 2015-07-11 13:15:34 -04:00
William Knauss
ba4c30add1 Addresses #51 2015-07-11 13:09:20 -04:00
a8b443d48c Merge pull request #57 from repat/patch-2
double array at save()
2015-05-05 11:33:53 +01:00
repat
9c6e0d64cf double array at save()
sic, see code example on line 68 https://github.com/parsecsv/parsecsv-for-php/blob/master/parsecsv.lib.php#L68
2015-05-05 10:42:12 +02:00
83ec2fbce7 Merge pull request #56 from repat/patch-1
typo
2015-05-04 20:52:36 +01:00
repat
e750fcfb07 typo 2015-05-04 18:57:32 +02:00
William Knauss
b7d1848363 Merge pull request #54 from williamknauss/53-flock-issue
Fixing flock issue
2015-03-25 22:23:31 -04:00
William Knauss
8bb51f8bab Fixing flock issue
Why not make life easier just use file put contents
2015-03-25 22:19:54 -04:00
William Knauss
22fcff2d24 Merge pull request #45 from helpse/patch-1
Added iconv() to output method
2014-12-03 12:41:03 -05:00
Sergio Melendez
5e8a5df988 Added iconv() to output method 2014-10-07 08:46:14 -05:00
813ef3849e Tweak indentation in Makefile to improved readability 2014-06-19 14:35:02 +01:00
d795ad0e05 Merge pull request #37 from commonquail/tabify-makefile
GNU Make requires tab-indentation
2014-06-19 14:33:01 +01:00
Mikkel Kjeldsen
ac4c4699cb GNU Make requires tab-indentation
GNU Make does not play nicely with leading spaces after rules. It
requires that the first line starts with a tab. Although it isn't
strictly necessary to change subsequent lines as well, mixing tabs and
spaces is a nightmare.
2014-06-19 14:36:50 +02:00
e0728a3941 Merge pull request #33 from williamknauss/code-cleanup2
Code cleanup2
2014-06-06 09:35:40 +01:00
William Knauss
2f3732e350 _wfile 2014-06-05 20:53:19 -04:00
William Knauss
01e71adf36 _rfile 2014-06-05 20:52:43 -04:00
William Knauss
0c4a804db1 _check_count 2014-06-05 20:52:23 -04:00
William Knauss
4366201dc0 _check_data 2014-06-05 20:51:26 -04:00
William Knauss
0422d5d9fe _enclose_value 2014-06-05 20:50:48 -04:00
William Knauss
6f4d150e6f _validate_offset 2014-06-05 20:50:08 -04:00
William Knauss
494087ab1d _validate_row_condition 2014-06-05 20:49:49 -04:00
William Knauss
ce19deec4e _validate_row_conditions 2014-06-05 20:48:11 -04:00
William Knauss
33825514d9 load_data 2014-06-05 20:46:29 -04:00
William Knauss
8af4d1e513 unparse 2014-06-05 20:45:28 -04:00
William Knauss
4d07760933 parse_string 2014-06-05 20:44:14 -04:00
William Knauss
710f22eeb9 parse_file 2014-06-05 20:40:00 -04:00
William Knauss
604872faad auto 2014-06-05 20:39:21 -04:00
William Knauss
8e19ecf94f encoding 2014-06-05 20:37:02 -04:00
William Knauss
31417caafd output 2014-06-05 20:36:32 -04:00
William Knauss
17e060ea33 save 2014-06-05 20:35:40 -04:00
William Knauss
936b6f4a50 parse 2014-06-05 20:34:08 -04:00
William Knauss
65061046bd __construct 2014-06-05 20:32:55 -04:00
William Knauss
4393781abc Merge pull request #8 from parsecsv/master
U2D
2014-06-05 20:29:02 -04:00
William Knauss
8bbd474e66 Merge pull request #32 from williamknauss/proper-access
Proper access
2014-06-05 20:22:09 -04:00
William Knauss
734b35abc5 made _validate_row_conditions protected 2014-06-05 20:18:17 -04:00
William Knauss
5cb602be2d made _validate_row_condition protected 2014-06-05 20:17:58 -04:00
William Knauss
b8920f99cb made _validate_offset protected 2014-06-05 20:17:29 -04:00
William Knauss
b8248af92e made _enclose_value protected 2014-06-05 20:17:08 -04:00
William Knauss
d1f25ee3df made _check_data protected 2014-06-05 20:16:45 -04:00
William Knauss
0d5ae35a34 made _check_count protected 2014-06-05 20:15:20 -04:00
William Knauss
e1c8cae852 made _rfile protected 2014-06-05 20:14:50 -04:00
William Knauss
844a1520f3 made _wfile proctected 2014-06-05 20:14:16 -04:00
William Knauss
81746a561f Merge pull request #31 from williamknauss/issue-27
fix for issue #27
2014-06-05 17:10:17 -04:00
William Knauss
1524618293 Fix for #27 2014-06-05 17:03:26 -04:00
William Knauss
e98cef4846 Merge pull request #7 from parsecsv/master
U2D
2014-06-05 16:55:43 -04:00
William Knauss
4ed88da7a2 Merge pull request #30 from williamknauss/start-testing
Start testing
2014-06-05 16:55:17 -04:00
William Knauss
18a6479aec EOF updates 2014-06-05 16:42:52 -04:00
William Knauss
1c4bcaffa6 bootstrap update 2014-06-05 16:37:32 -04:00
William Knauss
7527267c68 travis updates 2014-06-05 16:35:00 -04:00
William Knauss
b074f83644 travis updates 2014-06-05 15:56:08 -04:00
William Knauss
7b83653ee2 added travis.yml 2014-06-05 15:49:46 -04:00
William Knauss
0ed23e7b84 Makefile 2014-06-05 15:32:25 -04:00
William Knauss
4a76ed9ca9 EOF and report cleanup 2014-06-05 12:08:17 -04:00
William Knauss
68eab2de59 construct 2014-06-05 12:04:39 -04:00
William Knauss
32b50efe82 Merge branch 'master' of https://github.com/williamknauss/php-parsecsv into start-testing 2014-06-05 12:02:11 -04:00
William Knauss
372c43fba4 Merge pull request #6 from parsecsv/master
U2D
2014-06-05 12:00:02 -04:00
William Knauss
7d63a8c894 Merge pull request #29 from williamknauss/keep_file_data_construct_param
Keep file data construct param
2014-06-05 11:59:33 -04:00
William Knauss
7187bbd68f construct param 2014-06-05 11:56:50 -04:00
William Knauss
ee784f3180 Merge branch 'master' of https://github.com/williamknauss/php-parsecsv into start-testing 2014-06-05 11:44:10 -04:00
William Knauss
633666060b Merge pull request #5 from parsecsv/master
U2D
2014-06-05 11:43:33 -04:00
William Knauss
8a5f15bdd8 Merge pull request #26 from parsecsv/fix-end-of-data-issue
Fix last line parsing issue
2014-06-05 11:40:23 -04:00
William Knauss
a6f8c708f9 1 2014-06-05 01:51:46 -04:00
cff692d976 Fix issue when CSV data does not end with a newline
If CSV data didn't end with "\n", "\r", or "\r\n" the last line of the
CSV would be ignored, as the parser wouldn't trigger end of row logic
for the last row.

This change forces the parser to process the end of the CSV data as it's
own character (false), and deals with end of data just like it treats
end of row.
2014-06-05 01:56:14 +01:00
William Knauss
c3c13258f3 Merge pull request #4 from parsecsv/master
U2D
2014-06-04 14:38:48 -04:00
9cf0ba9f97 Merge pull request #23 from williamknauss/readme-update
Readme update
2014-06-04 18:56:01 +01:00
William Knauss
18eb8a8f11 Updated readme with installation instructions 2014-06-04 13:52:13 -04:00
William Knauss
44a5507e10 Updated Composer 2014-06-04 13:48:14 -04:00
William Knauss
3ffcd731ee Merge pull request #3 from parsecsv/master
UPD
2014-06-04 03:44:53 -04:00
William Knauss
3545dbeb00 Merge pull request #20 from Norcoen/master
Force enclosing of all columns with optional switch
2014-06-03 14:09:46 -04:00
Norcoen
0235c24b36 Pass delimiter from unparse function to _enclose_value function, revert
changes from previous approach
2014-06-03 15:52:36 +02:00
Norcoen
33b1a0d196 Fix local/global delimiter bug between output() and _enclose_value() by
setting global delimiter to local if not null
2014-06-03 15:02:49 +02:00
Norcoen
f3c70ad17c Fix local/global delimiter bug between output() and _enclose_value() by
setting global delimiter to local if not null
2014-06-03 15:01:04 +02:00
Norcoen
98a146bd38 Force enclosing of all columns with optional switch 2014-06-03 14:45:07 +02:00
William Knauss
0486a4bf3e Merge pull request #18 from parsecsv/williamknauss-new-issue-14
williamknauss new issue 14
2014-06-02 20:37:04 -04:00
William Knauss
90042a553c ugh 2014-06-02 20:35:20 -04:00
William Knauss
73d7acb493 fix conflicts 2014-06-02 20:34:08 -04:00
William Knauss
2ed5801b33 Merge branch 'williamknauss-new-issue-14' 2014-06-02 20:30:38 -04:00
William Knauss
7b6692d7fd @norcoen caching request 2014-06-02 20:13:31 -04:00
William Knauss
01d25e0fdd Tabs to spaces 2014-06-02 20:09:20 -04:00
William Knauss
c64a4bffd7 Merge pull request #12 from williamknauss/tab_to_spaces
Fix #11
2014-05-17 12:51:24 -04:00
William Knauss
2d7f18ebc9 converted tabs to spaces 2014-05-17 12:47:45 -04:00
William Knauss
ee5b34e1c1 Merge branch 'master' of https://github.com/parsecsv/parsecsv-for-php 2014-05-17 12:43:00 -04:00
William Knauss
44929708ca Merge pull request #10 from parsecsv/fix-author-name-spelling
Fix typo in author name
2014-05-17 12:41:36 -04:00
c55ab2ec2c Fix typo in author's last name 2014-05-17 10:50:01 +01:00
William Knauss
6784c614ea Merge pull request #2 from parsecsv/master
Fork Update
2014-05-16 19:49:55 -04:00
William Knauss
5a70a7bffa Merge pull request #9 from williamknauss/composer-support
Composer support
2014-05-16 19:37:46 -04:00
William Knauss
c1a6946815 added gitignore 2014-05-16 19:33:15 -04:00
William Knauss
dbf415bd92 Added Composer.json 2014-05-16 19:30:59 -04:00
William Knauss
c915579955 Merge pull request #8 from williamknauss/readme_update-1
Readme update
2014-05-16 17:36:59 -04:00
William Knauss
55aaa1eb17 Grammer Fix 2014-05-16 17:36:14 -04:00
William Knauss
ab069e5d2d Updated readme 2014-05-16 17:35:08 -04:00
William Knauss
7e7aeba761 Merge pull request #6 from williamknauss/issue-5
Issue 5
2014-05-14 10:29:48 -04:00
William Knauss
a3e3582222 Patch for #5 2014-05-14 10:26:32 -04:00
William Knauss
fff3e73f08 Merge pull request #1 from parsecsv/master
U2D
2014-05-14 10:20:18 -04:00
f59af53183 Add contributors section to readme 2014-05-14 14:50:10 +01:00
629b0c9fd5 Indent header comment start/end strings 2014-05-14 10:18:02 +01:00
698a570a11 Add license header 2014-05-14 10:12:45 +01:00
2aca09e05d Add URL to PHP class which inspired parseCSV's creation 2014-05-14 09:26:21 +01:00
7a9fc101f8 Update copyright year in readme and license file 2014-05-14 09:24:27 +01:00
a1564a9a99 Correct project URL, and update copyright 2014-05-14 09:19:42 +01:00
4b280885f4 Merge pull request #1 from williamknauss/master
Basic Cleanup
2014-05-14 09:14:26 +01:00
William Knauss
88ad81f061 removed end of php line
its not really needed
2014-05-13 21:26:06 -04:00
William Knauss
7e46cc193a line feed should only be \r 2014-05-13 21:23:53 -04:00
William Knauss
a274874084 documenation changes 2014-05-13 21:23:23 -04:00
William Knauss
dea1b453eb _validate_row_conditions readability 2014-05-13 21:21:58 -04:00
William Knauss
9a8bd77eb8 forgot access flag 2014-05-13 21:21:04 -04:00
William Knauss
89a2817765 _validate_row_condition readability 2014-05-13 21:19:44 -04:00
William Knauss
75d7d51a9c _validate_offset readability 2014-05-13 21:05:53 -04:00
William Knauss
9b6dbd9849 _enclose_value readability 2014-05-13 21:05:11 -04:00
William Knauss
61d1c27eac _check_data readability 2014-05-13 21:04:25 -04:00
William Knauss
ecbb0736f1 more changes 2014-05-13 18:56:26 -04:00
William Knauss
2ab7625bb5 _rfile readability 2014-05-13 18:24:31 -04:00
William Knauss
0f39cfa75a _wfile readability 2014-05-13 18:23:27 -04:00
William Knauss
0457fbfba2 removed back comments 2014-05-13 18:22:18 -04:00
William Knauss
af5d7cf70d load_data readability 2014-05-09 21:57:17 -04:00
William Knauss
531cc66a5e unparse readability 2014-05-09 21:55:54 -04:00
William Knauss
178699580e unparse readability 2014-05-09 21:55:36 -04:00
William Knauss
8c300568bb parse_string readability 2014-05-09 21:54:09 -04:00
William Knauss
28967dea20 extra space 2014-05-09 21:46:11 -04:00
William Knauss
46b42776e4 Properties documentation 2014-05-09 21:45:03 -04:00
William Knauss
8ba88c582d removed documentation whitespace 2014-05-09 21:31:22 -04:00
William Knauss
ba1d462044 updated properties to "public"
removed "var" and set to "public"
2014-05-09 21:30:47 -04:00
William Knauss
0323d5108b parse_file documentation 2014-02-06 18:31:34 -05:00
William Knauss
2988278f0b parse_file readability 2014-02-06 18:30:43 -05:00
William Knauss
9301b016c8 auto documentation 2014-02-06 18:30:11 -05:00
William Knauss
75038f9d2f auto readability 2014-02-06 18:27:54 -05:00
William Knauss
b72385395e condition spacing 2014-02-06 08:17:00 -05:00
William Knauss
eb3c9faa4a construct docblock spacing 2014-02-05 19:16:51 -05:00
William Knauss
2f142e7313 public encoding 2014-02-05 19:16:35 -05:00
William Knauss
05dbcaf652 encoding update 2014-02-05 19:14:00 -05:00
William Knauss
4639fa1701 Output documentation 2014-02-05 19:12:16 -05:00
William Knauss
8bb8e2d7cf output readability 2014-02-05 19:09:57 -05:00
William Knauss
c7e1f825a0 save documentation 2014-02-05 18:41:21 -05:00
William Knauss
0638049fb2 save readability 2014-02-05 18:38:55 -05:00
William Knauss
585a0d472e parse documentation 2014-02-05 18:37:23 -05:00
William Knauss
d6a070ce08 Change __constructor docblock stype 2014-02-05 18:33:44 -05:00
William Knauss
4454196b4c parse readability 2014-02-05 18:31:27 -05:00
William Knauss
6a6754ca04 __construct documentation 2014-02-05 18:29:01 -05:00
William Knauss
8dd2e52073 __construct readability 2014-02-05 18:25:13 -05:00
William Knauss
e16d818d07 cleaned up construct 2014-02-05 18:24:41 -05:00
William Knauss
9e6fdbb42a Updated project link 2014-02-05 18:22:20 -05:00
85ca7af160 Update License.txt file 2014-02-05 21:18:07 +00:00
1b91591d32 Add readme 2014-02-05 21:16:50 +00:00
zynode
dfe298f4d0 Fixed a typo in the header comment regarding example code.
git-svn-id: http://parsecsv-for-php.googlecode.com/svn/trunk@44 339761fc-0c37-0410-822d-8b8cac1f6a97
2008-11-17 15:48:46 +00:00
zynode
fc22bee7ca parseCSV 0.4.3 beta
- Issue #4. Added an option for setting sorting
  type behavior when sorting data.
  Simply set $csv->sort_type to "regular", "numeric",
  or "string".

- Issue #6. Raw loaded file data is now cleared from
  file_data property when it has been successfully
  parsed to keep parseCSV's memory footprint to a
  minimum. Specifically handy when using mulitple
  instances of parseCSV to process large files.

git-svn-id: http://parsecsv-for-php.googlecode.com/svn/trunk@41 339761fc-0c37-0410-822d-8b8cac1f6a97
2008-06-30 21:41:42 +00:00
zynode
9b64cb07c4 Fixed Issue #6 - Automatically clears $file_data property after successful parsing of input data. Set the $keep_file_data property to true to keep it around for debugging.
git-svn-id: http://parsecsv-for-php.googlecode.com/svn/trunk@39 339761fc-0c37-0410-822d-8b8cac1f6a97
2008-06-30 20:38:59 +00:00
zynode
2bfa3de220 Addressed Issue #4. Added option for sorting behavior type.
git-svn-id: http://parsecsv-for-php.googlecode.com/svn/trunk@38 339761fc-0c37-0410-822d-8b8cac1f6a97
2008-06-30 20:01:50 +00:00
zynode
c522cd87a7 fixed a small changelog typo in the 0.4.2 trunk and tag
git-svn-id: http://parsecsv-for-php.googlecode.com/svn/trunk@36 339761fc-0c37-0410-822d-8b8cac1f6a97
2008-05-31 18:12:15 +00:00
zynode
0395362d66 parseCSV 0.4.2
git-svn-id: http://parsecsv-for-php.googlecode.com/svn/trunk@34 339761fc-0c37-0410-822d-8b8cac1f6a97
2008-05-31 17:59:21 +00:00
zynode
20a6a9d1b1 parseCSV 0.4.1 beta
git-svn-id: http://parsecsv-for-php.googlecode.com/svn/trunk@31 339761fc-0c37-0410-822d-8b8cac1f6a97
2008-05-30 12:20:39 +00:00
52 changed files with 4508 additions and 1009 deletions

21
.editorconfig Normal file
View File

@@ -0,0 +1,21 @@
# @see http://editorconfig.org/
# This is the top-most .editorconfig file; do not search in parent directories.
root = true
# All files.
[*]
indent_style = space
indent_size = 4
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true
[composer.json]
indent_size = 4
[Makefile]
indent_style = tab
[*.yml,*.yaml]
indent_size = 2

9
.gitattributes vendored Normal file
View File

@@ -0,0 +1,9 @@
/.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

38
.github/workflows/ci.yml vendored Normal file
View File

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

7
.gitignore vendored Normal file
View File

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

View File

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

@@ -1,4 +1,6 @@
Copyright (c) 2007 Jim Myhrberg (jim@zydev.info). (The MIT license)
Copyright (c) 2014 Jim Myhrberg.
Permission is hereby granted, free of charge, to any person obtaining a copy Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal of this software and associated documentation files (the "Software"), to deal
@@ -7,13 +9,13 @@ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions: furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in The above copyright notice and this permission notice shall be included in all
all copies or substantial portions of the Software. copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 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 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
THE SOFTWARE. SOFTWARE.

31
Makefile Normal file
View File

@@ -0,0 +1,31 @@
COMPOSER_BIN_DIR := vendor/bin
PHPUNIT_ARGS = -c tests/phpunit.xml
test: phpunit-dep
${COMPOSER_BIN_DIR}/phpunit ${PHPUNIT_ARGS}
phpunit-dep:
test -f ${COMPOSER_BIN_DIR}/phpunit || ( \
echo "phpunit is required to run tests." \
"Please run: composer install" >&2 && \
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:
.PHONY: test phpunit-dep local-ci

246
README.md Normal file
View File

@@ -0,0 +1,246 @@
# ParseCsv
[![Financial Contributors on Open Collective](https://opencollective.com/parsecsv/all/badge.svg?label=financial+contributors)](https://opencollective.com/parsecsv)
ParseCsv is an easy-to-use PHP class that reads and writes CSV data properly. It
fully conforms to the specifications outlined on the on the
[Wikipedia article][CSV] (and thus RFC 4180). It has many advanced features which help make your
life easier when dealing with CSV data.
You may not need a library at all: before using ParseCsv, please make sure if PHP's own `str_getcsv()`, ``fgetcsv()`` or `fputcsv()` meets your needs.
This library was originally created in early 2007 by [jimeh](https://github.com/jimeh) due to the lack of built-in
and third-party support for handling CSV data in PHP.
[csv]: http://en.wikipedia.org/wiki/Comma-separated_values
## Features
* ParseCsv is a complete and fully featured CSV solution for PHP
* Supports enclosed values, enclosed commas, double quotes and new lines.
* Automatic delimiter character detection.
* Sort data by specific fields/columns.
* Easy data manipulation.
* Basic SQL-like _conditions_, _offset_ and _limit_ options for filtering
data.
* Error detection for incorrectly formatted input. It attempts to be
intelligent, but can not be trusted 100% due to the structure of CSV, and
how different programs like Excel for example outputs CSV data.
* Support for character encoding conversion using PHP's
`iconv()` and `mb_convert_encoding()` functions.
* Supports PHP 5.5 and higher.
It certainly works with PHP 7.2 and all versions in between.
## Installation
Installation is easy using Composer. Just run the following on the
command line:
```
composer require parsecsv/php-parsecsv
```
If you don't use a framework such as Drupal, Laravel, Symfony, Yii etc.,
you may have to manually include Composer's autoloader file in your PHP
script:
```php
require_once __DIR__ . '/vendor/autoload.php';
```
#### Without composer
Not recommended, but technically possible: you can also clone the
repository or extract the
[ZIP](https://github.com/parsecsv/parsecsv-for-php/archive/master.zip).
To use ParseCSV, you then have to add a `require 'parsecsv.lib.php';` line.
## Example Usage
**Parse a tab-delimited CSV file with encoding conversion**
```php
$csv = new \ParseCsv\Csv();
$csv->encoding('UTF-16', 'UTF-8');
$csv->delimiter = "\t";
$csv->parseFile('data.tsv');
print_r($csv->data);
```
**Auto-detect field delimiter character**
```php
$csv = new \ParseCsv\Csv();
$csv->auto('data.csv');
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**
Change data values:
```php
$csv = new \ParseCsv\Csv();
$csv->sort_by = 'id';
$csv->parseFile('data.csv');
# "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->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**
```php
$csv = new \ParseCsv\Csv();
$csv->fields = ['id', 'name', 'category'];
$csv->parseFile('data.csv');
```
**Add row/entry to end of CSV file**
_Only recommended when you know the exact structure of the file._
```php
$csv = new \ParseCsv\Csv();
$csv->save('data.csv', array(array('1986', 'Home', 'Nowhere', '')), /* append */ true);
```
**Convert 2D array to CSV data and send headers to browser to treat output as
a file and download it**
Your web app users would call this an export.
```php
$csv = new \ParseCsv\Csv();
$csv->linefeed = "\n";
$header = array('field 1', 'field 2');
$csv->output('movies.csv', $data_array, $header, ',');
```
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
* ParseCsv is based on the concept of [Ming Hong Ng][ming]'s [CsvFileParser][]
class.
[ming]: http://minghong.blogspot.com/
[CsvFileParser]: http://minghong.blogspot.com/2006/07/csv-parser-for-php.html
## Contributors
### Code Contributors
This project exists thanks to all the people who contribute.
Please find a complete list on the project's [contributors][] page.
[contributors]: https://github.com/parsecsv/parsecsv-for-php/graphs/contributors
<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
(The MIT license)
Copyright (c) 2014 Jim Myhrberg.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
[![Build Status](https://travis-ci.org/parsecsv/parsecsv-for-php.svg?branch=master)](https://travis-ci.org/parsecsv/parsecsv-for-php)

57
composer.json Normal file
View File

@@ -0,0 +1,57 @@
{
"name": "parsecsv/php-parsecsv",
"description": "CSV data parser for PHP",
"license": "MIT",
"authors": [
{
"name": "Jim Myhrberg",
"email": "contact@jimeh.me"
},
{
"name": "William Knauss",
"email": "will.knauss@gmail.com"
},
{
"name": "Susann Sgorzaly",
"homepage": "https://github.com/susgo"
},
{
"name": "Christian Bläul",
"homepage": "https://github.com/Fonata"
}
],
"autoload": {
"psr-4": {
"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": {
"issues": "https://github.com/parsecsv/parsecsv-for-php/issues",
"source": "https://github.com/parsecsv/parsecsv-for-php"
}
}

View File

@@ -1,13 +1,14 @@
<pre> <pre>
<?php <?php
# include parseCSV class. # include parseCSV class.
require_once('../parsecsv.lib.php'); require __DIR__ . '/../vendor/autoload.php';
use ParseCsv\Csv;
# create new parseCSV object. # create new parseCSV object.
$csv = new parseCSV(); $csv = new Csv();
# Parse '_books.csv' using automatic delimiter detection... # Parse '_books.csv' using automatic delimiter detection...
@@ -17,8 +18,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 parse() function. # ...and then use the parseFile() function.
// $csv->parse('_books.csv'); // $csv->parseFile('_books.csv');
# Output result. # Output result.
@@ -28,21 +29,29 @@ $csv->auto('_books.csv');
?> ?>
</pre> </pre>
<style type="text/css" media="screen"> <style type="text/css" media="screen">
table { background-color: #BBB; } table {
th { background-color: #EEE; } background-color: #BBB;
td { background-color: #FFF; } }
th {
background-color: #EEE;
}
td {
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>
<?php endforeach; ?> <?php endforeach; ?>
</tr> </tr>
<?php foreach ($csv->data as $key => $row): ?> <?php foreach ($csv->data as $key => $row): ?>
<tr> <tr>
<?php foreach ($row as $value): ?> <?php foreach ($row as $value): ?>
<td><?php echo $value; ?></td> <td><?php echo $value; ?></td>
<?php endforeach; ?> <?php endforeach; ?>
</tr> </tr>
<?php endforeach; ?> <?php endforeach; ?>
</table> </table>

View File

@@ -3,11 +3,13 @@
# include parseCSV class. # include parseCSV class.
require_once('../parsecsv.lib.php'); require __DIR__ . '/../vendor/autoload.php';
use ParseCsv\Csv;
# create new parseCSV object. # create new parseCSV object.
$csv = new parseCSV(); $csv = new Csv();
# Example conditions: # Example conditions:
@@ -15,6 +17,7 @@ $csv = new parseCSV();
$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.
@@ -28,21 +31,29 @@ $csv->auto('_books.csv');
?> ?>
</pre> </pre>
<style type="text/css" media="screen"> <style type="text/css" media="screen">
table { background-color: #BBB; } table {
th { background-color: #EEE; } background-color: #BBB;
td { background-color: #FFF; } }
th {
background-color: #EEE;
}
td {
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>
<?php endforeach; ?> <?php endforeach; ?>
</tr> </tr>
<?php foreach ($csv->data as $key => $row): ?> <?php foreach ($csv->data as $key => $row): ?>
<tr> <tr>
<?php foreach ($row as $value): ?> <?php foreach ($row as $value): ?>
<td><?php echo $value; ?></td> <td><?php echo $value; ?></td>
<?php endforeach; ?> <?php endforeach; ?>
</tr> </tr>
<?php endforeach; ?> <?php endforeach; ?>
</table> </table>

34
examples/download.php Normal file
View File

@@ -0,0 +1,34 @@
<?php
# include parseCSV class.
require __DIR__ . '/../vendor/autoload.php';
use ParseCsv\Csv;
# create new parseCSV object.
$csv = new Csv();
# Parse '_books.csv' using automatic delimiter detection...
$csv->auto('_books.csv');
# ...or if you know the delimiter, set the delimiter character
# if its not the default comma...
// $csv->delimiter = "\t"; # tab delimited
# ...and then use the parse() function.
// $csv->parse('_books.csv');
# now we have data in $csv->data, at which point we can modify
# it to our hearts content, like removing the last item...
array_pop($csv->data);
# then we output the file to the browser as a downloadable file...
$csv->output('books.csv');
# ...when the first parameter is given and is not null, the
# output method will itself send the correct headers and the
# 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
# output data, and will not output to the browser itself.

View File

@@ -3,11 +3,13 @@
# include parseCSV class. # include parseCSV class.
require_once('../parsecsv.lib.php'); require __DIR__ . '/../vendor/autoload.php';
use ParseCsv\Csv;
# create new parseCSV object. # create new parseCSV object.
$csv = new parseCSV(); $csv = new Csv();
# if sorting is enabled, the whole CSV file # if sorting is enabled, the whole CSV file
@@ -41,21 +43,29 @@ $csv->auto('_books.csv');
?> ?>
</pre> </pre>
<style type="text/css" media="screen"> <style type="text/css" media="screen">
table { background-color: #BBB; } table {
th { background-color: #EEE; } background-color: #BBB;
td { background-color: #FFF; } }
th {
background-color: #EEE;
}
td {
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>
<?php endforeach; ?> <?php endforeach; ?>
</tr> </tr>
<?php foreach ($csv->data as $key => $row): ?> <?php foreach ($csv->data as $key => $row): ?>
<tr> <tr>
<?php foreach ($row as $value): ?> <?php foreach ($row as $value): ?>
<td><?php echo $value; ?></td> <td><?php echo $value; ?></td>
<?php endforeach; ?> <?php endforeach; ?>
</tr> </tr>
<?php endforeach; ?> <?php endforeach; ?>
</table> </table>

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');

View File

@@ -1,755 +1,24 @@
<?php <?php
class parseCSV { // 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.
Class: parseCSV v0.4 beta // Check if people used Composer to include this project in theirs
http://code.google.com/p/parsecsv-for-php/ if (!file_exists(__DIR__ . '/vendor/autoload.php')) {
require __DIR__ . '/src/enums/AbstractEnum.php';
require __DIR__ . '/src/enums/DatatypeEnum.php';
Fully conforms to the specifications lined out on wikipedia: require __DIR__ . '/src/enums/FileProcessingModeEnum.php';
- http://en.wikipedia.org/wiki/Comma-separated_values require __DIR__ . '/src/enums/SortEnum.php';
require __DIR__ . '/src/extensions/DatatypeTrait.php';
Based on the concept of Ming Hong Ng's CsvFileParser class: require __DIR__ . '/src/Csv.php';
- http://minghong.blogspot.com/2006/07/csv-parser-for-php.html } else {
require __DIR__ . '/vendor/autoload.php';
Copyright (c) 2007 Jim Myhrberg (jim@zydev.info).
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
Code Examples
----------------
# general usage
$csv = new parseCSV('data.csv');
print_r($csv->data);
----------------
# tab delimited, and encoding conversion
$csv = new parseCSV();
$csv->encoding('UTF-16', 'UTF-8');
$csv->delimiter = "\t";
$csv->parse('data.tsv');
print_r($csv->data);
----------------
# auto-detect delimiter character
$csv = new parseCSV();
$csv->auto('data.csv');
print_r($csv->data);
----------------
# modify data in a csv file
$csv = new parseCSV();
$csv->sort_by = 'id';
$csv->parse('data.csv');
# "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->save();
----------------
# add row/entry to end of CSV file
# - only recommended when you know the extact sctructure of the file
$csv = new parseCSV();
$csv->save('data.csv', array('1986', 'Home', 'Nowhere', ''), true);
----------------
# convert 2D array to csv data and send headers
# to browser to treat output as a file and download it
$csv = new parseCSV();
$csv->output (true, 'movies.csv', $array);
----------------
*/
/**
* Configuration
* - set these options with $object->var_name = 'value';
*/
# use first line/entry as field names
var $heading = true;
# override field names
var $fields = array();
# sort entries by this field
var $sort_by = null;
var $sort_reverse = false;
# delimiter (comma) and enclosure (double quote)
var $delimiter = ',';
var $enclosure = '"';
# basic SQL-like conditions for row matching
var $conditions = null;
# number of rows to ignore from beginning of data
var $offset = null;
# limits the number of returned rows to specified amount
var $limit = null;
# number of rows to analyze when attempting to auto-detect delimiter
var $auto_depth = 15;
# characters to ignore when attempting to auto-detect delimiter
var $auto_non_chars = "a-zA-Z0-9\n\r";
# preferred delimiter characters, only used when all filtering method
# returns multiple possible delimiters (happens very rarely)
var $auto_preferred = ",;\t.:|";
# character encoding options
var $convert_encoding = false;
var $input_encoding = 'ISO-8859-1';
var $output_encoding = 'ISO-8859-1';
# used by unparse(), save(), and output() functions
var $linefeed = "\r\n";
# only used by output() function
var $output_delimiter = ',';
var $output_filename = 'data.csv';
/**
* Internal variables
*/
# current file
var $file;
# loaded file contents
var $file_data;
# error while parsing input data
# 0 = No errors found. Everything should be fine :)
# 1 = Hopefully correctable syntax error was found.
# 2 = Enclosure character (double quote by default)
# was found in non-enclosed field. This means
# the file is either corrupt, or does not
# standard CSV formatting. Please validate
# the parsed data yourself.
var $error = 0;
# detailed error info
var $error_info = array();
# array of field values in data parsed
var $titles = array();
# two dimentional array of CSV data
var $data = array();
/**
* Constructor
* @param input CSV file or string
* @return nothing
*/
function parseCSV ($input = null, $offset = null, $limit = null, $conditions = null) {
if ( $offset !== null ) $this->offset = $offset;
if ( $limit !== null ) $this->limit = $limit;
if ( count($conditions) > 0 ) $this->conditions = $conditions;
if ( !empty($input) ) $this->parse($input);
}
// ==============================================
// ----- [ Main Functions ] ---------------------
// ==============================================
/**
* Parse CSV file or string
* @param input CSV file or string
* @return nothing
*/
function parse ($input = null, $offset = null, $limit = null, $conditions = null) {
if ( $input === null ) $input = $this->file;
if ( !empty($input) ) {
if ( $offset !== null ) $this->offset = $offset;
if ( $limit !== null ) $this->limit = $limit;
if ( count($conditions) > 0 ) $this->conditions = $conditions;
if ( is_readable($input) ) {
$this->data = $this->parse_file($input);
} else {
$this->file_data = &$input;
$this->data = $this->parse_string();
}
if ( $this->data === false ) return false;
}
return true;
}
/**
* Save changes, or new file and/or data
* @param file file to save to
* @param data 2D array with data
* @param append append current data to end of target CSV if exists
* @param fields field names
* @return true or false
*/
function save ($file = null, $data = array(), $append = false, $fields = array()) {
if ( empty($file) ) $file = &$this->file;
$mode = ( $append ) ? 'at' : 'wt' ;
$is_php = ( preg_match('/\.php$/i', $file) ) ? true : false ;
return $this->_wfile($file, $this->unparse($data, $fields, $append, $is_php), $mode);
}
/**
* Generate CSV based string for output
* @param output if true, prints headers and strings to browser
* @param filename filename sent to browser in headers if output is true
* @param data 2D array with data
* @param fields field names
* @param delimiter delimiter used to separate data
* @return CSV data using delimiter of choice, or default
*/
function output ($output = true, $filename = null, $data = array(), $fields = array(), $delimiter = null) {
if ( empty($filename) ) $filename = $this->output_filename;
if ( $delimiter === null ) $delimiter = $this->output_delimiter;
$data = $this->unparse($data, $fields, null, null, $delimiter);
if ( $output ) {
header('Content-type: application/csv');
header('Content-Disposition: inline; filename="'.$filename.'"');
echo $data;
}
return $data;
}
/**
* Convert character encoding
* @param input input character encoding, uses default if left blank
* @param output output character encoding, uses default if left blank
* @return nothing
*/
function encoding ($input = null, $output = null) {
$this->convert_encoding = true;
if ( $input !== null ) $this->input_encoding = $input;
if ( $output !== null ) $this->output_encoding = $output;
}
/**
* Auto-Detect Delimiter: Find delimiter by analyzing a specific number of
* rows to determine most probable delimiter character
* @param file local CSV file
* @param parse true/false parse file directly
* @param search_depth number of rows to analyze
* @param preferred preferred delimiter characters
* @param enclosure enclosure character, default is double quote (").
* @return delimiter character
*/
function auto ($file = null, $parse = true, $search_depth = null, $preferred = null, $enclosure = null) {
if ( $file === null ) $file = $this->file;
if ( empty($search_depth) ) $search_depth = $this->auto_depth;
if ( $enclosure === null ) $enclosure = $this->enclosure;
if ( $preferred === null ) $preferred = $this->auto_preferred;
if ( empty($this->file_data) ) {
if ( $this->_check_data($file) ) {
$data = &$this->file_data;
} else return false;
} else {
$data = &$this->file_data;
}
$chars = array();
$strlen = strlen($data);
$enclosed = false;
$n = 1;
$to_end = true;
// walk specific depth finding posssible delimiter characters
for ( $i=0; $i < $strlen; $i++ ) {
$ch = $data{$i};
$nch = ( isset($data{$i+1}) ) ? $data{$i+1} : false ;
$pch = ( isset($data{$i-1}) ) ? $data{$i-1} : false ;
// open and closing quotes
if ( $ch == $enclosure ) {
if ( !$enclosed || $nch != $enclosure ) {
$enclosed = ( $enclosed ) ? false : true ;
} elseif ( $enclosed ) {
$i++;
}
// end of row
} elseif ( ($ch == "\n" && $pch != "\r" || $ch == "\r") && !$enclosed ) {
if ( $n >= $search_depth ) {
$strlen = 0;
$to_end = false;
} else {
$n++;
}
// count character
} elseif (!$enclosed) {
if ( !preg_match('/['.preg_quote($this->auto_non_chars, '/').']/i', $ch) ) {
if ( !isset($chars[$ch][$n]) ) {
$chars[$ch][$n] = 1;
} else {
$chars[$ch][$n]++;
}
}
}
}
// filtering
$depth = ( $to_end ) ? $n-1 : $n ;
$filtered = array();
foreach( $chars as $char => $value ) {
if ( $match = $this->_check_count($char, $value, $depth, $preferred) ) {
$filtered[$match] = $char;
}
}
// capture most probable delimiter
ksort($filtered);
$this->delimiter = reset($filtered);
// parse data
if ( $parse ) $this->data = $this->parse_string();
return $this->delimiter;
}
// ==============================================
// ----- [ Core Functions ] ---------------------
// ==============================================
/**
* Read file to string and call parse_string()
* @param file local CSV file
* @return 2D array with CSV data, or false on failure
*/
function parse_file ($file = null) {
if ( $file === null ) $file = $this->file;
if ( empty($this->file_data) ) $this->load_data($file);
return ( !empty($this->file_data) ) ? $this->parse_string() : false ;
}
/**
* Parse CSV strings to arrays
* @param data CSV string
* @return 2D array with CSV data, or false on failure
*/
function parse_string ($data = null) {
if ( empty($data) ) {
if ( $this->_check_data() ) {
$data = &$this->file_data;
} else return false;
}
$white_spaces = str_replace($this->delimiter, '', " \t\x0B\0");
$rows = array();
$row = array();
$row_count = 0;
$current = '';
$head = ( !empty($this->fields) ) ? $this->fields : array() ;
$col = 0;
$enclosed = false;
$was_enclosed = false;
$strlen = strlen($data);
// walk through each character
for ( $i=0; $i < $strlen; $i++ ) {
$ch = $data{$i};
$nch = ( isset($data{$i+1}) ) ? $data{$i+1} : false ;
$pch = ( isset($data{$i-1}) ) ? $data{$i-1} : false ;
// open/close quotes, and inline quotes
if ( $ch == $this->enclosure ) {
if ( !$enclosed ) {
if ( ltrim($current, $white_spaces) == '' ) {
$enclosed = true;
$was_enclosed = true;
} else {
$this->error = 2;
$error_row = count($rows) + 1;
$error_col = $col + 1;
if ( !isset($this->error_info[$error_row.'-'.$error_col]) ) {
$this->error_info[$error_row.'-'.$error_col] = array(
'type' => 2,
'info' => 'Syntax error found on row '.$error_row.'. Non-enclosed fields can not contain double-quotes.',
'row' => $error_row,
'field' => $error_col,
'field_name' => (!empty($head[$col])) ? $head[$col] : null,
);
}
$current .= $ch;
}
} elseif ($nch == $this->enclosure) {
$current .= $ch;
$i++;
} elseif ( $nch != $this->delimiter && $nch != "\r" && $nch != "\n" ) {
for ( $x=($i+1); isset($data{$x}) && ltrim($data{$x}, $white_spaces) == ''; $x++ ) {}
if ( $data{$x} == $this->delimiter ) {
$enclosed = false;
$i = $x;
} else {
if ( $this->error < 1 ) {
$this->error = 1;
}
$error_row = count($rows) + 1;
$error_col = $col + 1;
if ( !isset($this->error_info[$error_row.'-'.$error_col]) ) {
$this->error_info[$error_row.'-'.$error_col] = array(
'type' => 1,
'info' =>
'Syntax error found on row '.(count($rows) + 1).'. '.
'A single double-quote was found within an enclosed string. '.
'Enclosed double-quotes must be escaped with a second double-quote.',
'row' => count($rows) + 1,
'field' => $col + 1,
'field_name' => (!empty($head[$col])) ? $head[$col] : null,
);
}
$current .= $ch;
$enclosed = false;
}
} else {
$enclosed = false;
}
// end of field/row
} elseif ( ($ch == $this->delimiter || $ch == "\n" || $ch == "\r") && !$enclosed ) {
$key = ( !empty($head[$col]) ) ? $head[$col] : $col ;
$row[$key] = ( $was_enclosed ) ? $current : trim($current) ;
$current = '';
$was_enclosed = false;
$col++;
// end of row
if ( $ch == "\n" || $ch == "\r" ) {
if ( $this->_validate_offset($row_count) && $this->_validate_row_conditions($row, $this->conditions) ) {
if ( $this->heading && empty($head) ) {
$head = $row;
} elseif ( empty($this->fields) || (!empty($this->fields) && (($this->heading && $row_count > 0) || !$this->heading)) ) {
if ( !empty($this->sort_by) && !empty($row[$this->sort_by]) ) {
if ( isset($rows[$row[$this->sort_by]]) ) {
$rows[$row[$this->sort_by].'_0'] = &$rows[$row[$this->sort_by]];
unset($rows[$row[$this->sort_by]]);
for ( $sn=1; isset($rows[$row[$this->sort_by].'_'.$sn]); $sn++ ) {}
$rows[$row[$this->sort_by].'_'.$sn] = $row;
} else $rows[$row[$this->sort_by]] = $row;
} else $rows[] = $row;
}
}
$row = array();
$col = 0;
$row_count++;
if ( $this->sort_by === null && $this->limit !== null && count($rows) == $this->limit ) {
$i = $strlen;
}
if ( $ch == "\r" && $nch == "\n" ) $i++;
}
// append character to current field
} else {
$current .= $ch;
}
}
$this->titles = $head;
if ( !empty($this->sort_by) ) {
( $this->sort_reverse ) ? krsort($rows) : ksort($rows) ;
if ( $this->offset !== null || $this->limit !== null ) {
$rows = array_slice($rows, ($this->offset === null ? 0 : $this->offset) , $this->limit, true);
}
}
return $rows;
}
/**
* Create CSV data from array
* @param data 2D array with data
* @param fields field names
* @param append if true, field names will not be output
* @param is_php if a php die() call should be put on the first
* line of the file, this is later ignored when read.
* @param delimiter field delimiter to use
* @return CSV data (text string)
*/
function unparse ( $data = array(), $fields = array(), $append = false , $is_php = false, $delimiter = null) {
if ( !is_array($data) || empty($data) ) $data = &$this->data;
if ( !is_array($fields) || empty($fields) ) $fields = &$this->titles;
if ( $delimiter === null ) $delimiter = $this->delimiter;
$string = ( $is_php ) ? "<?php header('Status: 403'); die(' '); ?>".$this->linefeed : '' ;
$entry = array();
// create heading
if ( $this->heading && !$append ) {
foreach( $fields as $key => $value ) {
$entry[] = $this->_enclose_value($value);
}
$string .= implode($delimiter, $entry).$this->linefeed;
$entry = array();
}
// create data
foreach( $data as $key => $row ) {
foreach( $row as $field => $value ) {
$entry[] = $this->_enclose_value($value);
}
$string .= implode($delimiter, $entry).$this->linefeed;
$entry = array();
}
return $string;
}
/**
* Load local file or string
* @param input local CSV file
* @return true or false
*/
function load_data ($input = null) {
$data = null;
$file = null;
if ( $input === null ) {
$file = $this->file;
} elseif ( file_exists($input) ) {
$file = $input;
} else {
$data = $input;
}
if ( !empty($data) || $data = $this->_rfile($file) ) {
if ( $this->file != $file ) $this->file = $file;
if ( preg_match('/\.php$/i', $file) && preg_match('/<\?.*?\?>(.*)/ims', $data, $strip) ) {
$data = ltrim($strip[1]);
}
if ( $this->convert_encoding ) $data = iconv($this->input_encoding, $this->output_encoding, $data);
if ( substr($data, -1) != "\n" ) $data .= "\n";
$this->file_data = &$data;
return true;
}
return false;
}
// ==============================================
// ----- [ Internal Functions ] -----------------
// ==============================================
/**
* Validate a row against specified conditions
* @param row array with values from a row
* @param conditions specified conditions that the row must match
* @return true of false
*/
function _validate_row_conditions ($row = array(), $conditions = null) {
if ( !empty($row) ) {
if ( !empty($conditions) ) {
$conditions = (strpos($conditions, ' OR ') !== false) ? explode(' OR ', $conditions) : array($conditions) ;
$or = '';
foreach( $conditions as $key => $value ) {
if ( strpos($value, ' AND ') !== false ) {
$value = explode(' AND ', $value);
$and = '';
foreach( $value as $k => $v ) {
$and .= $this->_validate_row_condition($row, $v);
}
$or .= (strpos($and, '0') !== false) ? '0' : '1' ;
} else {
$or .= $this->_validate_row_condition($row, $value);
}
}
return (strpos($or, '1') !== false) ? true : false ;
}
return true;
}
return false;
}
/**
* Validate a row against a single condition
* @param row array with values from a row
* @param condition specified condition that the row must match
* @return true of false
*/
function _validate_row_condition ($row, $condition) {
$operators = array(
'=', 'equals', 'is',
'!=', 'is not',
'<', 'is less than',
'>', 'is greater than',
'<=', 'is less than or equals',
'>=', 'is greater than or equals',
'contains',
'does not contain',
);
$operators_regex = array();
foreach( $operators as $value ) {
$operators_regex[] = preg_quote($value, '/');
}
$operators_regex = implode('|', $operators_regex);
if ( preg_match('/^(.+) ('.$operators_regex.') (.+)$/i', trim($condition), $capture) ) {
$field = $capture[1];
$op = $capture[2];
$value = $capture[3];
if ( preg_match('/^([\'\"]{1})(.*)([\'\"]{1})$/i', $value, $capture) ) {
if ( $capture[1] == $capture[3] ) {
$value = $capture[2];
$value = str_replace("\\n", "\n", $value);
$value = str_replace("\\r", "\r", $value);
$value = str_replace("\\t", "\t", $value);
$value = stripslashes($value);
}
}
if ( array_key_exists($field, $row) ) {
if ( ($op == '=' || $op == 'equals' || $op == 'is') && $row[$field] == $value ) {
return '1';
} elseif ( ($op == '!=' || $op == 'is not') && $row[$field] != $value ) {
return '1';
} elseif ( ($op == '<' || $op == 'is less than' ) && $row[$field] < $value ) {
return '1';
} elseif ( ($op == '>' || $op == 'is greater than') && $row[$field] > $value ) {
return '1';
} elseif ( ($op == '<=' || $op == 'is less than or equals' ) && $row[$field] <= $value ) {
return '1';
} elseif ( ($op == '>=' || $op == 'is greater than or equals') && $row[$field] >= $value ) {
return '1';
} elseif ( $op == 'contains' && preg_match('/'.preg_quote($value, '/').'/i', $row[$field]) ) {
return '1';
} elseif ( $op == 'does not contain' && !preg_match('/'.preg_quote($value, '/').'/i', $row[$field]) ) {
return '1';
} else {
return '0';
}
}
}
return '1';
}
/**
* Validates if the row is within the offset or not if sorting is disabled
* @param current_row the current row number being processed
* @return true of false
*/
function _validate_offset ($current_row) {
if ( $this->sort_by === null && $this->offset !== null && $current_row < $this->offset ) return false;
return true;
}
/**
* Enclose values if needed
* - only used by unparse()
* @param value string to process
* @return Processed value
*/
function _enclose_value ($value = null) {
if ( $value !== null && $value != '' ) {
$delimiter = preg_quote($this->delimiter, '/');
$enclosure = preg_quote($this->enclosure, '/');
if ( preg_match("/".$delimiter."|".$enclosure."|\n|\r/i", $value) || ($value{0} == ' ' || substr($value, -1) == ' ') ) {
$value = str_replace($this->enclosure, $this->enclosure.$this->enclosure, $value);
$value = $this->enclosure.$value.$this->enclosure;
}
}
return $value;
}
/**
* Check file data
* @param file local filename
* @return true or false
*/
function _check_data ($file = null) {
if ( empty($this->file_data) ) {
if ( $file === null ) $file = $this->file;
return $this->load_data($file);
}
return true;
}
/**
* Check if passed info might be delimiter
* - only used by find_delimiter()
* @return special string used for delimiter selection, or false
*/
function _check_count ($char, $array, $depth, $preferred) {
if ( $depth == count($array) ) {
$first = null;
$equal = null;
$almost = false;
foreach( $array as $key => $value ) {
if ( $first == null ) {
$first = $value;
} elseif ( $value == $first && $equal !== false) {
$equal = true;
} elseif ( $value == $first+1 && $equal !== false ) {
$equal = true;
$almost = true;
} else {
$equal = false;
}
}
if ( $equal ) {
$match = ( $almost ) ? 2 : 1 ;
$pref = strpos($preferred, $char);
$pref = ( $pref !== false ) ? str_pad($pref, 3, '0', STR_PAD_LEFT) : '999' ;
return $pref.$match.'.'.(99999 - str_pad($first, 5, '0', STR_PAD_LEFT));
} else return false;
}
}
/**
* Read local file
* @param file local filename
* @return Data from file, or false on failure
*/
function _rfile ($file = null) {
if ( is_readable($file) ) {
if ( !($fh = fopen($file, 'r')) ) return false;
$data = fread($fh, filesize($file));
fclose($fh);
return $data;
}
return false;
}
/**
* Write to local file
* @param file local filename
* @param string data to write to file
* @param mode fopen() mode
* @param lock flock() mode
* @return true or false
*/
function _wfile ($file, $string = '', $mode = 'wb', $lock = 2) {
if ( $fp = fopen($file, $mode) ) {
flock($fp, $lock);
$re = fwrite($fp, $string);
$re2 = fclose($fp);
if ( $re != false && $re2 != false ) return true;
}
return false;
}
} }
?>
// 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 {
}

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>

1472
src/Csv.php Normal file

File diff suppressed because it is too large Load Diff

View File

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

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

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

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

29
src/enums/SortEnum.php Normal file
View File

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

@@ -0,0 +1,102 @@
<?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;
}
}

8
tests/Bootstrap.php Normal file
View File

@@ -0,0 +1,8 @@
<?php
chdir(__DIR__ . '/..');
if (!file_exists('vendor/autoload.php')) {
`composer dump-autoload`;
}
require __DIR__ . '/../vendor/autoload.php';

Binary file not shown.
1 idSite idVisit visitIp visitorId type (actionDetails 0) url (actionDetails 0) pageTitle (actionDetails 0) pageIdAction (actionDetails 0) idpageview (actionDetails 0) serverTimePretty (actionDetails 0) pageId (actionDetails 0) timeSpent (actionDetails 0) timeSpentPretty (actionDetails 0) interactionPosition (actionDetails 0) icon (actionDetails 0) timestamp (actionDetails 0) type (actionDetails 1) url (actionDetails 1) pageTitle (actionDetails 1) pageIdAction (actionDetails 1) idpageview (actionDetails 1) serverTimePretty (actionDetails 1) pageId (actionDetails 1) timeSpent (actionDetails 1) timeSpentPretty (actionDetails 1) generationTimeMilliseconds (actionDetails 1) generationTime (actionDetails 1) interactionPosition (actionDetails 1) icon (actionDetails 1) timestamp (actionDetails 1) type (actionDetails 2) url (actionDetails 2) pageTitle (actionDetails 2) pageIdAction (actionDetails 2) idpageview (actionDetails 2) serverTimePretty (actionDetails 2) pageId (actionDetails 2) timeSpent (actionDetails 2) timeSpentPretty (actionDetails 2) generationTimeMilliseconds (actionDetails 2) generationTime (actionDetails 2) interactionPosition (actionDetails 2) icon (actionDetails 2) timestamp (actionDetails 2) type (actionDetails 3) url (actionDetails 3) pageTitle (actionDetails 3) pageIdAction (actionDetails 3) idpageview (actionDetails 3) serverTimePretty (actionDetails 3) pageId (actionDetails 3) timeSpent (actionDetails 3) timeSpentPretty (actionDetails 3) generationTimeMilliseconds (actionDetails 3) generationTime (actionDetails 3) interactionPosition (actionDetails 3) icon (actionDetails 3) timestamp (actionDetails 3) type (actionDetails 4) url (actionDetails 4) pageTitle (actionDetails 4) pageIdAction (actionDetails 4) idpageview (actionDetails 4) serverTimePretty (actionDetails 4) pageId (actionDetails 4) timeSpent (actionDetails 4) timeSpentPretty (actionDetails 4) generationTimeMilliseconds (actionDetails 4) generationTime (actionDetails 4) interactionPosition (actionDetails 4) icon (actionDetails 4) timestamp (actionDetails 4) type (actionDetails 5) url (actionDetails 5) pageTitle (actionDetails 5) pageIdAction (actionDetails 5) idpageview (actionDetails 5) serverTimePretty (actionDetails 5) pageId (actionDetails 5) timeSpent (actionDetails 5) timeSpentPretty (actionDetails 5) generationTimeMilliseconds (actionDetails 5) generationTime (actionDetails 5) interactionPosition (actionDetails 5) icon (actionDetails 5) timestamp (actionDetails 5) type (actionDetails 6) url (actionDetails 6) pageTitle (actionDetails 6) pageIdAction (actionDetails 6) idpageview (actionDetails 6) serverTimePretty (actionDetails 6) pageId (actionDetails 6) timeSpent (actionDetails 6) timeSpentPretty (actionDetails 6) generationTimeMilliseconds (actionDetails 6) generationTime (actionDetails 6) interactionPosition (actionDetails 6) icon (actionDetails 6) timestamp (actionDetails 6) type (actionDetails 7) url (actionDetails 7) pageTitle (actionDetails 7) pageIdAction (actionDetails 7) idpageview (actionDetails 7) serverTimePretty (actionDetails 7) pageId (actionDetails 7) timeSpent (actionDetails 7) timeSpentPretty (actionDetails 7) generationTimeMilliseconds (actionDetails 7) generationTime (actionDetails 7) interactionPosition (actionDetails 7) icon (actionDetails 7) timestamp (actionDetails 7) type (actionDetails 8) url (actionDetails 8) pageTitle (actionDetails 8) pageIdAction (actionDetails 8) idpageview (actionDetails 8) serverTimePretty (actionDetails 8) pageId (actionDetails 8) timeSpent (actionDetails 8) timeSpentPretty (actionDetails 8) generationTimeMilliseconds (actionDetails 8) generationTime (actionDetails 8) interactionPosition (actionDetails 8) icon (actionDetails 8) timestamp (actionDetails 8) type (actionDetails 9) url (actionDetails 9) pageTitle (actionDetails 9) pageIdAction (actionDetails 9) idpageview (actionDetails 9) serverTimePretty (actionDetails 9) pageId (actionDetails 9) timeSpent (actionDetails 9) timeSpentPretty (actionDetails 9) generationTimeMilliseconds (actionDetails 9) generationTime (actionDetails 9) interactionPosition (actionDetails 9) icon (actionDetails 9) timestamp (actionDetails 9) type (actionDetails 10) url (actionDetails 10) pageTitle (actionDetails 10) pageIdAction (actionDetails 10) idpageview (actionDetails 10) serverTimePretty (actionDetails 10) pageId (actionDetails 10) timeSpent (actionDetails 10) timeSpentPretty (actionDetails 10) generationTimeMilliseconds (actionDetails 10) generationTime (actionDetails 10) interactionPosition (actionDetails 10) icon (actionDetails 10) timestamp (actionDetails 10) type (actionDetails 11) url (actionDetails 11) pageTitle (actionDetails 11) pageIdAction (actionDetails 11) idpageview (actionDetails 11) serverTimePretty (actionDetails 11) pageId (actionDetails 11) timeSpent (actionDetails 11) timeSpentPretty (actionDetails 11) generationTimeMilliseconds (actionDetails 11) generationTime (actionDetails 11) interactionPosition (actionDetails 11) icon (actionDetails 11) timestamp (actionDetails 11) type (actionDetails 12) url (actionDetails 12) pageTitle (actionDetails 12) pageIdAction (actionDetails 12) idpageview (actionDetails 12) serverTimePretty (actionDetails 12) pageId (actionDetails 12) timeSpent (actionDetails 12) timeSpentPretty (actionDetails 12) generationTimeMilliseconds (actionDetails 12) generationTime (actionDetails 12) interactionPosition (actionDetails 12) icon (actionDetails 12) timestamp (actionDetails 12) type (actionDetails 13) url (actionDetails 13) pageTitle (actionDetails 13) pageIdAction (actionDetails 13) idpageview (actionDetails 13) serverTimePretty (actionDetails 13) pageId (actionDetails 13) timeSpent (actionDetails 13) timeSpentPretty (actionDetails 13) generationTimeMilliseconds (actionDetails 13) generationTime (actionDetails 13) interactionPosition (actionDetails 13) icon (actionDetails 13) timestamp (actionDetails 13) type (actionDetails 14) url (actionDetails 14) pageTitle (actionDetails 14) pageIdAction (actionDetails 14) idpageview (actionDetails 14) serverTimePretty (actionDetails 14) pageId (actionDetails 14) timeSpent (actionDetails 14) timeSpentPretty (actionDetails 14) generationTimeMilliseconds (actionDetails 14) generationTime (actionDetails 14) interactionPosition (actionDetails 14) icon (actionDetails 14) timestamp (actionDetails 14) type (actionDetails 15) url (actionDetails 15) pageTitle (actionDetails 15) pageIdAction (actionDetails 15) idpageview (actionDetails 15) serverTimePretty (actionDetails 15) pageId (actionDetails 15) timeSpent (actionDetails 15) timeSpentPretty (actionDetails 15) generationTimeMilliseconds (actionDetails 15) generationTime (actionDetails 15) interactionPosition (actionDetails 15) icon (actionDetails 15) timestamp (actionDetails 15) type (actionDetails 16) url (actionDetails 16) pageTitle (actionDetails 16) pageIdAction (actionDetails 16) idpageview (actionDetails 16) serverTimePretty (actionDetails 16) pageId (actionDetails 16) timeSpent (actionDetails 16) timeSpentPretty (actionDetails 16) generationTimeMilliseconds (actionDetails 16) generationTime (actionDetails 16) interactionPosition (actionDetails 16) icon (actionDetails 16) timestamp (actionDetails 16) type (actionDetails 17) url (actionDetails 17) pageTitle (actionDetails 17) pageIdAction (actionDetails 17) idpageview (actionDetails 17) serverTimePretty (actionDetails 17) pageId (actionDetails 17) timeSpent (actionDetails 17) timeSpentPretty (actionDetails 17) generationTimeMilliseconds (actionDetails 17) generationTime (actionDetails 17) interactionPosition (actionDetails 17) icon (actionDetails 17) timestamp (actionDetails 17) type (actionDetails 18) url (actionDetails 18) pageTitle (actionDetails 18) pageIdAction (actionDetails 18) idpageview (actionDetails 18) serverTimePretty (actionDetails 18) pageId (actionDetails 18) timeSpent (actionDetails 18) timeSpentPretty (actionDetails 18) generationTimeMilliseconds (actionDetails 18) generationTime (actionDetails 18) interactionPosition (actionDetails 18) icon (actionDetails 18) timestamp (actionDetails 18) type (actionDetails 19) url (actionDetails 19) pageTitle (actionDetails 19) pageIdAction (actionDetails 19) idpageview (actionDetails 19) serverTimePretty (actionDetails 19) pageId (actionDetails 19) timeSpent (actionDetails 19) timeSpentPretty (actionDetails 19) generationTimeMilliseconds (actionDetails 19) generationTime (actionDetails 19) interactionPosition (actionDetails 19) icon (actionDetails 19) timestamp (actionDetails 19) type (actionDetails 20) url (actionDetails 20) pageTitle (actionDetails 20) pageIdAction (actionDetails 20) idpageview (actionDetails 20) serverTimePretty (actionDetails 20) pageId (actionDetails 20) timeSpent (actionDetails 20) timeSpentPretty (actionDetails 20) generationTimeMilliseconds (actionDetails 20) generationTime (actionDetails 20) interactionPosition (actionDetails 20) icon (actionDetails 20) timestamp (actionDetails 20) type (actionDetails 21) url (actionDetails 21) pageTitle (actionDetails 21) pageIdAction (actionDetails 21) idpageview (actionDetails 21) serverTimePretty (actionDetails 21) pageId (actionDetails 21) timeSpent (actionDetails 21) timeSpentPretty (actionDetails 21) generationTimeMilliseconds (actionDetails 21) generationTime (actionDetails 21) interactionPosition (actionDetails 21) icon (actionDetails 21) timestamp (actionDetails 21) type (actionDetails 22) url (actionDetails 22) pageTitle (actionDetails 22) pageIdAction (actionDetails 22) idpageview (actionDetails 22) serverTimePretty (actionDetails 22) pageId (actionDetails 22) timeSpent (actionDetails 22) timeSpentPretty (actionDetails 22) generationTimeMilliseconds (actionDetails 22) generationTime (actionDetails 22) interactionPosition (actionDetails 22) icon (actionDetails 22) timestamp (actionDetails 22) type (actionDetails 23) url (actionDetails 23) pageTitle (actionDetails 23) pageIdAction (actionDetails 23) idpageview (actionDetails 23) serverTimePretty (actionDetails 23) pageId (actionDetails 23) timeSpent (actionDetails 23) timeSpentPretty (actionDetails 23) generationTimeMilliseconds (actionDetails 23) generationTime (actionDetails 23) interactionPosition (actionDetails 23) icon (actionDetails 23) timestamp (actionDetails 23) type (actionDetails 24) url (actionDetails 24) pageTitle (actionDetails 24) pageIdAction (actionDetails 24) idpageview (actionDetails 24) serverTimePretty (actionDetails 24) pageId (actionDetails 24) timeSpent (actionDetails 24) timeSpentPretty (actionDetails 24) generationTimeMilliseconds (actionDetails 24) generationTime (actionDetails 24) interactionPosition (actionDetails 24) icon (actionDetails 24) timestamp (actionDetails 24) type (actionDetails 25) url (actionDetails 25) pageTitle (actionDetails 25) pageIdAction (actionDetails 25) idpageview (actionDetails 25) serverTimePretty (actionDetails 25) pageId (actionDetails 25) timeSpent (actionDetails 25) timeSpentPretty (actionDetails 25) generationTimeMilliseconds (actionDetails 25) generationTime (actionDetails 25) interactionPosition (actionDetails 25) icon (actionDetails 25) timestamp (actionDetails 25) type (actionDetails 26) url (actionDetails 26) pageTitle (actionDetails 26) pageIdAction (actionDetails 26) idpageview (actionDetails 26) serverTimePretty (actionDetails 26) pageId (actionDetails 26) timeSpent (actionDetails 26) timeSpentPretty (actionDetails 26) generationTimeMilliseconds (actionDetails 26) generationTime (actionDetails 26) interactionPosition (actionDetails 26) icon (actionDetails 26) timestamp (actionDetails 26) type (actionDetails 27) url (actionDetails 27) pageTitle (actionDetails 27) pageIdAction (actionDetails 27) idpageview (actionDetails 27) serverTimePretty (actionDetails 27) pageId (actionDetails 27) timeSpent (actionDetails 27) timeSpentPretty (actionDetails 27) generationTimeMilliseconds (actionDetails 27) generationTime (actionDetails 27) interactionPosition (actionDetails 27) icon (actionDetails 27) timestamp (actionDetails 27) type (actionDetails 28) url (actionDetails 28) pageTitle (actionDetails 28) pageIdAction (actionDetails 28) idpageview (actionDetails 28) serverTimePretty (actionDetails 28) pageId (actionDetails 28) timeSpent (actionDetails 28) timeSpentPretty (actionDetails 28) generationTimeMilliseconds (actionDetails 28) generationTime (actionDetails 28) interactionPosition (actionDetails 28) icon (actionDetails 28) timestamp (actionDetails 28) type (actionDetails 29) url (actionDetails 29) pageTitle (actionDetails 29) pageIdAction (actionDetails 29) idpageview (actionDetails 29) serverTimePretty (actionDetails 29) pageId (actionDetails 29) timeSpent (actionDetails 29) timeSpentPretty (actionDetails 29) generationTimeMilliseconds (actionDetails 29) generationTime (actionDetails 29) interactionPosition (actionDetails 29) icon (actionDetails 29) timestamp (actionDetails 29) type (actionDetails 30) url (actionDetails 30) pageTitle (actionDetails 30) pageIdAction (actionDetails 30) idpageview (actionDetails 30) serverTimePretty (actionDetails 30) pageId (actionDetails 30) timeSpent (actionDetails 30) timeSpentPretty (actionDetails 30) generationTimeMilliseconds (actionDetails 30) generationTime (actionDetails 30) interactionPosition (actionDetails 30) icon (actionDetails 30) timestamp (actionDetails 30) type (actionDetails 31) url (actionDetails 31) pageTitle (actionDetails 31) pageIdAction (actionDetails 31) idpageview (actionDetails 31) serverTimePretty (actionDetails 31) pageId (actionDetails 31) timeSpent (actionDetails 31) timeSpentPretty (actionDetails 31) generationTimeMilliseconds (actionDetails 31) generationTime (actionDetails 31) interactionPosition (actionDetails 31) icon (actionDetails 31) timestamp (actionDetails 31) type (actionDetails 32) url (actionDetails 32) pageTitle (actionDetails 32) pageIdAction (actionDetails 32) idpageview (actionDetails 32) serverTimePretty (actionDetails 32) pageId (actionDetails 32) timeSpent (actionDetails 32) timeSpentPretty (actionDetails 32) generationTimeMilliseconds (actionDetails 32) generationTime (actionDetails 32) interactionPosition (actionDetails 32) icon (actionDetails 32) timestamp (actionDetails 32) type (actionDetails 33) url (actionDetails 33) pageTitle (actionDetails 33) pageIdAction (actionDetails 33) idpageview (actionDetails 33) serverTimePretty (actionDetails 33) pageId (actionDetails 33) timeSpent (actionDetails 33) timeSpentPretty (actionDetails 33) generationTimeMilliseconds (actionDetails 33) generationTime (actionDetails 33) interactionPosition (actionDetails 33) icon (actionDetails 33) timestamp (actionDetails 33) type (actionDetails 34) url (actionDetails 34) pageTitle (actionDetails 34) pageIdAction (actionDetails 34) idpageview (actionDetails 34) serverTimePretty (actionDetails 34) pageId (actionDetails 34) timeSpent (actionDetails 34) timeSpentPretty (actionDetails 34) generationTimeMilliseconds (actionDetails 34) generationTime (actionDetails 34) interactionPosition (actionDetails 34) icon (actionDetails 34) timestamp (actionDetails 34) type (actionDetails 35) url (actionDetails 35) pageTitle (actionDetails 35) pageIdAction (actionDetails 35) idpageview (actionDetails 35) serverTimePretty (actionDetails 35) pageId (actionDetails 35) timeSpent (actionDetails 35) timeSpentPretty (actionDetails 35) generationTimeMilliseconds (actionDetails 35) generationTime (actionDetails 35) interactionPosition (actionDetails 35) icon (actionDetails 35) timestamp (actionDetails 35) type (actionDetails 36) url (actionDetails 36) pageTitle (actionDetails 36) pageIdAction (actionDetails 36) idpageview (actionDetails 36) serverTimePretty (actionDetails 36) pageId (actionDetails 36) timeSpent (actionDetails 36) timeSpentPretty (actionDetails 36) generationTimeMilliseconds (actionDetails 36) generationTime (actionDetails 36) interactionPosition (actionDetails 36) icon (actionDetails 36) timestamp (actionDetails 36) type (actionDetails 37) url (actionDetails 37) pageTitle (actionDetails 37) pageIdAction (actionDetails 37) idpageview (actionDetails 37) serverTimePretty (actionDetails 37) pageId (actionDetails 37) timeSpent (actionDetails 37) timeSpentPretty (actionDetails 37) interactionPosition (actionDetails 37) icon (actionDetails 37) timestamp (actionDetails 37) type (actionDetails 38) url (actionDetails 38) pageTitle (actionDetails 38) pageIdAction (actionDetails 38) idpageview (actionDetails 38) serverTimePretty (actionDetails 38) pageId (actionDetails 38) timeSpent (actionDetails 38) timeSpentPretty (actionDetails 38) interactionPosition (actionDetails 38) icon (actionDetails 38) timestamp (actionDetails 38) type (actionDetails 39) url (actionDetails 39) pageTitle (actionDetails 39) pageIdAction (actionDetails 39) idpageview (actionDetails 39) serverTimePretty (actionDetails 39) pageId (actionDetails 39) timeSpent (actionDetails 39) timeSpentPretty (actionDetails 39) generationTimeMilliseconds (actionDetails 39) generationTime (actionDetails 39) interactionPosition (actionDetails 39) icon (actionDetails 39) timestamp (actionDetails 39) type (actionDetails 40) url (actionDetails 40) pageTitle (actionDetails 40) pageIdAction (actionDetails 40) idpageview (actionDetails 40) serverTimePretty (actionDetails 40) pageId (actionDetails 40) generationTimeMilliseconds (actionDetails 40) generationTime (actionDetails 40) interactionPosition (actionDetails 40) icon (actionDetails 40) timestamp (actionDetails 40) goalConversions siteCurrency siteCurrencySymbol serverDate visitServerHour lastActionTimestamp lastActionDateTime serverTimestamp firstActionTimestamp serverTimePretty serverDatePretty serverDatePrettyFirstAction serverTimePrettyFirstAction userId visitorType visitorTypeIcon visitConverted visitConvertedIcon visitCount visitEcommerceStatus visitEcommerceStatusIcon daysSinceFirstVisit daysSinceLastEcommerceOrder visitDuration visitDurationPretty searches actions interactions referrerType referrerTypeName referrerName referrerKeyword referrerKeywordPosition referrerUrl referrerSearchEngineUrl referrerSearchEngineIcon languageCode language deviceType deviceTypeIcon deviceBrand deviceModel operatingSystem operatingSystemName operatingSystemIcon operatingSystemCode operatingSystemVersion browserFamily browserFamilyDescription browser browserName browserIcon browserCode browserVersion events continent continentCode country countryCode countryFlag region regionCode city location latitude longitude visitLocalTime visitLocalHour daysSinceLastVisit resolution plugins pluginsIcons provider providerName providerUrl customVariableName1 customVariableValue1 customVariableName2 customVariableValue2 customVariableName3 customVariableValue3 customVariableName4 customVariableValue4 customVariableName5 customVariableValue5 pageUrl__1 pageTitle__1 pageUrl__2 pageTitle__2 pageUrl__3 pageTitle__3 pageUrl__4 pageTitle__4 pageUrl__5 pageTitle__5 pageUrl__6 pageTitle__6 pageUrl__7 pageTitle__7 pageUrl__8 pageTitle__8 pageUrl__9 pageTitle__9 pageUrl__10 pageTitle__10 pageUrl__11 pageTitle__11 pageUrl__12 pageTitle__12 pageUrl__13 pageUrl__14 pageTitle__14 pageUrl__15 pageTitle__15 pageUrl__16 pageTitle__16 pageUrl__17 pageTitle__17 pageUrl__18 pageTitle__18 pageUrl__19 pageTitle__19 pageUrl__20 pageTitle__20 pageUrl__21 pageTitle__21 pageUrl__22 pageTitle__22 pageUrl__23 pageTitle__23 pageUrl__24 pageUrl__25 pageTitle__25 pageUrl__26 pageTitle__26 pageUrl__27 pageTitle__27 pageUrl__28 pageTitle__28 pageUrl__29 pageTitle__29 pageUrl__30 pageTitle__30 pageUrl__31 pageTitle__31 pageUrl__32 pageTitle__32 pageUrl__33 pageTitle__33 pageUrl__34 pageTitle__34 pageUrl__35 pageTitle__35 pageUrl__36 pageTitle__36 pageUrl__37 pageTitle__37 pageUrl__38 pageTitle__38 pageUrl__39 pageTitle__39 pageUrl__40 pageTitle__40 pageUrl__41 pageTitle__41 entryPageTitle entryPageUrl exitPageTitle exitPageUrl generationTimeMilliseconds (actionDetails 0) generationTime (actionDetails 0) timeSpentRef (actionDetails 9) custom_float (actionDetails 9)
2 13 129930 213. 6c38cb8dca6e1f5d action http://_asktermmesswert/Button1 Ok 9551 04.1.2017 17:42:12 1181863 20 20 s 1 1483551732 action http://application/_Main/mnDatenbankSpeichern Save changes in the database 9646 04.1.2017 17:42:32 1181864 15 15 s 1092 1,09 s 2 1483551752 action http://application/_Main/bbRingversuchwechseln Ring test 9386 04.1.2017 17:42:47 1181865 58 58 s 6966 6,97 s 3 1483551767 action http://application/_Main/mnPML_ToTest Sample-measurand-laboratory allocation 9915 04.1.2017 17:43:45 1181866 14 14 s 851 0,85 s 4 1483551825 action http://application/_Main/_ErstellePMLabKombination/btnAddAll Include allcombinations 9864 04.1.2017 17:43:59 1181867 22 22 s 204 0,2 s 5 1483551839 action http://application/_Main/mnHomogeneityImportMesswerte Import test results 9574 04.1.2017 17:44:21 1181868 9 9 s 189 0,19 s 6 1483551861 action http://application/_Main/mnCalcMean Ring test parameters 9289 04.1.2017 17:44:30 1181869 3 3 s 598 0,6 s 7 1483551870 action http://application/_Main/_CalcMeanSTD_MDI/btnReportMeanSTD Assigned values/s.d. 9659 04.1.2017 17:44:33 1181870 15 15 s 10369 10,37 s 8 1483551873 action http://application/_Main/_CalcMeanSTD_MDI/btnCalculateMean Computation 9290 04.1.2017 17:44:48 1181871 55 55 s 22762 22,76 s 9 1483551888 action http://application/_Main/_CalcMeanSTD_MDI/mnReportMitLaborcode with Lab code 9411 04.1.2017 17:45:43 1181872 80 1 Minuten 20s 6345 6,35 s 10 1483551943 action http://application/_Main/bbHistogram_NormalPlot Histogram normal plot 9361 04.1.2017 17:47:03 1181873 31 31 s 5985 5,99 s 11 1483552023 action http://application/_Main/bbVariance_ToleranceLimits Tolerance limits rel. standard deviations 9873 04.1.2017 17:47:34 1181874 12 12 s 567 0,57 s 12 1483552054 action http://application/_Main/_Youdenplot_MDI/PageControl1 9363 04.1.2017 17:47:46 1181875 0 0 s 4 0,004 s 13 1483552066 action http://application/_Main/bbYoudenplot Youden plot 9364 04.1.2017 17:47:46 1181876 30 30 s 497 0,5 s 14 1483552066 action http://application/_Main/bbOverAllSamples Laboratory mean values 9293 04.1.2017 17:48:16 1181877 33 33 s 458 0,46 s 15 1483552096 action http://application/_Main/bbLoadSelect Load selection 12749 04.1.2017 17:48:49 1181878 7 7 s 62 0,06 s 16 1483552129 action http://application/_Main/bbPML_ToTest Sample-measurand-laboratory allocation 9321 04.1.2017 17:48:56 1181879 5 5 s 1192 1,19 s 17 1483552136 action http://application/_Main/bbLCode Laboratories 9350 04.1.2017 17:49:01 1181880 4 4 s 635 0,64 s 18 1483552141 action http://application/_Main/_LaborCodierung/btnReset Delete all laboratory codes 10435 04.1.2017 17:49:05 1181881 14 14 s 4333 4,33 s 19 1483552145 action http://application/_Main/mnNewDatabase New database 9441 04.1.2017 17:49:19 1181882 17 17 s 6939 6,94 s 20 1483552159 action http://application/_Main/mnHomogeneityBerechnung Calculation (ISO 13528:2015 and Harmonized Protocol) 9579 04.1.2017 17:49:36 1181883 14 14 s 612 0,61 s 21 1483552176 action http://application/_Main/_CalcHomogeneity_MDI/mniReportChart Graphics and text for current combination 9643 04.1.2017 17:49:50 1181884 0 0 s 4912 4,91 s 22 1483552190 action http://application/_Main/bbYoudenplot Youden plot 9364 04.1.2017 17:50:05 1181886 16 16 s 855 0,86 s 24 1483552205 action http://application/_Main/_Youdenplot_MDI/PageControl1 9363 04.1.2017 17:50:06 1181885 0 0 s 5 0,005 s 23 1483552206 action http://application/_Main/bbEinzeldarstellung Summary results 9268 04.1.2017 17:50:10 1181888 6 6 s 2941 2,94 s 26 1483552210 action http://application/_Main/_GraphicMeanSTD_MDI/mnuYAutoscaleAll Automatic scaling for all chart contents 9301 04.1.2017 17:50:11 1181887 34 34 s 1 0,001 s 25 1483552211 action http://application/_Main/_GraphicMeanSTD_MDI/btnOutlier Outliers 9503 04.1.2017 17:50:44 1181889 2 2 s 76 0,08 s 27 1483552244 action http://application/_Main/_GraphicMeanSTD_MDI/btnConfBandOptions ... 9777 04.1.2017 17:50:46 1181890 1 1 s 1482 1,48 s 28 1483552246 action http://application/_Main/_GraphicMeanSTD_MDI/mnConfLinien Lines 10077 04.1.2017 17:50:47 1181891 18 18 s 1529 1,53 s 29 1483552247 action http://application/_Main/bbPM_ToTest Sample-measurand allocation 9319 04.1.2017 17:51:05 1181892 2 2 s 100 0,1 s 30 1483552265 action http://application/_Main/bbPML_ToTest Sample-measurand-laboratory allocation 9321 04.1.2017 17:51:07 1181893 3 3 s 1178 1,18 s 31 1483552267 action http://application/_Main/bbLabToTest Laboratory allocation 9317 04.1.2017 17:51:10 1181894 34 34 s 109 0,11 s 32 1483552270 action http://application/_Main/bbYoudenplot Youden plot 9364 04.1.2017 17:51:44 1181895 1 1 s 47 0,05 s 33 1483552304 action http://application/_Main/bbScoreGraphic Survey of Z-Scores 9269 04.1.2017 17:51:45 1181896 32 32 s 310 0,31 s 34 1483552305 action http://application/_Main/_GraphicZScores_MDI/btnLCode Lab code 9487 04.1.2017 17:52:17 1181897 8 8 s 234 0,23 s 35 1483552337 action http://application/_Main/_GraphicZScores_MDI/btnClose Close 9488 04.1.2017 17:52:25 1181898 2 2 s 130 0,13 s 36 1483552345 action http://application/_Main/_Youdenplot_MDI/btnClose Close 9799 04.1.2017 17:52:27 1181899 1 1 s 86 0,09 s 37 1483552347 action http://application/_Main/_LabStructure/btnClose Close 9866 04.1.2017 17:52:28 1181900 1 1 s 38 1483552348 action http://application/_Main/_ErstellePMLabKombination/btnClose Close 9946 04.1.2017 17:52:29 1181901 1 1 s 39 1483552349 action http://application/_Main/_ErstellePMKombination/btnClose Close 9831 04.1.2017 17:52:30 1181902 1 1 s 1 0,001 s 40 1483552350 action http://application/_Main/btnClose Close 9245 04.1.2017 17:52:31 1181903 29 0,03 s 41 1483552351 0 EUR 2017-01-04 16 1483548751 2017-01-04 16:52:31 1483548751 1483548132 17:52:31 Mittwoch, 4. Januar 2017 Mittwoch, 4. Januar 2017 17:42:12 new 0 1 none 0 0 620 10 Minuten 20s 0 41 41 direct Direkte Zugriffe en Englisch unbekannt plugins/Morpheus/icons/dist/devices/unknown.png unbekannt unbekannt unbekannt plugins/Morpheus/icons/dist/os/UNK.png UNK UNK unbekannt unbekannt unbekannt plugins/Morpheus/icons/dist/browsers/UNK.png UNK 0 Südamerika ams Brasilien br plugins/Morpheus/icons/dist/flags/br.png Sao Paulo 27 São Paulo São Paulo, Sao Paulo, Brasilien -23.473000 -46.666000 16:42:12 16 0 1920x1080 wcs.net.br Wcs http://www.wcs.net.br/ From _1710 Serial _1710 Version 21. App PROLab Plus Demo OsLanguage Portuguese http://_asktermmesswert/Button1 Ok http://application/_Main/mnDatenbankSpeichern Save changes in the database http://application/_Main/bbRingversuchwechseln Ring test http://application/_Main/mnPML_ToTest Sample-measurand-laboratory allocation http://application/_Main/_ErstellePMLabKombination/btnAddAll Include allcombinations http://application/_Main/mnHomogeneityImportMesswerte Import test results http://application/_Main/mnCalcMean Ring test parameters http://application/_Main/_CalcMeanSTD_MDI/btnReportMeanSTD Assigned values/s.d. http://application/_Main/_CalcMeanSTD_MDI/btnCalculateMean Computation http://application/_Main/_CalcMeanSTD_MDI/mnReportMitLaborcode with Lab code http://application/_Main/bbHistogram_NormalPlot Histogram normal plot http://application/_Main/bbVariance_ToleranceLimits Tolerance limits rel. standard deviations http://application/_Main/_Youdenplot_MDI/PageControl1 http://application/_Main/bbYoudenplot Youden plot http://application/_Main/bbOverAllSamples Laboratory mean values http://application/_Main/bbLoadSelect Load selection http://application/_Main/bbPML_ToTest Sample-measurand-laboratory allocation http://application/_Main/bbLCode Laboratories http://application/_Main/_LaborCodierung/btnReset Delete all laboratory codes http://application/_Main/mnNewDatabase New database http://application/_Main/mnHomogeneityBerechnung Calculation (ISO 13528:2015 and Harmonized Protocol) http://application/_Main/_CalcHomogeneity_MDI/mniReportChart Graphics and text for current combination http://application/_Main/bbYoudenplot Youden plot http://application/_Main/_Youdenplot_MDI/PageControl1 http://application/_Main/bbEinzeldarstellung Summary results http://application/_Main/_GraphicMeanSTD_MDI/mnuYAutoscaleAll Automatic scaling for all chart contents http://application/_Main/_GraphicMeanSTD_MDI/btnOutlier Outliers http://application/_Main/_GraphicMeanSTD_MDI/btnConfBandOptions ... http://application/_Main/_GraphicMeanSTD_MDI/mnConfLinien Lines http://application/_Main/bbPM_ToTest Sample-measurand allocation http://application/_Main/bbPML_ToTest Sample-measurand-laboratory allocation http://application/_Main/bbLabToTest Laboratory allocation http://application/_Main/bbYoudenplot Youden plot http://application/_Main/bbScoreGraphic Survey of Z-Scores http://application/_Main/_GraphicZScores_MDI/btnLCode Lab code http://application/_Main/_GraphicZScores_MDI/btnClose Close http://application/_Main/_Youdenplot_MDI/btnClose Close http://application/_Main/_LabStructure/btnClose Close http://application/_Main/_ErstellePMLabKombination/btnClose Close http://application/_Main/_ErstellePMKombination/btnClose Close http://application/_Main/btnClose Close Ok http://_asktermmesswert/Button1 Close http://application/_Main/btnClose
3 13 129999 154. 69dafac11ed871fb action http://application/_Main/Grundtabellen1 Basic tables 9295 04.1.2017 16:08:19 1182416 35 35 s 1 1483546099 action http://application/_Main/mnHomogeneityImportMesswerte Import test results 9574 04.1.2017 16:08:54 1182417 12 12 s 1107 1,11 s 2 1483546134 action http://application/_Main/_ImportGroups_FP/btnLoad Open 9576 04.1.2017 16:09:06 1182418 30 30 s 10551 10,55 s 3 1483546146 action http://application/_Main/_ImportGroups_FP/btnFiletransfer Transfer data 9578 04.1.2017 16:09:36 1182419 44 44 s 32089 32,09 s 4 1483546176 action http://application/_Main/mnHomogeneityBerechnung Calculation (ISO 13528:2015 and Harmonized Protocol) 9579 04.1.2017 16:10:20 1182420 889 0,89 s 5 1483546220 0 EUR 2017-01-04 15 1483542620 2017-01-04 15:10:20 1483542620 1483542499 16:10:20 Mittwoch, 4. Januar 2017 Mittwoch, 4. Januar 2017 16:08:19 new 0 1 none 0 0 122 2 Minuten 2s 0 5 5 direct Direkte Zugriffe en Englisch unbekannt plugins/Morpheus/icons/dist/devices/unknown.png unbekannt unbekannt unbekannt plugins/Morpheus/icons/dist/os/UNK.png UNK UNK unbekannt unbekannt unbekannt plugins/Morpheus/icons/dist/browsers/UNK.png UNK 0 Afrika afr Südafrika za plugins/Morpheus/icons/dist/flags/za.png Gauteng 06 Johannesburg Johannesburg, Gauteng, Südafrika -26.205000 28.050000 15:08:19 15 0 1366x768 telkomadsl.co.za Telkomadsl http://www.telkomadsl.co.za/ From _1710 Serial _1710 Version 30..0 App PROLab Plus OsLanguage English http://application/_Main/Grundtabellen1 Basic tables http://application/_Main/mnHomogeneityImportMesswerte Import test results http://application/_Main/_ImportGroups_FP/btnLoad Open http://application/_Main/_ImportGroups_FP/btnFiletransfer Transfer data http://application/_Main/mnHomogeneityBerechnung Calculation (ISO 13528:2015 and Harmonized Protocol) Basic tables http://application/_Main/Grundtabellen1 Calculation (ISO 13528:2015 and Harmonized Protocol) http://application/_Main/mnHomogeneityBerechnung 4945 4,95 s
4 13 129898 85..0 79a87d1a340cd850 action http://application/_Main/bbLabToTest Laboratory allocation 9317 04.1.2017 15:28:18 1181575 21 21 s 1 1483543698 action http://application/_Main/_LabStructure/btnDelete Exclude selectedlaboratories 9835 04.1.2017 15:28:39 1181576 13 13 s 3481 3,48 s 2 1483543719 action http://application/_Main/_LabStructure/btnAdd Include selectedlaboratories 9913 04.1.2017 15:28:52 1181577 214 3 Minuten 34s 24 0,02 s 3 1483543732 action http://application/_Main/_LabStructure/btnClose Close 9866 04.1.2017 15:32:26 1181578 4 4 s 1 0,001 s 4 1483543946 action http://application/_Main/Grundtabellen1 Basic tables 9295 04.1.2017 15:32:30 1181579 8 8 s 4355 4,36 s 5 1483543950 action http://application/_Main/_EditBasicTables/btnClose Close 9267 04.1.2017 15:32:38 1181580 2 2 s 9 0,009 s 6 1483543958 action http://application/_Main/Grundtabellen1 Basic tables 9295 04.1.2017 15:32:40 1181581 334 5 Minuten 34s 4211 4,21 s 7 1483543960 action http://application/_Main/_EditBasicTables/btnClose Close 9267 04.1.2017 15:38:14 1181582 0 0 s 10 0,01 s 8 1483544294 action http://application/_Main/mnCalcZScores_Results Computation of scores and tolerance limits 9260 04.1.2017 15:38:14 1181583 0 0 s 34018 34,02 s 9 1483544294 4 Save as Excel file 04.1.2017 15:38:14 1181584 10 1483544294 action http://application/_Main/_CalcZScores_Results_MDI/JvSpeedButton5 Close form 9772 04.1.2017 15:38:14 1181585 5 0,005 s 11 1483544294 0 EUR 2017-01-04 14 1483540694 2017-01-04 14:38:14 1483540694 1483540098 15:38:14 Mittwoch, 4. Januar 2017 Mittwoch, 4. Januar 2017 15:28:18 new 0 1 none 0 0 597 9 Minuten 57s 0 11 11 direct Direkte Zugriffe en Englisch unbekannt plugins/Morpheus/icons/dist/devices/unknown.png unbekannt unbekannt unbekannt plugins/Morpheus/icons/dist/os/UNK.png UNK UNK unbekannt unbekannt unbekannt plugins/Morpheus/icons/dist/browsers/UNK.png UNK 0 Europa eur Dänemark dk plugins/Morpheus/icons/dist/flags/dk.png Dänemark 56.000000 10.000000 14:28:18 14 0 1680x1050 Ip unbekannt From _1710 Serial _1710 Version 17..0 App PROLab Plus OsLanguage Danish http://application/_Main/bbLabToTest Laboratory allocation http://application/_Main/_LabStructure/btnDelete Exclude selectedlaboratories http://application/_Main/_LabStructure/btnAdd Include selectedlaboratories http://application/_Main/_LabStructure/btnClose Close http://application/_Main/Grundtabellen1 Basic tables http://application/_Main/_EditBasicTables/btnClose Close http://application/_Main/Grundtabellen1 Basic tables http://application/_Main/_EditBasicTables/btnClose Close http://application/_Main/mnCalcZScores_Results Computation of scores and tolerance limits Save as Excel file http://application/_Main/_CalcZScores_Results_MDI/JvSpeedButton5 Close form Laboratory allocation http://application/_Main/bbLabToTest Close form http://application/_Main/_CalcZScores_Results_MDI/JvSpeedButton5 2641 2,64 s 0 18873

Binary file not shown.
1 sep=;
2 title;isbn;publishedAt
3 Красивая кулинария;5454-5587-3210;21.05.2011
4 The Wine Connoisseurs;2547-8548-2541;12.12.2011
5 Weißwein;1313-4545-8875;23.02.2012

View File

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

View File

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

View File

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

@@ -0,0 +1,5 @@
SMS
0444
5555
6606
7777
1 SMS
2 0444
3 5555
4 6606
5 7777

View File

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

View File

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

@@ -0,0 +1,70 @@
<?php
namespace ParseCsv\tests\methods;
use ParseCsv\Csv;
use PHPUnit\Framework\TestCase;
class ConstructTest extends TestCase {
/**
* @var Csv object
*/
protected $csv = null;
public function test_offset_param() {
$offset = 10;
$this->csv = new Csv(null, $offset);
$this->assertTrue(is_numeric($this->csv->offset));
$this->assertEquals($offset, $this->csv->offset);
}
public function test_limit_param() {
$limit = 10;
$this->csv = new Csv(null, null, $limit);
$this->assertTrue(is_numeric($this->csv->limit));
$this->assertEquals($limit, $this->csv->limit);
}
public function test_conditions_param() {
$conditions = 'some column NOT value';
$this->csv = new Csv(null, null, null, $conditions);
$this->assertTrue(is_string($this->csv->conditions));
$this->assertEquals($conditions, $this->csv->conditions);
}
public function test_keep_file_data_param() {
$keep = true;
$this->csv = new Csv(null, null, null, null, $keep);
$this->assertTrue(is_bool($this->csv->keep_file_data));
$this->assertEquals($keep, $this->csv->keep_file_data);
}
public function test_input_param() {
$csv = "col1,col2,col3\r\nval1,val2,val3\r\nval1A,val2A,val3A\r\n";
$this->csv = new Csv($csv, null, null, null, true);
$this->assertTrue(is_string($this->csv->file_data));
$this->assertEquals($csv, $this->csv->file_data);
}
/**
* @runInSeparateProcess because download.php uses header()
*
* @see https://github.com/sebastianbergmann/phpunit/issues/720#issuecomment-10421092
*/
public function testCodeExamples() {
chdir('examples');
foreach (glob('*.php') as $script_file) {
ob_start();
/** @noinspection PhpIncludeInspection */
require $script_file;
$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

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

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

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

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

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

355
tests/methods/ParseTest.php Normal file
View File

@@ -0,0 +1,355 @@
<?php
namespace ParseCsv\tests\methods;
use ParseCsv\Csv;
use PHPUnit\Framework\TestCase;
use ReflectionClass;
class ParseTest extends TestCase {
/**
* @var Csv object
*/
protected $csv;
/**
* Setup
* Setup our test environment objects
*
* @access public
*/
protected function setUp(): void {
$this->csv = new Csv();
}
public function testParse() {
// can we trick 'is_readable' into whining? See #67.
$this->parseRepetitiveString('c:/looks/like/a/path');
$this->parseRepetitiveString('http://looks/like/an/url');
}
/**
* @param string $content
*/
private function parseRepetitiveString($content) {
$this->csv->delimiter = ';';
$this->csv->heading = false;
$success = $this->csv->parse(str_repeat($content . ';', 500));
self::assertEquals(true, $success);
$row = array_pop($this->csv->data);
$expected_data = array_fill(0, 500, $content);
$expected_data[] = '';
self::assertEquals($expected_data, $row);
}
/**
* @depends testParse
*
* @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() {
$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"
);
$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'];
self::assertEquals($expected_data, $row);
}
public function testAllNumericalCsv() {
$this->csv->heading = false;
$sInput = "86545235689\r\n34365587654\r\n13469874576";
self::assertEquals(false, $this->csv->autoDetectionForDataString($sInput));
self::assertEquals(null, $this->csv->delimiter);
$expected_data = explode("\r\n", $sInput);
$actual_data = array_map('reset', $this->csv->data);
self::assertEquals($expected_data, $actual_data);
}
public function testMissingEndingLineBreak() {
$this->csv->heading = false;
$this->csv->enclosure = '"';
$sInput = "86545235689,a\r\n34365587654,b\r\n13469874576,\"c\r\nd\"";
$expected_data = [86545235689, 34365587654, 13469874576];
$actual_data = $this->invokeMethod($this->csv, '_parse_string', [$sInput]);
$actual_column = array_map('reset', $actual_data);
self::assertEquals($expected_data, $actual_column);
self::assertEquals(
[
'a',
'b',
"c\r\nd",
],
array_map('next', $actual_data)
);
}
public function testSingleColumn() {
$this->csv->auto(__DIR__ . '/../example_files/single_column.csv');
$expected = [
['SMS' => '0444'],
['SMS' => '5555'],
['SMS' => '6606'],
['SMS' => '7777'],
];
self::assertEquals($expected, $this->csv->data);
}
public function testSingleRow() {
$this->csv->auto(__DIR__ . '/../example_files/single_row.csv');
self::assertEquals([], $this->csv->data, 'Single row is detected as header');
$this->csv->heading = false;
$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->output_encoding = 'UTF-8';
$this->csv->auto(__DIR__ . '/../example_files/Piwik_API_download.csv');
$aAction27 = array_column($this->csv->data, 'url (actionDetails 27)');
self::assertEquals(
[
'http://application/_Main/_GraphicMeanSTD_MDI/btnConfBandOptions',
'',
'',
],
$aAction27
);
$aCity = array_column($this->csv->data, 'city');
self::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->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() {
return [
[
'title' => 'Красивая кулинария',
'isbn' => '5454-5587-3210',
'publishedAt' => '21.05.2011',
],
[
'title' => 'The Wine Connoisseurs',
'isbn' => '2547-8548-2541',
'publishedAt' => '12.12.2011',
],
[
'title' => 'Weißwein',
'isbn' => '1313-4545-8875',
'publishedAt' => '23.02.2012',
],
];
}
/**
* @return array
*/
public function autoQuotesDataProvider(): array {
return array(
array('auto-double-enclosure.csv', '"'),
array('auto-single-enclosure.csv', "'"),
);
}
/**
* @depends testSepRowAutoDetection
*
* @dataProvider autoQuotesDataProvider
*
* @param string $file
* @param string $enclosure
*/
public function testAutoQuotes($file, $enclosure) {
$csv = new Csv();
$csv->auto(__DIR__ . '/fixtures/' . $file, true, null, null, $enclosure);
self::assertArrayHasKey('column1', $csv->data[0], 'Data parsed incorrectly with enclosure ' . $enclosure);
self::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

@@ -0,0 +1,77 @@
<?php
namespace ParseCsv\tests\methods;
use ParseCsv\Csv;
use PHPUnit\Framework\TestCase;
class SaveTest extends TestCase {
/** @var Csv */
private $csv;
private $temp_filename;
/**
* Setup our test environment objects; will be called before each test.
*/
protected function setUp(): void {
$this->csv = new Csv();
$this->csv->auto(__DIR__ . '/../example_files/single_column.csv');
// Remove last 2 lines to simplify comparison
unset($this->csv->data[2], $this->csv->data[3]);
$temp_dir = str_replace("\\", '/', sys_get_temp_dir());
if (substr($temp_dir, -1) != '/') {
// From the PHP.net documentation:
// This function does not always add trailing slash. This behaviour
// is inconsistent across systems.
$temp_dir .= '/';
}
$this->temp_filename = $temp_dir . 'parsecsv_test_file.csv';
}
public function testSaveWithDefaultSettings() {
$expected = "SMS\r0444\r5555\r";
$this->saveAndCompare($expected);
}
public function testSaveWithDosLineEnding() {
$this->csv->linefeed = "\r\n";
$expected = "SMS\r\n0444\r\n5555\r\n";
$this->saveAndCompare($expected);
}
public function testSaveWithUnixLineEnding() {
$this->csv->linefeed = "\n";
$expected = "SMS\n0444\n5555\n";
$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() {
$this->csv->linefeed = "\n";
$this->csv->heading = false;
$expected = "0444\n5555\n";
$this->saveAndCompare($expected);
}
public function testAllQuotes() {
$this->csv->enclose_all = true;
$expected = "\"SMS\"\r\"0444\"\r\"5555\"\r";
$this->saveAndCompare($expected);
}
private function saveAndCompare($expected) {
$this->csv->save($this->temp_filename);
$content = file_get_contents($this->temp_filename);
$this->assertEquals($expected, $content);
}
}

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 {
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

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

@@ -0,0 +1,3 @@
"column1","column2"
"value1","value2"
"value3","value4"
1 column1 column2
2 value1 value2
3 value3 value4

View File

@@ -0,0 +1,3 @@
'column1','column2'
'value1','value2'
'value3','value4'
1 'column1' 'column2'
2 'value1' 'value2'
3 'value3' 'value4'

View File

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

18
tests/phpunit.xml Normal file
View File

@@ -0,0 +1,18 @@
<?xml version="1.0" encoding="UTF-8"?>
<phpunit
bootstrap="Bootstrap.php"
colors="false"
convertNoticesToExceptions="true"
convertWarningsToExceptions="true"
stopOnError="true"
stopOnFailure="true"
stopOnIncomplete="true"
stopOnSkipped="false">
<testsuites>
<testsuite name="parseCSV Test Suite">
<directory suffix="est.php">properties/</directory>
<directory suffix="est.php">methods/</directory>
</testsuite>
</testsuites>
</phpunit>

View File

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

View File

@@ -0,0 +1,121 @@
<?php
namespace ParseCsv\tests\properties;
class ConditionsTest extends BaseClass {
public function testNotDanBrown() {
$this->csv->conditions = 'author does not contain dan brown';
$this->_compareWithExpected([
'The Killing Kind',
'The Third Secret',
'The Last Templar',
'The Traveller',
'Crisis Four',
'Prey',
'The Broker (Paperback)',
'Without Blood (Paperback)',
'State of Fear (Paperback)',
'The Rule of Four (Paperback)',
]);
}
public function testRatingEquals() {
$rating_of_3 = [
'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 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() {
$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',
'Prey',
'State of Fear (Paperback)',
'Digital Fortress : A Thriller (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() {
$this->csv->conditions = 'title contains code OR title contains SECRET';
$this->_compareWithExpected([
'The Third Secret',
'The Da Vinci Code (Hardcover)',
]);
}
}

View File

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

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

@@ -0,0 +1,171 @@
<?php
namespace ParseCsv\tests\properties;
use ParseCsv\Csv;
use ParseCsv\enums\SortEnum;
use PHPUnit\Framework\TestCase;
class PublicPropertiesTest extends TestCase {
/**
* CSV
* The parseCSV object
*
* @access protected
* @var Csv
*/
protected $csv = null;
/**
* Reflection Object
* The reflection class object
*
* @access protected
* @var \ReflectionClass
*/
protected $reflection = null;
/**
* Reflection Properties
* The reflected class properties
*
* @var \ReflectionProperty[]
* @access protected
*/
protected $properties = null;
/**
* Setup
* Setup our test environment objects
*
* @access public
*/
protected function setUp(): void {
//setup parse CSV
$this->csv = new Csv();
//setup the reflection class
$this->reflection = new \ReflectionClass($this->csv);
//setup the reflected class properties
$this->properties = $this->reflection->getProperties();
}
/**
* Tear down
* Tear down our test environment objects
*
* @access public
*/
protected function tearDown(): void {
$this->csv = null;
$this->reflection = null;
$this->properties = null;
}
/**
* test_propertiesCount
* Counts the number of properties to make sure we didn't add or
* subtract any without thinking
*
* @access public
*/
public function test_propertiesCount() {
$this->assertCount(29, $this->properties);
}
/**
* test_property_names
* We have an expected set of properties that should exists
* Make sure our expected number of properties matches the real
* count of properties and also check to make sure our expected
* properties exists within the class
*
* @access public
*/
public function test_property_names() {
//set our expected properties name(s)
$expected_names = array(
'heading',
'fields',
'sort_by',
'sort_reverse',
'sort_type',
'delimiter',
'enclosure',
'enclose_all',
'conditions',
'offset',
'limit',
'auto_depth',
'auto_non_chars',
'auto_preferred',
'convert_encoding',
'input_encoding',
'output_encoding',
'use_mb_convert_encoding',
'linefeed',
'output_delimiter',
'output_filename',
'keep_file_data',
'file',
'file_data',
'error',
'error_info',
'titles',
'data',
'data_types',
);
// Find our real properties
$real_properties = array_map(function (\ReflectionProperty $property) {
return $property->getName();
}, $this->properties);
// Lets make sure our expected matches the number of real properties
$this->assertEquals($expected_names, $real_properties);
}
/**
* test_count_public_properties
* We at this point only have public properties so
* lets verify all properties are public
*
* @access public
*/
public function test_count_public_properties() {
$counter = 0;
$propertiesCount = count($this->properties);
for ($a = 0; $a < $propertiesCount; $a++) {
if ($this->properties[$a]->isPublic() === true) {
$counter++;
}
}
$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);
}
}

View File

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