diff --git a/src/Spout/Reader/ODS/Helper/CellValueFormatter.php b/src/Spout/Reader/ODS/Helper/CellValueFormatter.php index 0a2f18d3..bd215762 100644 --- a/src/Spout/Reader/ODS/Helper/CellValueFormatter.php +++ b/src/Spout/Reader/ODS/Helper/CellValueFormatter.php @@ -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 @@ -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; } diff --git a/src/Spout/Reader/XLSX/Helper/CellValueFormatter.php b/src/Spout/Reader/XLSX/Helper/CellValueFormatter.php index 269168dd..c6c40f41 100644 --- a/src/Spout/Reader/XLSX/Helper/CellValueFormatter.php +++ b/src/Spout/Reader/XLSX/Helper/CellValueFormatter.php @@ -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); } } diff --git a/tests/Spout/Reader/XLSX/Helper/CellValueFormatterTest.php b/tests/Spout/Reader/XLSX/Helper/CellValueFormatterTest.php index b7eca715..68ad980e 100644 --- a/tests/Spout/Reader/XLSX/Helper/CellValueFormatterTest.php +++ b/tests/Spout/Reader/XLSX/Helper/CellValueFormatterTest.php @@ -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) @@ -39,7 +42,7 @@ 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(); @@ -47,8 +50,8 @@ public function testExcelDate($cellType, $nodeValue, $expectedDateAsString) ->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 @@ -57,7 +60,7 @@ 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()) @@ -65,9 +68,8 @@ public function testExcelDate($cellType, $nodeValue, $expectedDateAsString) ->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); @@ -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)); + } }