Вход Регистрация
Файл: concrete5.7.5.6/concrete/vendor/symfony/console/Helper/QuestionHelper.php
Строк: 404
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace SymfonyComponentConsoleHelper;

use 
SymfonyComponentConsoleInputInputInterface;
use 
SymfonyComponentConsoleOutputOutputInterface;
use 
SymfonyComponentConsoleFormatterOutputFormatterStyle;
use 
SymfonyComponentConsoleQuestionQuestion;
use 
SymfonyComponentConsoleQuestionChoiceQuestion;

/**
 * The QuestionHelper class provides helpers to interact with the user.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class QuestionHelper extends Helper
{
    private 
$inputStream;
    private static 
$shell;
    private static 
$stty;

    
/**
     * Asks a question to the user.
     *
     * @param InputInterface  $input    An InputInterface instance
     * @param OutputInterface $output   An OutputInterface instance
     * @param Question        $question The question to ask
     *
     * @return string The user answer
     *
     * @throws RuntimeException If there is no data to read in the input stream
     */
    
public function ask(InputInterface $inputOutputInterface $outputQuestion $question)
    {
        if (!
$input->isInteractive()) {
            return 
$question->getDefault();
        }

        if (!
$question->getValidator()) {
            return 
$this->doAsk($output$question);
        }

        
$that $this;

        
$interviewer = function () use ($output$question$that) {
            return 
$that->doAsk($output$question);
        };

        return 
$this->validateAttempts($interviewer$output$question);
    }

    
/**
     * Sets the input stream to read from when interacting with the user.
     *
     * This is mainly useful for testing purpose.
     *
     * @param resource $stream The input stream
     *
     * @throws InvalidArgumentException In case the stream is not a resource
     */
    
public function setInputStream($stream)
    {
        if (!
is_resource($stream)) {
            throw new 
InvalidArgumentException('Input stream must be a valid resource.');
        }

        
$this->inputStream $stream;
    }

    
/**
     * Returns the helper's input stream
     *
     * @return resource
     */
    
public function getInputStream()
    {
        return 
$this->inputStream;
    }

    
/**
     * {@inheritdoc}
     */
    
public function getName()
    {
        return 
'question';
    }

    
/**
     * Asks the question to the user.
     *
     * This method is public for PHP 5.3 compatibility, it should be private.
     *
     * @param OutputInterface $output
     * @param Question        $question
     *
     * @return bool|mixed|null|string
     *
     * @throws Exception
     * @throws RuntimeException
     */
    
public function doAsk(OutputInterface $outputQuestion $question)
    {
        
$this->writePrompt($output$question);

        
$inputStream $this->inputStream ?: STDIN;
        
$autocomplete $question->getAutocompleterValues();

        if (
null === $autocomplete || !$this->hasSttyAvailable()) {
            
$ret false;
            if (
$question->isHidden()) {
                try {
                    
$ret trim($this->getHiddenResponse($output$inputStream));
                } catch (
RuntimeException $e) {
                    if (!
$question->isHiddenFallback()) {
                        throw 
$e;
                    }
                }
            }

            if (
false === $ret) {
                
$ret fgets($inputStream4096);
                if (
false === $ret) {
                    throw new 
RuntimeException('Aborted');
                }
                
$ret trim($ret);
            }
        } else {
            
$ret trim($this->autocomplete($output$question$inputStream));
        }

        
$ret strlen($ret) > $ret $question->getDefault();

        if (
$normalizer $question->getNormalizer()) {
            return 
$normalizer($ret);
        }

        return 
$ret;
    }

    
/**
     * Outputs the question prompt.
     *
     * @param OutputInterface $output
     * @param Question $question
     */
    
protected function writePrompt(OutputInterface $outputQuestion $question)
    {
        
$message $question->getQuestion();

        if (
$question instanceof ChoiceQuestion) {
            
$width max(array_map('strlen'array_keys($question->getChoices())));

            
$messages = (array) $question->getQuestion();
            foreach (
$question->getChoices() as $key => $value) {
                
$messages[] = sprintf("  [<info>%-${width}s</info>] %s"$key$value);
            }

            
$output->writeln($messages);

            
$message $question->getPrompt();
        }

        
$output->write($message);
    }

    
/**
     * Outputs an error message.
     *
     * @param OutputInterface $output
     * @param Exception      $error
     */
    
protected function writeError(OutputInterface $outputException $error)
    {
        if (
null !== $this->getHelperSet() && $this->getHelperSet()->has('formatter')) {
            
$message $this->getHelperSet()->get('formatter')->formatBlock($error->getMessage(), 'error');
        } else {
            
$message '<error>'.$error->getMessage().'</error>';
        }

        
$output->writeln($message);
    }

    
/**
     * Autocompletes a question.
     *
     * @param OutputInterface $output
     * @param Question        $question
     *
     * @return string
     */
    
private function autocomplete(OutputInterface $outputQuestion $question$inputStream)
    {
        
$autocomplete $question->getAutocompleterValues();
        
$ret '';

        
$i 0;
        
$ofs = -1;
        
$matches $autocomplete;
        
$numMatches count($matches);

        
$sttyMode shell_exec('stty -g');

        
// Disable icanon (so we can fread each keypress) and echo (we'll do echoing here instead)
        
shell_exec('stty -icanon -echo');

        
// Add highlighted text style
        
$output->getFormatter()->setStyle('hl', new OutputFormatterStyle('black''white'));

        
// Read a keypress
        
while (!feof($inputStream)) {
            
$c fread($inputStream1);

            
// Backspace Character
            
if ("177" === $c) {
                if (
=== $numMatches && !== $i) {
                    
$i--;
                    
// Move cursor backwards
                    
$output->write("33[1D");
                }

                if (
$i === 0) {
                    
$ofs = -1;
                    
$matches $autocomplete;
                    
$numMatches count($matches);
                } else {
                    
$numMatches 0;
                }

                
// Pop the last character off the end of our string
                
$ret substr($ret0$i);
            } elseif (
"33" === $c) {
                
// Did we read an escape sequence?
                
$c .= fread($inputStream2);

                
// A = Up Arrow. B = Down Arrow
                
if (isset($c[2]) && ('A' === $c[2] || 'B' === $c[2])) {
                    if (
'A' === $c[2] && -=== $ofs) {
                        
$ofs 0;
                    }

                    if (
=== $numMatches) {
                        continue;
                    }

                    
$ofs += ('A' === $c[2]) ? -1;
                    
$ofs = ($numMatches $ofs) % $numMatches;
                }
            } elseif (
ord($c) < 32) {
                if (
"t" === $c || "n" === $c) {
                    if (
$numMatches && -!== $ofs) {
                        
$ret $matches[$ofs];
                        
// Echo out remaining chars for current match
                        
$output->write(substr($ret$i));
                        
$i strlen($ret);
                    }

                    if (
"n" === $c) {
                        
$output->write($c);
                        break;
                    }

                    
$numMatches 0;
                }

                continue;
            } else {
                
$output->write($c);
                
$ret .= $c;
                
$i++;

                
$numMatches 0;
                
$ofs 0;

                foreach (
$autocomplete as $value) {
                    
// If typed characters match the beginning chunk of value (e.g. [AcmeDe]moBundle)
                    
if (=== strpos($value$ret) && $i !== strlen($value)) {
                        
$matches[$numMatches++] = $value;
                    }
                }
            }

            
// Erase characters from cursor to end of line
            
$output->write("33[K");

            if (
$numMatches && -!== $ofs) {
                
// Save cursor position
                
$output->write("337");
                
// Write highlighted text
                
$output->write('<hl>'.substr($matches[$ofs], $i).'</hl>');
                
// Restore cursor position
                
$output->write("338");
            }
        }

        
// Reset stty so it behaves normally again
        
shell_exec(sprintf('stty %s'$sttyMode));

        return 
$ret;
    }

    
/**
     * Gets a hidden response from user.
     *
     * @param OutputInterface $output An Output instance
     *
     * @return string The answer
     *
     * @throws RuntimeException In case the fallback is deactivated and the response cannot be hidden
     */
    
private function getHiddenResponse(OutputInterface $output$inputStream)
    {
        if (
'\' === DIRECTORY_SEPARATOR) {
            $exe = __DIR__.'
/../Resources/bin/hiddeninput.exe';

            // handle code running from a phar
            if ('
phar:' === substr(__FILE__, 0, 5)) {
                $tmpExe = sys_get_temp_dir().'
/hiddeninput.exe';
                copy($exe, $tmpExe);
                $exe = $tmpExe;
            }

            $value = rtrim(shell_exec($exe));
            $output->writeln('');

            if (isset($tmpExe)) {
                unlink($tmpExe);
            }

            return $value;
        }

        if ($this->hasSttyAvailable()) {
            $sttyMode = shell_exec('
stty -g');

            shell_exec('
stty -echo');
            $value = fgets($inputStream, 4096);
            shell_exec(sprintf('
stty %s', $sttyMode));

            if (false === $value) {
                throw new RuntimeException('
Aborted');
            }

            $value = trim($value);
            $output->writeln('');

            return $value;
        }

        if (false !== $shell = $this->getShell()) {
            $readCmd = $shell === '
csh' ? 'set mypassword = $<' : 'read -r mypassword';
            $command = sprintf("/usr/bin/env %s -c '
stty -echo; %sstty echo; echo $mypassword'", $shell, $readCmd);
            $value = rtrim(shell_exec($command));
            $output->writeln('');

            return $value;
        }

        throw new RuntimeException('
Unable to hide the response.');
    }

    /**
     * Validates an attempt.
     *
     * @param callable        $interviewer A callable that will ask for a question and return the result
     * @param OutputInterface $output      An Output instance
     * @param Question        $question    A Question instance
     *
     * @return string The validated response
     *
     * @throws Exception In case the max number of attempts has been reached and no valid response has been given
     */
    private function validateAttempts($interviewer, OutputInterface $output, Question $question)
    {
        $error = null;
        $attempts = $question->getMaxAttempts();
        while (null === $attempts || $attempts--) {
            if (null !== $error) {
                $this->writeError($output, $error);
            }

            try {
                return call_user_func($question->getValidator(), $interviewer());
            } catch (Exception $error) {
            }
        }

        throw $error;
    }

    /**
     * Returns a valid unix shell.
     *
     * @return string|bool The valid shell name, false in case no valid shell is found
     */
    private function getShell()
    {
        if (null !== self::$shell) {
            return self::$shell;
        }

        self::$shell = false;

        if (file_exists('
/usr/bin/env')) {
            // handle other OSs with bash/zsh/ksh/csh if available to hide the answer
            $test = "/usr/bin/env %s -c '
echo OK' 2> /dev/null";
            foreach (array('
bash', 'zsh', 'ksh', 'csh') as $sh) {
                if ('
OK' === rtrim(shell_exec(sprintf($test, $sh)))) {
                    self::$shell = $sh;
                    break;
                }
            }
        }

        return self::$shell;
    }

    /**
     * Returns whether Stty is available or not.
     *
     * @return bool
     */
    private function hasSttyAvailable()
    {
        if (null !== self::$stty) {
            return self::$stty;
        }

        exec('
stty 2>&1', $output, $exitcode);

        return self::$stty = $exitcode === 0;
    }
}
Онлайн: 0
Реклама