From 3090c1e73f1a659a48752508d8bbbf85952e74b7 Mon Sep 17 00:00:00 2001 From: drewblin Date: Tue, 12 May 2020 11:17:07 +0300 Subject: [PATCH] Support CSV files with data wrapping a lot of lines If there is "line" splited on lot of lines we can reach limit of recursion nesting. It's better to use while instead of recursion. Closes #1468 --- CHANGELOG.md | 1 + src/PhpSpreadsheet/Reader/Csv.php | 40 +++++++++++++++---------------- 2 files changed, 20 insertions(+), 21 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4101e2eb..e3ba3de8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,7 @@ and this project adheres to [Semantic Versioning](https://semver.org). ### Added - Support writing to streams in all writers [#1292](https://github.com/PHPOffice/PhpSpreadsheet/issues/1292) +- Support CSV files with data wrapping a lot of lines [#1468](https://github.com/PHPOffice/PhpSpreadsheet/pull/1468) ### Fixed diff --git a/src/PhpSpreadsheet/Reader/Csv.php b/src/PhpSpreadsheet/Reader/Csv.php index ed3b70f1..4d104595 100644 --- a/src/PhpSpreadsheet/Reader/Csv.php +++ b/src/PhpSpreadsheet/Reader/Csv.php @@ -236,33 +236,31 @@ class Csv extends BaseReader /** * Get the next full line from the file. * - * @param string $line - * - * @return bool|string + * @return false|string */ - private function getNextLine($line = '') + private function getNextLine() { - // Get the next line in the file - $newLine = fgets($this->fileHandle); + $line = ''; + $enclosure = '(?escapeCharacter, '/') . ')' . preg_quote($this->enclosure, '/'); - // Return false if there is no next line - if ($newLine === false) { - return false; - } + do { + // Get the next line in the file + $newLine = fgets($this->fileHandle); - // Add the new line to the line passed in - $line = $line . $newLine; + // Return false if there is no next line + if ($newLine === false) { + return false; + } - // Drop everything that is enclosed to avoid counting false positives in enclosures - $enclosure = '(?escapeCharacter, '/') . ')' - . preg_quote($this->enclosure, '/'); - $line = preg_replace('/(' . $enclosure . '.*' . $enclosure . ')/Us', '', $line); + // Add the new line to the line passed in + $line = $line . $newLine; - // See if we have any enclosures left in the line - // if we still have an enclosure then we need to read the next line as well - if (preg_match('/(' . $enclosure . ')/', $line) > 0) { - $line = $this->getNextLine($line); - } + // Drop everything that is enclosed to avoid counting false positives in enclosures + $line = preg_replace('/(' . $enclosure . '.*' . $enclosure . ')/Us', '', $line); + + // See if we have any enclosures left in the line + // if we still have an enclosure then we need to read the next line as well + } while (preg_match('/(' . $enclosure . ')/', $line) > 0); return $line; }