diff --git a/src/DependencyInjection/CompilerPass/SetDoctrineAnnotatedPrefixesPass.php b/src/DependencyInjection/CompilerPass/SetDoctrineAnnotatedPrefixesPass.php index 5829f4a53..b2c379624 100644 --- a/src/DependencyInjection/CompilerPass/SetDoctrineAnnotatedPrefixesPass.php +++ b/src/DependencyInjection/CompilerPass/SetDoctrineAnnotatedPrefixesPass.php @@ -63,7 +63,7 @@ public function process(ContainerBuilder $container): void } if (null !== $annotatedPrefixes) { - $container->getDefinition('maker.doctrine_helper')->setArgument(4, $annotatedPrefixes); + $container->getDefinition('maker.doctrine_helper')->replaceArgument('$annotatedPrefixes', $annotatedPrefixes); } } } diff --git a/src/DependencyInjection/Configuration.php b/src/DependencyInjection/Configuration.php index 787672159..0bef0d593 100644 --- a/src/DependencyInjection/Configuration.php +++ b/src/DependencyInjection/Configuration.php @@ -32,6 +32,11 @@ public function getConfigTreeBuilder(): TreeBuilder $rootNode ->children() ->scalarNode('root_namespace')->defaultValue('App')->end() + ->arrayNode('custom_type_hints') + ->fixXmlConfig('custom_type_hints') + ->useAttributeAsKey('name') + ->prototype('scalar')->end() + ->end() ->end() ; diff --git a/src/DependencyInjection/MakerExtension.php b/src/DependencyInjection/MakerExtension.php index 0a173bcce..1d020b04f 100644 --- a/src/DependencyInjection/MakerExtension.php +++ b/src/DependencyInjection/MakerExtension.php @@ -63,7 +63,8 @@ public function load(array $configs, ContainerBuilder $container): void $makeCommandDefinition->replaceArgument(1, $rootNamespace); $doctrineHelperDefinition = $container->getDefinition('maker.doctrine_helper'); - $doctrineHelperDefinition->replaceArgument(0, $rootNamespace.'\\Entity'); + $doctrineHelperDefinition->replaceArgument('$entityNamespace', $rootNamespace.'\\Entity'); + $doctrineHelperDefinition->replaceArgument('$customTypeHints', $config['custom_type_hints']); $container->registerForAutoconfiguration(MakerInterface::class) ->addTag(MakeCommandRegistrationPass::MAKER_TAG); diff --git a/src/Doctrine/DoctrineHelper.php b/src/Doctrine/DoctrineHelper.php index 8c05db245..0c69ee584 100644 --- a/src/Doctrine/DoctrineHelper.php +++ b/src/Doctrine/DoctrineHelper.php @@ -57,16 +57,19 @@ final class DoctrineHelper private $attributeMappingSupport; + private $customTypeHints; + /** * @var ManagerRegistry|LegacyManagerRegistry */ - public function __construct(string $entityNamespace, PhpCompatUtil $phpCompatUtil, $registry = null, bool $attributeMappingSupport = false, array $annotatedPrefixes = null) + public function __construct(string $entityNamespace, PhpCompatUtil $phpCompatUtil, $registry = null, bool $attributeMappingSupport = false, array $annotatedPrefixes = null, array $customTypeHints = []) { $this->entityNamespace = trim($entityNamespace, '\\'); $this->phpCompatUtil = $phpCompatUtil; $this->registry = $registry; $this->attributeMappingSupport = $attributeMappingSupport; $this->mappingDriversByPrefix = $annotatedPrefixes; + $this->customTypeHints = $customTypeHints; } /** @@ -323,4 +326,9 @@ private function getMappingDriverForNamespace(string $namespace): ?MappingDriver return $foundDriver; } + + public function getCustomTypeHints(): array + { + return $this->customTypeHints; + } } diff --git a/src/Doctrine/EntityRegenerator.php b/src/Doctrine/EntityRegenerator.php index b5caadee7..8928698b9 100644 --- a/src/Doctrine/EntityRegenerator.php +++ b/src/Doctrine/EntityRegenerator.php @@ -210,7 +210,10 @@ private function createClassManipulator(string $classPath): ClassSourceManipulat // if properties need to be generated then, by definition, // some non-annotation config is being used, and so, the // properties should not have annotations added to them - false + false, + true, + false, + $this->doctrineHelper->getCustomTypeHints() ); } diff --git a/src/Maker/MakeEntity.php b/src/Maker/MakeEntity.php index 917013d4d..f61810231 100644 --- a/src/Maker/MakeEntity.php +++ b/src/Maker/MakeEntity.php @@ -801,7 +801,14 @@ private function createClassManipulator(string $path, ConsoleStyle $io, bool $ov $useAttributes = $this->doctrineHelper->doesClassUsesAttributes($className) && $this->doctrineHelper->isDoctrineSupportingAttributes(); $useAnnotations = $this->doctrineHelper->isClassAnnotated($className) || !$useAttributes; - $manipulator = new ClassSourceManipulator($this->fileManager->getFileContents($path), $overwrite, $useAnnotations, true, $useAttributes); + $manipulator = new ClassSourceManipulator( + $this->fileManager->getFileContents($path), + $overwrite, + $useAnnotations, + true, + $useAttributes, + $this->doctrineHelper->getCustomTypeHints() + ); $manipulator->setIo($io); diff --git a/src/Maker/MakeResetPassword.php b/src/Maker/MakeResetPassword.php index b84a75977..a23feb9ad 100644 --- a/src/Maker/MakeResetPassword.php +++ b/src/Maker/MakeResetPassword.php @@ -397,7 +397,8 @@ private function generateRequestEntity(Generator $generator, ClassNameDetails $r false, !$useAttributesForDoctrineMapping, true, - $useAttributesForDoctrineMapping + $useAttributesForDoctrineMapping, + $this->doctrineHelper->getCustomTypeHints() ); $manipulator->addInterface(ResetPasswordRequestInterface::class); diff --git a/src/Maker/MakeUser.php b/src/Maker/MakeUser.php index d2a8a92d1..61c657435 100644 --- a/src/Maker/MakeUser.php +++ b/src/Maker/MakeUser.php @@ -172,7 +172,8 @@ public function generate(InputInterface $input, ConsoleStyle $io, Generator $gen true, !$useAttributesForDoctrineMapping, true, - $useAttributesForDoctrineMapping + $useAttributesForDoctrineMapping, + $this->doctrineHelper->getCustomTypeHints() ); $manipulator->setIo($io); diff --git a/src/Resources/config/services.xml b/src/Resources/config/services.xml index a61bf9e19..93e2af562 100644 --- a/src/Resources/config/services.xml +++ b/src/Resources/config/services.xml @@ -36,10 +36,12 @@ - - - + + + %maker.compatible_check.doctrine.supports_attributes% + null + diff --git a/src/Util/ClassSourceManipulator.php b/src/Util/ClassSourceManipulator.php index cd6d8efa1..0d13b5997 100644 --- a/src/Util/ClassSourceManipulator.php +++ b/src/Util/ClassSourceManipulator.php @@ -63,7 +63,9 @@ final class ClassSourceManipulator private $pendingComments = []; - public function __construct(string $sourceCode, bool $overwrite = false, bool $useAnnotations = true, bool $fluentMutators = true, bool $useAttributesForDoctrineMapping = false) + private $customTypeHints = []; + + public function __construct(string $sourceCode, bool $overwrite = false, bool $useAnnotations = true, bool $fluentMutators = true, bool $useAttributesForDoctrineMapping = false, array $customTypeHints = []) { $this->overwrite = $overwrite; $this->useAnnotations = $useAnnotations; @@ -78,6 +80,7 @@ public function __construct(string $sourceCode, bool $overwrite = false, bool $u ]); $this->parser = new Parser\Php7($this->lexer); $this->printer = new PrettyPrinter(); + $this->customTypeHints = $customTypeHints; $this->setSourceCode($sourceCode); } @@ -1202,6 +1205,12 @@ private function getEntityTypeHint($doctrineType): ?string case 'binary': case 'blob': default: + if (isset($this->customTypeHints[$doctrineType])) { + $type = $this->customTypeHints[$doctrineType]; + + return '\\'.ltrim($type, '\\'); + } + return null; } } diff --git a/tests/DependencyInjection/ConfigurationTest.php b/tests/DependencyInjection/ConfigurationTest.php new file mode 100644 index 000000000..f4ddaf141 --- /dev/null +++ b/tests/DependencyInjection/ConfigurationTest.php @@ -0,0 +1,74 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Indragunawan\ApiRateLimitBundle\Tests\DependencyInjection; + +use DateTimeImmutable; +use PHPUnit\Framework\TestCase; +use Symfony\Bundle\MakerBundle\DependencyInjection\Configuration; +use Symfony\Component\Config\Definition\Processor; + +class ConfigurationTest extends TestCase +{ + /** + * @var Configuration + */ + private $configuration; + + /** + * @var Processor + */ + private $processor; + + /** + * {@inheritdoc} + */ + protected function setUp(): void + { + $this->configuration = new Configuration(); + $this->processor = new Processor(); + } + + protected function tearDown(): void + { + $this->configuration = null; + $this->processor = null; + } + + public function testDefaultConfig() + { + $config = $this->processor->processConfiguration( + $this->configuration, + [ + [], + ] + ); + + $this->assertSame('App', $config['root_namespace']); + $this->assertEmpty($config['custom_type_hints']); + } + + public function testCustomTypeHints() + { + $config = $this->processor->processConfiguration( + $this->configuration, + [ + [ + 'custom_type_hints' => [ + 'my_type' => DateTimeImmutable::class, + ], + ], + ] + ); + + $this->assertSame(['my_type' => DateTimeImmutable::class], $config['custom_type_hints']); + } +}