35
35
use Symfony \Bundle \SecurityBundle \SecurityBundle ;
36
36
use Symfony \Bundle \TwigBundle \TwigBundle ;
37
37
use Symfony \Component \Console \Command \Command ;
38
+ use Symfony \Component \Console \Input \InputArgument ;
38
39
use Symfony \Component \Console \Input \InputInterface ;
40
+ use Symfony \Component \Console \Input \InputOption ;
39
41
use Symfony \Component \HttpFoundation \Response ;
40
42
use Symfony \Component \PasswordHasher \Hasher \UserPasswordHasherInterface ;
41
43
use Symfony \Component \Routing \Attribute \Route ;
@@ -57,11 +59,11 @@ final class MakeFormLogin extends AbstractMaker
57
59
58
60
private const SECURITY_CONFIG_PATH = 'config/packages/security.yaml ' ;
59
61
private YamlSourceManipulator $ ysm ;
60
- private string $ controllerName ;
61
62
private string $ firewallToUpdate ;
62
63
private string $ userClass ;
63
64
private string $ userNameField ;
64
- private bool $ willLogout ;
65
+ /** @var ?array<string, mixed> */
66
+ private ?array $ securityData = null ;
65
67
66
68
public function __construct (
67
69
private FileManager $ fileManager ,
@@ -77,11 +79,12 @@ public static function getCommandName(): string
77
79
78
80
public function configureCommand (Command $ command , InputConfiguration $ inputConfig ): void
79
81
{
80
- $ command
81
- ->setHelp ( $ this -> getHelpFileContents ( ' security/MakeFormLogin.txt ' ) )
82
- ;
82
+ $ command-> addArgument ( ' controllerName ' , InputArgument:: OPTIONAL , ' The class name of the Controller (e.g. <fg=yellow>SecurityController</>) ' )
83
+ ->addOption ( ' will-logout ' , null , InputOption:: VALUE_NONE , ' Will generate a \' /logout \' URL? ' )
84
+ -> setHelp ( $ this -> getHelpFileContents ( ' security/MakeFormLogin.txt ' )) ;
83
85
84
86
$ this ->configureCommandWithTestsOption ($ command );
87
+ $ inputConfig ->setArgumentAsNonInteractive ('controllerName ' );
85
88
}
86
89
87
90
public static function getCommandDescription (): string
@@ -113,38 +116,44 @@ public function interact(InputInterface $input, ConsoleStyle $io, Command $comma
113
116
throw new RuntimeCommandException (\sprintf ('The file "%s" does not exist. PHP & XML configuration formats are currently not supported. ' , self ::SECURITY_CONFIG_PATH ));
114
117
}
115
118
116
- $ this ->ysm = new YamlSourceManipulator ($ this ->fileManager ->getFileContents (self ::SECURITY_CONFIG_PATH ));
117
- $ securityData = $ this ->ysm ->getData ();
119
+ $ securityData = $ this ->getSecurityData ();
118
120
119
121
if (!isset ($ securityData ['security ' ]['providers ' ]) || !$ securityData ['security ' ]['providers ' ]) {
120
122
throw new RuntimeCommandException ('To generate a form login authentication, you must configure at least one entry under "providers" in "security.yaml". ' );
121
123
}
122
124
123
- $ this ->controllerName = $ io ->ask (
124
- 'Choose a name for the controller class (e.g. <fg=yellow>SecurityController</>) ' ,
125
- 'SecurityController ' ,
126
- Validator::validateClassName (...)
127
- );
125
+ if (null === $ input ->getArgument ('controllerName ' )) {
126
+ $ input ->setArgument (
127
+ 'controllerName ' , $ io ->ask (
128
+ 'Choose a name for the controller class (e.g. <fg=yellow>SecurityController</>) ' ,
129
+ 'SecurityController ' ,
130
+ Validator::validateClassName (...)
131
+ ));
132
+ }
128
133
129
- $ securityHelper = new InteractiveSecurityHelper ();
130
- $ this ->firewallToUpdate = $ securityHelper ->guessFirewallName ($ io , $ securityData );
131
- $ this ->userClass = $ securityHelper ->guessUserClass ($ io , $ securityData ['security ' ]['providers ' ]);
132
- $ this ->userNameField = $ securityHelper ->guessUserNameField ($ io , $ this ->userClass , $ securityData ['security ' ]['providers ' ]);
133
- $ this ->willLogout = $ io ->confirm ('Do you want to generate a \'/logout \' URL? ' );
134
+ if (false === $ input ->getOption ('will-logout ' )) {
135
+ $ input ->setOption ('will-logout ' , $ io ->confirm ('Do you want to generate a \'/logout \' URL? ' ));
136
+ }
134
137
135
138
$ this ->interactSetGenerateTests ($ input , $ io );
136
139
}
137
140
138
141
public function generate (InputInterface $ input , ConsoleStyle $ io , Generator $ generator ): void
139
142
{
143
+ $ securityData = $ this ->getSecurityData ();
144
+ $ securityHelper = new InteractiveSecurityHelper ();
145
+ $ this ->firewallToUpdate = $ securityHelper ->guessFirewallName ($ io , $ securityData );
146
+ $ this ->userClass = $ securityHelper ->guessUserClass ($ io , $ securityData ['security ' ]['providers ' ]);
147
+ $ this ->userNameField = $ securityHelper ->guessUserNameField ($ io , $ this ->userClass , $ securityData ['security ' ]['providers ' ]);
148
+
140
149
$ useStatements = new UseStatementGenerator ([
141
150
AbstractController::class,
142
151
Response::class,
143
152
Route::class,
144
153
AuthenticationUtils::class,
145
154
]);
146
155
147
- $ controllerNameDetails = $ generator ->createClassNameDetails ($ this -> controllerName , 'Controller \\' , 'Controller ' );
156
+ $ controllerNameDetails = $ generator ->createClassNameDetails ($ input -> getArgument ( ' controllerName ' ) , 'Controller \\' , 'Controller ' );
148
157
$ templatePath = strtolower ($ controllerNameDetails ->getRelativeNameWithoutSuffix ());
149
158
150
159
$ controllerPath = $ generator ->generateController (
@@ -157,7 +166,7 @@ public function generate(InputInterface $input, ConsoleStyle $io, Generator $gen
157
166
]
158
167
);
159
168
160
- if ($ this -> willLogout ) {
169
+ if ($ input -> getOption ( ' will-logout ' ) ) {
161
170
$ manipulator = new ClassSourceManipulator ($ generator ->getFileContentsForPendingOperation ($ controllerPath ));
162
171
163
172
$ this ->securityControllerBuilder ->addLogoutMethod ($ manipulator );
@@ -169,26 +178,26 @@ public function generate(InputInterface $input, ConsoleStyle $io, Generator $gen
169
178
\sprintf ('%s/login.html.twig ' , $ templatePath ),
170
179
'security/formLogin/login_form.tpl.php ' ,
171
180
[
172
- 'logout_setup ' => $ this -> willLogout ,
181
+ 'logout_setup ' => $ input -> getOption ( ' will-logout ' ) ,
173
182
'username_label ' => Str::asHumanWords ($ this ->userNameField ),
174
183
'username_is_email ' => false !== stripos ($ this ->userNameField , 'email ' ),
175
184
]
176
185
);
177
186
178
187
$ securityData = $ this ->securityConfigUpdater ->updateForFormLogin ($ this ->ysm ->getContents (), $ this ->firewallToUpdate , 'app_login ' , 'app_login ' );
179
188
180
- if ($ this -> willLogout ) {
189
+ if ($ input -> getOption ( ' will-logout ' ) ) {
181
190
$ securityData = $ this ->securityConfigUpdater ->updateForLogout ($ securityData , $ this ->firewallToUpdate );
182
191
}
183
192
184
- if ($ this -> shouldGenerateTests ( )) {
193
+ if ($ input -> getOption ( ' with-tests ' )) {
185
194
$ userClassNameDetails = $ generator ->createClassNameDetails (
186
195
'\\' .$ this ->userClass ,
187
196
'Entity \\'
188
197
);
189
198
190
199
$ testClassDetails = $ generator ->createClassNameDetails (
191
- ' LoginControllerTest ' ,
200
+ $ controllerNameDetails -> getShortName (). ' Test ' ,
192
201
'Test \\' ,
193
202
);
194
203
@@ -225,4 +234,17 @@ public function generate(InputInterface $input, ConsoleStyle $io, Generator $gen
225
234
\sprintf ('Next: Review and adapt the login template: <info>%s/login.html.twig</info> to suit your needs. ' , $ templatePath ),
226
235
]);
227
236
}
237
+
238
+ /**
239
+ * @return array<string, mixed> $items
240
+ */
241
+ private function getSecurityData (): array
242
+ {
243
+ if (null === $ this ->securityData ) {
244
+ $ this ->ysm = new YamlSourceManipulator ($ this ->fileManager ->getFileContents (self ::SECURITY_CONFIG_PATH ));
245
+ $ this ->securityData = $ this ->ysm ->getData ();
246
+ }
247
+
248
+ return $ this ->securityData ;
249
+ }
228
250
}
0 commit comments