Skip to content

Commit 6c9b2a8

Browse files
authored
Merge pull request #4162 from oleibman/csv84
Php 8.4 Will Deprecate fgetcsv Parameter
2 parents fd96566 + 2a8fb60 commit 6c9b2a8

File tree

1 file changed

+47
-7
lines changed

1 file changed

+47
-7
lines changed

src/PhpSpreadsheet/Reader/Csv.php

Lines changed: 47 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -62,8 +62,19 @@ class Csv extends BaseReader
6262

6363
/**
6464
* The character that can escape the enclosure.
65+
* This will probably become unsupported in Php 9.
66+
* Not yet ready to mark deprecated in order to give users
67+
* a migration path.
6568
*/
66-
private string $escapeCharacter = '\\';
69+
private ?string $escapeCharacter = null;
70+
71+
/**
72+
* The character that will be supplied to fgetcsv
73+
* when escapeCharacter is null.
74+
* It is anticipated that it will conditionally be set
75+
* to null-string for Php9 and above.
76+
*/
77+
private static string $defaultEscapeCharacter = '\\';
6778

6879
/**
6980
* Callback for setting defaults in construction.
@@ -185,7 +196,7 @@ protected function inferSeparator(): void
185196
return;
186197
}
187198

188-
$inferenceEngine = new Delimiter($this->fileHandle, $this->escapeCharacter, $this->enclosure);
199+
$inferenceEngine = new Delimiter($this->fileHandle, $this->escapeCharacter ?? self::$defaultEscapeCharacter, $this->enclosure);
189200

190201
// If number of lines is 0, nothing to infer : fall back to the default
191202
if ($inferenceEngine->linesCounted() === 0) {
@@ -228,11 +239,11 @@ public function listWorksheetInfo(string $filename): array
228239
$delimiter = $this->delimiter ?? '';
229240

230241
// Loop through each line of the file in turn
231-
$rowData = fgetcsv($fileHandle, 0, $delimiter, $this->enclosure, $this->escapeCharacter);
242+
$rowData = self::getCsv($fileHandle, 0, $delimiter, $this->enclosure, $this->escapeCharacter);
232243
while (is_array($rowData)) {
233244
++$worksheetInfo[0]['totalRows'];
234245
$worksheetInfo[0]['lastColumnIndex'] = max($worksheetInfo[0]['lastColumnIndex'], count($rowData) - 1);
235-
$rowData = fgetcsv($fileHandle, 0, $delimiter, $this->enclosure, $this->escapeCharacter);
246+
$rowData = self::getCsv($fileHandle, 0, $delimiter, $this->enclosure, $this->escapeCharacter);
236247
}
237248

238249
$worksheetInfo[0]['lastColumnLetter'] = Coordinate::stringFromColumnIndex($worksheetInfo[0]['lastColumnIndex'] + 1);
@@ -379,7 +390,7 @@ private function loadStringOrFile(string $filename, Spreadsheet $spreadsheet, bo
379390

380391
// Loop through each line of the file in turn
381392
$delimiter = $this->delimiter ?? '';
382-
$rowData = fgetcsv($fileHandle, 0, $delimiter, $this->enclosure, $this->escapeCharacter);
393+
$rowData = self::getCsv($fileHandle, 0, $delimiter, $this->enclosure, $this->escapeCharacter);
383394
$valueBinder = Cell::getValueBinder();
384395
$preserveBooleanString = method_exists($valueBinder, 'getBooleanConversion') && $valueBinder->getBooleanConversion();
385396
$this->getTrue = Calculation::getTRUE();
@@ -416,7 +427,7 @@ private function loadStringOrFile(string $filename, Spreadsheet $spreadsheet, bo
416427
}
417428
++$columnLetter;
418429
}
419-
$rowData = fgetcsv($fileHandle, 0, $delimiter, $this->enclosure, $this->escapeCharacter);
430+
$rowData = self::getCsv($fileHandle, 0, $delimiter, $this->enclosure, $this->escapeCharacter);
420431
++$currentRow;
421432
}
422433

@@ -527,6 +538,11 @@ public function getContiguous(): bool
527538
return $this->contiguous;
528539
}
529540

541+
/**
542+
* Php9 intends to drop support for this parameter in fgetcsv.
543+
* Not yet ready to mark deprecated in order to give users
544+
* a migration path.
545+
*/
530546
public function setEscapeCharacter(string $escapeCharacter): self
531547
{
532548
$this->escapeCharacter = $escapeCharacter;
@@ -536,7 +552,7 @@ public function setEscapeCharacter(string $escapeCharacter): self
536552

537553
public function getEscapeCharacter(): string
538554
{
539-
return $this->escapeCharacter;
555+
return $this->escapeCharacter ?? self::$defaultEscapeCharacter;
540556
}
541557

542558
/**
@@ -649,4 +665,28 @@ public function setSheetNameIsFileName(bool $sheetNameIsFileName): self
649665

650666
return $this;
651667
}
668+
669+
/**
670+
* Php8.4 deprecates use of anything other than null string
671+
* as escape Character.
672+
*
673+
* @param resource $stream
674+
* @param null|int<0, max> $length
675+
*
676+
* @return array<int,?string>|false
677+
*/
678+
private static function getCsv(
679+
$stream,
680+
?int $length = null,
681+
string $separator = ',',
682+
string $enclosure = '"',
683+
?string $escape = null
684+
): array|false {
685+
$escape = $escape ?? self::$defaultEscapeCharacter;
686+
if (PHP_VERSION_ID >= 80400 && $escape !== '') {
687+
return @fgetcsv($stream, $length, $separator, $enclosure, $escape);
688+
}
689+
690+
return fgetcsv($stream, $length, $separator, $enclosure, $escape);
691+
}
652692
}

0 commit comments

Comments
 (0)