@@ -34,6 +34,7 @@ class QuestionHelper extends Helper
3434 private $ inputStream ;
3535 private static $ shell ;
3636 private static $ stty = true ;
37+ private static $ stdinIsInteractive = true ;
3738
3839 /**
3940 * Asks a question to the user.
@@ -417,35 +418,28 @@ private function getHiddenResponse(OutputInterface $output, $inputStream, bool $
417418 return $ value ;
418419 }
419420
420- if (self :: $ stty && Terminal::hasSttyAvailable ()) {
421+ if (Terminal::hasSttyAvailable ()) {
421422 $ sttyMode = shell_exec ('stty -g ' );
422-
423423 shell_exec ('stty -echo ' );
424- $ value = fgets ($ inputStream , 4096 );
425- shell_exec (sprintf ('stty %s ' , $ sttyMode ));
424+ } elseif ($ this ->isInteractiveInput ($ inputStream )) {
425+ throw new RuntimeException ('Unable to hide the response. ' );
426+ }
426427
427- if (false === $ value ) {
428- throw new MissingInputException ('Aborted. ' );
429- }
430- if ($ trimmable ) {
431- $ value = trim ($ value );
432- }
433- $ output ->writeln ('' );
428+ $ value = fgets ($ inputStream , 4096 );
434429
435- return $ value ;
430+ if (Terminal::hasSttyAvailable ()) {
431+ shell_exec (sprintf ('stty %s ' , $ sttyMode ));
436432 }
437433
438- if (false !== $ shell = $ this ->getShell ()) {
439- $ readCmd = 'csh ' === $ shell ? 'set mypassword = $< ' : 'read -r mypassword ' ;
440- $ command = sprintf ("/usr/bin/env %s -c 'stty -echo; %s; stty echo; echo \$mypassword' 2> /dev/null " , $ shell , $ readCmd );
441- $ sCommand = shell_exec ($ command );
442- $ value = $ trimmable ? rtrim ($ sCommand ) : $ sCommand ;
443- $ output ->writeln ('' );
444-
445- return $ value ;
434+ if (false === $ value ) {
435+ throw new MissingInputException ('Aborted. ' );
446436 }
437+ if ($ trimmable ) {
438+ $ value = trim ($ value );
439+ }
440+ $ output ->writeln ('' );
447441
448- throw new RuntimeException ( ' Unable to hide the response. ' ) ;
442+ return $ value ;
449443 }
450444
451445 /**
@@ -473,56 +467,35 @@ private function validateAttempts(callable $interviewer, OutputInterface $output
473467 throw $ e ;
474468 } catch (\Exception $ error ) {
475469 }
476-
477- $ attempts = $ attempts ?? -(int ) $ this ->askForever ();
478470 }
479471
480472 throw $ error ;
481473 }
482474
483- /**
484- * Returns a valid unix shell.
485- *
486- * @return string|bool The valid shell name, false in case no valid shell is found
487- */
488- private function getShell ()
475+ private function isInteractiveInput ($ inputStream ): bool
489476 {
490- if (null !== self :: $ shell ) {
491- return self :: $ shell ;
477+ if (' php://stdin ' !== ( stream_get_meta_data ( $ inputStream )[ ' uri ' ] ?? null ) ) {
478+ return false ;
492479 }
493480
494- self ::$ shell = false ;
495-
496- if (file_exists ('/usr/bin/env ' )) {
497- // handle other OSs with bash/zsh/ksh/csh if available to hide the answer
498- $ test = "/usr/bin/env %s -c 'echo OK' 2> /dev/null " ;
499- foreach (['bash ' , 'zsh ' , 'ksh ' , 'csh ' ] as $ sh ) {
500- if ('OK ' === rtrim (shell_exec (sprintf ($ test , $ sh )))) {
501- self ::$ shell = $ sh ;
502- break ;
503- }
504- }
505- }
506-
507- return self ::$ shell ;
508- }
509-
510- private function askForever (): bool
511- {
512- $ inputStream = $ this ->inputStream ?: fopen ('php://stdin ' , 'r ' );
513-
514- if ('php://stdin ' !== (stream_get_meta_data ($ inputStream )['url ' ] ?? null )) {
515- return true ;
481+ if (null !== self ::$ stdinIsInteractive ) {
482+ return self ::$ stdinIsInteractive ;
516483 }
517484
518485 if (\function_exists ('stream_isatty ' )) {
519- return stream_isatty ($ inputStream );
486+ return self :: $ stdinIsInteractive = stream_isatty (fopen ( ' php://stdin ' , ' r ' ) );
520487 }
521488
522489 if (\function_exists ('posix_isatty ' )) {
523- return posix_isatty ($ inputStream );
490+ return self :: $ stdinIsInteractive = posix_isatty (fopen ( ' php://stdin ' , ' r ' ) );
524491 }
525492
526- return true ;
493+ if (!\function_exists ('exec ' )) {
494+ return self ::$ stdinIsInteractive = true ;
495+ }
496+
497+ exec ('stty 2> /dev/null ' , $ output , $ status );
498+
499+ return self ::$ stdinIsInteractive = 1 !== $ status ;
527500 }
528501}
0 commit comments