Add Ability to Suppress Mac Line Ending Check for CSV Reader (#2623)

With the deprecation of `auto_detect_line_endings` in Php8.1, there have been some tickets (issue #2609 and PR #2438). Although the deprecation message is suppressed, users with a homegrown error handler may still see it. I am not very concerned about that symptom, but I imagine that there will be more similar tickets in future. This PR adds a new property/method to Reader/CSV to allow the user to avoid the deprecated code, at the negligible cost of being unable to read a CSV with Mac line endings even on a Php version that could support it.
This commit is contained in:
oleibman 2022-03-01 02:01:37 -08:00 committed by GitHub
parent 8258919d72
commit f575d2b8b2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 60 additions and 4 deletions

View File

@ -544,6 +544,25 @@ $reader->setSheetIndex(5);
$reader->loadIntoExisting("05featuredemo.csv", $spreadsheet); $reader->loadIntoExisting("05featuredemo.csv", $spreadsheet);
``` ```
#### Line endings
Line endings for Unix (`\n`) and Windows (`\r\n`) are supported.
Mac line endings (`\r`) are supported as long as PHP itself
supports them, which it does through release 8.0.
Support for Mac line endings is deprecated for 8.1,
and is scheduled to remain deprecated for all later PHP8 releases;
PhpSpreadsheet will continue to support them for 8.*.
Support is scheduled to be dropped with release 9;
PhpSpreadsheet will then no longer handle CSV files
with Mac line endings correctly.
You can suppress testing for Mac line endings as follows:
```php
$reader = new \PhpOffice\PhpSpreadsheet\Reader\Csv();
$reader->setTestAutoDetect(false);
```
### \PhpOffice\PhpSpreadsheet\Writer\Csv ### \PhpOffice\PhpSpreadsheet\Writer\Csv
#### Writing a CSV file #### Writing a CSV file

View File

@ -84,6 +84,13 @@ class Csv extends BaseReader
*/ */
private static $constructorCallback; private static $constructorCallback;
/**
* Attempt autodetect line endings (deprecated after PHP8.1)?
*
* @var bool
*/
private $testAutodetect = true;
/** /**
* Create a new CSV Reader instance. * Create a new CSV Reader instance.
*/ */
@ -269,10 +276,15 @@ class Csv extends BaseReader
} }
} }
private static function setAutoDetect(?string $value): ?string public function setTestAutoDetect(bool $value): void
{
$this->testAutodetect = $value;
}
private function setAutoDetect(?string $value): ?string
{ {
$retVal = null; $retVal = null;
if ($value !== null) { if ($value !== null && $this->testAutodetect) {
$retVal2 = @ini_set('auto_detect_line_endings', $value); $retVal2 = @ini_set('auto_detect_line_endings', $value);
if (is_string($retVal2)) { if (is_string($retVal2)) {
$retVal = $retVal2; $retVal = $retVal2;
@ -288,7 +300,7 @@ class Csv extends BaseReader
public function loadIntoExisting(string $filename, Spreadsheet $spreadsheet): Spreadsheet public function loadIntoExisting(string $filename, Spreadsheet $spreadsheet): Spreadsheet
{ {
// Deprecated in Php8.1 // Deprecated in Php8.1
$iniset = self::setAutoDetect('1'); $iniset = $this->setAutoDetect('1');
// Open file // Open file
$this->openFileOrMemory($filename); $this->openFileOrMemory($filename);
@ -339,7 +351,7 @@ class Csv extends BaseReader
// Close file // Close file
fclose($fileHandle); fclose($fileHandle);
self::setAutoDetect($iniset); $this->setAutoDetect($iniset);
// Return // Return
return $spreadsheet; return $spreadsheet;

View File

@ -36,6 +36,31 @@ class CsvLineEndingTest extends TestCase
$spreadsheet->disconnectWorksheets(); $spreadsheet->disconnectWorksheets();
} }
/**
* @dataProvider providerEndings
*/
public function testEndingsNoDetect(string $ending): void
{
$this->tempFile = $filename = File::temporaryFilename();
$data = ['123', '456', '789'];
file_put_contents($filename, implode($ending, $data));
$reader = new Csv();
$reader->setTestAutoDetect(false);
$spreadsheet = $reader->load($filename);
$sheet = $spreadsheet->getActiveSheet();
if ($ending === "\r") {
// Can't handle Mac line endings without autoDetect
self::assertEquals(implode("\n", $data), $sheet->getCell('A1')->getValue());
self::assertNull($sheet->getCell('A2')->getValue());
self::assertNull($sheet->getCell('A3')->getValue());
} else {
self::assertEquals($data[0], $sheet->getCell('A1')->getValue());
self::assertEquals($data[1], $sheet->getCell('A2')->getValue());
self::assertEquals($data[2], $sheet->getCell('A3')->getValue());
}
$spreadsheet->disconnectWorksheets();
}
public function providerEndings(): array public function providerEndings(): array
{ {
return [ return [