Skip to content

Commit f7ced83

Browse files
committed
feature #173 Add configuration of root namespace (Sergey Rabochiy, weaverryan)
This PR was merged into the 1.0-dev branch. Discussion ---------- Add configuration of root namespace This PR adds configuration for namespaces used in `make:*` commands that was discussed in #133. I've used [this doc](https://symfony.com/doc/current/bundles/configuration.html) in work and examples from `FrameworkBundle`. New parameter: `maker.root_namespace` - application root namespace, default: `App` To change it, you should create configuration file in `config/packages/dev` with name `maker.yaml` or `maker.xml` or `maker.php` with root node `maker`. For example YAML file: ```yaml # config/packages/dev/maker.yaml maker: root_namespace: 'App' ``` I've added some tests. I think we don't need Flex recipe but just document new feature. I need help for write documentation because my English. TODO: - [x] Tests - [x] Documentations - [ ] Squash commits Commits ------- 42b7008 Fixing accidental removal of property 545a422 Merge branch 'master' into configurable_namespace b92f19c Merge branch 'master' into configurable_namespace bf1b092 updating for now-missing property b5658c2 Merge branch 'master' into configurable_namespace 7440ade return type stuff 656116c Changing from an exception 5605d6e adding docs 23a715c Merge remote-tracking branch 'upstream/master' into configurable_namespace 152ffa6 The most important fix f34fa39 Add exception with hint message when root namespace is not found 758a2c9 Refactor AutoloaderUtil 5423250 Remove maker.root_namespace parameter and improve tests 7157e88 Fix file creation on Windows 657f653 Remove useless code a425953 Add functional tests for custom root namespace cases d4139d4 Make "abstract" command and remove entity namespace from config 51d7138 Add configuration of root and entity namespaces
2 parents 5f4d197 + 42b7008 commit f7ced83

File tree

30 files changed

+823
-127
lines changed

30 files changed

+823
-127
lines changed

src/Command/MakerCommand.php

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,13 @@ protected function initialize(InputInterface $input, OutputInterface $output)
7272

7373
protected function interact(InputInterface $input, OutputInterface $output)
7474
{
75+
if (!$this->fileManager->isNamespaceConfiguredToAutoload($this->generator->getRootNamespace())) {
76+
$this->io->note([
77+
sprintf('It looks like your app may be using a namespace other than "%s".', $this->generator->getRootNamespace()),
78+
'To configure this and make your life easier, see: https://symfony.com/doc/current/bundles/SymfonyMakerBundle/index.html#configuration.',
79+
]);
80+
}
81+
7582
foreach ($this->getDefinition()->getArguments() as $argument) {
7683
if ($input->getArgument($argument->getName())) {
7784
continue;

src/DependencyInjection/CompilerPass/MakeCommandRegistrationPass.php

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
use Symfony\Bundle\MakerBundle\Command\MakerCommand;
1515
use Symfony\Bundle\MakerBundle\MakerInterface;
1616
use Symfony\Bundle\MakerBundle\Str;
17+
use Symfony\Component\DependencyInjection\ChildDefinition;
1718
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
1819
use Symfony\Component\DependencyInjection\ContainerBuilder;
1920
use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
@@ -32,14 +33,12 @@ public function process(ContainerBuilder $container)
3233
throw new InvalidArgumentException(sprintf('Service "%s" must implement interface "%s".', $id, MakerInterface::class));
3334
}
3435

35-
$container->register(
36-
sprintf('maker.auto_command.%s', Str::asTwigVariable($class::getCommandName())),
37-
MakerCommand::class
38-
)->setArguments([
39-
new Reference($id),
40-
new Reference('maker.file_manager'),
41-
new Reference('maker.generator'),
42-
])->addTag('console.command', ['command' => $class::getCommandName()]);
36+
$commandDefinition = new ChildDefinition('maker.auto_command.abstract');
37+
$commandDefinition->setClass(MakerCommand::class);
38+
$commandDefinition->replaceArgument(0, new Reference($id));
39+
$commandDefinition->addTag('console.command', ['command' => $class::getCommandName()]);
40+
41+
$container->setDefinition(sprintf('maker.auto_command.%s', Str::asTwigVariable($class::getCommandName())), $commandDefinition);
4342
}
4443
}
4544
}
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony MakerBundle package.
5+
*
6+
* (c) Fabien Potencier <[email protected]>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Bundle\MakerBundle\DependencyInjection;
13+
14+
use Symfony\Component\Config\Definition\Builder\TreeBuilder;
15+
use Symfony\Component\Config\Definition\ConfigurationInterface;
16+
17+
class Configuration implements ConfigurationInterface
18+
{
19+
/**
20+
* {@inheritdoc}
21+
*/
22+
public function getConfigTreeBuilder()
23+
{
24+
$treeBuilder = new TreeBuilder();
25+
$rootNode = $treeBuilder->root('maker');
26+
27+
$rootNode
28+
->children()
29+
->scalarNode('root_namespace')->defaultValue('App')->end()
30+
->end()
31+
;
32+
33+
return $treeBuilder;
34+
}
35+
}

src/DependencyInjection/MakerExtension.php

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,17 @@ public function load(array $configs, ContainerBuilder $container)
3434
$loader->load('services.xml');
3535
$loader->load('makers.xml');
3636

37+
$configuration = $this->getConfiguration($configs, $container);
38+
$config = $this->processConfiguration($configuration, $configs);
39+
40+
$rootNamespace = trim($config['root_namespace'], '\\');
41+
42+
$makeCommandDefinition = $container->getDefinition('maker.generator');
43+
$makeCommandDefinition->replaceArgument(1, $rootNamespace);
44+
45+
$doctrineHelperDefinition = $container->getDefinition('maker.doctrine_helper');
46+
$doctrineHelperDefinition->replaceArgument(0, $rootNamespace.'\\Entity');
47+
3748
$container->registerForAutoconfiguration(MakerInterface::class)
3849
->addTag(MakeCommandRegistrationPass::MAKER_TAG);
3950
}

src/Doctrine/DoctrineHelper.php

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,13 +28,19 @@
2828
*/
2929
final class DoctrineHelper
3030
{
31+
/**
32+
* @var string
33+
*/
34+
private $entityNamespace;
35+
3136
/**
3237
* @var ManagerRegistry
3338
*/
3439
private $registry;
3540

36-
public function __construct(ManagerRegistry $registry = null)
41+
public function __construct(string $entityNamespace, ManagerRegistry $registry = null)
3742
{
43+
$this->entityNamespace = trim($entityNamespace, '\\');
3844
$this->registry = $registry;
3945
}
4046

@@ -54,6 +60,11 @@ private function isDoctrineInstalled(): bool
5460
return null !== $this->registry;
5561
}
5662

63+
public function getEntityNamespace(): string
64+
{
65+
return $this->entityNamespace;
66+
}
67+
5768
/**
5869
* @param string $className
5970
*
@@ -94,7 +105,7 @@ public function getEntitiesForAutocomplete(): array
94105

95106
/* @var ClassMetadata $metadata */
96107
foreach (array_keys($allMetadata) as $classname) {
97-
$entityClassDetails = new ClassNameDetails($classname, 'App\\Entity');
108+
$entityClassDetails = new ClassNameDetails($classname, $this->entityNamespace);
98109
$entities[] = $entityClassDetails->getRelativeName();
99110
}
100111
}

src/FileManager.php

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,11 @@ public function getNamespacePrefixForClass(string $className): string
163163
return $this->autoloaderUtil->getNamespacePrefixForClass($className);
164164
}
165165

166+
public function isNamespaceConfiguredToAutoload(string $namespace): bool
167+
{
168+
return $this->autoloaderUtil->isNamespaceConfiguredToAutoload($namespace);
169+
}
170+
166171
/**
167172
* Resolve '../' in paths (like real_path), but for non-existent files.
168173
*

src/Generator.php

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,11 +25,11 @@ class Generator
2525
private $pendingOperations = [];
2626
private $namespacePrefix;
2727

28-
public function __construct(FileManager $fileManager, $namespacePrefix)
28+
public function __construct(FileManager $fileManager, string $namespacePrefix)
2929
{
3030
$this->fileManager = $fileManager;
3131
$this->twigHelper = new GeneratorTwigHelper($fileManager);
32-
$this->namespacePrefix = rtrim($namespacePrefix, '\\');
32+
$this->namespacePrefix = trim($namespacePrefix, '\\');
3333
}
3434

3535
/**
@@ -170,4 +170,9 @@ public function writeChanges()
170170

171171
$this->pendingOperations = [];
172172
}
173+
174+
public function getRootNamespace(): string
175+
{
176+
return $this->namespacePrefix;
177+
}
173178
}

src/Maker/MakeEntity.php

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ final class MakeEntity extends AbstractMaker implements InputAwareMakerInterface
4848
private $doctrineHelper;
4949
private $generator;
5050

51-
public function __construct(FileManager $fileManager, string $projectDirectory, DoctrineHelper $doctrineHelper, Generator $generator = null)
51+
public function __construct(FileManager $fileManager, DoctrineHelper $doctrineHelper, string $projectDirectory, Generator $generator = null)
5252
{
5353
$this->fileManager = $fileManager;
5454
$this->doctrineHelper = $doctrineHelper;
@@ -92,7 +92,7 @@ public function interact(InputInterface $input, ConsoleStyle $io, Command $comma
9292
'This command will generate any missing methods (e.g. getters & setters) for a class or all classes in a namespace.',
9393
'To overwrite any existing methods, re-run this command with the --overwrite flag',
9494
], null, 'fg=yellow');
95-
$classOrNamespace = $io->ask('Enter a class or namespace to regenerate', 'App\\Entity', [Validator::class, 'notBlank']);
95+
$classOrNamespace = $io->ask('Enter a class or namespace to regenerate', $this->getEntityNamespace(), [Validator::class, 'notBlank']);
9696

9797
$input->setArgument('name', $classOrNamespace);
9898

@@ -518,14 +518,14 @@ private function askRelationDetails(ConsoleStyle $io, string $generatedEntityCla
518518
$targetEntityClass = $io->askQuestion($question);
519519

520520
if (!class_exists($targetEntityClass)) {
521-
if (!class_exists('App\\Entity\\'.$targetEntityClass)) {
521+
if (!class_exists($this->getEntityNamespace().'\\'.$targetEntityClass)) {
522522
$io->error(sprintf('Unknown class "%s"', $targetEntityClass));
523523
$targetEntityClass = null;
524524

525525
continue;
526526
}
527527

528-
$targetEntityClass = 'App\\Entity\\'.$targetEntityClass;
528+
$targetEntityClass = $this->getEntityNamespace().'\\'.$targetEntityClass;
529529
}
530530
}
531531

@@ -841,4 +841,9 @@ private function doesEntityUseAnnotationMapping(string $className): bool
841841

842842
return $driver instanceof AnnotationDriver;
843843
}
844+
845+
private function getEntityNamespace(): string
846+
{
847+
return $this->doctrineHelper->getEntityNamespace();
848+
}
844849
}

src/Resources/config/makers.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,8 @@
2727

2828
<service id="maker.maker.make_entity" class="Symfony\Bundle\MakerBundle\Maker\MakeEntity">
2929
<argument type="service" id="maker.file_manager" />
30-
<argument>%kernel.project_dir%</argument>
3130
<argument type="service" id="maker.doctrine_helper" />
31+
<argument>%kernel.project_dir%</argument>
3232
<argument type="service" id="maker.generator" />
3333
<tag name="maker.command" />
3434
</service>

src/Resources/config/services.xml

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,11 @@
1313
<argument>%kernel.project_dir%</argument>
1414
</service>
1515

16-
<service id="maker.autoloader_util" class="Symfony\Bundle\MakerBundle\Util\AutoloaderUtil" />
16+
<service id="maker.autoloader_finder" class="Symfony\Bundle\MakerBundle\Util\ComposerAutoloaderFinder" />
17+
18+
<service id="maker.autoloader_util" class="Symfony\Bundle\MakerBundle\Util\AutoloaderUtil">
19+
<argument type="service" id="maker.autoloader_finder" />
20+
</service>
1721

1822
<service id="maker.event_registry" class="Symfony\Bundle\MakerBundle\EventRegistry">
1923
<argument type="service" id="event_dispatcher" />
@@ -24,12 +28,19 @@
2428
</service>
2529

2630
<service id="maker.doctrine_helper" class="Symfony\Bundle\MakerBundle\Doctrine\DoctrineHelper">
27-
<argument type="service" id="doctrine" on-invalid="ignore"/>
31+
<argument /> <!-- entity namespace -->
32+
<argument type="service" id="doctrine" on-invalid="ignore" />
33+
</service>
34+
35+
<service id="maker.auto_command.abstract" class="Symfony\Bundle\MakerBundle\Command\MakerCommand" abstract="true">
36+
<argument /> <!-- maker -->
37+
<argument type="service" id="maker.file_manager" />
38+
<argument type="service" id="maker.generator" />
2839
</service>
2940

3041
<service id="maker.generator" class="Symfony\Bundle\MakerBundle\Generator">
3142
<argument type="service" id="maker.file_manager" />
32-
<argument>App\</argument>
43+
<argument /> <!-- root namespace -->
3344
</service>
3445
</services>
3546
</container>

0 commit comments

Comments
 (0)