mirror of
https://github.com/PHPOffice/PhpSpreadsheet.git
synced 2026-09-12 19:16:45 +00:00
Better Handling of Stringable Objects
This commit is contained in:
@@ -90,6 +90,7 @@ class StringValueBinder extends DefaultValueBinder implements IValueBinder
|
||||
$value = StringHelper::sanitizeUTF8($value);
|
||||
}
|
||||
|
||||
$ignoredErrors = false;
|
||||
if ($value === null && $this->convertNull === false) {
|
||||
$cell->setValueExplicit($value, DataType::TYPE_NULL);
|
||||
} elseif (is_bool($value) && $this->convertBoolean === false) {
|
||||
@@ -99,11 +100,12 @@ class StringValueBinder extends DefaultValueBinder implements IValueBinder
|
||||
} elseif (is_string($value) && strlen($value) > 1 && $value[0] === '=' && $this->convertFormula === false && parent::dataTypeForValue($value) === DataType::TYPE_FORMULA) {
|
||||
$cell->setValueExplicit($value, DataType::TYPE_FORMULA);
|
||||
} else {
|
||||
if ($this->setIgnoredErrors && is_numeric($value)) {
|
||||
$cell->getIgnoredErrors()->setNumberStoredAsText(true);
|
||||
}
|
||||
$ignoredErrors = is_numeric($value);
|
||||
$cell->setValueExplicit((string) $value, DataType::TYPE_STRING);
|
||||
}
|
||||
if ($this->setIgnoredErrors) {
|
||||
$cell->getIgnoredErrors()->setNumberStoredAsText($ignoredErrors);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -111,16 +113,22 @@ class StringValueBinder extends DefaultValueBinder implements IValueBinder
|
||||
protected function bindObjectValue(Cell $cell, object $value): bool
|
||||
{
|
||||
// Handle any objects that might be injected
|
||||
$ignoredErrors = false;
|
||||
if ($value instanceof DateTimeInterface) {
|
||||
$value = $value->format('Y-m-d H:i:s');
|
||||
$cell->setValueExplicit($value, DataType::TYPE_STRING);
|
||||
} elseif ($value instanceof RichText) {
|
||||
$cell->setValueExplicit($value, DataType::TYPE_INLINE);
|
||||
$ignoredErrors = is_numeric($value->getPlainText());
|
||||
} elseif ($value instanceof Stringable) {
|
||||
$cell->setValueExplicit((string) $value, DataType::TYPE_STRING);
|
||||
$ignoredErrors = is_numeric((string) $value);
|
||||
} else {
|
||||
throw new SpreadsheetException('Unable to bind unstringable object of type ' . get_class($value));
|
||||
}
|
||||
if ($this->setIgnoredErrors) {
|
||||
$cell->getIgnoredErrors()->setNumberStoredAsText($ignoredErrors);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -4,10 +4,12 @@ declare(strict_types=1);
|
||||
|
||||
namespace PhpOffice\PhpSpreadsheetTests\Cell;
|
||||
|
||||
use DateTime;
|
||||
use PhpOffice\PhpSpreadsheet\Cell\Cell;
|
||||
use PhpOffice\PhpSpreadsheet\Cell\DataType;
|
||||
use PhpOffice\PhpSpreadsheet\Cell\IValueBinder;
|
||||
use PhpOffice\PhpSpreadsheet\Cell\StringValueBinder;
|
||||
use PhpOffice\PhpSpreadsheet\RichText\RichText;
|
||||
use PhpOffice\PhpSpreadsheet\Spreadsheet;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
@@ -31,15 +33,24 @@ class StringValueBinder2Test extends TestCase
|
||||
Cell::setValueBinder($valueBinder);
|
||||
$spreadsheet = new Spreadsheet();
|
||||
$sheet = $spreadsheet->getActiveSheet();
|
||||
$richText = new RichText();
|
||||
$richText->createTextRun('6');
|
||||
$richText2 = new RichText();
|
||||
$richText2->createTextRun('a');
|
||||
$sheet->fromArray([
|
||||
[1, 'x', 3.2],
|
||||
['y', -5, 'z'],
|
||||
[new DateTime(), $richText, $richText2],
|
||||
[new StringableObject('a'), new StringableObject(2), 'z'],
|
||||
]);
|
||||
$ignoredCells = [];
|
||||
foreach ($sheet->getRowIterator() as $row) {
|
||||
foreach ($row->getCellIterator() as $cell) {
|
||||
$coordinate = $cell->getCoordinate();
|
||||
self::assertSame(DataType::TYPE_STRING, $cell->getDataType(), "not string for cell $coordinate");
|
||||
$dataType = $cell->getDataType();
|
||||
if ($dataType !== DataType::TYPE_INLINE) {
|
||||
self::assertSame(DataType::TYPE_STRING, $dataType, "not string for cell $coordinate");
|
||||
}
|
||||
if ($cell->getIgnoredErrors()->getNumberStoredAsText()) {
|
||||
$ignoredCells[] = $coordinate;
|
||||
}
|
||||
@@ -56,21 +67,30 @@ class StringValueBinder2Test extends TestCase
|
||||
Cell::setValueBinder($valueBinder);
|
||||
$spreadsheet = new Spreadsheet();
|
||||
$sheet = $spreadsheet->getActiveSheet();
|
||||
$richText = new RichText();
|
||||
$richText->createTextRun('6');
|
||||
$richText2 = new RichText();
|
||||
$richText2->createTextRun('a');
|
||||
$sheet->fromArray([
|
||||
[1, 'x', 3.2],
|
||||
['y', -5, 'z'],
|
||||
[new DateTime(), $richText, $richText2],
|
||||
[new StringableObject('a'), new StringableObject(2), 'z'],
|
||||
]);
|
||||
$ignoredCells = [];
|
||||
foreach ($sheet->getRowIterator() as $row) {
|
||||
foreach ($row->getCellIterator() as $cell) {
|
||||
$coordinate = $cell->getCoordinate();
|
||||
self::assertSame(DataType::TYPE_STRING, $cell->getDataType(), "not string for cell $coordinate");
|
||||
$dataType = $cell->getDataType();
|
||||
if ($dataType !== DataType::TYPE_INLINE) {
|
||||
self::assertSame(DataType::TYPE_STRING, $dataType, "not string for cell $coordinate");
|
||||
}
|
||||
if ($cell->getIgnoredErrors()->getNumberStoredAsText()) {
|
||||
$ignoredCells[] = $coordinate;
|
||||
}
|
||||
}
|
||||
}
|
||||
self::assertSame(['A1', 'C1', 'B2'], $ignoredCells);
|
||||
self::assertSame(['A1', 'C1', 'B2', 'B3', 'B4'], $ignoredCells);
|
||||
$spreadsheet->disconnectWorksheets();
|
||||
}
|
||||
|
||||
@@ -82,22 +102,28 @@ class StringValueBinder2Test extends TestCase
|
||||
Cell::setValueBinder($valueBinder);
|
||||
$spreadsheet = new Spreadsheet();
|
||||
$sheet = $spreadsheet->getActiveSheet();
|
||||
$richText = new RichText();
|
||||
$richText->createTextRun('6');
|
||||
$richText2 = new RichText();
|
||||
$richText2->createTextRun('a');
|
||||
$sheet->fromArray([
|
||||
[1, 'x', 3.2],
|
||||
['y', -5, 'z'],
|
||||
[new DateTime(), $richText, $richText2],
|
||||
[new StringableObject('a'), new StringableObject(2), 'z'],
|
||||
]);
|
||||
$ignoredCells = [];
|
||||
foreach ($sheet->getRowIterator() as $row) {
|
||||
foreach ($row->getCellIterator() as $cell) {
|
||||
$coordinate = $cell->getCoordinate();
|
||||
$expected = is_numeric($cell->getValue()) ? DataType::TYPE_NUMERIC : DataType::TYPE_STRING;
|
||||
$expected = (is_int($cell->getValue()) || is_float($cell->getValue())) ? DataType::TYPE_NUMERIC : (($cell->getValue() instanceof RichText) ? DataType::TYPE_INLINE : DataType::TYPE_STRING);
|
||||
self::assertSame($expected, $cell->getDataType(), "wrong type for cell $coordinate");
|
||||
if ($cell->getIgnoredErrors()->getNumberStoredAsText()) {
|
||||
$ignoredCells[] = $coordinate;
|
||||
}
|
||||
}
|
||||
}
|
||||
self::assertSame([], $ignoredCells);
|
||||
self::assertSame(['B3', 'B4'], $ignoredCells);
|
||||
$spreadsheet->disconnectWorksheets();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,8 +6,15 @@ namespace PhpOffice\PhpSpreadsheetTests\Cell;
|
||||
|
||||
class StringableObject
|
||||
{
|
||||
private int|string $value;
|
||||
|
||||
public function __construct(int|string $value = 'abc')
|
||||
{
|
||||
$this->value = $value;
|
||||
}
|
||||
|
||||
public function __toString(): string
|
||||
{
|
||||
return 'abc';
|
||||
return (string) $this->value;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user