3535use Symfony \Bundle \SecurityBundle \SecurityBundle ;
3636use Symfony \Bundle \TwigBundle \TwigBundle ;
3737use Symfony \Component \Console \Command \Command ;
38+ use Symfony \Component \Console \Input \InputArgument ;
3839use Symfony \Component \Console \Input \InputInterface ;
40+ use Symfony \Component \Console \Input \InputOption ;
3941use Symfony \Component \HttpFoundation \Response ;
4042use Symfony \Component \PasswordHasher \Hasher \UserPasswordHasherInterface ;
4143use Symfony \Component \Routing \Attribute \Route ;
@@ -57,11 +59,11 @@ final class MakeFormLogin extends AbstractMaker
5759
5860 private const SECURITY_CONFIG_PATH = 'config/packages/security.yaml ' ;
5961 private YamlSourceManipulator $ ysm ;
60- private string $ controllerName ;
6162 private string $ firewallToUpdate ;
6263 private string $ userClass ;
6364 private string $ userNameField ;
64- private bool $ willLogout ;
65+ /** @var ?array<string, mixed> */
66+ private ?array $ securityData = null ;
6567
6668 public function __construct (
6769 private FileManager $ fileManager ,
@@ -77,11 +79,12 @@ public static function getCommandName(): string
7779
7880 public function configureCommand (Command $ command , InputConfiguration $ inputConfig ): void
7981 {
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 ' )) ;
8385
8486 $ this ->configureCommandWithTestsOption ($ command );
87+ $ inputConfig ->setArgumentAsNonInteractive ('controllerName ' );
8588 }
8689
8790 public static function getCommandDescription (): string
@@ -113,38 +116,44 @@ public function interact(InputInterface $input, ConsoleStyle $io, Command $comma
113116 throw new RuntimeCommandException (\sprintf ('The file "%s" does not exist. PHP & XML configuration formats are currently not supported. ' , self ::SECURITY_CONFIG_PATH ));
114117 }
115118
116- $ this ->ysm = new YamlSourceManipulator ($ this ->fileManager ->getFileContents (self ::SECURITY_CONFIG_PATH ));
117- $ securityData = $ this ->ysm ->getData ();
119+ $ securityData = $ this ->getSecurityData ();
118120
119121 if (!isset ($ securityData ['security ' ]['providers ' ]) || !$ securityData ['security ' ]['providers ' ]) {
120122 throw new RuntimeCommandException ('To generate a form login authentication, you must configure at least one entry under "providers" in "security.yaml". ' );
121123 }
122124
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+ }
128133
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+ }
134137
135138 $ this ->interactSetGenerateTests ($ input , $ io );
136139 }
137140
138141 public function generate (InputInterface $ input , ConsoleStyle $ io , Generator $ generator ): void
139142 {
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+
140149 $ useStatements = new UseStatementGenerator ([
141150 AbstractController::class,
142151 Response::class,
143152 Route::class,
144153 AuthenticationUtils::class,
145154 ]);
146155
147- $ controllerNameDetails = $ generator ->createClassNameDetails ($ this -> controllerName , 'Controller \\' , 'Controller ' );
156+ $ controllerNameDetails = $ generator ->createClassNameDetails ($ input -> getArgument ( ' controllerName ' ) , 'Controller \\' , 'Controller ' );
148157 $ templatePath = strtolower ($ controllerNameDetails ->getRelativeNameWithoutSuffix ());
149158
150159 $ controllerPath = $ generator ->generateController (
@@ -157,7 +166,7 @@ public function generate(InputInterface $input, ConsoleStyle $io, Generator $gen
157166 ]
158167 );
159168
160- if ($ this -> willLogout ) {
169+ if ($ input -> getOption ( ' will-logout ' ) ) {
161170 $ manipulator = new ClassSourceManipulator ($ generator ->getFileContentsForPendingOperation ($ controllerPath ));
162171
163172 $ this ->securityControllerBuilder ->addLogoutMethod ($ manipulator );
@@ -169,26 +178,26 @@ public function generate(InputInterface $input, ConsoleStyle $io, Generator $gen
169178 \sprintf ('%s/login.html.twig ' , $ templatePath ),
170179 'security/formLogin/login_form.tpl.php ' ,
171180 [
172- 'logout_setup ' => $ this -> willLogout ,
181+ 'logout_setup ' => $ input -> getOption ( ' will-logout ' ) ,
173182 'username_label ' => Str::asHumanWords ($ this ->userNameField ),
174183 'username_is_email ' => false !== stripos ($ this ->userNameField , 'email ' ),
175184 ]
176185 );
177186
178187 $ securityData = $ this ->securityConfigUpdater ->updateForFormLogin ($ this ->ysm ->getContents (), $ this ->firewallToUpdate , 'app_login ' , 'app_login ' );
179188
180- if ($ this -> willLogout ) {
189+ if ($ input -> getOption ( ' will-logout ' ) ) {
181190 $ securityData = $ this ->securityConfigUpdater ->updateForLogout ($ securityData , $ this ->firewallToUpdate );
182191 }
183192
184- if ($ this -> shouldGenerateTests ( )) {
193+ if ($ input -> getOption ( ' with-tests ' )) {
185194 $ userClassNameDetails = $ generator ->createClassNameDetails (
186195 '\\' .$ this ->userClass ,
187196 'Entity \\'
188197 );
189198
190199 $ testClassDetails = $ generator ->createClassNameDetails (
191- ' LoginControllerTest ' ,
200+ $ controllerNameDetails -> getShortName (). ' Test ' ,
192201 'Test \\' ,
193202 );
194203
@@ -225,4 +234,17 @@ public function generate(InputInterface $input, ConsoleStyle $io, Generator $gen
225234 \sprintf ('Next: Review and adapt the login template: <info>%s/login.html.twig</info> to suit your needs. ' , $ templatePath ),
226235 ]);
227236 }
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+ }
228250}
0 commit comments