Skip to content

Commit 966c355

Browse files
committed
MakeUser: availability to chose table's name
1 parent 3585a2f commit 966c355

File tree

8 files changed

+98
-3
lines changed

8 files changed

+98
-3
lines changed

src/Doctrine/DoctrineHelper.php

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
use Doctrine\Common\Persistence\Mapping\ClassMetadata as LegacyClassMetadata;
1616
use Doctrine\Common\Persistence\Mapping\Driver\MappingDriver as LegacyMappingDriver;
1717
use Doctrine\Common\Persistence\Mapping\MappingException as LegacyPersistenceMappingException;
18+
use Doctrine\DBAL\Connection;
1819
use Doctrine\ORM\EntityManagerInterface;
1920
use Doctrine\ORM\Mapping\MappingException as ORMMappingException;
2021
use Doctrine\ORM\Tools\DisconnectedClassMetadataFactory;
@@ -219,4 +220,21 @@ private function isInstanceOf($object, string $class): bool
219220

220221
return $object instanceof $class || $object instanceof $legacyClass;
221222
}
223+
224+
public function escapeTableNameIfNeeded(string $tableName): string
225+
{
226+
if (!$this->isKeyword($tableName)) {
227+
return $tableName;
228+
}
229+
230+
return sprintf('`%s`', $tableName);
231+
}
232+
233+
private function isKeyword(string $name): bool
234+
{
235+
/** @var Connection $connection */
236+
$connection = $this->getRegistry()->getConnection();
237+
238+
return $connection->getDatabasePlatform()->getReservedKeywordsList()->isKeyword($name);
239+
}
222240
}

src/Maker/MakeUser.php

Lines changed: 27 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
use Doctrine\Bundle\DoctrineBundle\DoctrineBundle;
1515
use Symfony\Bundle\MakerBundle\ConsoleStyle;
1616
use Symfony\Bundle\MakerBundle\DependencyBuilder;
17+
use Symfony\Bundle\MakerBundle\Doctrine\DoctrineHelper;
1718
use Symfony\Bundle\MakerBundle\Doctrine\EntityClassGenerator;
1819
use Symfony\Bundle\MakerBundle\Doctrine\ORMDependencyBuilder;
1920
use Symfony\Bundle\MakerBundle\Exception\RuntimeCommandException;
@@ -49,11 +50,14 @@ final class MakeUser extends AbstractMaker
4950

5051
private $configUpdater;
5152

52-
public function __construct(FileManager $fileManager, UserClassBuilder $userClassBuilder, SecurityConfigUpdater $configUpdater)
53+
private $doctrineHelper;
54+
55+
public function __construct(FileManager $fileManager, UserClassBuilder $userClassBuilder, SecurityConfigUpdater $configUpdater, DoctrineHelper $doctrineHelper)
5356
{
5457
$this->fileManager = $fileManager;
5558
$this->userClassBuilder = $userClassBuilder;
5659
$this->configUpdater = $configUpdater;
60+
$this->doctrineHelper = $doctrineHelper;
5761
}
5862

5963
public static function getCommandName(): string
@@ -98,6 +102,15 @@ class_exists(DoctrineBundle::class)
98102
if ($missingPackagesMessage) {
99103
throw new RuntimeCommandException($missingPackagesMessage);
100104
}
105+
106+
$question = 'Enter the entity\'s table name. (<comment>It will be auto-escaped.</comment>)';
107+
$entityTableName = $io->ask(
108+
$question, 'user', function ($name) {
109+
return Validator::validateDoctrineTableName($name, $this->doctrineHelper->getRegistry());
110+
});
111+
112+
$command->addOption('entity-table-name', $entityTableName);
113+
$input->setOption('entity-table-name', $entityTableName);
101114
}
102115
$input->setOption('is-entity', $userIsEntity);
103116

@@ -157,9 +170,20 @@ public function generate(InputInterface $input, ConsoleStyle $io, Generator $gen
157170
$manipulator,
158171
$userClassConfiguration
159172
);
173+
174+
// C) Add @ORM\Table annotation
175+
if ($userClassConfiguration->isEntity()) {
176+
$manipulator->addAnnotationToClass(
177+
'ORM\\Table',
178+
[
179+
'name' => $this->doctrineHelper->escapeTableNameIfNeeded($input->getOption('entity-table-name'))
180+
]
181+
);
182+
}
183+
160184
$generator->dumpFile($classPath, $manipulator->getSourceCode());
161185

162-
// C) Generate a custom user provider, if necessary
186+
// D) Generate a custom user provider, if necessary
163187
if (!$userClassConfiguration->isEntity()) {
164188
$userClassConfiguration->setUserProviderClass($generator->getRootNamespace().'\\Security\\UserProvider');
165189
$customProviderPath = $generator->generateClass(
@@ -171,7 +195,7 @@ public function generate(InputInterface $input, ConsoleStyle $io, Generator $gen
171195
);
172196
}
173197

174-
// D) Update security.yaml
198+
// E) Update security.yaml
175199
$securityYamlUpdated = false;
176200
$path = 'config/packages/security.yaml';
177201
if ($this->fileManager->fileExists($path)) {

src/Resources/config/makers.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,7 @@
9797
<argument type="service" id="maker.file_manager" />
9898
<argument type="service" id="maker.user_class_builder" />
9999
<argument type="service" id="maker.security_config_updater" />
100+
<argument type="service" id="maker.doctrine_helper" />
100101
<tag name="maker.command" />
101102
</service>
102103

src/Util/ClassSourceManipulator.php

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -718,6 +718,12 @@ public function addUseStatementIfNecessary(string $class): string
718718
// everywhere and do not add another use statement
719719
return '\\'.$class;
720720
}
721+
722+
// we're dealing with a "directory" namespace (ie: Assert, ORM)
723+
// we should use entire given class as alias
724+
if (0 === strpos($class, $alias)) {
725+
return $class;
726+
}
721727
}
722728

723729
// if $class is alphabetically before this use statement, place it before

src/Validator.php

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
namespace Symfony\Bundle\MakerBundle;
1313

1414
use Doctrine\Common\Persistence\ManagerRegistry;
15+
use Doctrine\DBAL\Connection;
1516
use Symfony\Bundle\MakerBundle\Exception\RuntimeCommandException;
1617
use Symfony\Component\Security\Core\User\UserInterface;
1718

@@ -167,6 +168,21 @@ public static function validateDoctrineFieldName(string $name, ManagerRegistry $
167168
return $name;
168169
}
169170

171+
public static function validateDoctrineTableName(string $name, ManagerRegistry $registry)
172+
{
173+
/** @var Connection $connection */
174+
$connection = $registry->getConnection();
175+
if ($connection->getSchemaManager()->tablesExist($name)) {
176+
throw new \InvalidArgumentException(sprintf('Table "%s" already exists.', $name));
177+
}
178+
179+
if (!preg_match('/^([0-9a-zA-Z_$])+$/', $name)) {
180+
throw new \InvalidArgumentException(sprintf('"%s" is not a valid table name.', $name));
181+
}
182+
183+
return $name;
184+
}
185+
170186
public static function existsOrNull(string $className = null, array $entities = [])
171187
{
172188
if (null !== $className) {

tests/Maker/MakeUserTest.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ public function getTestDetails()
2525
// user class name
2626
'User',
2727
'y', // entity
28+
'user', // table name
2829
'email', // identity property
2930
'y', // with password
3031
'y', // argon

tests/Util/ClassSourceManipulatorTest.php

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -725,6 +725,35 @@ class Foo
725725
class Foo
726726
{
727727
}
728+
EOF
729+
];
730+
731+
yield 'directory_namespace' => [
732+
<<<EOF
733+
<?php
734+
735+
namespace Acme;
736+
737+
use Bar;
738+
739+
class Foo
740+
{
741+
}
742+
EOF
743+
,
744+
<<<EOF
745+
<?php
746+
747+
namespace Acme;
748+
749+
use Bar;
750+
751+
/**
752+
* @Bar\SomeAnnotation(message="Foo")
753+
*/
754+
class Foo
755+
{
756+
}
728757
EOF
729758
];
730759
}

tests/tmp/.gitignore

Whitespace-only changes.

0 commit comments

Comments
 (0)