Skip to content

Commit

Permalink
Merge pull request #4162 from oleibman/csv84
Browse files Browse the repository at this point in the history
Php 8.4 Will Deprecate fgetcsv Parameter
  • Loading branch information
oleibman authored Sep 7, 2024
2 parents fd96566 + 2a8fb60 commit 6c9b2a8
Showing 1 changed file with 47 additions and 7 deletions.
54 changes: 47 additions & 7 deletions src/PhpSpreadsheet/Reader/Csv.php
Original file line number Diff line number Diff line change
Expand Up @@ -62,8 +62,19 @@ class Csv extends BaseReader

/**
* The character that can escape the enclosure.
* This will probably become unsupported in Php 9.
* Not yet ready to mark deprecated in order to give users
* a migration path.
*/
private string $escapeCharacter = '\\';
private ?string $escapeCharacter = null;

/**
* The character that will be supplied to fgetcsv
* when escapeCharacter is null.
* It is anticipated that it will conditionally be set
* to null-string for Php9 and above.
*/
private static string $defaultEscapeCharacter = '\\';

/**
* Callback for setting defaults in construction.
Expand Down Expand Up @@ -185,7 +196,7 @@ protected function inferSeparator(): void
return;
}

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

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

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

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

// Loop through each line of the file in turn
$delimiter = $this->delimiter ?? '';
$rowData = fgetcsv($fileHandle, 0, $delimiter, $this->enclosure, $this->escapeCharacter);
$rowData = self::getCsv($fileHandle, 0, $delimiter, $this->enclosure, $this->escapeCharacter);
$valueBinder = Cell::getValueBinder();
$preserveBooleanString = method_exists($valueBinder, 'getBooleanConversion') && $valueBinder->getBooleanConversion();
$this->getTrue = Calculation::getTRUE();
Expand Down Expand Up @@ -416,7 +427,7 @@ private function loadStringOrFile(string $filename, Spreadsheet $spreadsheet, bo
}
++$columnLetter;
}
$rowData = fgetcsv($fileHandle, 0, $delimiter, $this->enclosure, $this->escapeCharacter);
$rowData = self::getCsv($fileHandle, 0, $delimiter, $this->enclosure, $this->escapeCharacter);
++$currentRow;
}

Expand Down Expand Up @@ -527,6 +538,11 @@ public function getContiguous(): bool
return $this->contiguous;
}

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

public function getEscapeCharacter(): string
{
return $this->escapeCharacter;
return $this->escapeCharacter ?? self::$defaultEscapeCharacter;
}

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

return $this;
}

/**
* Php8.4 deprecates use of anything other than null string
* as escape Character.
*
* @param resource $stream
* @param null|int<0, max> $length
*
* @return array<int,?string>|false
*/
private static function getCsv(
$stream,
?int $length = null,
string $separator = ',',
string $enclosure = '"',
?string $escape = null
): array|false {
$escape = $escape ?? self::$defaultEscapeCharacter;
if (PHP_VERSION_ID >= 80400 && $escape !== '') {
return @fgetcsv($stream, $length, $separator, $enclosure, $escape);
}

return fgetcsv($stream, $length, $separator, $enclosure, $escape);
}
}

0 comments on commit 6c9b2a8

Please sign in to comment.