|
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