*/ public function dataProviderForTestExcelDate() { return [ // use 1904 dates, node value, expected date as string // 1900 calendar [false, 3687.4207639, '1910-02-03 10:05:54'], [false, 2.5000000, '1900-01-01 12:00:00'], [false, 2958465.9999884, '9999-12-31 23:59:59'], [false, 2958465.9999885, null], [false, -2337.999989, '1893-08-05 00:00:01'], [false, -693593, '0001-01-01 00:00:00'], [false, -693593.0000001, null], [false, 0, '1899-12-30 00:00:00'], [false, 0.25, '1899-12-30 06:00:00'], [false, 0.5, '1899-12-30 12:00:00'], [false, 0.75, '1899-12-30 18:00:00'], [false, 0.99999, '1899-12-30 23:59:59'], [false, 1, '1899-12-31 00:00:00'], [false, '3687.4207639', '1910-02-03 10:05:54'], // 1904 calendar [true, 2225.4207639, '1910-02-03 10:05:54'], [true, 2.5000000, '1904-01-03 12:00:00'], [true, 2957003.9999884, '9999-12-31 23:59:59'], [true, 2957003.9999885, null], [true, -3799.999989, '1893-08-05 00:00:01'], [true, -695055, '0001-01-01 00:00:00'], [true, -695055.0000001, null], [true, 0, '1904-01-01 00:00:00'], [true, 0.25, '1904-01-01 06:00:00'], [true, 0.5, '1904-01-01 12:00:00'], [true, 0.75, '1904-01-01 18:00:00'], [true, 0.99999, '1904-01-01 23:59:59'], [true, 1, '1904-01-02 00:00:00'], [true, '2225.4207639', '1910-02-03 10:05:54'], ]; } /** * @dataProvider dataProviderForTestExcelDate * * @param bool $shouldUse1904Dates * @param int|float|string $nodeValue * @param string|null $expectedDateAsString * @return void */ public function testExcelDate($shouldUse1904Dates, $nodeValue, $expectedDateAsString) { $nodeListMock = $this->createMock(\DOMNodeList::class); $nodeListMock ->expects($this->atLeastOnce()) ->method('item') ->with(0) ->will($this->returnValue((object) ['nodeValue' => $nodeValue])); /** @var \DOMElement&MockObject $nodeMock */ $nodeMock = $this->createMock(\DOMElement::class); $nodeMock ->expects($this->atLeastOnce()) ->method('getAttribute') ->will($this->returnValueMap([ [CellValueFormatter::XML_ATTRIBUTE_TYPE, CellValueFormatter::CELL_TYPE_NUMERIC], [CellValueFormatter::XML_ATTRIBUTE_STYLE_ID, 123], ])); $nodeMock ->expects($this->atLeastOnce()) ->method('getElementsByTagName') ->with(CellValueFormatter::XML_NODE_VALUE) ->will($this->returnValue($nodeListMock)); /** @var StyleManager&MockObject $styleManagerMock */ $styleManagerMock = $this->createMock(StyleManager::class); $styleManagerMock ->expects($this->once()) ->method('shouldFormatNumericValueAsDate') ->with(123) ->will($this->returnValue(true)); /** @var SharedStringsManager $sharedStringManager */ $sharedStringManager = $this->createMock(SharedStringsManager::class); $formatter = new CellValueFormatter($sharedStringManager, $styleManagerMock, false, $shouldUse1904Dates, new Escaper\XLSX()); try { $result = $formatter->extractAndFormatNodeValue($nodeMock); if ($expectedDateAsString === null) { $this->fail('An exception should have been thrown'); } else { $this->assertInstanceOf(\DateTime::class, $result); /** @var \DateTime $datetime */ $datetime = $result; $this->assertSame($expectedDateAsString, $datetime->format('Y-m-d H:i:s')); } } catch (InvalidValueException $exception) { // do nothing } } /** * @return array */ public function dataProviderForTestFormatNumericCellValueWithNumbers() { // Some test values exceed PHP_INT_MAX on 32-bit PHP. They are // therefore converted to as doubles automatically by PHP. $expectedBigNumberType = (PHP_INT_SIZE < 8 ? 'double' : 'integer'); 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, $expectedBigNumberType], ['865640023012945', 865640023012945, $expectedBigNumberType], [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) { /** @var StyleManager&MockObject $styleManagerMock */ $styleManagerMock = $this->createMock(StyleManager::class); $styleManagerMock ->expects($this->once()) ->method('shouldFormatNumericValueAsDate') ->will($this->returnValue(false)); /** @var SharedStringsManager $sharedStringManager */ $sharedStringManager = $this->createMock(SharedStringsManager::class); $formatter = new CellValueFormatter($sharedStringManager, $styleManagerMock, false, false, new Escaper\XLSX()); $formattedValue = \ReflectionHelper::callMethodOnObject($formatter, 'formatNumericCellValue', $value, 0); $this->assertEquals($expectedFormattedValue, $formattedValue); $this->assertEquals($expectedType, gettype($formattedValue)); } /** * @return array */ public function dataProviderForTestFormatStringCellValue() { return [ ['A', 'A'], [' A ', ' A '], ["\n\tA\n\t", "\n\tA\n\t"], [' ', ' '], ]; } /** * @dataProvider dataProviderForTestFormatStringCellValue * * @param string $value * @param string $expectedFormattedValue * @return void */ public function testFormatInlineStringCellValue($value, $expectedFormattedValue) { $nodeListMock = $this->createMock(\DOMNodeList::class); $nodeListMock ->expects($this->atLeastOnce()) ->method('count') ->willReturn(1); $nodeListMock ->expects($this->atLeastOnce()) ->method('item') ->with(0) ->willReturn((object) ['nodeValue' => $value]); $nodeMock = $this->createMock(\DOMElement::class); $nodeMock ->expects($this->atLeastOnce()) ->method('getElementsByTagName') ->with(CellValueFormatter::XML_NODE_INLINE_STRING_VALUE) ->willReturn($nodeListMock); /** @var SharedStringsManager $sharedStringManager */ $sharedStringManager = $this->createMock(SharedStringsManager::class); /** @var StyleManager $styleManager */ $styleManager = $this->createMock(StyleManager::class); $formatter = new CellValueFormatter($sharedStringManager, $styleManager, false, false, new Escaper\XLSX()); $formattedValue = \ReflectionHelper::callMethodOnObject($formatter, 'formatInlineStringCellValue', $nodeMock); $this->assertEquals($expectedFormattedValue, $formattedValue); } }