Update Some Doc Block Annotations (#2351)

* Update Some Doc Block Annotations

See PR #2010. That PR was never completed, and has gone stale. However, it was correct in identifying a situation where the doc block was not entirely accurate. It did not go far enough - several closely-related methods have similar problems. This PR attempts to fix the original problem and its close relations. Aside from the doc block changes, there are very minor changes to executable code. It also changes some of the unit tests targeted at the methods in question to eliminate mocking in favor of 'real' tests.

* Change Method to Static

Otherwise Scrutinizer will complain, even though Phpstan doesn't.

* Scrutinizer

Various clean-up activities.

* Scrutinizer

@#&$(*#&$ Got complexity down from 53 to (I think) 50. Don't really know what the target is.

* Code Changes Suggested By Review

Some improvements suggested in review by @PowerKiKi.

* Update Cells.php

* Merge Conflict

A change to a parameter name caused several problems when trying to fix it on Github. Fixing it locally should do the trick.

* Merge Conflicts in Phpstan Baseline

PR #2382 made a large number of changes to Phpstan Baseline, some of which conflicted with the Phpstan Baseline changes in this PR. This should resolve them all.
This commit is contained in:
oleibman 2021-11-11 23:38:05 -08:00 committed by GitHub
parent 5a704158e1
commit ffdae8efac
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 257 additions and 377 deletions

View File

@ -220,11 +220,6 @@ parameters:
count: 1
path: src/PhpSpreadsheet/Calculation/Calculation.php
-
message: "#^Parameter \\#1 \\$row of method PhpOffice\\\\PhpSpreadsheet\\\\Worksheet\\\\Worksheet\\:\\:getHighestDataColumn\\(\\) expects string\\|null, mixed given\\.$#"
count: 1
path: src/PhpSpreadsheet/Calculation/Calculation.php
-
message: "#^Parameter \\#1 \\$str of function preg_quote expects string, int\\|string given\\.$#"
count: 1
@ -2950,46 +2945,11 @@ parameters:
count: 1
path: src/PhpSpreadsheet/Collection/Cells.php
-
message: "#^Cannot call method detach\\(\\) on PhpOffice\\\\PhpSpreadsheet\\\\Cell\\\\Cell\\|null\\.$#"
count: 1
path: src/PhpSpreadsheet/Collection/Cells.php
-
message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Collection\\\\Cells\\:\\:get\\(\\) should return PhpOffice\\\\PhpSpreadsheet\\\\Cell\\\\Cell\\|null but returns mixed\\.$#"
count: 1
path: src/PhpSpreadsheet/Collection/Cells.php
-
message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Collection\\\\Cells\\:\\:getCurrentCoordinate\\(\\) should return string but returns string\\|null\\.$#"
count: 1
path: src/PhpSpreadsheet/Collection/Cells.php
-
message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Collection\\\\Cells\\:\\:getParent\\(\\) should return PhpOffice\\\\PhpSpreadsheet\\\\Worksheet\\\\Worksheet but returns PhpOffice\\\\PhpSpreadsheet\\\\Worksheet\\\\Worksheet\\|null\\.$#"
count: 1
path: src/PhpSpreadsheet/Collection/Cells.php
-
message: "#^Parameter \\#1 \\$columnIndex of static method PhpOffice\\\\PhpSpreadsheet\\\\Cell\\\\Coordinate\\:\\:stringFromColumnIndex\\(\\) expects int, int\\|false given\\.$#"
count: 1
path: src/PhpSpreadsheet/Collection/Cells.php
-
message: "#^Parameter \\#1 \\$str of function sscanf expects string, string\\|null given\\.$#"
count: 2
path: src/PhpSpreadsheet/Collection/Cells.php
-
message: "#^Parameter \\#1 \\$string of function substr expects string, string\\|false given\\.$#"
count: 1
path: src/PhpSpreadsheet/Collection/Cells.php
-
message: "#^Possibly invalid array key type \\(array\\|string\\)\\.$#"
count: 1
path: src/PhpSpreadsheet/Collection/Cells.php
-
message: "#^Property PhpOffice\\\\PhpSpreadsheet\\\\Collection\\\\Cells\\:\\:\\$currentCell \\(PhpOffice\\\\PhpSpreadsheet\\\\Cell\\\\Cell\\|null\\) does not accept mixed\\.$#"
count: 1
@ -8680,11 +8640,6 @@ parameters:
count: 1
path: tests/PhpSpreadsheetTests/Collection/CellsTest.php
-
message: "#^Parameter \\#1 \\$row of method PhpOffice\\\\PhpSpreadsheet\\\\Collection\\\\Cells\\:\\:getHighestColumn\\(\\) expects string\\|null, int given\\.$#"
count: 3
path: tests/PhpSpreadsheetTests/Collection/CellsTest.php
-
message: "#^Parameter \\#1 \\$propertyName of method PhpOffice\\\\PhpSpreadsheet\\\\Document\\\\Properties\\:\\:getCustomPropertyType\\(\\) expects string, mixed given\\.$#"
count: 1

View File

@ -4230,7 +4230,9 @@ class Calculation
if (ctype_digit($val) && $val <= 1048576) {
// Row range
$stackItemType = 'Row Reference';
$endRowColRef = ($refSheet !== null) ? $refSheet->getHighestDataColumn($val) : 'XFD'; // Max 16,384 columns for Excel2007
/** @var string */
$valx = $val;
$endRowColRef = ($refSheet !== null) ? $refSheet->getHighestDataColumn($valx) : 'XFD'; // Max 16,384 columns for Excel2007
$val = "{$rangeWS2}{$endRowColRef}{$val}";
} elseif (ctype_alpha($val) && strlen($val) <= 3) {
// Column range

View File

@ -9,6 +9,7 @@ use PhpOffice\PhpSpreadsheet\RichText\RichText;
use PhpOffice\PhpSpreadsheet\Style\NumberFormat;
use PhpOffice\PhpSpreadsheet\Style\Style;
use PhpOffice\PhpSpreadsheet\Worksheet\Worksheet;
use Throwable;
class Cell
{
@ -139,7 +140,16 @@ class Cell
*/
public function getCoordinate()
{
return $this->parent->getCurrentCoordinate();
try {
$coordinate = $this->parent->getCurrentCoordinate();
} catch (Throwable $e) {
$coordinate = null;
}
if ($coordinate === null) {
throw new Exception('Coordinate no longer exists');
}
return $coordinate;
}
/**
@ -478,7 +488,17 @@ class Cell
*/
public function getWorksheet()
{
return $this->parent->getParent();
try {
$worksheet = $this->parent->getParent();
} catch (Throwable $e) {
$worksheet = null;
}
if ($worksheet === null) {
throw new Exception('Worksheet no longer exists');
}
return $worksheet;
}
/**

View File

@ -76,7 +76,7 @@ class Cells
/**
* Return the parent worksheet for this cell collection.
*
* @return Worksheet
* @return null|Worksheet
*/
public function getParent()
{
@ -181,7 +181,7 @@ class Cells
// Determine highest column and row
$highestRow = max($row);
$highestColumn = substr(max($col), 1);
$highestColumn = substr((string) @max($col), 1);
return [
'row' => $highestRow,
@ -192,7 +192,7 @@ class Cells
/**
* Return the cell coordinate of the currently active cell object.
*
* @return string
* @return null|string
*/
public function getCurrentCoordinate()
{
@ -209,7 +209,7 @@ class Cells
$column = '';
$row = 0;
sscanf($this->currentCoordinate, '%[A-Z]%d', $column, $row);
sscanf($this->currentCoordinate ?? '', '%[A-Z]%d', $column, $row);
return $column;
}
@ -224,7 +224,7 @@ class Cells
$column = '';
$row = 0;
sscanf($this->currentCoordinate, '%[A-Z]%d', $column, $row);
sscanf($this->currentCoordinate ?? '', '%[A-Z]%d', $column, $row);
return (int) $row;
}
@ -232,7 +232,7 @@ class Cells
/**
* Get highest worksheet column.
*
* @param string $row Return the highest column for the specified row,
* @param null|int|string $row Return the highest column for the specified row,
* or the highest column of any row if no row number is passed
*
* @return string Highest column name
@ -257,13 +257,13 @@ class Cells
$columnList[] = Coordinate::columnIndexFromString($c);
}
return Coordinate::stringFromColumnIndex(max($columnList));
return Coordinate::stringFromColumnIndex((int) @max($columnList));
}
/**
* Get highest worksheet row.
*
* @param string $column Return the highest row for the specified column,
* @param null|string $column Return the highest row for the specified column,
* or the highest row of any column if no column letter is passed
*
* @return int Highest row number
@ -304,8 +304,6 @@ class Cells
/**
* Clone the cell collection.
*
* @param Worksheet $worksheet The new worksheet that we're copying to
*
* @return self
*/
public function cloneCellCollection(Worksheet $worksheet)
@ -314,7 +312,7 @@ class Cells
$newCollection = clone $this;
$newCollection->parent = $worksheet;
if (($newCollection->currentCell !== null) && (is_object($newCollection->currentCell))) {
if (is_object($newCollection->currentCell)) {
$newCollection->currentCell->attach($this);
}
@ -327,16 +325,14 @@ class Cells
// Change prefix
$newCollection->cachePrefix = $newCollection->getUniqueID();
foreach ($oldValues as $oldKey => $value) {
$newValues[str_replace($oldCachePrefix, $newCollection->cachePrefix, $oldKey)] = clone $value;
/** @var string */
$newKey = str_replace($oldCachePrefix, $newCollection->cachePrefix, $oldKey);
$newValues[$newKey] = clone $value;
}
// Store new values
$stored = $newCollection->cache->setMultiple($newValues);
if (!$stored) {
$newCollection->__destruct();
throw new PhpSpreadsheetException('Failed to copy cells in cache');
}
$this->destructIfNeeded($stored, $newCollection, 'Failed to copy cells in cache');
return $newCollection;
}
@ -383,15 +379,11 @@ class Cells
*/
private function storeCurrentCell(): void
{
if ($this->currentCellIsDirty && !empty($this->currentCoordinate)) {
if ($this->currentCellIsDirty && isset($this->currentCoordinate, $this->currentCell)) {
$this->currentCell->detach();
$stored = $this->cache->set($this->cachePrefix . $this->currentCoordinate, $this->currentCell);
if (!$stored) {
$this->__destruct();
throw new PhpSpreadsheetException("Failed to store cell {$this->currentCoordinate} in cache");
}
$this->destructIfNeeded($stored, $this, "Failed to store cell {$this->currentCoordinate} in cache");
$this->currentCellIsDirty = false;
}
@ -399,6 +391,15 @@ class Cells
$this->currentCell = null;
}
private function destructIfNeeded(bool $stored, self $cells, string $message): void
{
if (!$stored) {
$cells->__destruct();
throw new PhpSpreadsheetException($message);
}
}
/**
* Add or update a cell identified by its coordinate into the collection.
*

View File

@ -1036,14 +1036,14 @@ class Worksheet implements IComparable
/**
* Get highest worksheet column.
*
* @param string $row Return the data highest column for the specified row,
* @param null|int|string $row Return the data highest column for the specified row,
* or the highest column of any row if no row number is passed
*
* @return string Highest column name
*/
public function getHighestColumn($row = null)
{
if ($row == null) {
if (empty($row)) {
return Coordinate::stringFromColumnIndex($this->cachedHighestColumn);
}
@ -1053,7 +1053,7 @@ class Worksheet implements IComparable
/**
* Get highest worksheet column that contains data.
*
* @param string $row Return the highest data column for the specified row,
* @param null|int|string $row Return the highest data column for the specified row,
* or the highest data column of any row if no row number is passed
*
* @return string Highest column name that contains data
@ -1066,7 +1066,7 @@ class Worksheet implements IComparable
/**
* Get highest worksheet row.
*
* @param string $column Return the highest data row for the specified column,
* @param null|string $column Return the highest data row for the specified column,
* or the highest row of any column if no column letter is passed
*
* @return int Highest row number
@ -1083,7 +1083,7 @@ class Worksheet implements IComparable
/**
* Get highest worksheet row that contains data.
*
* @param string $column Return the highest data row for the specified column,
* @param null|string $column Return the highest data row for the specified column,
* or the highest data row of any column if no column letter is passed
*
* @return int Highest row number that contains data

View File

@ -4,12 +4,9 @@ namespace PhpOffice\PhpSpreadsheetTests\Cell;
use PhpOffice\PhpSpreadsheet\Cell\AdvancedValueBinder;
use PhpOffice\PhpSpreadsheet\Cell\Cell;
use PhpOffice\PhpSpreadsheet\Cell\DataType;
use PhpOffice\PhpSpreadsheet\Collection\Cells;
use PhpOffice\PhpSpreadsheet\Cell\IValueBinder;
use PhpOffice\PhpSpreadsheet\Shared\StringHelper;
use PhpOffice\PhpSpreadsheet\Style\NumberFormat;
use PhpOffice\PhpSpreadsheet\Worksheet\Worksheet;
use PHPUnit\Framework\MockObject\MockObject;
use PhpOffice\PhpSpreadsheet\Spreadsheet;
use PHPUnit\Framework\TestCase;
class AdvancedValueBinderTest extends TestCase
@ -29,11 +26,18 @@ class AdvancedValueBinderTest extends TestCase
*/
private $thousandsSeparator;
/**
* @var IValueBinder
*/
private $valueBinder;
protected function setUp(): void
{
$this->currencyCode = StringHelper::getCurrencyCode();
$this->decimalSeparator = StringHelper::getDecimalSeparator();
$this->thousandsSeparator = StringHelper::getThousandsSeparator();
$this->valueBinder = Cell::getValueBinder();
Cell::setValueBinder(new AdvancedValueBinder());
}
protected function tearDown(): void
@ -41,23 +45,16 @@ class AdvancedValueBinderTest extends TestCase
StringHelper::setCurrencyCode($this->currencyCode);
StringHelper::setDecimalSeparator($this->decimalSeparator);
StringHelper::setThousandsSeparator($this->thousandsSeparator);
Cell::setValueBinder($this->valueBinder);
}
public function testNullValue(): void
{
/** @var Cell&MockObject $cellStub */
$cellStub = $this->getMockBuilder(Cell::class)
->disableOriginalConstructor()
->getMock();
// Configure the stub.
$cellStub->expects(self::once())
->method('setValueExplicit')
->with(null, DataType::TYPE_NULL)
->willReturn(true);
$binder = new AdvancedValueBinder();
$binder->bindValue($cellStub, null);
$spreadsheet = new Spreadsheet();
$sheet = $spreadsheet->getActiveSheet();
$sheet->getCell('A1')->setValue(null);
self::assertNull($sheet->getCell('A1')->getValue());
$spreadsheet->disconnectWorksheets();
}
/**
@ -65,65 +62,34 @@ class AdvancedValueBinderTest extends TestCase
*
* @param mixed $value
* @param mixed $valueBinded
* @param mixed $format
* @param mixed $thousandsSeparator
* @param mixed $decimalSeparator
* @param mixed $currencyCode
*/
public function testCurrency($value, $valueBinded, $format, $thousandsSeparator, $decimalSeparator, $currencyCode): void
public function testCurrency($value, $valueBinded, $thousandsSeparator, $decimalSeparator, $currencyCode): void
{
$sheet = $this->getMockBuilder(Worksheet::class)
->onlyMethods(['getStyle', 'getCellCollection'])
->addMethods(['getNumberFormat', 'setFormatCode'])
->getMock();
$cellCollection = $this->getMockBuilder(Cells::class)
->disableOriginalConstructor()
->getMock();
$cellCollection->expects(self::any())
->method('getParent')
->willReturn($sheet);
$sheet->expects(self::once())
->method('getStyle')
->willReturnSelf();
// @phpstan-ignore-next-line
$sheet->expects(self::once())
->method('getNumberFormat')
->willReturnSelf();
// @phpstan-ignore-next-line
$sheet->expects(self::once())
->method('setFormatCode')
->with($format)
->willReturnSelf();
$sheet->expects(self::any())
->method('getCellCollection')
->willReturn($cellCollection);
StringHelper::setCurrencyCode($currencyCode);
StringHelper::setDecimalSeparator($decimalSeparator);
StringHelper::setThousandsSeparator($thousandsSeparator);
$cell = new Cell(null, DataType::TYPE_STRING, $sheet);
$binder = new AdvancedValueBinder();
$binder->bindValue($cell, $value);
self::assertEquals($valueBinded, $cell->getValue());
$spreadsheet = new Spreadsheet();
$sheet = $spreadsheet->getActiveSheet();
$sheet->getCell('A1')->setValue($value);
self::assertEquals($valueBinded, $sheet->getCell('A1')->getValue());
$spreadsheet->disconnectWorksheets();
}
public function currencyProvider(): array
{
$currencyUSD = NumberFormat::FORMAT_CURRENCY_USD_SIMPLE;
$currencyEURO = str_replace('$', '€', NumberFormat::FORMAT_CURRENCY_USD_SIMPLE);
return [
['$10.11', 10.11, $currencyUSD, ',', '.', '$'],
['$1,010.12', 1010.12, $currencyUSD, ',', '.', '$'],
['$20,20', 20.2, $currencyUSD, '.', ',', '$'],
['$2.020,20', 2020.2, $currencyUSD, '.', ',', '$'],
['€2.020,20', 2020.2, $currencyEURO, '.', ',', '€'],
['€ 2.020,20', 2020.2, $currencyEURO, '.', ',', '€'],
['€2,020.22', 2020.22, $currencyEURO, ',', '.', '€'],
['$10.11', 10.11, $currencyUSD, ',', '.', '€'],
['$10.11', 10.11, ',', '.', '$'],
['$1,010.12', 1010.12, ',', '.', '$'],
['$20,20', 20.2, '.', ',', '$'],
['$2.020,20', 2020.2, '.', ',', '$'],
['€2.020,20', 2020.2, '.', ',', '€'],
['€ 2.020,20', 2020.2, '.', ',', '€'],
['€2,020.22', 2020.22, ',', '.', '€'],
['$10.11', 10.11, ',', '.', '€'],
];
}
@ -132,59 +98,30 @@ class AdvancedValueBinderTest extends TestCase
*
* @param mixed $value
* @param mixed $valueBinded
* @param mixed $format
*/
public function testFractions($value, $valueBinded, $format): void
public function testFractions($value, $valueBinded): void
{
$sheet = $this->getMockBuilder(Worksheet::class)
->onlyMethods(['getStyle', 'getCellCollection'])
->addMethods(['getNumberFormat', 'setFormatCode'])
->getMock();
$cellCollection = $this->getMockBuilder(Cells::class)
->disableOriginalConstructor()
->getMock();
$cellCollection->expects(self::any())
->method('getParent')
->willReturn($sheet);
$sheet->expects(self::once())
->method('getStyle')
->willReturnSelf();
// @phpstan-ignore-next-line
$sheet->expects(self::once())
->method('getNumberFormat')
->willReturnSelf();
// @phpstan-ignore-next-line
$sheet->expects(self::once())
->method('setFormatCode')
->with($format)
->willReturnSelf();
$sheet->expects(self::any())
->method('getCellCollection')
->willReturn($cellCollection);
$cell = new Cell(null, DataType::TYPE_STRING, $sheet);
$binder = new AdvancedValueBinder();
$binder->bindValue($cell, $value);
self::assertEquals($valueBinded, $cell->getValue());
$spreadsheet = new Spreadsheet();
$sheet = $spreadsheet->getActiveSheet();
$sheet->getCell('A1')->setValue($value);
self::assertEquals($valueBinded, $sheet->getCell('A1')->getValue());
$spreadsheet->disconnectWorksheets();
}
public function fractionProvider(): array
{
return [
['1/5', 0.2, '?/?'],
['-1/5', -0.2, '?/?'],
['12/5', 2.4, '??/?'],
['2/100', 0.02, '?/???'],
['15/12', 1.25, '??/??'],
['20/100', 0.2, '??/???'],
['1 3/5', 1.6, '# ?/?'],
['-1 3/5', -1.6, '# ?/?'],
['1 4/20', 1.2, '# ?/??'],
['1 16/20', 1.8, '# ??/??'],
['12 20/100', 12.2, '# ??/???'],
['1/5', 0.2],
['-1/5', -0.2],
['12/5', 2.4],
['2/100', 0.02],
['15/12', 1.25],
['20/100', 0.2],
['1 3/5', 1.6],
['-1 3/5', -1.6],
['1 4/20', 1.2],
['1 16/20', 1.8],
['12 20/100', 12.2],
];
}
@ -193,51 +130,23 @@ class AdvancedValueBinderTest extends TestCase
*
* @param mixed $value
* @param mixed $valueBinded
* @param mixed $format
*/
public function testPercentages($value, $valueBinded, $format): void
public function testPercentages($value, $valueBinded): void
{
$sheet = $this->getMockBuilder(Worksheet::class)
->onlyMethods(['getStyle', 'getCellCollection'])
->addMethods(['getNumberFormat', 'setFormatCode'])
->getMock();
$cellCollection = $this->getMockBuilder(Cells::class)
->disableOriginalConstructor()
->getMock();
$cellCollection->expects(self::any())
->method('getParent')
->willReturn($sheet);
$sheet->expects(self::once())
->method('getStyle')
->willReturnSelf();
// @phpstan-ignore-next-line
$sheet->expects(self::once())
->method('getNumberFormat')
->willReturnSelf();
// @phpstan-ignore-next-line
$sheet->expects(self::once())
->method('setFormatCode')
->with($format)
->willReturnSelf();
$sheet->expects(self::any())
->method('getCellCollection')
->willReturn($cellCollection);
$cell = new Cell(null, DataType::TYPE_STRING, $sheet);
$binder = new AdvancedValueBinder();
$binder->bindValue($cell, $value);
self::assertEquals($valueBinded, $cell->getValue());
$spreadsheet = new Spreadsheet();
$sheet = $spreadsheet->getActiveSheet();
$sheet->getCell('A1')->setValue($value);
self::assertEquals($valueBinded, $sheet->getCell('A1')->getValue());
$spreadsheet->disconnectWorksheets();
}
public function percentageProvider(): array
{
return [
['10%', 0.1, NumberFormat::FORMAT_PERCENTAGE_00],
['-12%', -0.12, NumberFormat::FORMAT_PERCENTAGE_00],
['120%', 1.2, NumberFormat::FORMAT_PERCENTAGE_00],
['12.5%', 0.125, NumberFormat::FORMAT_PERCENTAGE_00],
['10%', 0.1],
['-12%', -0.12],
['120%', 1.2],
['12.5%', 0.125],
];
}
@ -246,92 +155,37 @@ class AdvancedValueBinderTest extends TestCase
*
* @param mixed $value
* @param mixed $valueBinded
* @param mixed $format
*/
public function testTimes($value, $valueBinded, $format): void
public function testTimes($value, $valueBinded): void
{
$sheet = $this->getMockBuilder(Worksheet::class)
->onlyMethods(['getStyle', 'getCellCollection'])
->addMethods(['getNumberFormat', 'setFormatCode'])
->getMock();
$cellCollection = $this->getMockBuilder(Cells::class)
->disableOriginalConstructor()
->getMock();
$cellCollection->expects(self::any())
->method('getParent')
->willReturn($sheet);
$sheet->expects(self::once())
->method('getStyle')
->willReturnSelf();
// @phpstan-ignore-next-line
$sheet->expects(self::once())
->method('getNumberFormat')
->willReturnSelf();
// @phpstan-ignore-next-line
$sheet->expects(self::once())
->method('setFormatCode')
->with($format)
->willReturnSelf();
$sheet->expects(self::any())
->method('getCellCollection')
->willReturn($cellCollection);
$cell = new Cell(null, DataType::TYPE_STRING, $sheet);
$binder = new AdvancedValueBinder();
$binder->bindValue($cell, $value);
self::assertEquals($valueBinded, $cell->getValue());
$spreadsheet = new Spreadsheet();
$sheet = $spreadsheet->getActiveSheet();
$sheet->getCell('A1')->setValue($value);
self::assertEquals($valueBinded, $sheet->getCell('A1')->getValue());
$spreadsheet->disconnectWorksheets();
}
public function timeProvider(): array
{
return [
['1:20', 0.05555555556, NumberFormat::FORMAT_DATE_TIME3],
['09:17', 0.386805555556, NumberFormat::FORMAT_DATE_TIME3],
['15:00', 0.625, NumberFormat::FORMAT_DATE_TIME3],
['17:12:35', 0.71707175926, NumberFormat::FORMAT_DATE_TIME4],
['23:58:20', 0.99884259259, NumberFormat::FORMAT_DATE_TIME4],
['1:20', 0.05555555556],
['09:17', 0.386805555556],
['15:00', 0.625],
['17:12:35', 0.71707175926],
['23:58:20', 0.99884259259],
];
}
/**
* @dataProvider stringProvider
*/
public function testStringWrapping(string $value, bool $wrapped): void
public function testStringWrapping(string $value): void
{
$sheet = $this->getMockBuilder(Worksheet::class)
->onlyMethods(['getStyle', 'getCellCollection'])
->addMethods(['getAlignment', 'setWrapText'])
->getMock();
$cellCollection = $this->getMockBuilder(Cells::class)
->disableOriginalConstructor()
->getMock();
$cellCollection->expects(self::any())
->method('getParent')
->willReturn($sheet);
$sheet->expects($wrapped ? self::once() : self::never())
->method('getStyle')
->willReturnSelf();
// @phpstan-ignore-next-line
$sheet->expects($wrapped ? self::once() : self::never())
->method('getAlignment')
->willReturnSelf();
// @phpstan-ignore-next-line
$sheet->expects($wrapped ? self::once() : self::never())
->method('setWrapText')
->with($wrapped)
->willReturnSelf();
$sheet->expects(self::any())
->method('getCellCollection')
->willReturn($cellCollection);
$cell = new Cell(null, DataType::TYPE_STRING, $sheet);
$binder = new AdvancedValueBinder();
$binder->bindValue($cell, $value);
$spreadsheet = new Spreadsheet();
$sheet = $spreadsheet->getActiveSheet();
$sheet->getCell('A1')->setValue($value);
self::assertEquals($value, $sheet->getCell('A1')->getValue());
$spreadsheet->disconnectWorksheets();
}
public function stringProvider(): array

View File

@ -21,6 +21,7 @@ class CellTest extends TestCase
$cell->setValueExplicit($value, $dataType);
self::assertSame($expected, $cell->getValue());
$spreadsheet->disconnectWorksheets();
}
public function providerSetValueExplicit(): array
@ -64,5 +65,42 @@ class CellTest extends TestCase
$value = $spreadsheet->getActiveSheet()->getCell($cell)->getCalculatedValue();
self::assertEquals(0, $spreadsheet->getActiveSheetIndex());
self::assertEquals(247, $value);
$spreadsheet->disconnectWorksheets();
}
public function testDestroyWorksheet(): void
{
$spreadsheet = new Spreadsheet();
$sheet = $spreadsheet->getActiveSheet();
$cell = $sheet->getCell('A1');
self::assertSame($sheet, $cell->getWorksheet());
$this->expectException(Exception::class);
$this->expectExceptionMessage('Worksheet no longer exists');
$spreadsheet->disconnectWorksheets();
$cell->getWorksheet();
}
public function testDestroyCell1(): void
{
$spreadsheet = new Spreadsheet();
$sheet = $spreadsheet->getActiveSheet();
$cell = $sheet->getCell('A1');
self::assertSame('A1', $cell->getCoordinate());
$this->expectException(Exception::class);
$this->expectExceptionMessage('Coordinate no longer exists');
$spreadsheet->disconnectWorksheets();
$cell->getCoordinate();
}
public function testDestroyCell2(): void
{
$spreadsheet = new Spreadsheet();
$sheet = $spreadsheet->getActiveSheet();
$cell = $sheet->getCell('A1');
self::assertSame('A1', $cell->getCoordinate());
$this->expectException(Exception::class);
$this->expectExceptionMessage('Coordinate no longer exists');
$cell->getParent()->delete('A1');
$cell->getCoordinate();
}
}

View File

@ -4,31 +4,14 @@ namespace PhpOffice\PhpSpreadsheetTests\Cell;
use DateTime;
use DateTimeImmutable;
use PhpOffice\PhpSpreadsheet\Cell\Cell;
use PhpOffice\PhpSpreadsheet\Cell\DataType;
use PhpOffice\PhpSpreadsheet\Cell\DefaultValueBinder;
use PhpOffice\PhpSpreadsheet\RichText\RichText;
use PHPUnit\Framework\MockObject\MockObject;
use PhpOffice\PhpSpreadsheet\Spreadsheet;
use PHPUnit\Framework\TestCase;
class DefaultValueBinderTest extends TestCase
{
private function createCellStub(): Cell
{
// Create a stub for the Cell class.
/** @var Cell&MockObject $cellStub */
$cellStub = $this->getMockBuilder(Cell::class)
->disableOriginalConstructor()
->getMock();
// Configure the stub.
$cellStub->expects(self::any())
->method('setValueExplicit')
->willReturn(true);
return $cellStub;
}
/**
* @dataProvider binderProvider
*
@ -36,10 +19,13 @@ class DefaultValueBinderTest extends TestCase
*/
public function testBindValue($value): void
{
$cellStub = $this->createCellStub();
$spreadsheet = new Spreadsheet();
$sheet = $spreadsheet->getActiveSheet();
$cell = $sheet->getCell('A1');
$binder = new DefaultValueBinder();
$result = $binder->bindValue($cellStub, $value);
$result = $binder->bindValue($cell, $value);
self::assertTrue($result);
$spreadsheet->disconnectWorksheets();
}
public function binderProvider(): array
@ -91,11 +77,14 @@ class DefaultValueBinderTest extends TestCase
public function testCanOverrideStaticMethodWithoutOverridingBindValue(): void
{
$cellStub = $this->createCellStub();
$spreadsheet = new Spreadsheet();
$sheet = $spreadsheet->getActiveSheet();
$cell = $sheet->getCell('A1');
$binder = new ValueBinderWithOverriddenDataTypeForValue();
self::assertFalse($binder::$called);
$binder->bindValue($cellStub, 123);
$binder->bindValue($cell, 123);
self::assertTrue($binder::$called);
$spreadsheet->disconnectWorksheets();
}
}

View File

@ -6,41 +6,27 @@ use DateTime;
use DateTimeZone;
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\Style\Style;
use PHPUnit\Framework\MockObject\MockObject;
use PhpOffice\PhpSpreadsheet\Spreadsheet;
use PHPUnit\Framework\TestCase;
class StringValueBinderTest extends TestCase
{
/**
* @param mixed $expectedValue
*
* @return Cell&MockObject
* @var IValueBinder
*/
protected function createCellStub($expectedValue, string $expectedDataType, bool $quotePrefix = false): MockObject
private $valueBinder;
protected function setUp(): void
{
/** @var Style&MockObject $styleStub */
$styleStub = $this->getMockBuilder(Style::class)
->disableOriginalConstructor()
->getMock();
$this->valueBinder = Cell::getValueBinder();
}
/** @var Cell&MockObject $cellStub */
$cellStub = $this->getMockBuilder(Cell::class)
->disableOriginalConstructor()
->getMock();
// Configure the stub.
$cellStub->expects(self::once())
->method('setValueExplicit')
->with($expectedValue, $expectedDataType)
->willReturn(true);
$cellStub->expects($quotePrefix ? self::once() : self::never())
->method('getStyle')
->willReturn($styleStub);
return $cellStub;
protected function tearDown(): void
{
Cell::setValueBinder($this->valueBinder);
}
/**
@ -52,13 +38,16 @@ class StringValueBinderTest extends TestCase
public function testStringValueBinderDefaultBehaviour(
$value,
$expectedValue,
string $expectedDataType,
bool $quotePrefix = false
string $expectedDataType
): void {
$cellStub = $this->createCellStub($expectedValue, $expectedDataType, $quotePrefix);
$binder = new StringValueBinder();
$binder->bindValue($cellStub, $value);
Cell::setValueBinder(new StringValueBinder());
$spreadsheet = new Spreadsheet();
$sheet = $spreadsheet->getActiveSheet();
$cell = $sheet->getCell('A1');
$cell->setValue($value);
self::assertSame($expectedValue, $cell->getValue());
self::assertSame($expectedDataType, $cell->getDataType());
$spreadsheet->disconnectWorksheets();
}
public function providerDataValuesDefault(): array
@ -76,7 +65,7 @@ class StringValueBinderTest extends TestCase
['-.123', '-.123', DataType::TYPE_STRING],
['1.23e-4', '1.23e-4', DataType::TYPE_STRING],
['ABC', 'ABC', DataType::TYPE_STRING],
['=SUM(A1:C3)', '=SUM(A1:C3)', DataType::TYPE_STRING, true],
['=SUM(A1:C3)', '=SUM(A1:C3)', DataType::TYPE_STRING],
[123, '123', DataType::TYPE_STRING],
[123.456, '123.456', DataType::TYPE_STRING],
[0.123, '0.123', DataType::TYPE_STRING],
@ -98,20 +87,26 @@ class StringValueBinderTest extends TestCase
public function testStringValueBinderSuppressNullConversion(
$value,
$expectedValue,
string $expectedDataType,
bool $quotePrefix = false
string $expectedDataType
): void {
$cellStub = $this->createCellStub($expectedValue, $expectedDataType, $quotePrefix);
$binder = new StringValueBinder();
$binder->setNullConversion(false);
$binder->bindValue($cellStub, $value);
Cell::setValueBinder($binder);
$spreadsheet = new Spreadsheet();
$sheet = $spreadsheet->getActiveSheet();
$cell = $sheet->getCell('A1');
$cell->setValue($value);
self::assertSame($expectedValue, $cell->getValue());
self::assertSame($expectedDataType, $cell->getDataType());
$spreadsheet->disconnectWorksheets();
}
public function providerDataValuesSuppressNullConversion(): array
{
return [
[null, null, DataType::TYPE_NULL],
[true, '1', DataType::TYPE_STRING],
[123, '123', DataType::TYPE_STRING],
];
}
@ -124,14 +119,18 @@ class StringValueBinderTest extends TestCase
public function testStringValueBinderSuppressBooleanConversion(
$value,
$expectedValue,
string $expectedDataType,
bool $quotePrefix = false
string $expectedDataType
): void {
$cellStub = $this->createCellStub($expectedValue, $expectedDataType, $quotePrefix);
$binder = new StringValueBinder();
$binder->setBooleanConversion(false);
$binder->bindValue($cellStub, $value);
Cell::setValueBinder($binder);
$spreadsheet = new Spreadsheet();
$sheet = $spreadsheet->getActiveSheet();
$cell = $sheet->getCell('A1');
$cell->setValue($value);
self::assertSame($expectedValue, $cell->getValue());
self::assertSame($expectedDataType, $cell->getDataType());
$spreadsheet->disconnectWorksheets();
}
public function providerDataValuesSuppressBooleanConversion(): array
@ -139,6 +138,8 @@ class StringValueBinderTest extends TestCase
return [
[true, true, DataType::TYPE_BOOL],
[false, false, DataType::TYPE_BOOL],
[null, '', DataType::TYPE_STRING],
[123, '123', DataType::TYPE_STRING],
];
}
@ -151,14 +152,18 @@ class StringValueBinderTest extends TestCase
public function testStringValueBinderSuppressNumericConversion(
$value,
$expectedValue,
string $expectedDataType,
bool $quotePrefix = false
string $expectedDataType
): void {
$cellStub = $this->createCellStub($expectedValue, $expectedDataType, $quotePrefix);
$binder = new StringValueBinder();
$binder->setNumericConversion(false);
$binder->bindValue($cellStub, $value);
Cell::setValueBinder($binder);
$spreadsheet = new Spreadsheet();
$sheet = $spreadsheet->getActiveSheet();
$cell = $sheet->getCell('A1');
$cell->setValue($value);
self::assertSame($expectedValue, $cell->getValue());
self::assertSame($expectedDataType, $cell->getDataType());
$spreadsheet->disconnectWorksheets();
}
public function providerDataValuesSuppressNumericConversion(): array
@ -172,6 +177,9 @@ class StringValueBinderTest extends TestCase
[-.123, -0.123, DataType::TYPE_NUMERIC],
[1.23e-4, 0.000123, DataType::TYPE_NUMERIC],
[1.23e-24, 1.23E-24, DataType::TYPE_NUMERIC],
[true, '1', DataType::TYPE_STRING],
[false, '', DataType::TYPE_STRING],
[null, '', DataType::TYPE_STRING],
];
}
@ -184,14 +192,18 @@ class StringValueBinderTest extends TestCase
public function testStringValueBinderSuppressFormulaConversion(
$value,
$expectedValue,
string $expectedDataType,
bool $quotePrefix = false
string $expectedDataType
): void {
$cellStub = $this->createCellStub($expectedValue, $expectedDataType, $quotePrefix);
$binder = new StringValueBinder();
$binder->setFormulaConversion(false);
$binder->bindValue($cellStub, $value);
Cell::setValueBinder($binder);
$spreadsheet = new Spreadsheet();
$sheet = $spreadsheet->getActiveSheet();
$cell = $sheet->getCell('A1');
$cell->setValue($value);
self::assertSame($expectedValue, $cell->getValue());
self::assertSame($expectedDataType, $cell->getDataType());
$spreadsheet->disconnectWorksheets();
}
public function providerDataValuesSuppressFormulaConversion(): array
@ -210,14 +222,18 @@ class StringValueBinderTest extends TestCase
public function testStringValueBinderSuppressAllConversion(
$value,
$expectedValue,
string $expectedDataType,
bool $quotePrefix = false
string $expectedDataType
): void {
$cellStub = $this->createCellStub($expectedValue, $expectedDataType, $quotePrefix);
$binder = new StringValueBinder();
$binder->setConversionForAllValueTypes(false);
$binder->bindValue($cellStub, $value);
Cell::setValueBinder($binder);
$spreadsheet = new Spreadsheet();
$sheet = $spreadsheet->getActiveSheet();
$cell = $sheet->getCell('A1');
$cell->setValue($value);
self::assertSame($expectedValue, $cell->getValue());
self::assertSame($expectedDataType, $cell->getDataType());
$spreadsheet->disconnectWorksheets();
}
public function providerDataValuesSuppressAllConversion(): array
@ -252,10 +268,15 @@ class StringValueBinderTest extends TestCase
$objRichText = new RichText();
$objRichText->createText('Hello World');
$cellStub = $this->createCellStub($objRichText, DataType::TYPE_INLINE);
$binder = new StringValueBinder();
$binder->setConversionForAllValueTypes(false);
$binder->bindValue($cellStub, $objRichText);
Cell::setValueBinder($binder);
$spreadsheet = new Spreadsheet();
$sheet = $spreadsheet->getActiveSheet();
$cell = $sheet->getCell('A1');
$cell->setValue($objRichText);
self::assertSame('inlineStr', $cell->getDataType());
self::assertSame('Hello World', $cell->getCalculatedValue());
$spreadsheet->disconnectWorksheets();
}
}