55
66namespace fsmaker \Console ;
77
8+ use Laravel \Prompts \MultiSelectPrompt ;
9+ use Laravel \Prompts \Prompt ;
10+ use Laravel \Prompts \SelectPrompt ;
11+ use Laravel \Prompts \TextPrompt ;
812use Symfony \Component \Console \Application as BaseApplication ;
913use Symfony \Component \Console \Input \InputDefinition ;
1014use Symfony \Component \Console \Input \InputArgument ;
1115use Symfony \Component \Console \Input \InputOption ;
16+ use Symfony \Component \Console \Input \InputInterface ;
17+ use Symfony \Component \Console \Output \OutputInterface ;
18+ use Symfony \Component \Console \Question \ChoiceQuestion ;
19+ use Symfony \Component \Console \Style \SymfonyStyle ;
1220
1321class Application extends BaseApplication
1422{
@@ -18,6 +26,119 @@ public function __construct()
1826 $ this ->addCommands ($ this ->getCommands ());
1927 }
2028
29+ public function doRun (InputInterface $ input , OutputInterface $ output ): int
30+ {
31+ // Fix para windows (la librería prompt no lo soporta)
32+ Prompt::fallbackWhen (PHP_OS_FAMILY === 'Windows ' );
33+ // Prompt::fallbackWhen(true); // para tests
34+
35+ $ io = new SymfonyStyle ($ input , $ output );
36+
37+ TextPrompt::fallbackUsing (function (TextPrompt $ prompt ) use ($ io ) {
38+ while (true ) {
39+ $ value = $ io ->ask ($ prompt ->label , $ prompt ->default );
40+
41+ if ($ prompt ->validate ) {
42+ $ error = ($ prompt ->validate )($ value ?? '' );
43+ if (is_string ($ error ) && strlen ($ error ) > 0 ) {
44+ $ io ->writeln ("<fg=red>Error: $ error</> " );
45+ continue ;
46+ }
47+ }
48+ return (string )$ value ;
49+ }
50+ });
51+
52+ SelectPrompt::fallbackUsing (function (SelectPrompt $ prompt ) use ($ io ) {
53+ $ question = new ChoiceQuestion ($ prompt ->label , $ prompt ->options , $ prompt ->default );
54+ // Capturar el validador por defecto
55+ $ validator = $ question ->getValidator ();
56+
57+ $ question ->setValidator (function ($ answer ) {
58+ return $ answer ;
59+ });
60+
61+ while (true ) {
62+ // Aquí el askQuestion llamará a nuestro validador nulo.
63+ $ answer = $ io ->askQuestion ($ question );
64+
65+ try {
66+ // Validar manualmente con el validador original.
67+ // El validador original espera el valor tal cual sale del normalizador interno.
68+ $ choice = $ validator ($ answer );
69+
70+ // Ensure we return the key if options are associative
71+ if (array_is_list ($ prompt ->options )) {
72+ return $ choice ;
73+ }
74+ return array_search ($ choice , $ prompt ->options ) ?: $ choice ;
75+ } catch (\Exception $ e ) {
76+ $ msg = $ e ->getMessage ();
77+ if (preg_match ('/^Value "(.*)" is invalid$/ ' , $ msg , $ matches )) {
78+ $ msg = "El valor \"{$ matches [1 ]}\" es inválido " ;
79+ }
80+ $ io ->writeln ("<fg=red>Error: $ msg</> " );
81+ }
82+ }
83+ });
84+
85+ MultiSelectPrompt::fallbackUsing (function (MultiSelectPrompt $ prompt ) use ($ io ) {
86+ $ default = $ prompt ->default ;
87+ if (is_array ($ default ) && !empty ($ default )) {
88+ $ default = implode (', ' , $ default );
89+ } elseif (empty ($ default )) {
90+ $ default = null ;
91+ }
92+
93+ $ question = new ChoiceQuestion ($ prompt ->label , $ prompt ->options , $ default );
94+ $ question ->setMultiselect (true );
95+
96+ // Normalizador para permitir separar por espacios además de comas
97+ $ question ->setNormalizer (function ($ value ) {
98+ if ($ value === null ) {
99+ return $ value ;
100+ }
101+ // Reemplaza uno o más espacios/comas con una sola coma
102+ return preg_replace ('/[\s,]+/ ' , ', ' , trim ($ value ));
103+ });
104+
105+ // Capturar el validador por defecto
106+ $ validator = $ question ->getValidator ();
107+ // Anular el validador en la pregunta
108+ $ question ->setValidator (function ($ answer ) {
109+ return $ answer ;
110+ });
111+
112+ while (true ) {
113+ $ result = $ io ->askQuestion ($ question );
114+ try {
115+ // Validar manualmente
116+ $ result = $ validator ($ result );
117+
118+ if (array_is_list ($ prompt ->options )) {
119+ return $ result ;
120+ }
121+
122+ // Map values back to keys
123+ $ mapped = [];
124+ foreach ($ result as $ val ) {
125+ $ key = array_search ($ val , $ prompt ->options );
126+ $ mapped [] = $ key !== false ? $ key : $ val ;
127+ }
128+ return $ mapped ;
129+ } catch (\Exception $ e ) {
130+ $ msg = $ e ->getMessage ();
131+ if (preg_match ('/^Value "(.*)" is invalid$/ ' , $ msg , $ matches )) {
132+ $ msg = "El valor \"{$ matches [1 ]}\" es inválido " ;
133+ }
134+ $ io ->writeln ("<fg=red>Error: $ msg</> " );
135+ }
136+ }
137+ });
138+
139+ return parent ::doRun ($ input , $ output );
140+ }
141+
21142 /**
22143 * Esto es para definir solo las opciones existentes (en fsmaker no existen opciones)
23144 */
0 commit comments