diff --git a/src/PhpSpreadsheet/Cell/StringValueBinder.php b/src/PhpSpreadsheet/Cell/StringValueBinder.php index 5b6e3db1..d525faff 100644 --- a/src/PhpSpreadsheet/Cell/StringValueBinder.php +++ b/src/PhpSpreadsheet/Cell/StringValueBinder.php @@ -42,6 +42,11 @@ class StringValueBinder implements IValueBinder return $this; } + public function getBooleanConversion(): bool + { + return $this->convertBoolean; + } + public function setNumericConversion(bool $suppressConversion = false): self { $this->convertNumeric = $suppressConversion; diff --git a/src/PhpSpreadsheet/Reader/Csv.php b/src/PhpSpreadsheet/Reader/Csv.php index 6d99cb1d..185f064c 100644 --- a/src/PhpSpreadsheet/Reader/Csv.php +++ b/src/PhpSpreadsheet/Reader/Csv.php @@ -2,6 +2,7 @@ namespace PhpOffice\PhpSpreadsheet\Reader; +use PhpOffice\PhpSpreadsheet\Cell\Cell; use PhpOffice\PhpSpreadsheet\Cell\Coordinate; use PhpOffice\PhpSpreadsheet\Reader\Csv\Delimiter; use PhpOffice\PhpSpreadsheet\Reader\Exception as ReaderException; @@ -314,11 +315,13 @@ class Csv extends BaseReader // Loop through each line of the file in turn $rowData = fgetcsv($fileHandle, 0, $this->delimiter ?? '', $this->enclosure, $this->escapeCharacter); + $valueBinder = Cell::getValueBinder(); + $preserveBooleanString = method_exists($valueBinder, 'getBooleanConversion') && $valueBinder->getBooleanConversion(); while (is_array($rowData)) { $noOutputYet = true; $columnLetter = 'A'; foreach ($rowData as $rowDatum) { - self::convertBoolean($rowDatum); + $this->convertBoolean($rowDatum, $preserveBooleanString); if ($rowDatum !== '' && $this->readFilter->readCell($columnLetter, $currentRow)) { if ($this->contiguous) { if ($noOutputYet) { @@ -351,9 +354,9 @@ class Csv extends BaseReader * * @param mixed $rowDatum */ - private static function convertBoolean(&$rowDatum): void + private function convertBoolean(&$rowDatum, bool $preserveBooleanString): void { - if (is_string($rowDatum)) { + if (is_string($rowDatum) && !$preserveBooleanString) { if (strcasecmp('true', $rowDatum) === 0) { $rowDatum = true; } elseif (strcasecmp('false', $rowDatum) === 0) { @@ -405,7 +408,7 @@ class Csv extends BaseReader public function setContiguous(bool $contiguous): self { - $this->contiguous = (bool) $contiguous; + $this->contiguous = $contiguous; return $this; } diff --git a/tests/PhpSpreadsheetTests/Reader/Csv/CsvIssue2232Test.php b/tests/PhpSpreadsheetTests/Reader/Csv/CsvIssue2232Test.php new file mode 100644 index 00000000..c463c271 --- /dev/null +++ b/tests/PhpSpreadsheetTests/Reader/Csv/CsvIssue2232Test.php @@ -0,0 +1,63 @@ +valueBinder = Cell::getValueBinder(); + } + + protected function tearDown(): void + { + Cell::setValueBinder($this->valueBinder); + } + + /** + * @dataProvider providerIssue2232 + * + * @param mixed $b2Value + * @param mixed $b3Value + */ + public function testEncodings(bool $useStringBinder, ?bool $preserveBoolString, $b2Value, $b3Value): void + { + if ($useStringBinder) { + $binder = new StringValueBinder(); + if (is_bool($preserveBoolString)) { + $binder->setBooleanConversion($preserveBoolString); + } + Cell::setValueBinder($binder); + } + $reader = new Csv(); + $filename = 'tests/data/Reader/CSV/issue.2232.csv'; + $spreadsheet = $reader->load($filename); + $sheet = $spreadsheet->getActiveSheet(); + self::assertSame($b2Value, $sheet->getCell('B2')->getValue()); + self::assertSame($b3Value, $sheet->getCell('B3')->getValue()); + $spreadsheet->disconnectWorksheets(); + } + + public function providerIssue2232(): array + { + return [ + [false, false, false, true], + [false, null, false, true], + [false, true, false, true], + [true, false, false, true], + [true, null, 'FaLSe', 'tRUE'], + [true, true, 'FaLSe', 'tRUE'], + ]; + } +} diff --git a/tests/data/Reader/CSV/issue.2232.csv b/tests/data/Reader/CSV/issue.2232.csv new file mode 100644 index 00000000..626d0255 --- /dev/null +++ b/tests/data/Reader/CSV/issue.2232.csv @@ -0,0 +1,3 @@ +1,2,3 +a,FaLSe,b +cc,tRUE,cc