-
-
Notifications
You must be signed in to change notification settings - Fork 404
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add configuration of root namespace #173
Conversation
86ad830
to
51d7138
Compare
Doc and Recipe sound good ! |
You did a conf for entity namespace, should we have for others classes (Form, Repo, Twig, etc)? |
@LeJeanbono Yes, I think we should. This PR is WIP. |
Hey @upyx! Woo! Thanks for starting this! I have some thoughts:
Cheers! |
Hi @weaverryan ! |
public function getAlias() | ||
{ | ||
return 'maker'; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't believe this is needed
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh, I'm not sure... I will be grateful if you explain it. I see doctrine and many others do the same. As I understand, result of this method won't cached. So avoiding it (as you say earlier) has minor negative performance impact.
public function getConfiguration(array $config, ContainerBuilder $container) | ||
{ | ||
return new Configuration(); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This also should not be needed
$configuration = $this->getConfiguration($configs, $container); | ||
$config = $this->processConfiguration($configuration, $configs); | ||
|
||
$container->setParameter('maker.root_namespace', $config['root_namespace']); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmm, we should not create a parameter if we can avoid it - it has minor negative performance impact, and there's just not advantage.
But, making this happen IS a bit technical, so I'll explain, but let me know if you need help. The process is:
- First, we need to create an "abstract" service in
services.xml
that basically registers this service:maker-bundle/src/DependencyInjection/CompilerPass/MakeCommandRegistrationPass.php
Lines 35 to 41 in 5110979
$container->register( sprintf('maker.auto_command.%s', Str::asTwigVariable($class::getCommandName())), MakerCommand::class )->setArguments([ new Reference($id), new Reference('maker.file_manager'), ])->addTag('console.command', ['command' => $class::getCommandName()]);
2 In the compiler pass, we would then use ChildDefinition to effectively "duplicate" that service and make any changes we need. Here's an example from core: https://github.com/symfony/symfony/blob/cada38f520784cc3f248874ad268e76fc99ba8d9/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php#L563
- In this class, instead of creating a parameter, we would simply set the 3rd argument to the abstract service (created in step 1) to this value.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Use abstract service is great idea! I'll try it.
However where I can get root_namespace
in DI context (compiler pass or service.xml
) if it is not stored as "parameter"?
The second, if we are deciding to configure root namespace only, it can be more practical - to remove config and use just a parameter. What do think?
P.S.
My English leaves much to be desired. Please, fill free to correct me and ask to explain.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah, great question. And, you've done a REALLY good job so far making this all work with ChildDefinition
:).
For this last part, in this file, you should fetch the maker.auto_command.abstract
definition and HERE set its first argument to $config['root_namespace']
. You're doing this in the compiler pass right now. Just move that one part of the code here, and then you won't need to rely on the parameter.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh, and for DoctrineHelper
, instead of referencing the %maker.root_namespace%
parameter in services.xml
, you will also just leave that blank in services.xml
, and set the argument manually in this class.
ff6c4f2
to
d4139d4
Compare
Other ways to fix it for 'advanced users with other namespace then App' would be:
Right now 3rd option gives error:
|
About that error - that looks like a bug to me - we may have too much validation on make:command. We need to fix that :) |
Guys! Let's finish this work. Could you help me with these questions:
@weaverryan what do you think about it? |
About this solution:
If we got special config for 'entity', why not special config for 'command'? I think that options '--namespace My\Name\Space\CustomDir' and '--dirpath src/CustomDir' would be much better (directory path relational to folder with composer.json). Issue should be renamed to 'Add configurable namespace and file path'. About performance: |
Hello @LeJeanbono! I've already removed Symfony uses aggressive caching of configuration so performance very weak depends on configuration size. However default $loader->load($confDir . '/{packages}/*' . self::CONFIG_EXTS, 'glob');
$loader->load($confDir . '/{packages}/' . $this->environment . '/**/*' . self::CONFIG_EXTS, 'glob'); So if you will place |
I've added tests for changed namespace cases. @weaverryan could you check it, please? |
Done for dev env @upyx |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hey @upyx!
Nice work - we're close, I've left some more comments :).
I also have 3 other requests, if you want to try them!
-
For tests, make sure we have a
MakeEntity
test, and one that has a relation. I want to make sure that you can (A) generate an entity correctly when your root namespace is changed and (B) the system correctly looks in the custom namespace for the relation (e.g. if I just type that I want to relate to aComment
entity, it will look for that inCustom\Entity\Comment
. I also want to make sure that the repository class generates into theCustom\Repository
namespace, there is a current bug where it generates intoApp\Repository
, -
At the beginning of ALL commands (so, probably in
MakerCommand
, if we do not detect that the user's app has any autoload rules for theirroot_namespace
, let's add a warning:
It looks like your app may be using a namespace other than "ROOT_NAMESPACE_HERE". see https://link-to-docs for how to configure this.
- And finally, we DO need to add a little note in the docs for this bundle about this new option :). I don't think we should have a recipe.
new Reference('maker.file_manager'), | ||
])->addTag('console.command', ['command' => $class::getCommandName()]); | ||
$commandDefinition = new ChildDefinition('maker.auto_command.abstract'); | ||
$commandDefinition->setClass(MakerCommand::class); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this is not needed, because you already specified it in services.xml
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It is needed - actually class
not inherits to child services. However it may be bug. Documentation says:
All attributes on the parent service are shared with the child except for
shared
,abstract
andtags
. These are not inherited from the parent.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I debugged it. Really class
inherits. It is resolved in ResolveChildDefinitionsPass
but AddConsoleCommandPass
calls earlier (when class
is set to null
).
$configuration = $this->getConfiguration($configs, $container); | ||
$config = $this->processConfiguration($configuration, $configs); | ||
|
||
$container->setParameter('maker.root_namespace', $config['root_namespace']); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah, great question. And, you've done a REALLY good job so far making this all work with ChildDefinition
:).
For this last part, in this file, you should fetch the maker.auto_command.abstract
definition and HERE set its first argument to $config['root_namespace']
. You're doing this in the compiler pass right now. Just move that one part of the code here, and then you won't need to rely on the parameter.
$configuration = $this->getConfiguration($configs, $container); | ||
$config = $this->processConfiguration($configuration, $configs); | ||
|
||
$container->setParameter('maker.root_namespace', $config['root_namespace']); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh, and for DoctrineHelper
, instead of referencing the %maker.root_namespace%
parameter in services.xml
, you will also just leave that blank in services.xml
, and set the argument manually in this class.
src/Maker/MakeEntity.php
Outdated
|
||
public function __construct(FileManager $fileManager, string $projectDirectory, DoctrineHelper $doctrineHelper) | ||
public function __construct(FileManager $fileManager, DoctrineHelper $doctrineHelper, string $projectDirectory, string $entityNamespace) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To avoid needing to inject the $entityNamespace
ALSO here, let's add a getEntityNamespace()
method to DoctrineHelper
.
'phpunit.xml.dist', | ||
'<env name="KERNEL_CLASS" value="App\\Kernel" />', | ||
'<env name="KERNEL_CLASS" value="'.$rootNamespace.'\\Kernel" />' | ||
); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't know if we need to do all of this. I should be enough to create the maker.yaml
file with the config AND add one new PSR4 namespace autoload to composer.json
. I don't think we need to completely eliminate and convert the rest of the app from the App\
namespace.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
At first I did so. But such solution has issue: tests pass when it mustn't because autoloader. After debugging tests we can remove it. But I think complete converting namespace is better because it is case for we are doing all of this 😄
tests/Maker/FunctionalTest.php
Outdated
->changeRootNamespace('Custom') | ||
->addPreMakeCommand('composer dump-autoload') | ||
]; | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we only really need to test one case, because each maker is using the exact same code to place files. Well, maybe 2 cases: MakeCommand
(as a general case) and MakeEntity
, because it is indeed a bit more complex.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It is. I will remove useless tests
Thank you for review @weaverryan! I've done changes by your requests. Could you review again, please? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is great! I think this is the last round of changes :)
src/Command/MakerCommand.php
Outdated
$this->rootNamespace | ||
) | ||
); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Instead of an exception, let's convert this to a warning. Something like:
$this->io->note([
sprintf('It looks like your app may be using a namespace other than "%s".', $this->rootNamespace),
'See https://symfony.com/doc/current/bundles/SymfonyMakerBundle/index.html#configuration to configure this.
]);
The #configuration
part of the link doesn't exist yet, but we'll add it.
src/FileManager.php
Outdated
@@ -163,6 +163,11 @@ public function getNamespacePrefixForClass(string $className): string | |||
return $this->autoloaderUtil->getNamespacePrefixForClass($className); | |||
} | |||
|
|||
public function isNamespaceConfiguredToAutoload(string $namespace): string |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
: bool
return type
src/Util/AutoloaderUtil.php
Outdated
* | ||
* @return bool | ||
*/ | ||
public function isNamespaceConfiguredToAutoload(string $namespace) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add : bool
return type, and remove the @param
and @return
- they are duplicated by the code itself.
tests/Command/MakerCommandTest.php
Outdated
$command->setName('make:foo'); | ||
$tester = new CommandTester($command); | ||
$tester->execute(array()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I like this test. We'll just need to instead look at the output, instead of the exception when we convert it to just a message.
Actually, I just made all the changes - including the docs - because they were so minor. Let's see if the tests still pass! |
* master: improve make:form arguments description Make the Generator class a service Add a functional test Check if the class exists Add an interactive question API Platform support: add an --api-resource flag for the make:entity command
Also updated after a nasty merge conflict with a related PR. Let's see if the tests pass. @upyx can you check out the latest code to make sure the conflict didn't mess anything up? A lot of the same lines of code were changed. |
Oh! Great! I see you strongly determined to comlete this 😃 |
Ha - I am! It’s a missing feature. I knew that :). And I’ll make a release as soon as it’s done. |
Thanks for you work @upyx! The test failures are unrelated, they need to be fixed on master. |
…averryan) 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
I am glad to work with you :) |
This PR adds configuration for namespaces used in
make:*
commands that was discussed in #133.I've used this doc 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 namemaker.yaml
ormaker.xml
ormaker.php
with root nodemaker
. For example YAML file: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: