Skip to content

Commit

Permalink
support for root namespaces and suffix's
Browse files Browse the repository at this point in the history
  • Loading branch information
jrushlow committed May 19, 2024
1 parent 7826980 commit 522869b
Show file tree
Hide file tree
Showing 9 changed files with 105 additions and 31 deletions.
1 change: 1 addition & 0 deletions src/DependencyInjection/MakerExtension.php
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ public function load(array $configs, ContainerBuilder $container): void
$componentGeneratorDefinition
->replaceArgument(0, $config['generate_final_classes'])
->replaceArgument(1, $config['generate_final_entities'])
->replaceArgument(2, $rootNamespace)
;

$container->registerForAutoconfiguration(MakerInterface::class)
Expand Down
10 changes: 6 additions & 4 deletions src/Maker/MakeCrud.php
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,8 @@ public function generate(InputInterface $input, ConsoleStyle $io, Generator $gen
} while (class_exists($formClassDetails->getFullName()));

$controllerClassData = ClassData::create(
class: sprintf('App\Controller\%sController', $this->controllerClassName),
class: sprintf('Controller\%s', $this->controllerClassName),
suffix: 'Controller',
extendsClass: AbstractController::class,
useStatements: [
$entityClassDetails->getFullName(),
Expand All @@ -175,7 +176,7 @@ class: sprintf('App\Controller\%sController', $this->controllerClassName),
}

$generator->generateController(
$controllerClassDetails->getFullName(),
$controllerClassData->getFullClassName(),
'crud/controller/Controller.tpl.php',
array_merge([
'class_data' => $controllerClassData,
Expand Down Expand Up @@ -247,7 +248,8 @@ class: sprintf('App\Controller\%sController', $this->controllerClassName),

if ($this->shouldGenerateTests()) {
$testClassData = ClassData::create(
class: sprintf('App\Tests\Controller\%sControllerTest', $entityClassDetails->getRelativeNameWithoutSuffix()),
class: sprintf('Tests\Controller\%s', $entityClassDetails->getRelativeNameWithoutSuffix()),
suffix: 'ControllerTest',
extendsClass: WebTestCase::class,
useStatements: [
$entityClassDetails->getFullName(),
Expand All @@ -263,7 +265,7 @@ class: sprintf('App\Tests\Controller\%sControllerTest', $entityClassDetails->get
}

$generator->generateClass(
$testClassData->fullClassName,
$testClassData->getFullClassName(),
'crud/test/Test.EntityManager.tpl.php',
[
'class_data' => $testClassData,
Expand Down
22 changes: 12 additions & 10 deletions src/Maker/MakeVoter.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,9 @@
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\Security\Core\Authorization\Voter\Voter;
use Symfony\Component\Security\Core\User\UserInterface;

/**
* @author Javier Eguiluz <javier.eguiluz@gmail.com>
Expand Down Expand Up @@ -47,21 +49,21 @@ public function configureCommand(Command $command, InputConfiguration $inputConf

public function generate(InputInterface $input, ConsoleStyle $io, Generator $generator): void
{
$classMetaData = ClassData::create(
class: sprintf('App\Security\Voter\%sVoter', $input->getArgument('name')),
$voterClassData = ClassData::create(
class: sprintf('Security\Voter\%s', $input->getArgument('name')),
suffix: 'Voter',
extendsClass: Voter::class,
);

$voterClassNameDetails = $generator->createClassNameDetails(
$input->getArgument('name'),
'Security\\Voter\\',
'Voter'
useStatements: [
TokenInterface::class,
Voter::class,
UserInterface::class,
]
);

$generator->generateClass(
$voterClassNameDetails->getFullName(),
$voterClassData->getFullClassName(),
'security/Voter.tpl.php',
['class_data' => $classMetaData]
['class_data' => $voterClassData]
);

$generator->writeChanges();
Expand Down
5 changes: 3 additions & 2 deletions src/Resources/config/services.xml
Original file line number Diff line number Diff line change
Expand Up @@ -80,8 +80,9 @@
</service>

<service id="maker.template_component_generator" class="Symfony\Bundle\MakerBundle\Util\TemplateComponentGenerator">
<argument /> <!-- generate_final_classes -->
<argument /> <!-- generate_final_entities -->
<argument /> <!-- generate_final_classes -->
<argument /> <!-- generate_final_entities -->
<argument /> <!-- root_namespace -->
</service>
</services>
</container>
2 changes: 1 addition & 1 deletion src/Resources/skeleton/crud/controller/Controller.tpl.php
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<?= "<?php\n" ?>

namespace <?= $namespace ?>;
namespace <?= $class_data->getNamespace() ?>;

<?= $class_data->getUseStatements(); ?>

Expand Down
8 changes: 3 additions & 5 deletions src/Resources/skeleton/security/Voter.tpl.php
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
<?= "<?php\n" ?>

namespace <?= $namespace; ?>;
namespace <?= $class_data->getNamespace(); ?>;

use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\Security\Core\Authorization\Voter\Voter;
use Symfony\Component\Security\Core\User\UserInterface;
<?= $class_data->getUseStatements(); ?>

<?= $class_data->getClassDeclaration() ?>
{
Expand All @@ -16,7 +14,7 @@ protected function supports(string $attribute, mixed $subject): bool
// replace with your own logic
// https://symfony.com/doc/current/security/voters.html
return in_array($attribute, [self::EDIT, self::VIEW])
&& $subject instanceof \App\Entity\<?= str_replace('Voter', null, $class_name) ?>;
&& $subject instanceof \App\Entity\<?= str_replace('Voter', null, $class_data->getClassName()) ?>;
}

protected function voteOnAttribute(string $attribute, mixed $subject, TokenInterface $token): bool
Expand Down
43 changes: 37 additions & 6 deletions src/Util/ClassSource/Model/ClassData.php
Original file line number Diff line number Diff line change
Expand Up @@ -22,34 +22,65 @@
final class ClassData
{
private function __construct(
public readonly string $className,
public readonly string $namespace,
public readonly string $fullClassName,
private string $className,
private string $namespace,
public readonly ?string $extends,
public readonly bool $isEntity,
private UseStatementGenerator $useStatementGenerator,
private bool $isFinal = true,
private string $rootNamespace = 'App',
) {
}

public static function create(string $class, ?string $extendsClass = null, bool $isEntity = false, array $useStatements = []): self
public static function create(string $class, ?string $suffix = null, ?string $extendsClass = null, bool $isEntity = false, array $useStatements = []): self
{
$className = Str::getShortClassName($class);

if (null !== $suffix && !str_ends_with($className, $suffix)) {
$className = Str::asClassName(sprintf('%s%s', $className, $suffix));
}

$useStatements = new UseStatementGenerator($useStatements);

if ($extendsClass) {
$useStatements->addUseStatement($extendsClass);
}

return new self(
className: Str::getShortClassName($class),
className: Str::asClassName($className),
namespace: Str::getNamespace($class),
fullClassName: $class,
extends: null === $extendsClass ? null : Str::getShortClassName($extendsClass),
isEntity: $isEntity,
useStatementGenerator: $useStatements,
);
}

public function getClassName(): string
{
return $this->className;
}

public function getNamespace(): string
{
if (empty($this->namespace)) {
return $this->rootNamespace;
}

return sprintf('%s\%s', $this->rootNamespace, $this->namespace);
}

public function getFullClassName(): string
{
return sprintf('%s\%s', $this->getNamespace(), $this->className);
}

public function setRootNamespace(string $rootNamespace): self
{
$this->rootNamespace = $rootNamespace;

return $this;
}

public function getClassDeclaration(): string
{
$extendsDeclaration = '';
Expand Down
3 changes: 3 additions & 0 deletions src/Util/TemplateComponentGenerator.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ final class TemplateComponentGenerator
public function __construct(
private bool $generateFinalClasses,
private bool $generateFinalEntities,
private string $rootNamespace,
) {
}

Expand Down Expand Up @@ -54,6 +55,8 @@ public function getPropertyType(ClassNameDetails $classNameDetails): ?string

public function configureClass(ClassData $classMetadata): ClassData
{
$classMetadata->setRootNamespace($this->rootNamespace);

if ($classMetadata->isEntity) {
return $classMetadata->setIsFinal($this->generateFinalEntities);
}
Expand Down
42 changes: 39 additions & 3 deletions tests/Util/ClassSource/ClassDataTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,9 @@ public function testStaticConstructor(): void
// Sanity check in case Maker's NS changes
self::assertSame('Symfony\Bundle\MakerBundle\MakerBundle', MakerBundle::class);

self::assertSame('MakerBundle', $meta->className);
self::assertSame('Symfony\Bundle\MakerBundle', $meta->namespace);
self::assertSame('Symfony\Bundle\MakerBundle\MakerBundle', $meta->fullClassName);
self::assertSame('MakerBundle', $meta->getClassName());
self::assertSame('App\Symfony\Bundle\MakerBundle', $meta->getNamespace());
self::assertSame('App\Symfony\Bundle\MakerBundle\MakerBundle', $meta->getFullClassName());
}

public function testGetClassDeclaration(): void
Expand Down Expand Up @@ -55,4 +55,40 @@ public function testGetClassDeclarationWithExtends(): void

self::assertSame('final class MakerBundle extends MakerTestKernel', $meta->getClassDeclaration());
}

/** @dataProvider suffixDataProvider */
public function testSuffix(?string $suffix, string $expectedResult): void
{
$data = ClassData::create(class: MakerBundle::class, suffix: $suffix);

self::assertSame($expectedResult, $data->getClassName());
}

public function suffixDataProvider(): \Generator
{
yield [null, 'MakerBundle'];
yield ['Testing', 'MakerBundleTesting'];
yield ['Bundle', 'MakerBundle'];
}

/** @dataProvider namespaceDataProvider */
public function testNamespace(string $class, ?string $rootNamespace, string $expectedNamespace, string $expectedFullClassName): void
{
$class = ClassData::create($class);

if (null !== $rootNamespace) {
$class->setRootNamespace($rootNamespace);
}

self::assertSame($expectedNamespace, $class->getNamespace());
self::assertSame($expectedFullClassName, $class->getFullClassName());
}

public function namespaceDataProvider(): \Generator
{
yield ['MyController', null, 'App', 'App\MyController'];
yield ['Controller\MyController', null, 'App\Controller', 'App\Controller\MyController'];
yield ['MyController', 'Maker', 'Maker', 'Maker\MyController'];
yield ['Controller\MyController', 'Maker', 'Maker\Controller', 'Maker\Controller\MyController'];
}
}

0 comments on commit 522869b

Please sign in to comment.