PageRenderTime 30ms CodeModel.GetById 21ms RepoModel.GetById 0ms app.codeStats 0ms

/typo3/sysext/extbase/Tests/Unit/Property/TypeConverter/DateTimeConverterTest.php

https://github.com/TYPO3/TYPO3.CMS
PHP | 392 lines | 253 code | 37 blank | 102 comment | 10 complexity | 946e14a59ec2b8abed741b9f42b2a283 MD5 | raw file
  1. <?php
  2. declare(strict_types=1);
  3. /*
  4. * This file is part of the TYPO3 CMS project.
  5. *
  6. * It is free software; you can redistribute it and/or modify it under
  7. * the terms of the GNU General Public License, either version 2
  8. * of the License, or any later version.
  9. *
  10. * For the full copyright and license information, please read the
  11. * LICENSE.txt file that was distributed with this source code.
  12. *
  13. * The TYPO3 project - inspiring people to share!
  14. */
  15. namespace TYPO3\CMS\Extbase\Tests\Unit\Property\TypeConverter;
  16. use TYPO3\CMS\Extbase\Error\Error;
  17. use TYPO3\CMS\Extbase\Property\Exception\TypeConverterException;
  18. use TYPO3\CMS\Extbase\Property\PropertyMappingConfiguration;
  19. use TYPO3\CMS\Extbase\Property\PropertyMappingConfigurationInterface;
  20. use TYPO3\CMS\Extbase\Property\TypeConverter\DateTimeConverter;
  21. use TYPO3\CMS\Extbase\Tests\Unit\Property\TypeConverter\Fixtures\DateTimeSubFixture;
  22. use TYPO3\TestingFramework\Core\Unit\UnitTestCase;
  23. /**
  24. * Test case
  25. */
  26. class DateTimeConverterTest extends UnitTestCase
  27. {
  28. protected DateTimeConverter $converter;
  29. protected function setUp(): void
  30. {
  31. parent::setUp();
  32. $this->converter = new DateTimeConverter();
  33. }
  34. /** String to DateTime testcases **/
  35. /**
  36. * @test
  37. */
  38. public function convertFromReturnsErrorIfGivenStringCantBeConverted(): void
  39. {
  40. $error = $this->converter->convertFrom('1980-12-13', 'DateTime');
  41. self::assertInstanceOf(Error::class, $error);
  42. }
  43. /**
  44. * @test
  45. */
  46. public function convertFromProperlyConvertsStringWithDefaultDateFormat(): void
  47. {
  48. $expectedResult = '1980-12-13T20:15:07+01:23';
  49. $date = $this->converter->convertFrom($expectedResult, 'DateTime');
  50. $actualResult = $date->format('Y-m-d\\TH:i:sP');
  51. self::assertSame($expectedResult, $actualResult);
  52. }
  53. /**
  54. * @test
  55. */
  56. public function convertFromUsesDefaultDateFormatIfItIsNotConfigured(): void
  57. {
  58. $expectedResult = '1980-12-13T20:15:07+01:23';
  59. $mockMappingConfiguration = $this->createMock(PropertyMappingConfigurationInterface::class);
  60. $mockMappingConfiguration
  61. ->expects(self::atLeastOnce())
  62. ->method('getConfigurationValue')
  63. ->with(DateTimeConverter::class, DateTimeConverter::CONFIGURATION_DATE_FORMAT)
  64. ->willReturn(null);
  65. $date = $this->converter->convertFrom($expectedResult, 'DateTime', [], $mockMappingConfiguration);
  66. $actualResult = $date->format(DateTimeConverter::DEFAULT_DATE_FORMAT);
  67. self::assertSame($expectedResult, $actualResult);
  68. }
  69. /**
  70. * @test
  71. */
  72. public function convertFromEmptyStringReturnsNull(): void
  73. {
  74. $date = $this->converter->convertFrom('', 'DateTime', [], null);
  75. self::assertNull($date);
  76. }
  77. /**
  78. * @return array
  79. * @see convertFromStringTests()
  80. */
  81. public function convertFromStringDataProvider(): array
  82. {
  83. return [
  84. ['1308174051', '', false],
  85. ['13-12-1980', 'd.m.Y', false],
  86. ['1308174051', 'Y-m-d', false],
  87. ['12:13', 'H:i', true],
  88. ['13.12.1980', 'd.m.Y', true],
  89. ['2005-08-15T15:52:01+00:00', null, true],
  90. ['2005-08-15T15:52:01+00:00', \DateTimeInterface::ATOM, true],
  91. ['1308174051', 'U', true],
  92. ];
  93. }
  94. /**
  95. * @param string $source the string to be converted
  96. * @param string|null $dateFormat the expected date format
  97. * @param bool $isValid TRUE if the conversion is expected to be successful, otherwise FALSE
  98. * @test
  99. * @dataProvider convertFromStringDataProvider
  100. */
  101. public function convertFromStringTests(string $source, ?string $dateFormat, bool $isValid): void
  102. {
  103. if ($dateFormat !== null) {
  104. $mockMappingConfiguration = $this->createMock(PropertyMappingConfigurationInterface::class);
  105. $mockMappingConfiguration
  106. ->expects(self::atLeastOnce())
  107. ->method('getConfigurationValue')
  108. ->with(DateTimeConverter::class, DateTimeConverter::CONFIGURATION_DATE_FORMAT)
  109. ->willReturn($dateFormat);
  110. } else {
  111. $mockMappingConfiguration = null;
  112. }
  113. $date = $this->converter->convertFrom($source, 'DateTime', [], $mockMappingConfiguration);
  114. if ($isValid !== true) {
  115. self::assertInstanceOf(Error::class, $date);
  116. return;
  117. }
  118. self::assertInstanceOf('DateTime', $date);
  119. if ($dateFormat === null) {
  120. $dateFormat = DateTimeConverter::DEFAULT_DATE_FORMAT;
  121. }
  122. self::assertSame($source, $date->format($dateFormat));
  123. }
  124. /**
  125. * @return array
  126. * @see convertFromIntegerOrDigitStringWithoutConfigurationTests()
  127. * @see convertFromIntegerOrDigitStringInArrayWithoutConfigurationTests()
  128. */
  129. public function convertFromIntegerOrDigitStringsWithoutConfigurationDataProvider(): array
  130. {
  131. return [
  132. ['1308174051'],
  133. [1308174051],
  134. ];
  135. }
  136. /**
  137. * @test
  138. * @dataProvider convertFromIntegerOrDigitStringsWithoutConfigurationDataProvider
  139. */
  140. public function convertFromIntegerOrDigitStringWithoutConfigurationTests(string|int $source): void
  141. {
  142. $date = $this->converter->convertFrom($source, 'DateTime', [], null);
  143. self::assertInstanceOf('DateTime', $date);
  144. self::assertSame((string)$source, $date->format('U'));
  145. }
  146. /** Array to DateTime testcases **/
  147. /**
  148. * @test
  149. * @dataProvider convertFromIntegerOrDigitStringsWithoutConfigurationDataProvider
  150. */
  151. public function convertFromIntegerOrDigitStringInArrayWithoutConfigurationTests(string|int $source): void
  152. {
  153. $date = $this->converter->convertFrom(['date' => $source], 'DateTime', [], null);
  154. self::assertInstanceOf('DateTime', $date);
  155. self::assertSame((string)$source, $date->format('U'));
  156. }
  157. /**
  158. * @test
  159. */
  160. public function convertFromReturnsErrorIfGivenArrayCantBeConverted(): void
  161. {
  162. $error = $this->converter->convertFrom(['date' => '1980-12-13'], 'DateTime');
  163. self::assertInstanceOf(Error::class, $error);
  164. }
  165. /**
  166. * @test
  167. */
  168. public function convertFromThrowsExceptionIfGivenArrayDoesNotSpecifyTheDate(): void
  169. {
  170. $this->expectException(TypeConverterException::class);
  171. $this->expectExceptionCode(1308003914);
  172. $this->converter->convertFrom(['hour' => '12', 'minute' => '30'], 'DateTime');
  173. }
  174. /**
  175. * @test
  176. */
  177. public function convertFromProperlyConvertsArrayWithDefaultDateFormat(): void
  178. {
  179. $expectedResult = '1980-12-13T20:15:07+01:23';
  180. $date = $this->converter->convertFrom(['date' => $expectedResult], 'DateTime');
  181. $actualResult = $date->format('Y-m-d\\TH:i:sP');
  182. self::assertSame($expectedResult, $actualResult);
  183. }
  184. /**
  185. * @return array
  186. * @see convertFromThrowsExceptionIfDatePartKeysHaveInvalidValuesSpecified
  187. */
  188. public function invalidDatePartKeyValuesDataProvider(): array
  189. {
  190. return [
  191. [['day' => '13.0', 'month' => '10', 'year' => '2010']],
  192. [['day' => '13', 'month' => '10.0', 'year' => '2010']],
  193. [['day' => '13', 'month' => '10', 'year' => '2010.0']],
  194. [['day' => '-13', 'month' => '10', 'year' => '2010']],
  195. [['day' => '13', 'month' => '-10', 'year' => '2010']],
  196. [['day' => '13', 'month' => '10', 'year' => '-2010']],
  197. ];
  198. }
  199. /**
  200. * @test
  201. * @dataProvider invalidDatePartKeyValuesDataProvider
  202. */
  203. public function convertFromThrowsExceptionIfDatePartKeysHaveInvalidValuesSpecified($source): void
  204. {
  205. $this->expectException(TypeConverterException::class);
  206. $this->expectExceptionCode(1308003914);
  207. $this->converter->convertFrom($source, 'DateTime');
  208. }
  209. /**
  210. * @test
  211. */
  212. public function convertFromProperlyConvertsArrayWithDateAsArray(): void
  213. {
  214. $source = ['day' => '13', 'month' => '10', 'year' => '2010'];
  215. $mappingConfiguration = new PropertyMappingConfiguration();
  216. $mappingConfiguration->setTypeConverterOption(
  217. DateTimeConverter::class,
  218. DateTimeConverter::CONFIGURATION_DATE_FORMAT,
  219. 'Y-m-d'
  220. );
  221. $date = $this->converter->convertFrom($source, 'DateTime', [], $mappingConfiguration);
  222. $actualResult = $date->format('Y-m-d');
  223. self::assertSame('2010-10-13', $actualResult);
  224. }
  225. /**
  226. * @test
  227. */
  228. public function convertFromAllowsToOverrideTheTime(): void
  229. {
  230. $source = [
  231. 'date' => '2011-06-16',
  232. 'dateFormat' => 'Y-m-d',
  233. 'hour' => '12',
  234. 'minute' => '30',
  235. 'second' => '59',
  236. ];
  237. $date = $this->converter->convertFrom($source, 'DateTime');
  238. self::assertSame('2011-06-16', $date->format('Y-m-d'));
  239. self::assertSame('12', $date->format('H'));
  240. self::assertSame('30', $date->format('i'));
  241. self::assertSame('59', $date->format('s'));
  242. }
  243. /**
  244. * @test
  245. */
  246. public function convertFromAllowsToOverrideTheTimezone(): void
  247. {
  248. $source = [
  249. 'date' => '2011-06-16 12:30:59',
  250. 'dateFormat' => 'Y-m-d H:i:s',
  251. 'timezone' => 'Atlantic/Reykjavik',
  252. ];
  253. $date = $this->converter->convertFrom($source, 'DateTime');
  254. self::assertSame('2011-06-16', $date->format('Y-m-d'));
  255. self::assertSame('12', $date->format('H'));
  256. self::assertSame('30', $date->format('i'));
  257. self::assertSame('59', $date->format('s'));
  258. self::assertSame('Atlantic/Reykjavik', $date->getTimezone()->getName());
  259. }
  260. /**
  261. * @test
  262. */
  263. public function convertFromThrowsExceptionIfSpecifiedTimezoneIsInvalid(): void
  264. {
  265. $this->expectException(TypeConverterException::class);
  266. $this->expectExceptionCode(1308240974);
  267. $source = [
  268. 'date' => '2011-06-16',
  269. 'dateFormat' => 'Y-m-d',
  270. 'timezone' => 'Invalid/Timezone',
  271. ];
  272. $this->converter->convertFrom($source, 'DateTime');
  273. }
  274. /**
  275. * @test
  276. */
  277. public function convertFromArrayThrowsExceptionForEmptyArray(): void
  278. {
  279. $this->expectException(TypeConverterException::class);
  280. $this->expectExceptionCode(1308003914);
  281. $this->converter->convertFrom([], 'DateTime', [], null);
  282. }
  283. /**
  284. * @test
  285. */
  286. public function convertFromArrayReturnsNullForEmptyDate(): void
  287. {
  288. self::assertNull($this->converter->convertFrom(['date' => ''], 'DateTime', [], null));
  289. }
  290. /**
  291. * @return array
  292. * @see convertFromArrayTests()
  293. */
  294. public function convertFromArrayDataProvider(): array
  295. {
  296. return [
  297. [['date' => '2005-08-15T15:52:01+01:00'], true, '2005-08-15T15:52:01+01:00'],
  298. [['date' => '1308174051', 'dateFormat' => ''], false, null],
  299. [['date' => '13-12-1980', 'dateFormat' => 'd.m.Y'], false, null],
  300. [['date' => '1308174051', 'dateFormat' => 'Y-m-d'], false, null],
  301. [['date' => '12:13', 'dateFormat' => 'H:i'], true, null],
  302. [['date' => '13.12.1980', 'dateFormat' => 'd.m.Y'], true, null],
  303. [['date' => '2005-08-15T15:52:01+00:00', 'dateFormat' => ''], true, '2005-08-15T15:52:01+00:00'],
  304. [['date' => '2005-08-15T15:52:01+00:00', 'dateFormat' => \DateTimeInterface::ATOM], true, '2005-08-15T15:52:01+00:00'],
  305. [['date' => '1308174051', 'dateFormat' => 'U'], true, '2011-06-15T21:40:51+00:00'],
  306. [['date' => 1308174051, 'dateFormat' => 'U'], true, '2011-06-15T21:40:51+00:00'],
  307. [['date' => -1308174051, 'dateFormat' => 'U'], true, '1928-07-19T02:19:09+00:00'],
  308. ];
  309. }
  310. /**
  311. * @param array $source the array to be converted
  312. * @param bool $isValid TRUE if the conversion is expected to be successful, otherwise FALSE
  313. * @param string|null $expectedResult
  314. * @test
  315. * @dataProvider convertFromArrayDataProvider
  316. */
  317. public function convertFromArrayTests(array $source, $isValid, ?string $expectedResult): void
  318. {
  319. $dateFormat = isset($source['dateFormat']) && $source['dateFormat'] !== '' ? $source['dateFormat'] : null;
  320. if ($dateFormat !== null) {
  321. $mockMappingConfiguration = $this->createMock(PropertyMappingConfigurationInterface::class);
  322. $mockMappingConfiguration
  323. ->expects(self::atLeastOnce())
  324. ->method('getConfigurationValue')
  325. ->with(DateTimeConverter::class, DateTimeConverter::CONFIGURATION_DATE_FORMAT)
  326. ->willReturn($dateFormat);
  327. } else {
  328. $mockMappingConfiguration = null;
  329. }
  330. $date = $this->converter->convertFrom($source, 'DateTime', [], $mockMappingConfiguration);
  331. if ($isValid !== true) {
  332. self::assertInstanceOf(Error::class, $date);
  333. return;
  334. }
  335. self::assertInstanceOf('DateTime', $date);
  336. if ($dateFormat === null) {
  337. $dateFormat = DateTimeConverter::DEFAULT_DATE_FORMAT;
  338. }
  339. $dateAsString = isset($source['date']) ? (string)$source['date'] : '';
  340. self::assertSame($dateAsString, $date->format($dateFormat));
  341. if ($expectedResult !== null) {
  342. self::assertSame($expectedResult, $date->format('c'));
  343. }
  344. }
  345. /**
  346. * @test
  347. */
  348. public function convertFromSupportsDateTimeSubClasses(): void
  349. {
  350. $className = DateTimeSubFixture::class;
  351. $date = $this->converter->convertFrom('2005-08-15T15:52:01+00:00', $className);
  352. self::assertInstanceOf($className, $date);
  353. self::assertSame('Bar', $date->foo());
  354. }
  355. }