Skip to content

Commit b0aa109

Browse files
fix(controller): fix error undefined when generate controller
1 parent d3ca5d4 commit b0aa109

File tree

3 files changed

+101
-5
lines changed

3 files changed

+101
-5
lines changed

src/Command/MakeTwcController.php

Lines changed: 99 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,13 +13,16 @@
1313

1414
use Doctrine\Common\Annotations\Annotation;
1515
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
16+
use Symfony\Bundle\FrameworkBundle\Test\WebTestCase;
1617
use Symfony\Bundle\MakerBundle\ConsoleStyle;
1718
use Symfony\Bundle\MakerBundle\DependencyBuilder;
1819
use Symfony\Bundle\MakerBundle\FileManager;
1920
use Symfony\Bundle\MakerBundle\Generator;
2021
use Symfony\Bundle\MakerBundle\InputConfiguration;
2122
use Symfony\Bundle\MakerBundle\Maker\AbstractMaker;
23+
use Symfony\Bundle\MakerBundle\Maker\Common\CanGenerateTestsTrait;
2224
use Symfony\Bundle\MakerBundle\Str;
25+
use Symfony\Bundle\MakerBundle\Util\ClassSource\Model\ClassData;
2326
use Symfony\Bundle\MakerBundle\Util\PhpCompatUtil;
2427
use Symfony\Bundle\MakerBundle\Util\UseStatementGenerator;
2528
use Symfony\Bundle\TwigBundle\TwigBundle;
@@ -36,10 +39,15 @@
3639
final class MakeTwcController extends AbstractMaker
3740
{
3841

42+
use CanGenerateTestsTrait;
43+
44+
private bool $isInvokable;
45+
private ClassData $controllerClassData;
46+
private bool $usesTwigTemplate;
47+
private string $twigTemplatePath;
3948

4049
public function __construct(
4150
private ContextGenerator $contextGenerator,
42-
private FileManager $fileManager,
4351
private ?PhpCompatUtil $phpCompatUtil = null,
4452

4553
) {
@@ -71,9 +79,99 @@ public function configureCommand(Command $command, InputConfiguration $inputConf
7179
->addOption('invokable', 'i', InputOption::VALUE_NONE, 'Use this option to create an invokable controller')
7280
->addOption('context', 'c', InputOption::VALUE_OPTIONAL, 'your context config to generate on your target')
7381
;
82+
$this->configureCommandWithTestsOption($command);
83+
}
84+
85+
public function interact(InputInterface $input, ConsoleStyle $io, Command $command): void
86+
{
87+
$this->usesTwigTemplate = $this->isTwigInstalled() && !$input->getOption('no-template');
88+
$this->isInvokable = (bool) $input->getOption('invokable');
89+
90+
$controllerClass = $input->getArgument('controller-class');
91+
$controllerClassName = \sprintf('Controller\%s', $controllerClass);
92+
93+
$context = $input->getOption('context');
94+
95+
$namespaceContext = $this->contextGenerator->classNameByContext(
96+
Support::CONTROLLER,
97+
Str::addSuffix($controllerClass, 'Controller'),
98+
$context
99+
);
100+
101+
// If the class name provided is absolute, we do not assume it will live in src/Controller
102+
// e.g. src/Custom/Location/For/MyController instead of src/Controller/MyController
103+
if ($isAbsoluteNamespace = '\\' === $controllerClass[0]) {
104+
$controllerClassName = substr($controllerClass, 1);
105+
}
106+
107+
$this->controllerClassData = ClassData::create(
108+
class: $namespaceContext,
109+
suffix: 'Controller',
110+
extendsClass: AbstractController::class,
111+
useStatements: [
112+
$this->usesTwigTemplate ? Response::class : JsonResponse::class,
113+
\Symfony\Component\Routing\Attribute\Route::class,
114+
]
115+
);
116+
117+
// Again if the class name is absolute, lets not make assumptions about where the twig template
118+
// should live. E.g. templates/custom/location/for/my_controller.html.twig instead of
119+
// templates/my/controller.html.twig. We do however remove the root_namespace prefix in either case
120+
// so we don't end up with templates/app/my/controller.html.twig
121+
$templateName = $this->controllerClassData->getFullClassName(withoutRootNamespace: true, withoutSuffix: true);
122+
123+
$dir = $this->contextGenerator->getDirTemplateByContext('template', $context);
124+
// Convert the twig template name into a file path where it will be generated.
125+
$this->twigTemplatePath = \sprintf('%s%s', $dir, $this->isInvokable ? '.html.twig' : '/index.html.twig');
126+
127+
$this->interactSetGenerateTests($input, $io);
74128
}
75129

76130
public function generate(InputInterface $input, ConsoleStyle $io, Generator $generator): void
131+
{
132+
$controllerPath = $generator->generateClassFromClassData($this->controllerClassData, 'controller/Controller.tpl.php', [
133+
'route_path' => Str::asRoutePath($this->controllerClassData->getClassName(relative: true, withoutSuffix: true)),
134+
'route_name' => Str::AsRouteName($this->controllerClassData->getClassName(relative: true, withoutSuffix: true)),
135+
'method_name' => $this->isInvokable ? '__invoke' : 'index',
136+
'with_template' => $this->usesTwigTemplate,
137+
'template_name' => $this->twigTemplatePath,
138+
], true);
139+
140+
if ($this->usesTwigTemplate) {
141+
$generator->generateTemplate(
142+
$this->twigTemplatePath,
143+
'controller/twig_template.tpl.php',
144+
[
145+
'controller_path' => $controllerPath,
146+
'root_directory' => $generator->getRootDirectory(),
147+
'class_name' => $this->controllerClassData->getClassName(),
148+
]
149+
);
150+
}
151+
152+
if ($this->shouldGenerateTests()) {
153+
$testClassData = ClassData::create(
154+
class: \sprintf('Tests\Controller\%s', $this->controllerClassData->getClassName(relative: true, withoutSuffix: true)),
155+
suffix: 'ControllerTest',
156+
extendsClass: WebTestCase::class,
157+
);
158+
159+
$generator->generateClassFromClassData($testClassData, 'controller/test/Test.tpl.php', [
160+
'route_path' => Str::asRoutePath($this->controllerClassData->getClassName(relative: true, withoutSuffix: true)),
161+
]);
162+
163+
if (!class_exists(WebTestCase::class)) {
164+
$io->caution('You\'ll need to install the `symfony/test-pack` to execute the tests for your new controller.');
165+
}
166+
}
167+
168+
$generator->writeChanges();
169+
170+
$this->writeSuccessMessage($io);
171+
$io->text('Next: Open your new controller class and add some pages!');
172+
}
173+
174+
public function generate1(InputInterface $input, ConsoleStyle $io, Generator $generator): void
77175
{
78176
$controllerClass = $input->getArgument('controller-class');
79177
$context = $input->getOption('context');

src/Command/MakeTwcEntity.php

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -60,11 +60,10 @@ final class MakeTwcEntity extends AbstractMaker implements InputAwareMakerInterf
6060
public function __construct(
6161
private FileManager $fileManager,
6262
private DoctrineHelper $doctrineHelper,
63+
ContextGenerator $contextGenerator,
6364
?string $projectDirectory = null,
6465
?Generator $generator = null,
6566
?EntityClassGenerator $entityClassGenerator = null,
66-
ContextGenerator $contextGenerator,
67-
6867
) {
6968
$this->contextGenerator = $contextGenerator;
7069

src/Resources/config/services.yaml

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ services:
77
Twc\MakerBundle\Command\MakeTwcController:
88
arguments:
99
- '@Twc\MakerBundle\ContextGenerator'
10-
- '@maker.file_manager'
1110
tags:
1211
- { name: 'maker.command'}
1312

@@ -62,9 +61,9 @@ services:
6261
arguments:
6362
- '@maker.file_manager'
6463
- '@maker.doctrine_helper'
64+
- '@Twc\MakerBundle\ContextGenerator'
6565
- '%kernel.project_dir%'
6666
- '@maker.generator'
6767
- '@Twc\MakerBundle\Doctrine\EntityClassGenerator'
68-
- '@Twc\MakerBundle\ContextGenerator'
6968
tags:
7069
- { name: 'maker.command'}

0 commit comments

Comments
 (0)