diff --git a/Build/phpstan/phpstan-baseline.neon b/Build/phpstan/phpstan-baseline.neon index 9f4c1a7c39d455c001f84297784f3e538efdbb19..3c487458229d2bd62d9eaee9a1c5b629f5454c54 100644 --- a/Build/phpstan/phpstan-baseline.neon +++ b/Build/phpstan/phpstan-baseline.neon @@ -1815,16 +1815,6 @@ parameters: count: 1 path: ../../typo3/sysext/extbase/Tests/Unit/Mvc/View/JsonViewTest.php - - - message: "#^Call to static method PHPUnit\\\\Framework\\\\Assert\\:\\:assertNull\\(\\) with DateTime&PHPUnit\\\\Framework\\\\MockObject\\\\MockObject&TYPO3\\\\TestingFramework\\\\Core\\\\AccessibleObjectInterface will always evaluate to false\\.$#" - count: 1 - path: ../../typo3/sysext/extbase/Tests/Unit/Persistence/Generic/Mapper/DataMapperTest.php - - - - message: "#^Parameter \\#2 \\$identifier of method TYPO3\\\\CMS\\\\Extbase\\\\Persistence\\\\Generic\\\\Session\\:\\:registerObject\\(\\) expects string, int given\\.$#" - count: 1 - path: ../../typo3/sysext/extbase/Tests/Unit/Persistence/Generic/Mapper/DataMapperTest.php - - message: "#^Call to static method PHPUnit\\\\Framework\\\\Assert\\:\\:assertNull\\(\\) with object will always evaluate to false\\.$#" count: 1 diff --git a/composer.json b/composer.json index 5a49c07550ad48bbfb8568febd001d202b81240a..721dc1968f132368a2f7a56f2f8c96825b28a217 100644 --- a/composer.json +++ b/composer.json @@ -295,6 +295,7 @@ "TYPO3\\CMS\\Recycler\\Tests\\": "typo3/sysext/recycler/Tests/", "TYPO3\\CMS\\T3editor\\Tests\\": "typo3/sysext/t3editor/Tests/", "TYPO3\\CMS\\Tstemplate\\Tests\\": "typo3/sysext/tstemplate/Tests/", + "TYPO3Tests\\TestDataMapper\\": "typo3/sysext/extbase/Tests/Functional/Fixtures/Extensions/test_data_mapper/Classes/", "TYPO3Tests\\TestFluidTemplate\\": "typo3/sysext/frontend/Tests/Functional/Fixtures/Extensions/test_fluid_template/Classes/", "TYPO3Tests\\TestLogger\\": "typo3/sysext/core/Tests/Functional/Fixtures/Extensions/test_logger/Classes/", "TYPO3Tests\\TestTyposcriptAstFunctionEvent\\": "typo3/sysext/core/Tests/Functional/Fixtures/Extensions/test_typoscript_ast_function_event/Classes/" diff --git a/typo3/sysext/extbase/Tests/Unit/Persistence/Fixture/Model/CustomDateTime.php b/typo3/sysext/extbase/Tests/Functional/Fixtures/Extensions/test_data_mapper/Classes/Domain/Model/CustomDateTime.php similarity index 88% rename from typo3/sysext/extbase/Tests/Unit/Persistence/Fixture/Model/CustomDateTime.php rename to typo3/sysext/extbase/Tests/Functional/Fixtures/Extensions/test_data_mapper/Classes/Domain/Model/CustomDateTime.php index 03029a2c14aadbeedd66156e434f7fc701236b99..644cbd61bf998feb762c9dc0a0f06eabfd97725a 100644 --- a/typo3/sysext/extbase/Tests/Unit/Persistence/Fixture/Model/CustomDateTime.php +++ b/typo3/sysext/extbase/Tests/Functional/Fixtures/Extensions/test_data_mapper/Classes/Domain/Model/CustomDateTime.php @@ -15,7 +15,7 @@ declare(strict_types=1); * The TYPO3 project - inspiring people to share! */ -namespace TYPO3\CMS\Extbase\Tests\Unit\Persistence\Fixture\Model; +namespace TYPO3Tests\TestDataMapper\Domain\Model; class CustomDateTime extends \DateTime { diff --git a/typo3/sysext/extbase/Tests/Functional/Fixtures/Extensions/test_data_mapper/Classes/Domain/Model/Example.php b/typo3/sysext/extbase/Tests/Functional/Fixtures/Extensions/test_data_mapper/Classes/Domain/Model/Example.php new file mode 100644 index 0000000000000000000000000000000000000000..6a7449a4c89bf351d334593676ac4e784610b9f4 --- /dev/null +++ b/typo3/sysext/extbase/Tests/Functional/Fixtures/Extensions/test_data_mapper/Classes/Domain/Model/Example.php @@ -0,0 +1,124 @@ +<?php + +declare(strict_types=1); + +/* + * This file is part of the TYPO3 CMS project. + * + * It is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License, either version 2 + * of the License, or any later version. + * + * For the full copyright and license information, please read the + * LICENSE.txt file that was distributed with this source code. + * + * The TYPO3 project - inspiring people to share! + */ + +namespace TYPO3Tests\TestDataMapper\Domain\Model; + +use TYPO3\CMS\Extbase\DomainObject\AbstractEntity; + +class Example extends AbstractEntity +{ + protected string $firstProperty = ''; + protected int $secondProperty = 0; + protected float $thirdProperty = 0.0; + protected bool $fourthProperty = true; + protected string $uninitializedStringProperty; + protected ?\DateTime $uninitializedDateTimeProperty; + protected \DateTime $uninitializedMandatoryDateTimeProperty; + protected ?\DateTime $initializedDateTimeProperty = null; + protected ?CustomDateTime $customDateTime = null; + public $unknownType; + + public function getFirstProperty(): string + { + return $this->firstProperty; + } + + public function setFirstProperty(string $firstProperty): void + { + $this->firstProperty = $firstProperty; + } + + public function getSecondProperty(): int + { + return $this->secondProperty; + } + + public function setSecondProperty(int $secondProperty): void + { + $this->secondProperty = $secondProperty; + } + + public function getThirdProperty(): float + { + return $this->thirdProperty; + } + + public function setThirdProperty(float $thirdProperty): void + { + $this->thirdProperty = $thirdProperty; + } + + public function isFourthProperty(): bool + { + return $this->fourthProperty; + } + + public function setFourthProperty(bool $fourthProperty): void + { + $this->fourthProperty = $fourthProperty; + } + + public function getUninitializedStringProperty(): string + { + return $this->uninitializedStringProperty; + } + + public function setUninitializedStringProperty(string $uninitializedStringProperty): void + { + $this->uninitializedStringProperty = $uninitializedStringProperty; + } + + public function getUninitializedDateTimeProperty(): ?\DateTime + { + return $this->uninitializedDateTimeProperty; + } + + public function setUninitializedDateTimeProperty(?\DateTime $uninitializedDateTimeProperty): void + { + $this->uninitializedDateTimeProperty = $uninitializedDateTimeProperty; + } + + public function getUninitializedMandatoryDateTimeProperty(): \DateTime + { + return $this->uninitializedMandatoryDateTimeProperty; + } + + public function setUninitializedMandatoryDateTimeProperty(\DateTime $uninitializedMandatoryDateTimeProperty): void + { + $this->uninitializedMandatoryDateTimeProperty = $uninitializedMandatoryDateTimeProperty; + } + + public function getInitializedDateTimeProperty(): ?\DateTime + { + return $this->initializedDateTimeProperty; + } + + public function setInitializedDateTimeProperty(?\DateTime $initializedDateTimeProperty): void + { + $this->initializedDateTimeProperty = $initializedDateTimeProperty; + } + + public function getCustomDateTime(): ?CustomDateTime + { + return $this->customDateTime; + } + + public function setCustomDateTime(?CustomDateTime $customDateTime): void + { + $this->customDateTime = $customDateTime; + } +} diff --git a/typo3/sysext/extbase/Tests/Unit/Persistence/Generic/Mapper/Fixture/DummyChildEntity.php b/typo3/sysext/extbase/Tests/Functional/Fixtures/Extensions/test_data_mapper/Classes/Domain/Model/TraversableDomainObjectExample.php similarity index 51% rename from typo3/sysext/extbase/Tests/Unit/Persistence/Generic/Mapper/Fixture/DummyChildEntity.php rename to typo3/sysext/extbase/Tests/Functional/Fixtures/Extensions/test_data_mapper/Classes/Domain/Model/TraversableDomainObjectExample.php index 94de351563cb06828be112b444f29738b50a2836..782292635b2aa4cc560a880c482ff700818153d6 100644 --- a/typo3/sysext/extbase/Tests/Unit/Persistence/Generic/Mapper/Fixture/DummyChildEntity.php +++ b/typo3/sysext/extbase/Tests/Functional/Fixtures/Extensions/test_data_mapper/Classes/Domain/Model/TraversableDomainObjectExample.php @@ -15,13 +15,37 @@ declare(strict_types=1); * The TYPO3 project - inspiring people to share! */ -namespace TYPO3\CMS\Extbase\Tests\Unit\Persistence\Generic\Mapper\Fixture; +namespace TYPO3Tests\TestDataMapper\Domain\Model; use TYPO3\CMS\Extbase\DomainObject\AbstractEntity; -/** - * Fixture - */ -class DummyChildEntity extends AbstractEntity +class TraversableDomainObjectExample extends AbstractEntity implements \Iterator { + public function getUid(): ?int + { + return 1; + } + + public function current(): mixed + { + return []; + } + + public function next(): void + { + } + + public function key(): mixed + { + return 1; + } + + public function valid(): bool + { + return true; + } + + public function rewind(): void + { + } } diff --git a/typo3/sysext/extbase/Tests/Functional/Fixtures/Extensions/test_data_mapper/Configuration/TCA/tx_testdatamapper_domain_model_example.php b/typo3/sysext/extbase/Tests/Functional/Fixtures/Extensions/test_data_mapper/Configuration/TCA/tx_testdatamapper_domain_model_example.php new file mode 100644 index 0000000000000000000000000000000000000000..e2123dada3bf2ac161e183ddef2c1136b76c4c2d --- /dev/null +++ b/typo3/sysext/extbase/Tests/Functional/Fixtures/Extensions/test_data_mapper/Configuration/TCA/tx_testdatamapper_domain_model_example.php @@ -0,0 +1,58 @@ +<?php + +return [ + 'columns' => [ + 'first_property' => [ + 'config' => [ + 'type' => 'input', + ], + ], + 'second_property' => [ + 'config' => [ + 'type' => 'number', + ], + ], + 'third_property' => [ + 'config' => [ + 'type' => 'number', + 'format' => 'decimal', + ], + ], + 'fourth_property' => [ + 'config' => [ + 'type' => 'check', + ], + ], + 'uninitialized_string_property' => [ + 'config' => [ + 'type' => 'input', + ], + ], + 'uninitialized_date_time_property' => [ + 'config' => [ + 'type' => 'datetime', + ], + ], + 'uninitialized_mandatory_date_time_property' => [ + 'config' => [ + 'type' => 'datetime', + ], + ], + 'initialized_date_time_property' => [ + 'config' => [ + 'type' => 'datetime', + ], + ], + 'custom_date_time' => [ + 'config' => [ + 'type' => 'datetime', + 'dbType' => 'datetime', + ], + ], + 'unknown_type' => [ + 'config' => [ + 'type' => 'passthrough', + ], + ], + ], +]; diff --git a/typo3/sysext/extbase/Tests/Functional/Fixtures/Extensions/test_data_mapper/ext_emconf.php b/typo3/sysext/extbase/Tests/Functional/Fixtures/Extensions/test_data_mapper/ext_emconf.php new file mode 100644 index 0000000000000000000000000000000000000000..17ee481f4d391316fa552634d7efe63634f44c2e --- /dev/null +++ b/typo3/sysext/extbase/Tests/Functional/Fixtures/Extensions/test_data_mapper/ext_emconf.php @@ -0,0 +1,21 @@ +<?php + +declare(strict_types=1); + +$EM_CONF[$_EXTKEY] = [ + 'title' => 'Extension for testing DataMapper functionality.', + 'description' => 'Extension for testing DataMapper functionality.', + 'category' => 'example', + 'author' => 'TYPO3 core team', + 'author_company' => '', + 'author_email' => '', + 'state' => 'stable', + 'version' => '12.1.0', + 'constraints' => [ + 'depends' => [ + 'typo3' => '12.1.0', + ], + 'conflicts' => [], + 'suggests' => [], + ], +]; diff --git a/typo3/sysext/extbase/Tests/Functional/Persistence/Generic/Mapper/DataMapperTest.php b/typo3/sysext/extbase/Tests/Functional/Persistence/Generic/Mapper/DataMapperTest.php index 69275bdcf7f5c25e31e5495d54be334cbcba727c..7077059786aa167e5b2480183142d9b6e5dd26f5 100644 --- a/typo3/sysext/extbase/Tests/Functional/Persistence/Generic/Mapper/DataMapperTest.php +++ b/typo3/sysext/extbase/Tests/Functional/Persistence/Generic/Mapper/DataMapperTest.php @@ -17,17 +17,29 @@ declare(strict_types=1); namespace TYPO3\CMS\Extbase\Tests\Functional\Persistence\Generic\Mapper; +use ExtbaseTeam\BlogExample\Domain\Model\Blog; use ExtbaseTeam\BlogExample\Domain\Model\DateExample; use ExtbaseTeam\BlogExample\Domain\Model\DateTimeImmutableExample; +use ExtbaseTeam\BlogExample\Domain\Model\Post; use TYPO3\CMS\Core\Authentication\BackendUserAuthentication; +use TYPO3\CMS\Core\Cache\CacheManager; use TYPO3\CMS\Core\Core\SystemEnvironmentBuilder; use TYPO3\CMS\Core\Http\ServerRequest; +use TYPO3\CMS\Extbase\Persistence\Generic\Mapper\ColumnMap; +use TYPO3\CMS\Extbase\Persistence\Generic\Mapper\DataMapper; +use TYPO3\CMS\Extbase\Persistence\Generic\Mapper\Exception\UnknownPropertyTypeException; use TYPO3\CMS\Extbase\Persistence\Generic\PersistenceManager; use TYPO3\TestingFramework\Core\Functional\FunctionalTestCase; +use TYPO3Tests\TestDataMapper\Domain\Model\CustomDateTime; +use TYPO3Tests\TestDataMapper\Domain\Model\Example; +use TYPO3Tests\TestDataMapper\Domain\Model\TraversableDomainObjectExample; class DataMapperTest extends FunctionalTestCase { - protected array $testExtensionsToLoad = ['typo3/sysext/extbase/Tests/Functional/Fixtures/Extensions/blog_example']; + protected array $testExtensionsToLoad = [ + 'typo3/sysext/extbase/Tests/Functional/Fixtures/Extensions/blog_example', + 'typo3/sysext/extbase/Tests/Functional/Fixtures/Extensions/test_data_mapper', + ]; protected PersistenceManager $persistenceManager; @@ -160,4 +172,332 @@ class DataMapperTest extends FunctionalTestCase self::assertSame($date->getTimestamp(), $subject->getDatetimeImmutableDatetime()->getTimestamp()); } + + /** + * @test + */ + public function mapMapsArrayToObject(): void + { + $rows = [['uid' => 1234]]; + /** @var DataMapper $dataMapper */ + $dataMapper = $this->get(DataMapper::class); + + $mappedObjectArray = $dataMapper->map(Blog::class, $rows); + + self::assertCount(1, $mappedObjectArray); + self::assertSame(1234, $mappedObjectArray[0]->getUid()); + } + + /** + * @test + */ + public function mapMapsArrayToObjectFromPersistence(): void + { + $rows1 = [['uid' => 1234, 'title' => 'From persistence']]; + $rows2 = [['uid' => 1234, 'title' => 'Already persisted']]; + /** @var DataMapper $dataMapper */ + $dataMapper = $this->get(DataMapper::class); + + $dataMapper->map(Blog::class, $rows1); + $mappedObjectArray = $dataMapper->map(Blog::class, $rows2); + + self::assertCount(1, $mappedObjectArray); + self::assertSame(1234, $mappedObjectArray[0]->getUid()); + self::assertSame('From persistence', $mappedObjectArray[0]->getTitle()); + } + + /** + * @test + */ + public function thawPropertiesSetsPropertyValues(): void + { + $rows = [ + [ + 'uid' => '1234', + 'first_property' => 'firstValue', + 'second_property' => 1234, + 'third_property' => 1.234, + 'fourth_property' => false, + 'uninitialized_string_property' => 'foo', + 'uninitialized_date_time_property' => 0, + 'uninitialized_mandatory_date_time_property' => 0, + 'initialized_date_time_property' => 0, + ], + ]; + /** @var DataMapper $dataMapper */ + $dataMapper = $this->get(DataMapper::class); + + $mappedObjectsArray = $dataMapper->map(Example::class, $rows); + + /** @var Example $object */ + $object = $mappedObjectsArray[0]; + self::assertEquals('firstValue', $object->getFirstProperty()); + self::assertEquals(1234, $object->getSecondProperty()); + self::assertEquals(1.234, $object->getThirdProperty()); + self::assertFalse($object->isFourthProperty()); + self::assertSame('foo', $object->getUninitializedStringProperty()); + self::assertNull($object->getUninitializedDateTimeProperty()); + $reflectionProperty = new \ReflectionProperty($object, 'uninitializedMandatoryDateTimeProperty'); + self::assertFalse($reflectionProperty->isInitialized($object)); + $reflectionProperty = new \ReflectionProperty($object, 'initializedDateTimeProperty'); + self::assertTrue($reflectionProperty->isInitialized($object)); + } + + /** + * @test + */ + public function thawPropertiesThrowsExceptionOnUnknownPropertyType(): void + { + $rows = [ + [ + 'uid' => '1234', + 'unknown_type' => 'What am I?', + ], + ]; + + /** @var DataMapper $dataMapper */ + $dataMapper = $this->get(DataMapper::class); + + $this->expectException(UnknownPropertyTypeException::class); + $dataMapper->map(Example::class, $rows); + } + + /** + * @test + */ + public function fetchRelatedEagerReturnsNullForEmptyRelationHasOne(): void + { + $rows = [ + [ + 'uid' => 123, + 'blog' => '', + ], + ]; + /** @var DataMapper $dataMapper */ + $dataMapper = $this->get(DataMapper::class); + $mappedObjectsArray = $dataMapper->map(Post::class, $rows); + + self::assertNull($mappedObjectsArray[0]->getBlog()); + } + + /** + * @test + */ + public function fetchRelatedEagerReturnsEmptyArrayForEmptyRelationNotHasOne(): void + { + $rows = [ + [ + 'uid' => 123, + 'posts' => 0, + ], + ]; + /** @var DataMapper $dataMapper */ + $dataMapper = $this->get(DataMapper::class); + $mappedObjectsArray = $dataMapper->map(Blog::class, $rows); + + self::assertCount(0, $mappedObjectsArray[0]->getPosts()); + } + + /** + * @test + */ + public function mapObjectToClassPropertyReturnsExistingObjectWithoutCallingFetchRelated(): void + { + $blogRows = [ + [ + 'uid' => 123, + 'posts' => 1, + ], + ]; + /** @var DataMapper $dataMapper */ + $dataMapper = $this->get(DataMapper::class); + $dataMapper->map(Blog::class, $blogRows); + $postRows = [ + [ + 'uid' => 234, + 'blog' => 123, + ], + ]; + + $mappedObjectsArray = $dataMapper->map(Post::class, $postRows); + + self::assertSame(123, $mappedObjectsArray[0]->getBlog()->getUid()); + } + + /** + * Data provider for date checks. Date will be stored based on UTC in + * the database. That's why it's not possible to check for explicit date + * strings but using the date('c') conversion instead, which considers the + * current local timezone setting. + */ + public function mapDateTimeHandlesDifferentFieldEvaluationsDataProvider(): array + { + return [ + 'nothing' => [null, null, null], + 'timestamp' => [1, null, date('c', 1)], + 'invalid date' => ['0000-00-00', 'date', null], + 'valid date' => ['2013-01-01', 'date', date('c', strtotime('2013-01-01 00:00:00'))], + 'invalid datetime' => ['0000-00-00 00:00:00', 'datetime', null], + 'valid datetime' => ['2013-01-01 01:02:03', 'datetime', date('c', strtotime('2013-01-01 01:02:03'))], + ]; + } + + /** + * @test + * @dataProvider mapDateTimeHandlesDifferentFieldEvaluationsDataProvider + */ + public function mapDateTimeHandlesDifferentFieldEvaluations(string|int|null $value, string|null $storageFormat, string|null $expectedValue): void + { + $GLOBALS['TCA']['tx_testdatamapper_domain_model_example']['columns']['initialized_date_time_property']['config']['dbType'] = $storageFormat; + $rows = [ + [ + 'uid' => 123, + 'initialized_date_time_property' => $value, + ], + ]; + /** @var DataMapper $dataMapper */ + $dataMapper = $this->get(DataMapper::class); + $mappedObjectsArray = $dataMapper->map(Example::class, $rows); + + self::assertSame($expectedValue, $mappedObjectsArray[0]->getInitializedDateTimeProperty()?->format('c')); + + // Flush DataMapFactory cache on each run. + /** @var CacheManager $cacheManager */ + $cacheManager = $this->get(CacheManager::class); + $cacheManager->getCache('extbase')->flush(); + } + + public function mapDateTimeHandlesDifferentFieldEvaluationsWithTimeZoneDataProvider(): array + { + return [ + 'nothing' => [null, null, null], + 'timestamp' => [1, null, '@1'], + 'invalid date' => ['0000-00-00', 'date', null], + 'valid date' => ['2013-01-01', 'date', '2013-01-01T00:00:00'], + 'invalid datetime' => ['0000-00-00 00:00:00', 'datetime', null], + 'valid datetime' => ['2013-01-01 01:02:03', 'datetime', '2013-01-01T01:02:03'], + ]; + } + + /** + * @test + * @dataProvider mapDateTimeHandlesDifferentFieldEvaluationsWithTimeZoneDataProvider + */ + public function mapDateTimeHandlesDifferentFieldEvaluationsWithTimeZone(string|int|null $value, ?string $storageFormat, ?string $expectedValue): void + { + $originalTimeZone = date_default_timezone_get(); + date_default_timezone_set('America/Chicago'); + $usedTimeZone = date_default_timezone_get(); + + $GLOBALS['TCA']['tx_testdatamapper_domain_model_example']['columns']['initialized_date_time_property']['config']['dbType'] = $storageFormat; + $rows = [ + [ + 'uid' => 123, + 'initialized_date_time_property' => $value, + ], + ]; + /** @var DataMapper $dataMapper */ + $dataMapper = $this->get(DataMapper::class); + $mappedObjectsArray = $dataMapper->map(Example::class, $rows); + + $expectedValue = $expectedValue !== null ? new \DateTime($expectedValue, new \DateTimeZone($usedTimeZone)) : $expectedValue; + self::assertEquals($expectedValue, $mappedObjectsArray[0]->getInitializedDateTimeProperty()); + + // Flush DataMapFactory cache on each run. + /** @var CacheManager $cacheManager */ + $cacheManager = $this->get(CacheManager::class); + $cacheManager->getCache('extbase')->flush(); + + // Restore the systems current timezone + date_default_timezone_set($originalTimeZone); + } + + /** + * @test + */ + public function mapDateTimeHandlesSubclassesOfDateTime(): void + { + $rows = [ + [ + 'uid' => 123, + 'custom_date_time' => '2013-01-01 01:02:03', + ], + ]; + /** @var DataMapper $dataMapper */ + $dataMapper = $this->get(DataMapper::class); + $mappedObjectsArray = $dataMapper->map(Example::class, $rows); + + self::assertInstanceOf(CustomDateTime::class, $mappedObjectsArray[0]->getCustomDateTime()); + } + + /** + * @test + */ + public function getPlainValueReturnsCorrectDateTimeFormat(): void + { + /** @var DataMapper $dataMapper */ + $dataMapper = $this->get(DataMapper::class); + $columnMapDateTime = new ColumnMap('column_name', 'propertyName'); + $columnMapDateTime->setDateTimeStorageFormat('datetime'); + $columnMapDate = new ColumnMap('column_name', 'propertyName'); + $columnMapDate->setDateTimeStorageFormat('date'); + $input = new \DateTime('2013-04-15 09:30:00'); + + $plainValueDateTime = $dataMapper->getPlainValue($input, $columnMapDateTime); + $plainValueDate = $dataMapper->getPlainValue($input, $columnMapDate); + + self::assertSame('2013-04-15 09:30:00', $plainValueDateTime); + self::assertSame('2013-04-15', $plainValueDate); + } + + public function getPlainValueReturnsExpectedValuesDataProvider(): array + { + return [ + 'datetime to timestamp' => ['1365866253', new \DateTime('@1365866253')], + 'boolean true to 1' => [1, true], + 'boolean false to 0' => [0, false], + 'NULL is handled as string' => ['NULL', null], + 'string value is returned unchanged' => ['RANDOM string', 'RANDOM string'], + 'array is flattened' => ['a,b,c', ['a', 'b', 'c']], + 'deep array is flattened' => ['a,b,c', [['a', 'b'], 'c']], + 'traversable domain object to identifier' => [1, new TraversableDomainObjectExample()], + 'integer value is returned unchanged' => [1234, 1234], + 'float is converted to string' => ['1234.56', 1234.56], + ]; + } + + /** + * @test + * @dataProvider getPlainValueReturnsExpectedValuesDataProvider + */ + public function getPlainValueReturnsExpectedValues(string|int $expectedValue, mixed $input): void + { + /** @var DataMapper $dataMapper */ + $dataMapper = $this->get(DataMapper::class); + + $plainValue = $dataMapper->getPlainValue($input); + + self::assertSame($expectedValue, $plainValue); + } + + /** + * @test + */ + public function getPlainValueCallsGetRealInstanceOnInputIfInputIsInstanceOfLazyLoadingProxy(): void + { + $this->importCSVDataSet('typo3/sysext/extbase/Tests/Functional/Persistence/Generic/Mapper/Fixtures/administrators.csv'); + /** @var DataMapper $dataMapper */ + $dataMapper = $this->get(DataMapper::class); + $rowsBlog = [ + [ + 'uid' => 1234, + 'administrator' => 1, + ], + ]; + $mappedObjectArray = $dataMapper->map(Blog::class, $rowsBlog); + + $plainValue = $dataMapper->getPlainValue($mappedObjectArray[0]->getAdministrator()); + + self::assertSame(1, $plainValue); + } } diff --git a/typo3/sysext/extbase/Tests/Functional/Persistence/Generic/Mapper/Fixtures/administrators.csv b/typo3/sysext/extbase/Tests/Functional/Persistence/Generic/Mapper/Fixtures/administrators.csv new file mode 100644 index 0000000000000000000000000000000000000000..eacec578f9a03d97b14d057fce622a59c5201d30 --- /dev/null +++ b/typo3/sysext/extbase/Tests/Functional/Persistence/Generic/Mapper/Fixtures/administrators.csv @@ -0,0 +1,3 @@ +"fe_users" +,"uid","pid","tx_extbase_type" +,1,0,"ExtbaseTeam\BlogExample\Domain\Model\Administrator" diff --git a/typo3/sysext/extbase/Tests/Unit/Persistence/Generic/Mapper/DataMapperTest.php b/typo3/sysext/extbase/Tests/Unit/Persistence/Generic/Mapper/DataMapperTest.php deleted file mode 100644 index ea37a5981a99588c0c237bef36b94cc178252e81..0000000000000000000000000000000000000000 --- a/typo3/sysext/extbase/Tests/Unit/Persistence/Generic/Mapper/DataMapperTest.php +++ /dev/null @@ -1,521 +0,0 @@ -<?php - -declare(strict_types=1); - -/* - * This file is part of the TYPO3 CMS project. - * - * It is free software; you can redistribute it and/or modify it under - * the terms of the GNU General Public License, either version 2 - * of the License, or any later version. - * - * For the full copyright and license information, please read the - * LICENSE.txt file that was distributed with this source code. - * - * The TYPO3 project - inspiring people to share! - */ - -namespace TYPO3\CMS\Extbase\Tests\Unit\Persistence\Generic\Mapper; - -use PHPUnit\Framework\MockObject\MockObject; -use Prophecy\PhpUnit\ProphecyTrait; -use Psr\Container\ContainerInterface; -use Psr\EventDispatcher\EventDispatcherInterface; -use TYPO3\CMS\Core\Cache\Frontend\NullFrontend; -use TYPO3\CMS\Extbase\DomainObject\AbstractEntity; -use TYPO3\CMS\Extbase\DomainObject\DomainObjectInterface; -use TYPO3\CMS\Extbase\Persistence\Generic\Exception\UnexpectedTypeException; -use TYPO3\CMS\Extbase\Persistence\Generic\LazyLoadingProxy; -use TYPO3\CMS\Extbase\Persistence\Generic\Mapper\ColumnMap; -use TYPO3\CMS\Extbase\Persistence\Generic\Mapper\DataMap; -use TYPO3\CMS\Extbase\Persistence\Generic\Mapper\DataMapFactory; -use TYPO3\CMS\Extbase\Persistence\Generic\Mapper\DataMapper; -use TYPO3\CMS\Extbase\Persistence\Generic\Mapper\Exception\UnknownPropertyTypeException; -use TYPO3\CMS\Extbase\Persistence\Generic\Qom\QueryObjectModelFactory; -use TYPO3\CMS\Extbase\Persistence\Generic\QueryFactoryInterface; -use TYPO3\CMS\Extbase\Persistence\Generic\Session; -use TYPO3\CMS\Extbase\Reflection\ClassSchema; -use TYPO3\CMS\Extbase\Reflection\ReflectionService; -use TYPO3\CMS\Extbase\Tests\Unit\Persistence\Generic\Mapper\Fixture\DummyChildEntity; -use TYPO3\CMS\Extbase\Tests\Unit\Persistence\Generic\Mapper\Fixture\DummyEntity; -use TYPO3\CMS\Extbase\Tests\Unit\Persistence\Generic\Mapper\Fixture\DummyParentEntity; -use TYPO3\TestingFramework\Core\AccessibleObjectInterface; -use TYPO3\TestingFramework\Core\Unit\UnitTestCase; - -class DataMapperTest extends UnitTestCase -{ - use ProphecyTrait; - - /** - * This test does not actually test anything rather than map calls both mocked methods getTargetType and mapSingleRow - * while completely ignoring the result of the method. - * @todo: Cover this functionality by a functional test - * - * @test - */ - public function mapMapsArrayToObjectByCallingmapToObject(): void - { - $rows = [['uid' => '1234']]; - $object = new \stdClass(); - - $dataMapper = $this->getMockBuilder(DataMapper::class) - ->setConstructorArgs([ - $this->createMock(ReflectionService::class), - $this->createMock(QueryObjectModelFactory::class), - $this->createMock(Session::class), - $this->createMock(DataMapFactory::class), - $this->createMock(QueryFactoryInterface::class), - $this->createMock(EventDispatcherInterface::class), - ]) - ->onlyMethods(['mapSingleRow', 'getTargetType']) - ->getMock(); - - $dataMapper->method('getTargetType')->willReturnArgument(1); - $dataMapper->expects(self::once())->method('mapSingleRow')->with($rows[0])->willReturn($object); - - $dataMapper->map(get_class($object), $rows); - } - - /** - * This test does not actually test anything rather than mapSingleRow delegates functionality to - * the persistence session which is a mock itself. - * @todo: Cover this functionality by a functional test - * - * @test - */ - public function mapSingleRowReturnsObjectFromPersistenceSessionIfAvailable(): void - { - $row = ['uid' => '1234']; - $object = new \stdClass(); - $persistenceSession = $this->createMock(Session::class); - $persistenceSession->expects(self::once())->method('hasIdentifier')->with('1234')->willReturn(true); - $persistenceSession->expects(self::once())->method('getObjectByIdentifier')->with('1234')->willReturn($object); - - $dataMapper = $this->getAccessibleMock( - DataMapper::class, - ['dummy'], - [ - $this->createMock(ReflectionService::class), - $this->createMock(QueryObjectModelFactory::class), - $persistenceSession, - $this->createMock(DataMapFactory::class), - $this->createMock(QueryFactoryInterface::class), - $this->createMock(EventDispatcherInterface::class), - ] - ); - - $dataMapper->_call('mapSingleRow', get_class($object), $row); - } - - /** - * This test has a far too complex setup to test a single unit. This actually is a functional test, accomplished - * by mocking the whole dependency chain. This test only tests code structure while it should test functionality. - * @todo: Cover this functionality by a functional test - * - * @test - */ - public function thawPropertiesSetsPropertyValues(): void - { - $className = DummyEntity::class; - $object = new DummyEntity(); - $row = [ - 'uid' => '1234', - 'firstProperty' => 'firstValue', - 'secondProperty' => 1234, - 'thirdProperty' => 1.234, - 'fourthProperty' => false, - 'uninitializedStringProperty' => 'foo', - 'uninitializedDateTimeProperty' => 0, - 'uninitializedMandatoryDateTimeProperty' => 0, - 'initializedDateTimeProperty' => 0, - ]; - $columnMaps = [ - 'uid' => new ColumnMap('uid', 'uid'), - 'pid' => new ColumnMap('pid', 'pid'), - 'firstProperty' => new ColumnMap('firstProperty', 'firstProperty'), - 'secondProperty' => new ColumnMap('secondProperty', 'secondProperty'), - 'thirdProperty' => new ColumnMap('thirdProperty', 'thirdProperty'), - 'fourthProperty' => new ColumnMap('fourthProperty', 'fourthProperty'), - 'uninitializedStringProperty' => new ColumnMap('uninitializedStringProperty', 'uninitializedStringProperty'), - 'uninitializedDateTimeProperty' => new ColumnMap('uninitializedDateTimeProperty', 'uninitializedDateTimeProperty'), - 'uninitializedMandatoryDateTimeProperty' => new ColumnMap('uninitializedMandatoryDateTimeProperty', 'uninitializedMandatoryDateTimeProperty'), - 'initializedDateTimeProperty' => new ColumnMap('initializedDateTimeProperty', 'initializedDateTimeProperty'), - ]; - $dataMap = $this->getAccessibleMock(DataMap::class, null, [$className, $className]); - $dataMap->_set('columnMaps', $columnMaps); - $dataMaps = [ - $className => $dataMap, - ]; - $classSchema = new ClassSchema($className); - $mockReflectionService = $this->getMockBuilder(ReflectionService::class) - ->setConstructorArgs([new NullFrontend('extbase'), 'ClassSchemata']) - ->onlyMethods(['getClassSchema']) - ->getMock(); - $mockReflectionService->method('getClassSchema')->willReturn($classSchema); - $dataMapFactory = $this->getAccessibleMock(DataMapFactory::class, null, [], '', false); - $dataMapFactory->_set('dataMaps', $dataMaps); - $dataMapper = $this->getAccessibleMock( - DataMapper::class, - ['dummy'], - [ - $mockReflectionService, - $this->createMock(QueryObjectModelFactory::class), - $this->createMock(Session::class), - $dataMapFactory, - $this->createMock(QueryFactoryInterface::class), - $this->createMock(EventDispatcherInterface::class), - ] - ); - $dataMapper->_call('thawProperties', $object, $row); - - self::assertEquals('firstValue', $object->firstProperty); - self::assertEquals(1234, $object->secondProperty); - self::assertEquals(1.234, $object->thirdProperty); - self::assertFalse($object->fourthProperty); - self::assertSame('foo', $object->uninitializedStringProperty); - self::assertNull($object->uninitializedDateTimeProperty); - self::assertFalse(isset($object->uninitializedMandatoryDateTimeProperty)); - - // Property is initialized with "null", so isset would return false. - // Test, if property was "really" initialized. - $reflectionProperty = new \ReflectionProperty($object, 'initializedDateTimeProperty'); - self::assertTrue($reflectionProperty->isInitialized($object)); - } - - /** - * @test - */ - public function thawPropertiesThrowsExceptionOnUnknownPropertyType(): void - { - $className = DummyEntity::class; - $object = new DummyEntity(); - $row = [ - 'uid' => '1234', - 'unknownType' => 'What am I?', - ]; - $columnMaps = [ - 'unknownType' => new ColumnMap('unknownType', 'unknownType'), - ]; - $dataMap = $this->getAccessibleMock(DataMap::class, null, [$className, $className]); - $dataMap->_set('columnMaps', $columnMaps); - $dataMaps = [ - $className => $dataMap, - ]; - $classSchema = new ClassSchema($className); - $mockReflectionService = $this->getMockBuilder(ReflectionService::class) - ->setConstructorArgs([new NullFrontend('extbase'), 'ClassSchemata']) - ->onlyMethods(['getClassSchema']) - ->getMock(); - $mockReflectionService->method('getClassSchema')->willReturn($classSchema); - $dataMapFactory = $this->getAccessibleMock(DataMapFactory::class, null, [], '', false); - $dataMapFactory->_set('dataMaps', $dataMaps); - $dataMapper = $this->getAccessibleMock( - DataMapper::class, - ['dummy'], - [ - $mockReflectionService, - $this->createMock(QueryObjectModelFactory::class), - $this->createMock(Session::class), - $dataMapFactory, - $this->createMock(QueryFactoryInterface::class), - $this->createMock(EventDispatcherInterface::class), - ] - ); - $this->expectException(UnknownPropertyTypeException::class); - $dataMapper->_call('thawProperties', $object, $row); - } - - /** - * Test if fetchRelatedEager method returns NULL when $fieldValue = '' and relation type == RELATION_HAS_ONE - * - * This is actually a functional test as it tests multiple units along with a very specific setup of dependencies. - * @todo: Cover this functionality by a functional test - * - * @test - */ - public function fetchRelatedEagerReturnsNullForEmptyRelationHasOne(): void - { - $columnMap = new ColumnMap('columnName', 'propertyName'); - $columnMap->setTypeOfRelation(ColumnMap::RELATION_HAS_ONE); - $dataMap = $this->getMockBuilder(DataMap::class) - ->onlyMethods(['getColumnMap']) - ->disableOriginalConstructor() - ->getMock(); - $dataMap->method('getColumnMap')->willReturn($columnMap); - $dataMapper = $this->getAccessibleMock(DataMapper::class, ['getDataMap'], [], '', false); - $dataMapper->method('getDataMap')->willReturn($dataMap); - $result = $dataMapper->_call('fetchRelatedEager', $this->createMock(AbstractEntity::class), 'SomeName', ''); - self::assertNull($result); - } - - /** - * Test if fetchRelatedEager method returns empty array when $fieldValue = '' and relation type != RELATION_HAS_ONE - * - * This is actually a functional test as it tests multiple units along with a very specific setup of dependencies. - * @todo: Cover this functionality by a functional test - * - * @test - */ - public function fetchRelatedEagerReturnsEmptyArrayForEmptyRelationNotHasOne(): void - { - $columnMap = new ColumnMap('columnName', 'propertyName'); - $columnMap->setTypeOfRelation(ColumnMap::RELATION_BELONGS_TO_MANY); - $dataMap = $this->getMockBuilder(DataMap::class) - ->onlyMethods(['getColumnMap']) - ->disableOriginalConstructor() - ->getMock(); - $dataMap->method('getColumnMap')->willReturn($columnMap); - $dataMapper = $this->getAccessibleMock(DataMapper::class, ['getDataMap'], [], '', false); - $dataMapper->method('getDataMap')->willReturn($dataMap); - $result = $dataMapper->_call('fetchRelatedEager', $this->createMock(AbstractEntity::class), 'SomeName', ''); - self::assertEquals([], $result); - } - - /** - * Test if fetchRelatedEager method returns NULL when $fieldValue = '' - * and relation type == RELATION_HAS_ONE without calling fetchRelated - * - * This is actually a functional test as it tests multiple units along with a very specific setup of dependencies. - * @todo: Cover this functionality by a functional test - * - * @test - */ - public function MapObjectToClassPropertyReturnsNullForEmptyRelationHasOne(): void - { - $columnMap = new ColumnMap('columnName', 'propertyName'); - $columnMap->setTypeOfRelation(ColumnMap::RELATION_HAS_ONE); - $dataMap = $this->getMockBuilder(DataMap::class) - ->onlyMethods(['getColumnMap']) - ->disableOriginalConstructor() - ->getMock(); - $dataMap->method('getColumnMap')->willReturn($columnMap); - $dataMapper = $this->getAccessibleMock(DataMapper::class, ['getDataMap', 'fetchRelated'], [], '', false); - $dataMapper->method('getDataMap')->willReturn($dataMap); - $dataMapper->expects(self::never())->method('fetchRelated'); - $result = $dataMapper->_call('mapObjectToClassProperty', $this->createMock(AbstractEntity::class), 'SomeName', ''); - self::assertNull($result); - } - - /** - * Test if mapObjectToClassProperty method returns objects - * that are already registered in the persistence session - * without query it from the persistence layer - * - * This is actually a functional test as it tests multiple units along with a very specific setup of dependencies. - * @todo: Cover this functionality by a functional test - * - * @test - */ - public function mapObjectToClassPropertyReturnsExistingObjectWithoutCallingFetchRelated(): void - { - $columnMap = new ColumnMap('columnName', 'propertyName'); - $columnMap->setTypeOfRelation(ColumnMap::RELATION_HAS_ONE); - $dataMap = $this->getMockBuilder(DataMap::class) - ->onlyMethods(['getColumnMap']) - ->disableOriginalConstructor() - ->getMock(); - - $object = new DummyParentEntity(); - $child = new DummyChildEntity(); - - $classSchema1 = new ClassSchema(DummyParentEntity::class); - $identifier = 1; - - $psrContainer = $this->getMockBuilder(ContainerInterface::class) - ->onlyMethods(['has', 'get']) - ->disableOriginalConstructor() - ->getMock(); - $psrContainer->method('has')->willReturn(false); - - $session = new Session(); - $session->registerObject($child, $identifier); - - $mockReflectionService = $this->getMockBuilder(ReflectionService::class) - ->onlyMethods(['getClassSchema']) - ->disableOriginalConstructor() - ->getMock(); - $mockReflectionService->method('getClassSchema')->willReturn($classSchema1); - - $dataMap->method('getColumnMap')->willReturn($columnMap); - - $dataMapper = $this->getAccessibleMock( - DataMapper::class, - ['getDataMap', 'getNonEmptyRelationValue'], - [ - $mockReflectionService, - $this->createMock(QueryObjectModelFactory::class), - $session, - $this->createMock(DataMapFactory::class), - $this->createMock(QueryFactoryInterface::class), - $this->createMock(EventDispatcherInterface::class), - ] - ); - $dataMapper->method('getDataMap')->willReturn($dataMap); - $dataMapper->expects(self::never())->method('getNonEmptyRelationValue'); - $result = $dataMapper->_call('mapObjectToClassProperty', $object, 'relationProperty', $identifier); - self::assertEquals($child, $result); - } - - /** - * Data provider for date checks. Date will be stored based on UTC in - * the database. That's why it's not possible to check for explicit date - * strings but using the date('c') conversion instead, which considers the - * current local timezone setting. - */ - public function mapDateTimeHandlesDifferentFieldEvaluationsDataProvider(): array - { - return [ - 'nothing' => [null, null, null], - 'timestamp' => [1, null, date('c', 1)], - 'invalid date' => ['0000-00-00', 'date', null], - 'valid date' => ['2013-01-01', 'date', date('c', strtotime('2013-01-01 00:00:00'))], - 'invalid datetime' => ['0000-00-00 00:00:00', 'datetime', null], - 'valid datetime' => ['2013-01-01 01:02:03', 'datetime', date('c', strtotime('2013-01-01 01:02:03'))], - ]; - } - - /** - * @param string|int|null $value - * @param string|null $storageFormat - * @param string|null $expectedValue - * @test - * @dataProvider mapDateTimeHandlesDifferentFieldEvaluationsDataProvider - */ - public function mapDateTimeHandlesDifferentFieldEvaluations($value, $storageFormat, $expectedValue): void - { - $accessibleDataMapFactory = $this->getAccessibleMock(DataMapper::class, null, [], '', false); - - $dateTime = $accessibleDataMapFactory->_call('mapDateTime', $value, $storageFormat); - - if ($expectedValue === null) { - self::assertNull($dateTime); - } else { - self::assertEquals($expectedValue, $dateTime->format('c')); - } - } - - public function mapDateTimeHandlesDifferentFieldEvaluationsWithTimeZoneDataProvider(): array - { - return [ - 'nothing' => [null, null, null], - 'timestamp' => [1, null, '@1'], - 'invalid date' => ['0000-00-00', 'date', null], - 'valid date' => ['2013-01-01', 'date', '2013-01-01T00:00:00'], - 'invalid datetime' => ['0000-00-00 00:00:00', 'datetime', null], - 'valid datetime' => ['2013-01-01 01:02:03', 'datetime', '2013-01-01T01:02:03'], - ]; - } - - /** - * @param string|int|null $value - * @test - * @dataProvider mapDateTimeHandlesDifferentFieldEvaluationsWithTimeZoneDataProvider - */ - public function mapDateTimeHandlesDifferentFieldEvaluationsWithTimeZone($value, ?string $storageFormat, ?string $expectedValue): void - { - $originalTimeZone = date_default_timezone_get(); - date_default_timezone_set('America/Chicago'); - $usedTimeZone = date_default_timezone_get(); - $accessibleDataMapFactory = $this->getAccessibleMock(DataMapper::class, null, [], '', false); - - /** @var \DateTime|MockObject|AccessibleObjectInterface $dateTime */ - $dateTime = $accessibleDataMapFactory->_call('mapDateTime', $value, $storageFormat); - - if ($expectedValue === null) { - self::assertNull($dateTime); - } else { - self::assertEquals(new \DateTime($expectedValue, new \DateTimeZone($usedTimeZone)), $dateTime); - } - // Restore the systems current timezone - date_default_timezone_set($originalTimeZone); - } - - /** - * @test - */ - public function mapDateTimeHandlesSubclassesOfDateTime(): void - { - $accessibleDataMapFactory = $this->getAccessibleMock(DataMapper::class, null, [], '', false); - $targetType = 'TYPO3\CMS\Extbase\Tests\Unit\Persistence\Fixture\Model\CustomDateTime'; - $date = '2013-01-01 01:02:03'; - $storageFormat = 'datetime'; - - /** @var \DateTime|MockObject|AccessibleObjectInterface $dateTime */ - $dateTime = $accessibleDataMapFactory->_call('mapDateTime', $date, $storageFormat, $targetType); - - self::assertInstanceOf($targetType, $dateTime); - } - - /** - * @test - */ - public function getPlainValueReturnsCorrectDateTimeFormat(): void - { - $subject = $this->createPartialMock(DataMapper::class, []); - - $columnMap = new ColumnMap('column_name', 'propertyName'); - $columnMap->setDateTimeStorageFormat('datetime'); - $input = new \DateTime('2013-04-15 09:30:00'); - self::assertEquals('2013-04-15 09:30:00', $subject->getPlainValue($input, $columnMap)); - $columnMap->setDateTimeStorageFormat('date'); - self::assertEquals('2013-04-15', $subject->getPlainValue($input, $columnMap)); - } - - /** - * @test - * @dataProvider getPlainValueReturnsExpectedValuesDataProvider - */ - public function getPlainValueReturnsExpectedValues($expectedValue, $input): void - { - $dataMapper = $this->createPartialMock(DataMapper::class, []); - - self::assertSame($expectedValue, $dataMapper->getPlainValue($input)); - } - - public function getPlainValueReturnsExpectedValuesDataProvider(): array - { - $traversableDomainObject = $this->prophesize() - ->willImplement(\Iterator::class) - ->willImplement(DomainObjectInterface::class); - $traversableDomainObject->getUid()->willReturn(1); - - return [ - 'datetime to timestamp' => ['1365866253', new \DateTime('@1365866253')], - 'boolean true to 1' => [1, true], - 'boolean false to 0' => [0, false], - 'NULL is handled as string' => ['NULL', null], - 'string value is returned unchanged' => ['RANDOM string', 'RANDOM string'], - 'array is flattened' => ['a,b,c', ['a', 'b', 'c']], - 'deep array is flattened' => ['a,b,c', [['a', 'b'], 'c']], - 'traversable domain object to identifier' => [1, $traversableDomainObject->reveal()], - 'integer value is returned unchanged' => [1234, 1234], - 'float is converted to string' => ['1234.56', 1234.56], - ]; - } - - /** - * @test - */ - public function getPlainValueCallsGetRealInstanceOnInputIfInputIsInstanceOfLazyLoadingProxy(): void - { - $this->expectException(UnexpectedTypeException::class); - $this->expectExceptionCode(1274799934); - - $dataMapper = $this->createPartialMock(DataMapper::class, []); - $input = $this->createMock(LazyLoadingProxy::class); - $input->expects(self::once())->method('_loadRealInstance')->willReturn($dataMapper); - $dataMapper->getPlainValue($input); - } - - /** - * @test - */ - public function getPlainValueCallsGetUidOnDomainObjectInterfaceInput(): void - { - $dataMapper = $this->createPartialMock(DataMapper::class, []); - $input = $this->createMock(DomainObjectInterface::class); - - $input->expects(self::once())->method('getUid')->willReturn(23); - self::assertSame(23, $dataMapper->getPlainValue($input)); - } -} diff --git a/typo3/sysext/extbase/Tests/Unit/Persistence/Generic/Mapper/Fixture/DummyEntity.php b/typo3/sysext/extbase/Tests/Unit/Persistence/Generic/Mapper/Fixture/DummyEntity.php deleted file mode 100644 index 0526dcb313312f1900e390b97d7ed60b3147e502..0000000000000000000000000000000000000000 --- a/typo3/sysext/extbase/Tests/Unit/Persistence/Generic/Mapper/Fixture/DummyEntity.php +++ /dev/null @@ -1,60 +0,0 @@ -<?php - -declare(strict_types=1); - -/* - * This file is part of the TYPO3 CMS project. - * - * It is free software; you can redistribute it and/or modify it under - * the terms of the GNU General Public License, either version 2 - * of the License, or any later version. - * - * For the full copyright and license information, please read the - * LICENSE.txt file that was distributed with this source code. - * - * The TYPO3 project - inspiring people to share! - */ - -namespace TYPO3\CMS\Extbase\Tests\Unit\Persistence\Generic\Mapper\Fixture; - -use TYPO3\CMS\Extbase\DomainObject\AbstractEntity; - -/** - * Fixture - * @todo Specifying the property types results in test bench errors - */ -class DummyEntity extends AbstractEntity -{ - /** - * @var string - */ - public $firstProperty; - - /** - * @var int - */ - public $secondProperty; - - /** - * @var float - */ - public $thirdProperty; - - /** - * @var bool - */ - public $fourthProperty; - - /** - * no var here :( - */ - public $unknownType; - - public string $uninitializedStringProperty; - - public ?\DateTime $uninitializedDateTimeProperty; - - public \DateTime $uninitializedMandatoryDateTimeProperty; - - public ?\DateTime $initializedDateTimeProperty = null; -} diff --git a/typo3/sysext/extbase/Tests/Unit/Persistence/Generic/Mapper/Fixture/DummyParentEntity.php b/typo3/sysext/extbase/Tests/Unit/Persistence/Generic/Mapper/Fixture/DummyParentEntity.php deleted file mode 100644 index 1f6d4d1354defcfe0b9ea5d1bb7f5831403fd0b1..0000000000000000000000000000000000000000 --- a/typo3/sysext/extbase/Tests/Unit/Persistence/Generic/Mapper/Fixture/DummyParentEntity.php +++ /dev/null @@ -1,28 +0,0 @@ -<?php - -declare(strict_types=1); - -/* - * This file is part of the TYPO3 CMS project. - * - * It is free software; you can redistribute it and/or modify it under - * the terms of the GNU General Public License, either version 2 - * of the License, or any later version. - * - * For the full copyright and license information, please read the - * LICENSE.txt file that was distributed with this source code. - * - * The TYPO3 project - inspiring people to share! - */ - -namespace TYPO3\CMS\Extbase\Tests\Unit\Persistence\Generic\Mapper\Fixture; - -use TYPO3\CMS\Extbase\DomainObject\AbstractEntity; - -/** - * Fixture - */ -class DummyParentEntity extends AbstractEntity -{ - public DummyChildEntity $relationProperty; -}