Skip to content

Commit

Permalink
feat(2.x): allow to configure default namespace fo make:factory (#600)
Browse files Browse the repository at this point in the history
  • Loading branch information
nikophil authored May 8, 2024
1 parent 71bbaa2 commit 2c8e048
Show file tree
Hide file tree
Showing 6 changed files with 62 additions and 6 deletions.
11 changes: 7 additions & 4 deletions config/makers.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,18 +7,21 @@
use Zenstruck\Foundry\Maker\Factory\FactoryClassMap;
use Zenstruck\Foundry\Maker\Factory\FactoryGenerator;
use Zenstruck\Foundry\Maker\Factory\LegacyORMDefaultPropertiesGuesser;
use Zenstruck\Foundry\Maker\Factory\NamespaceGuesser;
use Zenstruck\Foundry\Maker\Factory\NoPersistenceObjectsAutoCompleter;
use Zenstruck\Foundry\Maker\Factory\ObjectDefaultPropertiesGuesser;
use Zenstruck\Foundry\Maker\Factory\ODMDefaultPropertiesGuesser;
use Zenstruck\Foundry\Maker\Factory\ORMDefaultPropertiesGuesser;
use Zenstruck\Foundry\Maker\MakeFactory;
use Zenstruck\Foundry\Maker\MakeStory;
use Zenstruck\Foundry\Maker\NamespaceGuesser;
use Zenstruck\Foundry\ORM\DoctrineOrmVersionGuesser;

return static function (ContainerConfigurator $container): void {
$container->services()
->set('.zenstruck_foundry.make_story', MakeStory::class)
->set('.zenstruck_foundry.maker.story', MakeStory::class)
->args([
service('.zenstruck_foundry.maker.namespace_guesser')
])
->tag('maker.command')

->set('.zenstruck_foundry.maker.factory', MakeFactory::class)
Expand Down Expand Up @@ -72,7 +75,7 @@
service('kernel'),
tagged_iterator('foundry.make_factory.default_properties_guesser'),
service('.zenstruck_foundry.maker.factory.factory_class_map'),
service('.zenstruck_foundry.maker.factory.namespace_guesser'),
service('.zenstruck_foundry.maker.namespace_guesser'),
])

->set('.zenstruck_foundry.maker.factory.autoCompleter', NoPersistenceObjectsAutoCompleter::class)
Expand All @@ -86,7 +89,7 @@
service('.zenstruck_foundry.maker.factory.factory_class_map'),
])

->set('.zenstruck_foundry.maker.factory.namespace_guesser', NamespaceGuesser::class)
->set('.zenstruck_foundry.maker.namespace_guesser', NamespaceGuesser::class)
->args([
service('.zenstruck_foundry.persistence_manager')->nullOnInvalid(),
])
Expand Down
1 change: 1 addition & 0 deletions src/Maker/Factory/FactoryGenerator.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
use Symfony\Component\Console\Style\SymfonyStyle;
use Symfony\Component\HttpKernel\KernelInterface;
use Zenstruck\Foundry\Maker\Factory\Exception\FactoryClassAlreadyExistException;
use Zenstruck\Foundry\Maker\NamespaceGuesser;
use Zenstruck\Foundry\Persistence\Exception\NoPersistenceStrategy;
use Zenstruck\Foundry\Persistence\PersistenceManager;

Expand Down
13 changes: 12 additions & 1 deletion src/Maker/MakeStory.php
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,13 @@
*/
final class MakeStory extends AbstractMaker
{
public function __construct(
private NamespaceGuesser $namespaceGuesser,
private string $defaultNamespace,
)
{
}

public static function getCommandName(): string
{
return 'make:story';
Expand All @@ -45,6 +52,7 @@ public function configureCommand(Command $command, InputConfiguration $inputConf
->setDescription(self::getCommandDescription())
->addArgument('name', InputArgument::OPTIONAL, 'The name of the story class (e.g. <fg=yellow>DefaultCategoriesStory</>)')
->addOption('test', null, InputOption::VALUE_NONE, 'Create in <fg=yellow>tests/</> instead of <fg=yellow>src/</>')
->addOption('namespace', null, InputOption::VALUE_REQUIRED, 'Customize the namespace for generated factories')
;

$inputConfig->setArgumentAsNonInteractive('name');
Expand All @@ -68,9 +76,12 @@ public function interact(InputInterface $input, ConsoleStyle $io, Command $comma

public function generate(InputInterface $input, ConsoleStyle $io, Generator $generator): void
{
$class = $input->getArgument('name');
$namespace = ($this->namespaceGuesser)($generator, $class, $input->getOption('namespace') ?? $this->defaultNamespace, $input->getOption('test'));

$storyClassNameDetails = $generator->createClassNameDetails(
$input->getArgument('name'),
$input->getOption('test') ? 'Tests\\Story' : 'Story',
$namespace,
'Story'
);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
* file that was distributed with this source code.
*/

namespace Zenstruck\Foundry\Maker\Factory;
namespace Zenstruck\Foundry\Maker;

use Symfony\Bundle\MakerBundle\Generator;
use Symfony\Bundle\MakerBundle\Str;
Expand Down
13 changes: 13 additions & 0 deletions src/ZenstruckFoundryBundle.php
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,16 @@ public function configure(DefinitionConfigurator $definition): void
->end()
->end()
->end()
->arrayNode('make_story')
->addDefaultsIfNotSet()
->children()
->scalarNode('default_namespace')
->info('Default namespace where stories will be created by maker.')
->defaultValue('Story')
->cannotBeEmpty()
->end()
->end()
->end()
->end()
;
}
Expand Down Expand Up @@ -177,6 +187,9 @@ public function loadExtension(array $config, ContainerConfigurator $configurator
$makeFactoryDefinition = $container->getDefinition('.zenstruck_foundry.maker.factory');
$makeFactoryDefinition->setArgument('$defaultNamespace', $config['make_factory']['default_namespace']);

$makeStoryDefinition = $container->getDefinition('.zenstruck_foundry.maker.story');
$makeStoryDefinition->setArgument('$defaultNamespace', $config['make_story']['default_namespace']);

if (!isset($bundles['DoctrineBundle'])) {
$container->removeDefinition('.zenstruck_foundry.maker.factory.orm_default_properties_guesser');
}
Expand Down
28 changes: 28 additions & 0 deletions tests/Integration/Maker/MakeStoryTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -205,4 +205,32 @@ public static function storyNameProvider(): iterable
yield ['FooBar'];
yield ['FooBarStory'];
}

/**
* @test
* @dataProvider namespaceProvider
* @param array<string, mixed> $commandOptions
*/
public function can_customize_namespace(string $filePath, array $commandOptions, string $expectedFullNamespace): void
{
$tester = new CommandTester((new Application(self::bootKernel()))->find('make:story'));

$this->assertFileDoesNotExist(self::tempFile($filePath));

$tester->execute(['name' => 'FooBar'] + $commandOptions);

$this->assertFileExists(self::tempFile($filePath));
self::assertStringContainsString("namespace $expectedFullNamespace", file_get_contents(self::tempFile($filePath))); // @phpstan-ignore-line
}

/**
* @return iterable<array{string, array<string, mixed>, string}>
*/
public static function namespaceProvider(): iterable
{
yield ['src/Some/Namespace/FooBarStory.php', ['--namespace' => 'Some\\Namespace'], 'App\\Some\\Namespace'];
yield ['src/Some/Namespace/FooBarStory.php', ['--namespace' => 'App\\Some\\Namespace'], 'App\\Some\\Namespace'];
yield ['tests/Some/Namespace/FooBarStory.php', ['--namespace' => 'Some\\Namespace', '--test' => true], 'App\\Tests\\Some\\Namespace'];
yield ['tests/Some/Namespace/FooBarStory.php', ['--namespace' => 'App\\Tests\\Some\\Namespace', '--test' => true], 'App\\Tests\\Some\\Namespace'];
}
}

0 comments on commit 2c8e048

Please sign in to comment.