diff --git a/changelog.md b/changelog.md
index 2b82dc4..2db274f 100644
--- a/changelog.md
+++ b/changelog.md
@@ -2,9 +2,12 @@
## Changelog
-See GitHub for [the complete changelog](https://github.com/webaware/events-manager-import-export/blob/master/changelog.md).
+## Changelog 0.0.20, 2023-12-03
+* Fix export to export all events (not just future events)
+* changed: parsecsv upgraded to v1.3.2
+* added export CSV option
-### 0.0.12, soon...
+### 0.0.12
* changed: requires PHP 5.6+ (recommend PHP 7.2+)
* changed: Google Maps lookup is removed for now, will return soon as an Ajax-driven process post-import
diff --git a/events-manager-import-export.php b/events-manager-import-export.php
index 3b0730f..8f85092 100644
--- a/events-manager-import-export.php
+++ b/events-manager-import-export.php
@@ -3,7 +3,7 @@
Plugin Name: Events Manager Import Export
Plugin URI: https://github.com/webaware/events-manager-import-export
Description: import and export function for Events Manager
-Version: 0.0.12
+Version: 0.0.13
Author: WebAware
Author URI: https://shop.webaware.com.au/
Text Domain: events-manager-import-export
diff --git a/includes/class.Exporter.php b/includes/class.Exporter.php
index 6f2e352..d0c1391 100644
--- a/includes/class.Exporter.php
+++ b/includes/class.Exporter.php
@@ -22,7 +22,7 @@ public function render() {
* export the data in selected format
*/
public function export() {
- $EM_Events = EM_Events::get();
+ $EM_Events = EM_Events::get(array('scope' => 'all'));
$format = isset($_POST['exp_format']) ? wp_unslash($_POST['exp_format']) : '';
@@ -424,5 +424,70 @@ public function exportEventEspresso($EM_Events) {
exit;
}
-
+
+ /**
+ * export data in Event CSV format
+ * @param EM_Events $EM_Events
+ */
+ public function exportCSV($EM_Events) {
+ if (isset($_REQUEST['plaintext']) && $_REQUEST['plaintext'] === '1') {
+ header('Content-Type: text/plain; charset=utf-8');
+ }
+ else {
+ header('Content-Type: text/csv; charset=utf-8');
+ header('Content-Disposition: attachment; filename="events.csv"');
+ }
+
+ nocache_headers();
+
+ // character conversion arrays
+ $charFrom = ['\\', ';', ',', "\n", "\t"];
+ $charTo = ['\\\\', '\;', '\,', '\\n', '\\t'];
+ // send header row
+
+ echo "uid,summary,dtstart,dtend,dtformat,categories,post_content,location_name,location_address,location_town,location_state,location_postcode,location_country,location_latitude,location_longitude\r\n";
+
+ foreach ($EM_Events as $EM_Event) {
+ echo $EM_Event->event_id, ','; // event_identifier
+
+ echo text_to_csv($EM_Event->event_name), ','; // event_summary
+ $gmtOffset = HOUR_IN_SECONDS * get_option('gmt_offset');
+ echo text_to_csv(date('Y-m-d', $EM_Event->start - $gmtOffset)), ','; // start_date
+ echo text_to_csv(date('Y-m-d', $EM_Event->end - $gmtOffset)), ','; // end_date
+ echo text_to_csv("Y-m-d"), ','; // dtformat
+ // get categories as comma-separated list
+ $cats = $EM_Event->get_categories()->categories;
+ if (count($cats) > 0) {
+ $categories = [];
+ foreach ($cats as $cat) {
+ $categories[] = str_replace($charFrom, $charTo, $cat->output('#_CATEGORYNAME'));
+ }
+ echo text_to_csv(implode(',', $categories)), ',';
+ }
+ else {
+ echo ',';
+ }
+ echo text_to_csv(preg_replace('/\s+/', ' ', strip_tags($EM_Event->post_content))), ','; // event_desc
+
+ $location = $EM_Event->get_location();
+ if (is_object($location)) {
+ echo text_to_csv($location->location_name), ',';// address
+ echo text_to_csv($location->location_address), ','; // address
+ echo text_to_csv($location->location_town), ',';// city
+ echo text_to_csv($location->location_state), ','; // state
+ echo text_to_csv($location->location_postcode), ','; // zip
+ echo text_to_csv($location->get_country()), ',';// country
+ echo text_to_csv($location->latitude), ','; // country
+ echo text_to_csv($location->longitude), ','; // country
+ }
+ else {
+ echo ',,,,,,,';
+ }
+
+ echo "\r\n";
+
+ }
+
+ exit;
+ }
}
diff --git a/includes/class.Importer.php b/includes/class.Importer.php
index ccce16b..befd3c8 100644
--- a/includes/class.Importer.php
+++ b/includes/class.Importer.php
@@ -368,7 +368,7 @@ protected function importEventsCSV($filepath) {
while ($line = fgets($fp)) {
$line = "\n$line\n"; // fix up line so that it can be parsed correctly
- $cols = $csv->parse_string($line);
+ $cols = $csv->parseFile($line);
if ($cols) {
$rows++;
diff --git a/lib/parsecsv/.githup/workflows/phpunit.yml b/lib/parsecsv/.githup/workflows/phpunit.yml
new file mode 100644
index 0000000..06c9759
--- /dev/null
+++ b/lib/parsecsv/.githup/workflows/phpunit.yml
@@ -0,0 +1,43 @@
+---
+name: PHPUnit
+on:
+ push:
+
+jobs:
+ test:
+ runs-on: ubuntu-latest
+ strategy:
+ fail-fast: false
+ matrix:
+ php_version:
+ - "8.2"
+ - "8.1"
+ - "8.0"
+ - "7.4"
+ - "7.3"
+ - "7.2"
+ - "7.1"
+ steps:
+ - uses: actions/checkout@v3
+ - 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: Update PHPUnit
+ run: composer require phpunit/phpunit --dev -W
+ - name: Install dependencies
+ run: composer update
+ - name: Validate dependencies
+ run: composer validate
+ - name: Run tests
+ run: vendor/bin/phpunit --configuration tests/phpunit.xml
diff --git a/lib/parsecsv/ChangeLog.txt b/lib/parsecsv/ChangeLog.txt
deleted file mode 100644
index 76ae0ee..0000000
--- a/lib/parsecsv/ChangeLog.txt
+++ /dev/null
@@ -1,288 +0,0 @@
-ParseCSV dev-master
------------------------------------
-Date: unreleased
-
-- New function getTotalDataRowCount() - useful if
- $limit is set - see pull request #122.
-
-- Dropped support for PHP 5.4
-
-- Added support for Laravel-style collections via the
- new getCollection() function - see
- https://github.com/parsecsv/parsecsv-for-php/pull/134
-
------------------------------------
-
-
-ParseCSV 1.0.0
------------------------------------
-Date: 3-March-2018
-
-- Renamed class from parseCSV to Csv and added name-
- space "ParseCsv" for PSR compliance.
-
-- Added support for MS Excel's "sep=" to detect the
- delimiter (Issue #60).
-
-- Added data type detection - function getDatatypes()
- guesses the type of each column.
-
-- MIME: output() sends correct MIME type to browser
- if the separator is a tab char (Issue #79).
-
-- Added support for mb_convert_encoding() instead of
- iconv() - see issue #109.
-
-- A number of minor bug fixes - see GitHub issues.
-
-- Added many more unit tests.
-
------------------------------------
-
-
-parseCSV 0.4.3 beta
------------------------------------
-Date: 1-July-2008
-
-- 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 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
-
------------------------------------
diff --git a/lib/parsecsv/README.md b/lib/parsecsv/README.md
new file mode 100644
index 0000000..b2ebfb2
--- /dev/null
+++ b/lib/parsecsv/README.md
@@ -0,0 +1,247 @@
+# ParseCsv
+[](https://opencollective.com/parsecsv)
+
+
+ParseCsv is an easy-to-use PHP class that reads and writes CSV data properly. It
+fully conforms to the specifications outlined on the on the
+[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
+
+
+### Financial Contributors
+
+Become a financial contributor and help us sustain our community. [[Contribute](https://opencollective.com/parsecsv/contribute)]
+
+#### Individuals
+
+
+
+#### 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)]
+
+
+
+
+
+
+
+
+
+
+
+
+## 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.
+
+[](https://travis-ci.org/parsecsv/parsecsv-for-php)
diff --git a/lib/parsecsv/composer.json b/lib/parsecsv/composer.json
new file mode 100644
index 0000000..cbbaca0
--- /dev/null
+++ b/lib/parsecsv/composer.json
@@ -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"
+ }
+}
diff --git a/lib/parsecsv/src/Csv.php b/lib/parsecsv/src/Csv.php
index 0980a93..c7fa5be 100644
--- a/lib/parsecsv/src/Csv.php
+++ b/lib/parsecsv/src/Csv.php
@@ -49,7 +49,7 @@ class Csv {
*/
/**
- * Heading
+ * Header row:
* Use first line/entry as field names
*
* @var bool
@@ -57,7 +57,6 @@ class Csv {
public $heading = true;
/**
- * Fields
* Override field names
*
* @var array
@@ -65,7 +64,6 @@ class Csv {
public $fields = array();
/**
- * Sort By
* Sort CSV by this field
*
* @var string|null
@@ -73,15 +71,13 @@ class Csv {
public $sort_by = null;
/**
- * Sort Reverse
- * Reverse the sort function
+ * Reverse the sort direction
*
* @var bool
*/
public $sort_reverse = false;
/**
- * Sort Type
* Sort behavior passed to sort methods
*
* regular = SORT_REGULAR
@@ -93,31 +89,34 @@ class Csv {
public $sort_type = SortEnum::SORT_TYPE_REGULAR;
/**
- * Delimiter
- * Delimiter character
+ * Field delimiter character
*
* @var string
*/
public $delimiter = ',';
/**
- * Enclosure
* Enclosure character
*
+ * This is useful for cell values that are either multi-line
+ * or contain the field delimiter character.
+ *
* @var string
*/
public $enclosure = '"';
/**
- * Enclose All
- * Force enclosing all columns
+ * Force enclosing all columns.
+ *
+ * If false, only cells that are either multi-line or
+ * contain the field delimiter character are enclosed
+ * in the $enclosure char.
*
* @var bool
*/
public $enclose_all = false;
/**
- * Conditions
* Basic SQL-Like conditions for row matching
*
* @var string|null
@@ -125,7 +124,6 @@ class Csv {
public $conditions = null;
/**
- * Offset
* Number of rows to ignore from beginning of data. If present, the heading
* row is also counted (if $this->heading == true). In other words,
* $offset == 1 and $offset == 0 have the same meaning in that situation.
@@ -135,7 +133,6 @@ class Csv {
public $offset = null;
/**
- * Limit
* Limits the number of returned rows to the specified amount
*
* @var int|null
@@ -143,7 +140,6 @@ class Csv {
public $limit = null;
/**
- * Auto Depth
* Number of rows to analyze when attempting to auto-detect delimiter
*
* @var int
@@ -151,7 +147,6 @@ class Csv {
public $auto_depth = 15;
/**
- * Auto Non Chars
* Characters that should be ignored when attempting to auto-detect delimiter
*
* @var string
@@ -159,7 +154,6 @@ class Csv {
public $auto_non_chars = "a-zA-Z0-9\n\r";
/**
- * Auto Preferred
* preferred delimiter characters, only used when all filtering method
* returns multiple possible delimiters (happens very rarely)
*
@@ -168,15 +162,14 @@ class Csv {
public $auto_preferred = ",;\t.:|";
/**
- * Convert Encoding
- * Should we convert the csv encoding?
+ * Should we convert the CSV character encoding?
+ * Used for both parse and unparse operations.
*
* @var bool
*/
public $convert_encoding = false;
/**
- * Input Encoding
* Set the input encoding
*
* @var string
@@ -184,7 +177,6 @@ class Csv {
public $input_encoding = 'ISO-8859-1';
/**
- * Output Encoding
* Set the output encoding
*
* @var string
@@ -202,15 +194,14 @@ class Csv {
public $use_mb_convert_encoding = false;
/**
- * Linefeed
* Line feed characters used by unparse, save, and output methods
+ * Popular choices are "\r\n" and "\n".
*
* @var string
*/
public $linefeed = "\r";
/**
- * Output Delimiter
* Sets the output delimiter used by the output method
*
* @var string
@@ -218,7 +209,6 @@ class Csv {
public $output_delimiter = ',';
/**
- * Output filename
* Sets the output filename
*
* @var string
@@ -226,7 +216,6 @@ class Csv {
public $output_filename = 'data.csv';
/**
- * Keep File Data
* keep raw file data in memory after successful parsing (useful for debugging)
*
* @var bool
@@ -270,7 +259,6 @@ class Csv {
public $error = 0;
/**
- * Error Information
* Detailed error information
*
* @var array
@@ -278,54 +266,69 @@ class Csv {
public $error_info = array();
/**
- * Titles
- * CSV titles if they exists
+ * $titles has 4 distinct tasks:
+ * 1. After reading in CSV data, $titles will contain the column headers
+ * present in the data.
+ *
+ * 2. It defines which fields from the $data array to write e.g. when
+ * calling unparse(), and in which order. This lets you skip columns you
+ * don't want in your output, but are present in $data.
+ * See examples/save_to_file_without_header_row.php.
+ *
+ * 3. It lets you rename columns. See StreamTest::testWriteStream for an
+ * example.
+ *
+ * 4. When writing data and $header is true, then $titles is also used for
+ * the first row.
*
* @var array
*/
public $titles = array();
/**
- * Data
- * Two-dimensional array of CSV data
+ * Two-dimensional array of CSV data.
+ * The first dimension are the line numbers. Each line is represented as an array with field names as keys.
*
- * @var array
+ * @var array
*/
public $data = array();
use DatatypeTrait;
/**
- * Constructor
* Class constructor
*
- * @param string|null $input The CSV string or a direct file path
- * @param integer|null $offset Number of rows to ignore from the
- * beginning of the data
- * @param integer|null $limit Limits the number of returned rows
- * to specified amount
- * @param string|null $conditions Basic SQL-like conditions for row
- * matching
- * @param null|true $keep_file_data Keep raw file data in memory after
- * successful parsing
- * (useful for debugging)
+ * @param string|null $data The CSV string or a direct file path.
+ *
+ * WARNING: Supplying file paths here is
+ * deprecated. Use parseFile() instead.
+ *
+ * @param int|null $offset Number of rows to ignore from the
+ * beginning of the data
+ * @param int|null $limit Limits the number of returned rows
+ * to specified amount
+ * @param string|null $conditions Basic SQL-like conditions for row
+ * matching
+ * @param null|true $keep_file_data Keep raw file data in memory after
+ * successful parsing
+ * (useful for debugging)
*/
- public function __construct($input = null, $offset = null, $limit = null, $conditions = null, $keep_file_data = null) {
+ public function __construct($data = null, $offset = null, $limit = null, $conditions = null, $keep_file_data = null) {
$this->init($offset, $limit, $conditions, $keep_file_data);
- if (!empty($input)) {
- $this->parse($input);
+ if (!empty($data)) {
+ $this->parse($data);
}
}
/**
- * @param integer|null $offset Number of rows to ignore from the
+ * @param int|null $offset Number of rows to ignore from the
* beginning of the data
- * @param integer|null $limit Limits the number of returned rows
+ * @param int|null $limit Limits the number of returned rows
* to specified amount
- * @param string|null $conditions Basic SQL-like conditions for row
+ * @param string|null $conditions Basic SQL-like conditions for row
* matching
- * @param null|true $keep_file_data Keep raw file data in memory after
+ * @param null|true $keep_file_data Keep raw file data in memory after
* successful parsing
* (useful for debugging)
*/
@@ -352,36 +355,45 @@ public function init($offset = null, $limit = null, $conditions = null, $keep_fi
// ==============================================
/**
- * Parse
* Parse a CSV file or string
*
- * @param string|null $input The CSV string or a direct file path
- * @param integer $offset Number of rows to ignore from the
+ * @param string|null $dataString The CSV string or a direct file path
+ * WARNING: Supplying file paths here is
+ * deprecated and will trigger an
+ * E_USER_DEPRECATED error.
+ * @param int|null $offset Number of rows to ignore from the
* beginning of the data
- * @param integer $limit Limits the number of returned rows to
+ * @param int|null $limit Limits the number of returned rows to
* specified amount
- * @param string $conditions Basic SQL-like conditions for row
+ * @param string|null $conditions Basic SQL-like conditions for row
* matching
*
* @return bool True on success
*/
- public function parse($input = null, $offset = null, $limit = null, $conditions = null) {
- if (is_null($input)) {
- $input = $this->file;
+ public function parse($dataString = null, $offset = null, $limit = null, $conditions = null) {
+ if (is_null($dataString)) {
+ $this->data = $this->parseFile();
+ return $this->data !== false;
}
- if (empty($input)) {
+ if (empty($dataString)) {
return false;
}
$this->init($offset, $limit, $conditions);
- if (strlen($input) <= PHP_MAXPATHLEN && is_readable($input)) {
- $this->file = $input;
- $this->data = $this->_parse_file();
+ if (strlen($dataString) <= PHP_MAXPATHLEN && is_readable($dataString)) {
+ $this->file = $dataString;
+ $this->data = $this->parseFile();
+ trigger_error(
+ 'Supplying file paths to parse() will no longer ' .
+ 'be supported in a future version of ParseCsv. ' .
+ 'Use ->parseFile() instead.',
+ E_USER_DEPRECATED
+ );
} else {
$this->file = null;
- $this->file_data = &$input;
+ $this->file_data = &$dataString;
$this->data = $this->_parse_string();
}
@@ -389,17 +401,17 @@ public function parse($input = null, $offset = null, $limit = null, $conditions
}
/**
- * Save
- * Save changes, or write a new file and/or data
+ * Save changes, or write a new file and/or data.
*
- * @param string $file File location to save to
- * @param array $data 2D array of data
- * @param bool $append Append current data to end of target CSV, if file
+ * @param string $file File location to save to
+ * @param array $data 2D array of data
+ * @param bool $append Append current data to end of target CSV, if file
* exists
- * @param array $fields Field names. Sets the header. If it is not set
+ * @param array $fields Field names. Sets the header. If it is not set
* $this->titles would be used instead.
*
* @return bool
+ * True on success
*/
public function save($file = '', $data = array(), $append = FileProcessingModeEnum::MODE_FILE_OVERWRITE, $fields = array()) {
if (empty($file)) {
@@ -407,25 +419,26 @@ public function save($file = '', $data = array(), $append = FileProcessingModeEn
}
$mode = FileProcessingModeEnum::getAppendMode($append);
- $is_php = preg_match('/\.php$/i', $file) ? true : false;
+ $is_php = (bool) preg_match('/\.php$/i', $file);
return $this->_wfile($file, $this->unparse($data, $fields, $append, $is_php), $mode);
}
/**
- * Output
- * Generate a CSV based string for output.
+ * Generate a CSV-based string for output.
*
- * @param string|null $filename If a filename is specified here or in the
+ * Useful for exports in web applications.
+ *
+ * @param string|null $filename If a filename is specified here or in the
* object, headers and data will be output
* directly to browser as a downloadable
* file. This file doesn't have to exist on
* the server; the parameter only affects
* how the download is called to the
* browser.
- * @param array[] $data 2D array with data
- * @param array $fields Field names
- * @param string|null $delimiter character used to separate data
+ * @param array[] $data 2D array with data
+ * @param array $fields Field names
+ * @param string|null $delimiter character used to separate data
*
* @return string The resulting CSV string
*/
@@ -458,11 +471,17 @@ public function output($filename = null, $data = array(), $fields = array(), $de
}
/**
- * Encoding
* Convert character encoding
*
- * @param string $input Input character encoding, uses default if left blank
- * @param string $output Output character encoding, uses default if left blank
+ * Specify the encoding to use for the next parsing or unparsing.
+ * Calling this function will not change the data held in the object immediately.
+ *
+ * @param string|null $input Input character encoding
+ * If the value null is passed, the existing input encoding remains set (default: ISO-8859-1).
+ * @param string|null $output Output character encoding, uses default if left blank
+ * If the value null is passed, the existing input encoding remains set (default: ISO-8859-1).
+ *
+ * @return void
*/
public function encoding($input = null, $output = null) {
$this->convert_encoding = true;
@@ -476,17 +495,19 @@ public function encoding($input = null, $output = null) {
}
/**
- * Auto
- * Auto-Detect Delimiter: Find delimiter by analyzing a specific number of
+ * Auto-detect delimiter: Find delimiter by analyzing a specific number of
* rows to determine most probable delimiter character
*
- * @param string|null $file Local CSV file
- * @param bool $parse True/false parse file directly
- * @param int $search_depth Number of rows to analyze
- * @param string $preferred Preferred delimiter characters
- * @param string|null $enclosure Enclosure character, default is double quote (").
+ * @param string|null $file Local CSV file
+ * Supplying CSV data (file content) here is deprecated.
+ * For CSV data, please use autoDetectionForDataString().
+ * Support for CSV data will be removed in v2.0.0.
+ * @param bool $parse True/false parse file directly
+ * @param int|null $search_depth Number of rows to analyze
+ * @param string|null $preferred Preferred delimiter characters
+ * @param string|null $enclosure Enclosure character, default is double quote (").
*
- * @return string The detected field delimiter
+ * @return string|false The detected field delimiter
*/
public function auto($file = null, $parse = true, $search_depth = null, $preferred = null, $enclosure = null) {
if (is_null($file)) {
@@ -517,6 +538,13 @@ public function auto($file = null, $parse = true, $search_depth = null, $preferr
$data = &$this->file_data;
}
+ $this->autoDetectionForDataString($data, $parse, $search_depth, $preferred, $enclosure);
+
+ return $this->delimiter;
+ }
+
+ public function autoDetectionForDataString($data, $parse = true, $search_depth = null, $preferred = null, $enclosure = null) {
+ $this->file_data = &$data;
if (!$this->_detect_and_remove_sep_row_from_data($data)) {
$this->_guess_delimiter($search_depth, $preferred, $enclosure, $data);
}
@@ -559,12 +587,10 @@ public function getTotalDataRowCount() {
$headingRow = $this->heading ? 1 : 0;
- $count = substr_count($data, "\r")
+ return substr_count($data, "\r")
+ substr_count($data, "\n")
- substr_count($data, "\r\n")
- $headingRow;
-
- return $count;
}
// ==============================================
@@ -572,23 +598,33 @@ public function getTotalDataRowCount() {
// ==============================================
/**
- * Parse File
* Read file to string and call _parse_string()
*
- * @param string|null $file Local CSV file
+ * @param string|null $file Path to a CSV file.
+ * If configured in files such as php.ini,
+ * the path may also contain a protocol:
+ * https://example.org/some/file.csv
*
- * @return array|bool
+ * @return array|false
*/
- protected function _parse_file($file = null) {
+ public function parseFile($file = null) {
if (is_null($file)) {
$file = $this->file;
}
- if (empty($this->file_data)) {
- $this->load_data($file);
+ /**
+ * @see self::keep_file_data
+ * Usually, _parse_string will clean this
+ * Instead of leaving stale data for the next parseFile call behind.
+ */
+ if (empty($this->file_data) && !$this->loadFile($file)) {
+ return false;
}
- return !empty($this->file_data) ? $this->_parse_string() : false;
+ if (empty($this->file_data)) {
+ return false;
+ }
+ return $this->data = $this->_parse_string();
}
/**
@@ -600,9 +636,10 @@ protected function _parse_file($file = null) {
*
* To detect field separators, please use auto() instead.
*
- * @param string $data CSV data
+ * @param string|null $data CSV data
*
- * @return array|false - 2D array with CSV data, or false on failure
+ * @return array|false
+ * 2D array with CSV data, or false on failure
*/
protected function _parse_string($data = null) {
if (empty($data)) {
@@ -627,7 +664,7 @@ protected function _parse_string($data = null) {
// force the parser to process end of data as a character (false) when
// data does not end with a line feed or carriage return character.
- $lch = $data{$strlen - 1};
+ $lch = $data[$strlen - 1];
if ($lch != "\n" && $lch != "\r") {
$data .= "\n";
$strlen++;
@@ -635,8 +672,8 @@ protected function _parse_string($data = null) {
// walk through each character
for ($i = 0; $i < $strlen; $i++) {
- $ch = isset($data{$i}) ? $data{$i} : false;
- $nch = isset($data{$i + 1}) ? $data{$i + 1} : false;
+ $ch = isset($data[$i]) ? $data[$i] : false;
+ $nch = isset($data[$i + 1]) ? $data[$i + 1] : false;
// open/close quotes, and inline quotes
if ($ch == $this->enclosure) {
@@ -666,10 +703,10 @@ protected function _parse_string($data = null) {
$i++;
} elseif ($nch != $this->delimiter && $nch != "\r" && $nch != "\n") {
$x = $i + 1;
- while (isset($data{$x}) && ltrim($data{$x}, $white_spaces) == '') {
+ while (isset($data[$x]) && ltrim($data[$x], $white_spaces) == '') {
$x++;
}
- if ($data{$x} == $this->delimiter) {
+ if ($data[$x] == $this->delimiter) {
$enclosed = false;
$i = $x;
} else {
@@ -699,9 +736,8 @@ protected function _parse_string($data = null) {
} else {
$enclosed = false;
}
-
// end of field/row/csv
- } elseif (($ch === $this->delimiter || $ch == "\n" || $ch == "\r" || $ch === false) && !$enclosed) {
+ } elseif ((in_array($ch, [$this->delimiter, "\n", "\r", false], true)) && !$enclosed) {
$key = !empty($head[$col]) ? $head[$col] : $col;
$row[$key] = $was_enclosed ? $current : trim($current);
$current = '';
@@ -709,7 +745,7 @@ protected function _parse_string($data = null) {
$col++;
// end of row
- if ($ch == "\n" || $ch == "\r" || $ch === false) {
+ if (in_array($ch, ["\n", "\r", false], true)) {
if ($this->_validate_offset($row_count) && $this->_validate_row_conditions($row, $this->conditions)) {
if ($this->heading && empty($head)) {
$head = $row;
@@ -819,9 +855,8 @@ public function unparse($data = array(), $fields = array(), $append = FileProces
$string .= implode($delimiter, $entry) . $this->linefeed;
$entry = array();
}
-
// create data
- foreach ($data as $key => $row) {
+ foreach ($data as $row) {
foreach (array_keys($fieldOrder) as $index) {
$cell_value = $row[$index];
$entry[] = $this->_enclose_value($cell_value, $delimiter);
@@ -832,13 +867,28 @@ public function unparse($data = array(), $fields = array(), $append = FileProces
}
if ($this->convert_encoding) {
- $string = iconv($this->input_encoding, $this->output_encoding, $string);
+ /** @noinspection PhpComposerExtensionStubsInspection
+ *
+ * If you receive an error at the following 3 lines, you must enable
+ * the following PHP extension:
+ *
+ * - if $use_mb_convert_encoding is true: mbstring
+ * - if $use_mb_convert_encoding is false: iconv
+ */
+ $string = $this->use_mb_convert_encoding ?
+ mb_convert_encoding($string, $this->output_encoding, $this->input_encoding) :
+ iconv($this->input_encoding, $this->output_encoding, $string);
}
return $string;
}
- private function _validate_fields_for_unparse($fields) {
+ /**
+ * @param array $fields
+ *
+ * @return array|false
+ */
+ private function _validate_fields_for_unparse(array $fields) {
if (empty($fields)) {
$fields = $this->titles;
}
@@ -886,32 +936,71 @@ private function _validate_fields_for_unparse($fields) {
* This function load_data() is able to handle BOMs and encodings. The data
* is stored within the $this->file_data class field.
*
- * @param string|null $input local CSV file or CSV data as a string
+ * @param string|null $input CSV file path or CSV data as a string
+ *
+ * Supplying CSV data (file content) here is deprecated.
+ * For CSV data, please use loadDataString().
+ * Support for CSV data will be removed in v2.0.0.
*
* @return bool True on success
+ * @deprecated Use loadDataString() or loadFile() instead.
*/
public function load_data($input = null) {
- $data = null;
- $file = null;
+ return $this->loadFile($input);
+ }
- if (is_null($input)) {
- $file = $this->file;
- } elseif (\strlen($input) <= PHP_MAXPATHLEN && file_exists($input)) {
- $file = $input;
- } else {
- // It is CSV data as a string.
- $data = $input;
- }
+ /**
+ * Load a file, but don't parse it.
+ *
+ * Only use this function if auto() and parseFile() don't handle your data well.
+ *
+ * This function is able to handle BOMs and encodings. The data
+ * is stored within the $this->file_data class field.
+ *
+ * @param string|null $file CSV file path
+ *
+ * @return bool True on success
+ */
+ public function loadFile($file = null) {
+ $data = null;
- if (!empty($data) || $data = $this->_rfile($file)) {
+ if (is_null($file)) {
+ $data = $this->_rfile($this->file);
+ } elseif (\strlen($file) <= PHP_MAXPATHLEN && file_exists($file)) {
+ $data = $this->_rfile($file);
if ($this->file != $file) {
$this->file = $file;
}
+ } else {
+ // It is CSV data as a string.
- if (preg_match('/\.php$/i', $file) && preg_match('/<\?.*?\?>(.*)/ms', $data, $strip)) {
- $data = ltrim($strip[1]);
- }
+ // WARNING:
+ // Supplying CSV data to load_data() will no longer
+ // be supported in a future version of ParseCsv.
+ // This function will return false for invalid paths from v2.0.0 onwards.
+
+ // Use ->loadDataString() instead.
+
+ $data = $file;
+ }
+
+ return $this->loadDataString($data);
+ }
+ /**
+ * Load a data string, but don't parse it.
+ *
+ * Only use this function if autoDetectionForDataString() and parse() don't handle your data well.
+ *
+ * This function is able to handle BOMs and encodings. The data
+ * is stored within the $this->file_data class field.
+ *
+ * @param string|null $file_path CSV file path
+ *
+ * @return bool True on success
+ */
+ public function loadDataString($data) {
+ if (!empty($data)) {
if (strpos($data, "\xef\xbb\xbf") === 0) {
// strip off BOM (UTF-8)
$data = substr($data, 3);
@@ -927,6 +1016,14 @@ public function load_data($input = null) {
}
if ($this->convert_encoding && $this->input_encoding !== $this->output_encoding) {
+ /** @noinspection PhpComposerExtensionStubsInspection
+ *
+ * If you receive an error at the following 3 lines, you must enable
+ * the following PHP extension:
+ *
+ * - if $use_mb_convert_encoding is true: mbstring
+ * - if $use_mb_convert_encoding is false: iconv
+ */
$data = $this->use_mb_convert_encoding ?
mb_convert_encoding($data, $this->output_encoding, $this->input_encoding) :
iconv($this->input_encoding, $this->output_encoding, $data);
@@ -953,7 +1050,7 @@ public function load_data($input = null) {
* @param array $row array with values from a row
* @param string|null $conditions specified conditions that the row must match
*
- * @return true of false
+ * @return bool
*/
protected function _validate_row_conditions($row = array(), $conditions = null) {
if (!empty($row)) {
@@ -1011,6 +1108,8 @@ protected function _validate_row_condition($row, $condition) {
'is greater than or equals',
'contains',
'does not contain',
+ 'is number',
+ 'is not number',
);
$operators_regex = array();
@@ -1023,10 +1122,22 @@ protected function _validate_row_condition($row, $condition) {
if (preg_match('/^(.+) (' . $operators_regex . ') (.+)$/i', trim($condition), $capture)) {
$field = $capture[1];
- $op = $capture[2];
+ $op = strtolower($capture[2]);
$value = $capture[3];
+ if ($op == 'equals' && preg_match('/^(.+) is (less|greater) than or$/i', $field, $m)) {
+ $field = $m[1];
+ $op = strtolower($m[2]) == 'less' ? '<=' : '>=';
+ }
+ if ($op == 'is' && preg_match('/^(less|greater) than (.+)$/i', $value, $m)) {
+ $value = $m[2];
+ $op = strtolower($m[1]) == 'less' ? '<' : '>';
+ }
+ if ($op == 'is' && preg_match('/^not (.+)$/i', $value, $m)) {
+ $value = $m[1];
+ $op = '!=';
+ }
- if (preg_match('/^([\'\"]{1})(.*)([\'\"]{1})$/', $value, $capture) && $capture[1] == $capture[3]) {
+ if (preg_match('/^([\'"])(.*)([\'"])$/', $value, $capture) && $capture[1] == $capture[3]) {
$value = strtr($capture[2], array(
"\\n" => "\n",
"\\r" => "\r",
@@ -1037,7 +1148,12 @@ protected function _validate_row_condition($row, $condition) {
}
if (array_key_exists($field, $row)) {
- if (($op == '=' || $op == 'equals' || $op == 'is') && $row[$field] == $value) {
+ $op_equals = in_array($op, ['=', 'equals', 'is'], true);
+ if ($op_equals && $row[$field] == $value) {
+ return '1';
+ } elseif ($op_equals && $value == 'number' && is_numeric($row[$field])) {
+ return '1';
+ } elseif (($op == '!=' || $op == 'is not') && $value == 'number' && !is_numeric($row[$field])) {
return '1';
} elseif (($op == '!=' || $op == 'is not') && $row[$field] != $value) {
return '1';
@@ -1067,7 +1183,7 @@ protected function _validate_row_condition($row, $condition) {
*
* @param int $current_row the current row number being processed
*
- * @return true of false
+ * @return bool
*/
protected function _validate_offset($current_row) {
return
@@ -1093,7 +1209,7 @@ protected function _enclose_value($value, $delimiter) {
: '';
$enclosure_quoted = preg_quote($this->enclosure, '/');
$pattern = "/" . $delimiter_quoted . $enclosure_quoted . "|\n|\r/i";
- if ($this->enclose_all || preg_match($pattern, $value) || ($value{0} == ' ' || substr($value, -1) == ' ')) {
+ if ($this->enclose_all || preg_match($pattern, $value) || strpos($value, ' ') === 0 || substr($value, -1) == ' ') {
$value = str_replace($this->enclosure, $this->enclosure . $this->enclosure, $value);
$value = $this->enclosure . $value . $this->enclosure;
}
@@ -1105,7 +1221,7 @@ protected function _enclose_value($value, $delimiter) {
/**
* Check file data
*
- * @param string|null $file local filename
+ * @param string|null $file local filename
*
* @return bool
*/
@@ -1115,20 +1231,20 @@ protected function _check_data($file = null) {
$file = $this->file;
}
- return $this->load_data($file);
+ return $this->loadFile($file);
}
return true;
}
/**
- * Check if passed info might be delimiter
+ * Check if passed info might be delimiter.
* Only used by find_delimiter
*
- * @param string $char Potential field separating character
- * @param array $array Frequency
- * @param int $depth Number of analyzed rows
- * @param string $preferred Preferred delimiter characters
+ * @param string $char Potential field separating character
+ * @param array $array Frequency
+ * @param int $depth Number of analyzed rows
+ * @param string $preferred Preferred delimiter characters
*
* @return string|false special string used for delimiter selection, or false
*/
@@ -1137,7 +1253,7 @@ protected function _check_count($char, $array, $depth, $preferred) {
$first = null;
$equal = null;
$almost = false;
- foreach ($array as $key => $value) {
+ foreach ($array as $value) {
if ($first == null) {
$first = $value;
} elseif ($value == $first && $equal !== false) {
@@ -1150,7 +1266,7 @@ protected function _check_count($char, $array, $depth, $preferred) {
}
}
- if ($equal) {
+ if ($equal || $depth === 1) {
$match = $almost ? 2 : 1;
$pref = strpos($preferred, $char);
$pref = ($pref !== false) ? str_pad($pref, 3, '0', STR_PAD_LEFT) : '999';
@@ -1166,16 +1282,23 @@ protected function _check_count($char, $array, $depth, $preferred) {
/**
* Read local file.
*
- * @param string $file local filename
+ * @param string $filePath local filename
*
* @return string|false Data from file, or false on failure
*/
- protected function _rfile($file) {
- if (is_readable($file)) {
- $data = file_get_contents($file);
+ protected function _rfile($filePath) {
+ if (is_readable($filePath)) {
+ $data = file_get_contents($filePath);
if ($data === false) {
return false;
}
+
+ if (preg_match('/\.php$/i', $filePath) && preg_match('/<\?.*?\?>(.*)/ms', $data, $strip)) {
+ // Return section behind closing tags.
+ // This parsing is deprecated and will be removed in v2.0.0.
+ $data = ltrim($strip[1]);
+ }
+
return rtrim($data, "\r\n");
}
@@ -1185,12 +1308,14 @@ protected function _rfile($file) {
/**
* Write to local file
*
- * @param string $file local filename
- * @param string $content data to write to file
- * @param string $mode fopen() mode
- * @param int $lock flock() mode
+ * @param string $file local filename
+ * @param string $content data to write to file
+ * @param string $mode fopen() mode
+ * @param int $lock flock() mode
+ *
+ * @return bool
+ * True on success
*
- * @return true or false
*/
protected function _wfile($file, $content = '', $mode = 'wb', $lock = LOCK_EX) {
if ($fp = fopen($file, $mode)) {
@@ -1252,7 +1377,6 @@ protected function _detect_and_remove_sep_row_from_data(&$data_string) {
}
// remove delimiter and its line-end (the data param is by-ref!)
- /** @noinspection CallableParameterUseCaseInTypeContextInspection */
$data_string = substr($data_string, $pos);
return true;
}
@@ -1263,7 +1387,7 @@ protected function _detect_and_remove_sep_row_from_data(&$data_string) {
* @param string $enclosure Enclosure character, default is double quote
* @param string $data The file content
*/
- protected function _guess_delimiter($search_depth, $preferred, $enclosure, &$data) {
+ protected function _guess_delimiter($search_depth, $preferred, $enclosure, $data) {
$chars = [];
$strlen = strlen($data);
$enclosed = false;
@@ -1278,15 +1402,15 @@ protected function _guess_delimiter($search_depth, $preferred, $enclosure, &$dat
// walk specific depth finding possible 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;
+ $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
$is_newline = ($ch == "\n" && $pch != "\r") || $ch == "\r";
if ($ch == $enclosure) {
if (!$enclosed || $nch != $enclosure) {
- $enclosed = $enclosed ? false : true;
+ $enclosed = !$enclosed;
} elseif ($enclosed) {
$i++;
}
diff --git a/lib/parsecsv/src/enums/SortEnum.php b/lib/parsecsv/src/enums/SortEnum.php
index fd1cb1e..5d50e79 100644
--- a/lib/parsecsv/src/enums/SortEnum.php
+++ b/lib/parsecsv/src/enums/SortEnum.php
@@ -26,5 +26,4 @@ public static function getSorting($type) {
return self::$sorting[self::__DEFAULT];
}
-
}
diff --git a/lib/parsecsv/src/extensions/DatatypeTrait.php b/lib/parsecsv/src/extensions/DatatypeTrait.php
index 5b22935..c0a4c10 100644
--- a/lib/parsecsv/src/extensions/DatatypeTrait.php
+++ b/lib/parsecsv/src/extensions/DatatypeTrait.php
@@ -19,7 +19,7 @@ trait DatatypeTrait {
* Check data type for one column.
* Check for most commonly data type for one column.
*
- * @param array $datatypes
+ * @param array $datatypes
*
* @return string|false
*/
@@ -36,7 +36,6 @@ private function getMostFrequentDatatypeForColumn($datatypes) {
reset($typesFreq);
return key($typesFreq);
-
}
/**
diff --git a/views/export.php b/views/export.php
index bc2a4fa..2a533b8 100644
--- a/views/export.php
+++ b/views/export.php
@@ -30,6 +30,10 @@
+