From c226679c60fc0ba6be5139ce6c4f7aa16f063864 Mon Sep 17 00:00:00 2001 From: Ivanchuk Dmitriy Aleksandrovich Date: Fri, 12 Jul 2019 19:16:49 +0300 Subject: [PATCH] Add enum_name_type_mapping true/false to config --- src/DBAL/EnumType.php | 30 ++++++ src/DBAL/EnumTypeInitializer.php | 11 ++- src/DependencyInjection/Configuration.php | 3 + .../LamodaEnumExtension.php | 3 +- tests/Functional/Fixtures/TestKernel.php | 36 ++++++- .../Fixtures/config_type_mapping.yml | 7 ++ .../Fixtures/config_type_mapping_false.yml | 7 ++ tests/Functional/TestCustomTypeMapping.php | 96 +++++++++++++++++++ tests/Unit/DBAL/EnumTypeInitializerTest.php | 50 ++++++++++ .../LamodaEnumExtensionTest.php | 4 + 10 files changed, 242 insertions(+), 5 deletions(-) create mode 100644 tests/Functional/Fixtures/config_type_mapping.yml create mode 100644 tests/Functional/Fixtures/config_type_mapping_false.yml create mode 100644 tests/Functional/TestCustomTypeMapping.php diff --git a/src/DBAL/EnumType.php b/src/DBAL/EnumType.php index b8eb672..e3a96f4 100644 --- a/src/DBAL/EnumType.php +++ b/src/DBAL/EnumType.php @@ -12,13 +12,20 @@ final class EnumType extends Type { + private const MAPPED_TYPE_STRING = 'string'; + /** @var string */ private $fqcn; + /** @var string */ private $name; + /** @var NamingStrategyInterface */ private $strategy; + /** @var bool */ + private $enumNameTypeMapping = false; + public function setName(string $name): void { $this->name = $name; @@ -43,6 +50,16 @@ private function getStrategy(): NamingStrategyInterface return $this->strategy; } + public function setEnumNameTypeMapping(bool $enumNameTypeMapping): void + { + $this->enumNameTypeMapping = $enumNameTypeMapping; + } + + public function isEnumNameTypeMapping(): bool + { + return $this->enumNameTypeMapping; + } + /** * {@inheritdoc} */ @@ -81,6 +98,10 @@ public function convertToDatabaseValue($value, AbstractPlatform $platform) /** {@inheritdoc} */ public function getSQLDeclaration(array $fieldDeclaration, AbstractPlatform $platform) { + if ($this->isEnumNameTypeMapping() === true) { + return $this->getName(); + } + return $platform->getVarcharTypeDeclarationSQL($fieldDeclaration); } @@ -89,4 +110,13 @@ public function getName(): string { return $this->name; } + + public function getMappedDatabaseTypes(AbstractPlatform $platform) + { + if ($this->isEnumNameTypeMapping() === true) { + return [$this->name => $this->name]; + } + + return [$this->name => self::MAPPED_TYPE_STRING]; + } } diff --git a/src/DBAL/EnumTypeInitializer.php b/src/DBAL/EnumTypeInitializer.php index 6c135da..bcd9198 100644 --- a/src/DBAL/EnumTypeInitializer.php +++ b/src/DBAL/EnumTypeInitializer.php @@ -11,16 +11,22 @@ final class EnumTypeInitializer * @param string $type * @param string $fqcn * @param NamingStrategyInterface|null $strategy + * @param bool $enumNameTypeMapping * * @throws \Doctrine\DBAL\DBALException */ - public function initialize(string $type, string $fqcn, NamingStrategyInterface $strategy = null): void - { + public function initialize( + string $type, + string $fqcn, + NamingStrategyInterface $strategy = null, + bool $enumNameTypeMapping = false + ): void { if (Type::hasType($type)) { return; } Type::addType($type, EnumType::class); + /** @var EnumType $typeInstance */ $typeInstance = Type::getType($type); $typeInstance->setFqcn($fqcn); @@ -28,5 +34,6 @@ public function initialize(string $type, string $fqcn, NamingStrategyInterface $ if ($strategy) { $typeInstance->setStrategy($strategy); } + $typeInstance->setEnumNameTypeMapping($enumNameTypeMapping); } } diff --git a/src/DependencyInjection/Configuration.php b/src/DependencyInjection/Configuration.php index 20b85e9..9a85237 100644 --- a/src/DependencyInjection/Configuration.php +++ b/src/DependencyInjection/Configuration.php @@ -15,6 +15,9 @@ public function getConfigTreeBuilder(): TreeBuilder $root = $builder->root('lamoda_enum'); + $root->children()->booleanNode('enum_name_type_mapping') + ->defaultValue(false); + $this->configureEnumNodes($root); return $builder; diff --git a/src/DependencyInjection/LamodaEnumExtension.php b/src/DependencyInjection/LamodaEnumExtension.php index 68ba74e..ac4c18a 100644 --- a/src/DependencyInjection/LamodaEnumExtension.php +++ b/src/DependencyInjection/LamodaEnumExtension.php @@ -2,6 +2,7 @@ namespace Lamoda\EnumBundle\DependencyInjection; +use Doctrine\ORM\EntityManager; use Lamoda\EnumBundle\DBAL\EnumTypeInitializer; use Lamoda\EnumBundle\Naming\IdenticalNamingStrategy; use Lamoda\EnumBundle\Naming\LowercaseNamingStrategy; @@ -25,7 +26,7 @@ public function load(array $configs, ContainerBuilder $container): void foreach ($configs['dbal_types'] ?? [] as $name => $typeConfig) { $fqcn = $typeConfig['class']; $strategy = $this->getStrategy($typeConfig['strategy'] ?? null); - $typeInitializer->addMethodCall('initialize', [$name, $fqcn, $strategy]); + $typeInitializer->addMethodCall('initialize', [$name, $fqcn, $strategy, $configs['enum_name_type_mapping']]); } } diff --git a/tests/Functional/Fixtures/TestKernel.php b/tests/Functional/Fixtures/TestKernel.php index 631357f..b6ac084 100644 --- a/tests/Functional/Fixtures/TestKernel.php +++ b/tests/Functional/Fixtures/TestKernel.php @@ -8,6 +8,12 @@ final class TestKernel extends Kernel { + /** @var string */ + private $configFileName = 'config.yml'; + + /** @var string */ + private $cacheDirPostfix = ''; + /** {@inheritdoc} */ public function registerBundles() { @@ -18,16 +24,42 @@ public function registerBundles() public function registerContainerConfiguration(LoaderInterface $loader) { - $loader->load(__DIR__ . '/config.yml'); + $loader->load(__DIR__.'/'.$this->getConfigFileName()); } public function getCacheDir() { - return __DIR__.'/../../../build/cache'; + return __DIR__.'/../../../build/cache'.$this->getCacheDirPostfix(); } public function getLogDir() { return __DIR__.'/../../../build/logs'; } + + /** + * @return string + */ + public function getConfigFileName(): string + { + return $this->configFileName; + } + + /** + * @param string $configFileName + */ + public function setConfigFileName(string $configFileName): void + { + $this->configFileName = $configFileName; + } + + public function getCacheDirPostfix(): string + { + return $this->cacheDirPostfix; + } + + public function setCacheDirPostfix(string $cacheDirPostfix): void + { + $this->cacheDirPostfix = $cacheDirPostfix; + } } diff --git a/tests/Functional/Fixtures/config_type_mapping.yml b/tests/Functional/Fixtures/config_type_mapping.yml new file mode 100644 index 0000000..a54ae34 --- /dev/null +++ b/tests/Functional/Fixtures/config_type_mapping.yml @@ -0,0 +1,7 @@ +lamoda_enum: + enum_name_type_mapping: true + dbal_types: + test_enum: Lamoda\EnumBundle\Tests\Functional\Fixtures\TestEnum + test_enum_extended: + class: Lamoda\EnumBundle\Tests\Functional\Fixtures\TestEnum + strategy: lowercase diff --git a/tests/Functional/Fixtures/config_type_mapping_false.yml b/tests/Functional/Fixtures/config_type_mapping_false.yml new file mode 100644 index 0000000..b31d476 --- /dev/null +++ b/tests/Functional/Fixtures/config_type_mapping_false.yml @@ -0,0 +1,7 @@ +lamoda_enum: + enum_name_type_mapping: false + dbal_types: + test_enum: Lamoda\EnumBundle\Tests\Functional\Fixtures\TestEnum + test_enum_extended: + class: Lamoda\EnumBundle\Tests\Functional\Fixtures\TestEnum + strategy: lowercase diff --git a/tests/Functional/TestCustomTypeMapping.php b/tests/Functional/TestCustomTypeMapping.php new file mode 100644 index 0000000..8aadaa5 --- /dev/null +++ b/tests/Functional/TestCustomTypeMapping.php @@ -0,0 +1,96 @@ +getProperty('_typesMap'); + $typesMapProperty->setAccessible(true); + $typesMapProperty->setValue([]); + } + + /** + * @param string $configFileName + * @param string $expectedTestEnumSqlDeclaration + * @param string $expectedTestEnumExtendedSqlDeclaration + * @param array $expectedTestEnumMappedTypes + * @param array $expectedTestEnumExtendedMappedTypes + * + * @throws \Doctrine\DBAL\DBALException + * + * @dataProvider dataTypeMapping + */ + public function testTypeMapping( + string $configFileName, + string $expectedTestEnumSqlDeclaration, + string $expectedTestEnumExtendedSqlDeclaration, + array $expectedTestEnumMappedTypes, + array $expectedTestEnumExtendedMappedTypes + ): void { + $kernel = $this->createKernel($configFileName); + + $basic = Type::getType('test_enum'); + $extended = Type::getType('test_enum_extended'); + + $platform = $this->createMock(AbstractPlatform::class); + $platform->method('getVarcharTypeDeclarationSQL') + ->willReturn('VARCHAR(255)'); + + self::assertSame($expectedTestEnumSqlDeclaration, $basic->getSQLDeclaration([], $platform)); + self::assertSame($expectedTestEnumExtendedSqlDeclaration, $extended->getSQLDeclaration([], $platform)); + + self::assertSame($expectedTestEnumMappedTypes, $basic->getMappedDatabaseTypes($platform)); + self::assertSame($expectedTestEnumExtendedMappedTypes, $extended->getMappedDatabaseTypes($platform)); + + $kernel->shutdown(); + } + + public function dataTypeMapping(): array + { + return [ + [ + 'config.yml', + 'VARCHAR(255)', + 'VARCHAR(255)', + ['test_enum' => 'string'], + ['test_enum_extended' => 'string'], + ], + [ + 'config_type_mapping.yml', + 'test_enum', + 'test_enum_extended', + ['test_enum' => 'test_enum'], + ['test_enum_extended' => 'test_enum_extended'], + ], + [ + 'config_type_mapping_false.yml', + 'VARCHAR(255)', + 'VARCHAR(255)', + ['test_enum' => 'string'], + ['test_enum_extended' => 'string'], + ], + ]; + } + + private function createKernel(string $configFileName): Kernel + { + $kernel = new TestKernel('test', true); + $kernel->setConfigFileName($configFileName); + $kernel->setCacheDirPostfix(sha1($configFileName)); + $kernel->boot(); + + return $kernel; + } +} diff --git a/tests/Unit/DBAL/EnumTypeInitializerTest.php b/tests/Unit/DBAL/EnumTypeInitializerTest.php index f758d86..bb13af5 100644 --- a/tests/Unit/DBAL/EnumTypeInitializerTest.php +++ b/tests/Unit/DBAL/EnumTypeInitializerTest.php @@ -19,6 +19,15 @@ final class EnumTypeInitializerTest extends TestCase { private const TESTED_TYPE = 'test_type'; + protected function setUp(): void + { + $typeReflectionClass = new \ReflectionClass(Type::class); + + $typesMapProperty = $typeReflectionClass->getProperty('_typesMap'); + $typesMapProperty->setAccessible(true); + $typesMapProperty->setValue([]); + } + public function testInitializerLoadsType(): void { $initalizer = new EnumTypeInitializer(); @@ -33,6 +42,47 @@ public function testInitializerLoadsType(): void self::assertEquals('ONE', (string) $enum); } + /** + * @param bool $enumNameTypeMapping + * @param string $expectedType + * @param array $expectedMappedTypes + * + * @throws \Doctrine\DBAL\DBALException + * + * @dataProvider dataInitializerLoadsTypeWithMappingFlag + */ + public function testInitializerLoadsTypeWithMappingFlag( + bool $enumNameTypeMapping, + string $expectedType, + array $expectedMappedTypes + ): void { + $initalizer = new EnumTypeInitializer(); + $initalizer->initialize( + self::TESTED_TYPE, + TestEnum::class, + new IdenticalNamingStrategy(), + $enumNameTypeMapping + ); + + $platform = $this->createMock(AbstractPlatform::class); + $platform->method('getVarcharTypeDeclarationSQL') + ->willReturn('VARCHAR(255)'); + + $type = Type::getType(self::TESTED_TYPE); + + self::assertEquals($enumNameTypeMapping, $type->isEnumNameTypeMapping()); + self::assertEquals($expectedType, $type->getSQLDeclaration([], $platform)); + self::assertEquals($expectedMappedTypes, $type->getMappedDatabaseTypes($platform)); + } + + public function dataInitializerLoadsTypeWithMappingFlag() + { + return [ + [false, 'VARCHAR(255)', [self::TESTED_TYPE => 'string']], + [true, self::TESTED_TYPE, [self::TESTED_TYPE => self::TESTED_TYPE]] + ]; + } + /** * @runInSeparateProcess */ diff --git a/tests/Unit/DependencyInjection/LamodaEnumExtensionTest.php b/tests/Unit/DependencyInjection/LamodaEnumExtensionTest.php index 7b08b77..c4d8100 100644 --- a/tests/Unit/DependencyInjection/LamodaEnumExtensionTest.php +++ b/tests/Unit/DependencyInjection/LamodaEnumExtensionTest.php @@ -38,6 +38,7 @@ public function testExtensionLoadsFilledConfigs(): void $extension->load( [ [ + 'enum_name_type_mapping' => true, 'dbal_types' => [ 'type_1' => TestEnum::class, 'type_2' => [ @@ -52,10 +53,12 @@ public function testExtensionLoadsFilledConfigs(): void $initDef = $builder->getDefinition(EnumTypeInitializer::class); $calls = $initDef->getMethodCalls(); + self::assertCount(2, $calls); self::assertSame('initialize', $calls[0][0]); self::assertSame('type_1', $calls[0][1][0]); self::assertSame(TestEnum::class, $calls[0][1][1]); + self::assertSame(true, $calls[0][1][3]); /** @var Reference $strat1 */ $strat1 = $calls[0][1][2]; self::assertInstanceOf(Reference::class, $strat1); @@ -64,6 +67,7 @@ public function testExtensionLoadsFilledConfigs(): void self::assertSame('initialize', $calls[1][0]); self::assertSame('type_2', $calls[1][1][0]); self::assertSame(TestEnum::class, $calls[1][1][1]); + self::assertSame(true, $calls[1][1][3]); /** @var Reference $strat1 */ $strat1 = $calls[1][1][2]; self::assertInstanceOf(Reference::class, $strat1);