|
10 | 10 | use PhpOffice\PhpSpreadsheet\Shared\StringHelper; |
11 | 11 | use PhpOffice\PhpSpreadsheet\Spreadsheet; |
12 | 12 | use PhpOffice\PhpSpreadsheet\Worksheet\Worksheet; |
| 13 | +use Throwable; |
13 | 14 |
|
14 | 15 | class Csv extends BaseReader |
15 | 16 | { |
@@ -74,7 +75,7 @@ class Csv extends BaseReader |
74 | 75 | * It is anticipated that it will conditionally be set |
75 | 76 | * to null-string for Php9 and above. |
76 | 77 | */ |
77 | | - private static string $defaultEscapeCharacter = '\\'; |
| 78 | + private static string $defaultEscapeCharacter = PHP_VERSION_ID < 90000 ? '\\' : ''; |
78 | 79 |
|
79 | 80 | /** |
80 | 81 | * Callback for setting defaults in construction. |
@@ -288,6 +289,12 @@ private function openFileOrMemory(string $filename): void |
288 | 289 | if (!$fhandle) { |
289 | 290 | throw new ReaderException($filename . ' is an Invalid Spreadsheet file.'); |
290 | 291 | } |
| 292 | + if ($this->inputEncoding === 'UTF-8') { |
| 293 | + $encoding = self::guessEncodingBom($filename); |
| 294 | + if ($encoding !== '') { |
| 295 | + $this->inputEncoding = $encoding; |
| 296 | + } |
| 297 | + } |
291 | 298 | if ($this->inputEncoding === self::GUESS_ENCODING) { |
292 | 299 | $this->inputEncoding = self::guessEncoding($filename, $this->fallbackEncoding); |
293 | 300 | } |
@@ -315,7 +322,7 @@ public function setTestAutoDetect(bool $value): self |
315 | 322 | private function setAutoDetect(?string $value): ?string |
316 | 323 | { |
317 | 324 | $retVal = null; |
318 | | - if ($value !== null && $this->testAutodetect) { |
| 325 | + if ($value !== null && $this->testAutodetect && PHP_VERSION_ID < 90000) { |
319 | 326 | $retVal2 = @ini_set('auto_detect_line_endings', $value); |
320 | 327 | if (is_string($retVal2)) { |
321 | 328 | $retVal = $retVal2; |
@@ -364,6 +371,21 @@ private function loadStringOrFile(string $filename, Spreadsheet $spreadsheet, bo |
364 | 371 | // Deprecated in Php8.1 |
365 | 372 | $iniset = $this->setAutoDetect('1'); |
366 | 373 |
|
| 374 | + try { |
| 375 | + $this->loadStringOrFile2($filename, $spreadsheet, $dataUri); |
| 376 | + $this->setAutoDetect($iniset); |
| 377 | + } catch (Throwable $e) { |
| 378 | + $this->setAutoDetect($iniset); |
| 379 | + |
| 380 | + throw $e; |
| 381 | + } |
| 382 | + |
| 383 | + return $spreadsheet; |
| 384 | + } |
| 385 | + |
| 386 | + private function loadStringOrFile2(string $filename, Spreadsheet $spreadsheet, bool $dataUri): void |
| 387 | + { |
| 388 | + |
367 | 389 | // Open file |
368 | 390 | if ($dataUri) { |
369 | 391 | $this->openDataUri($filename); |
@@ -435,11 +457,6 @@ private function loadStringOrFile(string $filename, Spreadsheet $spreadsheet, bo |
435 | 457 |
|
436 | 458 | // Close file |
437 | 459 | fclose($fileHandle); |
438 | | - |
439 | | - $this->setAutoDetect($iniset); |
440 | | - |
441 | | - // Return |
442 | | - return $spreadsheet; |
443 | 460 | } |
444 | 461 |
|
445 | 462 | /** |
@@ -547,6 +564,10 @@ public function getContiguous(): bool |
547 | 564 | */ |
548 | 565 | public function setEscapeCharacter(string $escapeCharacter): self |
549 | 566 | { |
| 567 | + if (PHP_VERSION_ID >= 90000 && $escapeCharacter !== '') { |
| 568 | + throw new ReaderException('Escape character must be null string for Php9+'); |
| 569 | + } |
| 570 | + |
550 | 571 | $this->escapeCharacter = $escapeCharacter; |
551 | 572 |
|
552 | 573 | return $this; |
@@ -624,17 +645,15 @@ private static function guessEncodingTestBom(string &$encoding, string $first4, |
624 | 645 | } |
625 | 646 | } |
626 | 647 |
|
627 | | - private static function guessEncodingBom(string $filename): string |
| 648 | + public static function guessEncodingBom(string $filename, ?string $convertString = null): string |
628 | 649 | { |
629 | 650 | $encoding = ''; |
630 | | - $first4 = file_get_contents($filename, false, null, 0, 4); |
631 | | - if ($first4 !== false) { |
632 | | - self::guessEncodingTestBom($encoding, $first4, self::UTF8_BOM, 'UTF-8'); |
633 | | - self::guessEncodingTestBom($encoding, $first4, self::UTF16BE_BOM, 'UTF-16BE'); |
634 | | - self::guessEncodingTestBom($encoding, $first4, self::UTF32BE_BOM, 'UTF-32BE'); |
635 | | - self::guessEncodingTestBom($encoding, $first4, self::UTF32LE_BOM, 'UTF-32LE'); |
636 | | - self::guessEncodingTestBom($encoding, $first4, self::UTF16LE_BOM, 'UTF-16LE'); |
637 | | - } |
| 651 | + $first4 = $convertString ?? (string) file_get_contents($filename, false, null, 0, 4); |
| 652 | + self::guessEncodingTestBom($encoding, $first4, self::UTF8_BOM, 'UTF-8'); |
| 653 | + self::guessEncodingTestBom($encoding, $first4, self::UTF16BE_BOM, 'UTF-16BE'); |
| 654 | + self::guessEncodingTestBom($encoding, $first4, self::UTF32BE_BOM, 'UTF-32BE'); |
| 655 | + self::guessEncodingTestBom($encoding, $first4, self::UTF32LE_BOM, 'UTF-32LE'); |
| 656 | + self::guessEncodingTestBom($encoding, $first4, self::UTF16LE_BOM, 'UTF-16LE'); |
638 | 657 |
|
639 | 658 | return $encoding; |
640 | 659 | } |
@@ -691,4 +710,39 @@ private static function getCsv( |
691 | 710 |
|
692 | 711 | return fgetcsv($stream, $length, $separator, $enclosure, $escape); |
693 | 712 | } |
| 713 | + |
| 714 | + public static function affectedByPhp9( |
| 715 | + string $filename, |
| 716 | + string $inputEncoding = 'UTF-8', |
| 717 | + ?string $delimiter = null, |
| 718 | + string $enclosure = '"', |
| 719 | + string $escapeCharacter = '\\' |
| 720 | + ): bool { |
| 721 | + if (PHP_VERSION_ID < 70400 || PHP_VERSION_ID >= 90000) { |
| 722 | + throw new ReaderException('Function valid only for Php7.4 or Php8'); // @codeCoverageIgnore |
| 723 | + } |
| 724 | + $reader1 = new self(); |
| 725 | + $reader1->setInputEncoding($inputEncoding) |
| 726 | + ->setTestAutoDetect(true) |
| 727 | + ->setEscapeCharacter($escapeCharacter) |
| 728 | + ->setDelimiter($delimiter) |
| 729 | + ->setEnclosure($enclosure); |
| 730 | + $spreadsheet1 = $reader1->load($filename); |
| 731 | + $sheet1 = $spreadsheet1->getActiveSheet(); |
| 732 | + $array1 = $sheet1->toArray(null, false, false); |
| 733 | + $spreadsheet1->disconnectWorksheets(); |
| 734 | + |
| 735 | + $reader2 = new self(); |
| 736 | + $reader2->setInputEncoding($inputEncoding) |
| 737 | + ->setTestAutoDetect(false) |
| 738 | + ->setEscapeCharacter('') |
| 739 | + ->setDelimiter($delimiter) |
| 740 | + ->setEnclosure($enclosure); |
| 741 | + $spreadsheet2 = $reader2->load($filename); |
| 742 | + $sheet2 = $spreadsheet2->getActiveSheet(); |
| 743 | + $array2 = $sheet2->toArray(null, false, false); |
| 744 | + $spreadsheet2->disconnectWorksheets(); |
| 745 | + |
| 746 | + return $array1 !== $array2; |
| 747 | + } |
694 | 748 | } |
0 commit comments