Skip to content
This repository has been archived by the owner on May 26, 2022. It is now read-only.

Commit

Permalink
Merge pull request #167 from box/fix_int_float_value_formatters
Browse files Browse the repository at this point in the history
Fix CellValueFormatter for numeric values
  • Loading branch information
adrilo committed Jan 14, 2016
2 parents c48c07d + 4a5da2a commit 2093724
Show file tree
Hide file tree
Showing 3 changed files with 67 additions and 20 deletions.
4 changes: 2 additions & 2 deletions src/Spout/Reader/ODS/Helper/CellValueFormatter.php
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,6 @@ public function __construct()

/**
* Returns the (unescaped) correctly marshalled, cell value associated to the given XML node.
* @TODO Add other types !!
* @see http://docs.oasis-open.org/office/v1.2/os/OpenDocument-v1.2-os-part1.html#refTable13
*
* @param \DOMNode $node
Expand Down Expand Up @@ -119,7 +118,8 @@ protected function formatStringCellValue($node)
protected function formatFloatCellValue($node)
{
$nodeValue = $node->getAttribute(self::XML_ATTRIBUTE_VALUE);
$cellValue = is_int($nodeValue) ? intval($nodeValue) : floatval($nodeValue);
$nodeIntValue = intval($nodeValue);
$cellValue = ($nodeIntValue == $nodeValue) ? $nodeIntValue : floatval($nodeValue);
return $cellValue;
}

Expand Down
3 changes: 2 additions & 1 deletion src/Spout/Reader/XLSX/Helper/CellValueFormatter.php
Original file line number Diff line number Diff line change
Expand Up @@ -169,7 +169,8 @@ protected function formatNumericCellValue($nodeValue, $cellStyleId)
if ($shouldFormatAsDate) {
return $this->formatExcelTimestampValue(floatval($nodeValue));
} else {
return is_int($nodeValue) ? intval($nodeValue) : floatval($nodeValue);
$nodeIntValue = intval($nodeValue);
return ($nodeIntValue == $nodeValue) ? $nodeIntValue : floatval($nodeValue);
}
}

Expand Down
80 changes: 63 additions & 17 deletions tests/Spout/Reader/XLSX/Helper/CellValueFormatterTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,23 +12,26 @@ class CellValueFormatterTest extends \PHPUnit_Framework_TestCase
/**
* @return array
*/
public function dataProviderForExcelDateTest()
public function dataProviderForTestExcelDate()
{
return [
[ CellValueFormatter::CELL_TYPE_NUMERIC, 42429, '2016-02-29 00:00:00' ],
[ CellValueFormatter::CELL_TYPE_NUMERIC, '146098', '2299-12-31 00:00:00' ],
[ CellValueFormatter::CELL_TYPE_NUMERIC, -700, null ],
[ CellValueFormatter::CELL_TYPE_NUMERIC, 0, null ],
[ CellValueFormatter::CELL_TYPE_NUMERIC, 0.5, null ],
[ CellValueFormatter::CELL_TYPE_NUMERIC, 1, '1900-01-01 00:00:00' ],
[ CellValueFormatter::CELL_TYPE_NUMERIC, 59.999988425926, '1900-02-28 23:59:59' ],
[ CellValueFormatter::CELL_TYPE_NUMERIC, 60.458333333333, '1900-02-28 11:00:00' ],
[CellValueFormatter::CELL_TYPE_NUMERIC, 42429, '2016-02-29 00:00:00'],
[CellValueFormatter::CELL_TYPE_NUMERIC, '146098', '2299-12-31 00:00:00'],
[CellValueFormatter::CELL_TYPE_NUMERIC, -700, null],
[CellValueFormatter::CELL_TYPE_NUMERIC, 0, null],
[CellValueFormatter::CELL_TYPE_NUMERIC, 0.5, null],
[CellValueFormatter::CELL_TYPE_NUMERIC, 1, '1900-01-01 00:00:00'],
[CellValueFormatter::CELL_TYPE_NUMERIC, 59.999988425926, '1900-02-28 23:59:59'],
[CellValueFormatter::CELL_TYPE_NUMERIC, 60.458333333333, '1900-02-28 11:00:00'],
];
}

/**
* @dataProvider dataProviderForExcelDateTest
* @dataProvider dataProviderForTestExcelDate
*
* @param string $cellType
* @param int|float|string $nodeValue
* @param string|null $expectedDateAsString
* @return void
*/
public function testExcelDate($cellType, $nodeValue, $expectedDateAsString)
Expand All @@ -39,16 +42,16 @@ public function testExcelDate($cellType, $nodeValue, $expectedDateAsString)
->expects($this->atLeastOnce())
->method('item')
->with(0)
->will($this->returnValue((object)[ 'nodeValue' => $nodeValue ]));
->will($this->returnValue((object)['nodeValue' => $nodeValue]));

$nodeMock = $this->getMockBuilder('DOMElement')->disableOriginalConstructor()->getMock();

$nodeMock
->expects($this->atLeastOnce())
->method('getAttribute')
->will($this->returnValueMap([
[ CellValueFormatter::XML_ATTRIBUTE_TYPE, $cellType ],
[ CellValueFormatter::XML_ATTRIBUTE_STYLE_ID, 123 ],
[CellValueFormatter::XML_ATTRIBUTE_TYPE, $cellType],
[CellValueFormatter::XML_ATTRIBUTE_STYLE_ID, 123],
]));

$nodeMock
Expand All @@ -57,17 +60,16 @@ public function testExcelDate($cellType, $nodeValue, $expectedDateAsString)
->with(CellValueFormatter::XML_NODE_VALUE)
->will($this->returnValue($nodeListMock));

$styleHelperMock = $this->getMockBuilder(__NAMESPACE__ . '\StyleHelper')->disableOriginalConstructor()->getMock();
$styleHelperMock = $this->getMockBuilder('Box\Spout\Reader\XLSX\Helper\StyleHelper')->disableOriginalConstructor()->getMock();

$styleHelperMock
->expects($this->once())
->method('shouldFormatNumericValueAsDate')
->with(123)
->will($this->returnValue(true));

$instance = new CellValueFormatter(null, $styleHelperMock);

$result = $instance->extractAndFormatNodeValue($nodeMock);
$formatter = new CellValueFormatter(null, $styleHelperMock);
$result = $formatter->extractAndFormatNodeValue($nodeMock);

if ($expectedDateAsString === null) {
$this->assertNull($result);
Expand All @@ -77,4 +79,48 @@ public function testExcelDate($cellType, $nodeValue, $expectedDateAsString)
}
}

/**
* @return array
*/
public function dataProviderForTestFormatNumericCellValueWithNumbers()
{
return [
[42, 42, 'integer'],
[42.5, 42.5, 'double'],
[-42, -42, 'integer'],
[-42.5, -42.5, 'double'],
['42', 42, 'integer'],
['42.5', 42.5, 'double'],
[865640023012945, 865640023012945, 'integer'],
['865640023012945', 865640023012945, 'integer'],
[865640023012945.5, 865640023012945.5, 'double'],
['865640023012945.5', 865640023012945.5, 'double'],
[PHP_INT_MAX, PHP_INT_MAX, 'integer'],
[~PHP_INT_MAX + 1, ~PHP_INT_MAX + 1, 'integer'], // ~PHP_INT_MAX === PHP_INT_MIN, PHP_INT_MIN being PHP7+
[PHP_INT_MAX + 1, PHP_INT_MAX + 1, 'double'],
];
}

/**
* @dataProvider dataProviderForTestFormatNumericCellValueWithNumbers
*
* @param int|float|string $value
* @param int|float $expectedFormattedValue
* @param string $expectedType
* @return void
*/
public function testFormatNumericCellValueWithNumbers($value, $expectedFormattedValue, $expectedType)
{
$styleHelperMock = $this->getMockBuilder('Box\Spout\Reader\XLSX\Helper\StyleHelper')->disableOriginalConstructor()->getMock();
$styleHelperMock
->expects($this->once())
->method('shouldFormatNumericValueAsDate')
->will($this->returnValue(false));

$formatter = new CellValueFormatter(null, $styleHelperMock);
$formattedValue = \ReflectionHelper::callMethodOnObject($formatter, 'formatNumericCellValue', $value, 0);

$this->assertEquals($expectedFormattedValue, $formattedValue);
$this->assertEquals($expectedType, gettype($formattedValue));
}
}

0 comments on commit 2093724

Please sign in to comment.