Overview

Namespaces

  • Contrib
    • Bundle
      • CoverallsBundle
        • Console
        • Entity
      • CoverallsV1Bundle
        • Api
        • Collector
        • Command
        • Config
        • Entity
          • Git
    • Component
      • File
      • Log
      • System
        • Git
  • Guzzle
    • Batch
      • Exception
    • Cache
    • Common
      • Exception
    • Http
      • Curl
      • Exception
      • Message
      • QueryAggregator
    • Inflection
    • Iterator
    • Log
    • Parser
      • Cookie
      • Message
      • UriTemplate
      • Url
    • Plugin
      • Async
      • Backoff
      • Cache
      • Cookie
        • CookieJar
        • Exception
      • CurlAuth
      • ErrorResponse
        • Exception
      • History
      • Log
      • Md5
      • Mock
      • Oauth
    • Service
      • Builder
      • Command
        • Factory
        • LocationVisitor
          • Request
          • Response
      • Description
      • Exception
      • Resource
    • Stream
  • PHP
  • Psr
    • Log
  • Symfony
    • Component
      • Config
        • Definition
          • Builder
          • Exception
        • Exception
        • Loader
        • Resource
        • Util
      • Console
        • Command
        • Formatter
        • Helper
        • Input
        • Output
        • Tester
      • EventDispatcher
        • Debug
      • Finder
        • Adapter
        • Comparator
        • Exception
        • Expression
        • Iterator
        • Shell
      • Stopwatch
      • Yaml
        • Exception

Classes

  • Application
  • Shell
  • Overview
  • Namespace
  • Class
  • Tree
  • Todo
  1: <?php
  2: 
  3: /*
  4:  * This file is part of the Symfony package.
  5:  *
  6:  * (c) Fabien Potencier <fabien@symfony.com>
  7:  *
  8:  * For the full copyright and license information, please view the LICENSE
  9:  * file that was distributed with this source code.
 10:  */
 11: 
 12: namespace Symfony\Component\Console;
 13: 
 14: use Symfony\Component\Console\Application;
 15: use Symfony\Component\Console\Input\StringInput;
 16: use Symfony\Component\Console\Output\ConsoleOutput;
 17: use Symfony\Component\Process\ProcessBuilder;
 18: use Symfony\Component\Process\PhpExecutableFinder;
 19: 
 20: /**
 21:  * A Shell wraps an Application to add shell capabilities to it.
 22:  *
 23:  * Support for history and completion only works with a PHP compiled
 24:  * with readline support (either --with-readline or --with-libedit)
 25:  *
 26:  * @author Fabien Potencier <fabien@symfony.com>
 27:  * @author Martin HasoĊˆ <martin.hason@gmail.com>
 28:  */
 29: class Shell
 30: {
 31:     private $application;
 32:     private $history;
 33:     private $output;
 34:     private $hasReadline;
 35:     private $prompt;
 36:     private $processIsolation;
 37: 
 38:     /**
 39:      * Constructor.
 40:      *
 41:      * If there is no readline support for the current PHP executable
 42:      * a \RuntimeException exception is thrown.
 43:      *
 44:      * @param Application $application An application instance
 45:      */
 46:     public function __construct(Application $application)
 47:     {
 48:         $this->hasReadline = function_exists('readline');
 49:         $this->application = $application;
 50:         $this->history = getenv('HOME').'/.history_'.$application->getName();
 51:         $this->output = new ConsoleOutput();
 52:         $this->prompt = $application->getName().' > ';
 53:         $this->processIsolation = false;
 54:     }
 55: 
 56:     /**
 57:      * Runs the shell.
 58:      */
 59:     public function run()
 60:     {
 61:         $this->application->setAutoExit(false);
 62:         $this->application->setCatchExceptions(true);
 63: 
 64:         if ($this->hasReadline) {
 65:             readline_read_history($this->history);
 66:             readline_completion_function(array($this, 'autocompleter'));
 67:         }
 68: 
 69:         $this->output->writeln($this->getHeader());
 70:         $php = null;
 71:         if ($this->processIsolation) {
 72:             $finder = new PhpExecutableFinder();
 73:             $php = $finder->find();
 74:             $this->output->writeln(<<<EOF
 75: <info>Running with process isolation, you should consider this:</info>
 76:   * each command is executed as separate process,
 77:   * commands don't support interactivity, all params must be passed explicitly,
 78:   * commands output is not colorized.
 79: 
 80: EOF
 81:             );
 82:         }
 83: 
 84:         while (true) {
 85:             $command = $this->readline();
 86: 
 87:             if (false === $command) {
 88:                 $this->output->writeln("\n");
 89: 
 90:                 break;
 91:             }
 92: 
 93:             if ($this->hasReadline) {
 94:                 readline_add_history($command);
 95:                 readline_write_history($this->history);
 96:             }
 97: 
 98:             if ($this->processIsolation) {
 99:                 $pb = new ProcessBuilder();
100: 
101:                 $process = $pb
102:                     ->add($php)
103:                     ->add($_SERVER['argv'][0])
104:                     ->add($command)
105:                     ->inheritEnvironmentVariables(true)
106:                     ->getProcess()
107:                 ;
108: 
109:                 $output = $this->output;
110:                 $process->run(function($type, $data) use ($output) {
111:                     $output->writeln($data);
112:                 });
113: 
114:                 $ret = $process->getExitCode();
115:             } else {
116:                 $ret = $this->application->run(new StringInput($command), $this->output);
117:             }
118: 
119:             if (0 !== $ret) {
120:                 $this->output->writeln(sprintf('<error>The command terminated with an error status (%s)</error>', $ret));
121:             }
122:         }
123:     }
124: 
125:     /**
126:      * Returns the shell header.
127:      *
128:      * @return string The header string
129:      */
130:     protected function getHeader()
131:     {
132:         return <<<EOF
133: 
134: Welcome to the <info>{$this->application->getName()}</info> shell (<comment>{$this->application->getVersion()}</comment>).
135: 
136: At the prompt, type <comment>help</comment> for some help,
137: or <comment>list</comment> to get a list of available commands.
138: 
139: To exit the shell, type <comment>^D</comment>.
140: 
141: EOF;
142:     }
143: 
144:     /**
145:      * Tries to return autocompletion for the current entered text.
146:      *
147:      * @param string $text The last segment of the entered text
148:      *
149:      * @return Boolean|array A list of guessed strings or true
150:      */
151:     private function autocompleter($text)
152:     {
153:         $info = readline_info();
154:         $text = substr($info['line_buffer'], 0, $info['end']);
155: 
156:         if ($info['point'] !== $info['end']) {
157:             return true;
158:         }
159: 
160:         // task name?
161:         if (false === strpos($text, ' ') || !$text) {
162:             return array_keys($this->application->all());
163:         }
164: 
165:         // options and arguments?
166:         try {
167:             $command = $this->application->find(substr($text, 0, strpos($text, ' ')));
168:         } catch (\Exception $e) {
169:             return true;
170:         }
171: 
172:         $list = array('--help');
173:         foreach ($command->getDefinition()->getOptions() as $option) {
174:             $list[] = '--'.$option->getName();
175:         }
176: 
177:         return $list;
178:     }
179: 
180:     /**
181:      * Reads a single line from standard input.
182:      *
183:      * @return string The single line from standard input
184:      */
185:     private function readline()
186:     {
187:         if ($this->hasReadline) {
188:             $line = readline($this->prompt);
189:         } else {
190:             $this->output->write($this->prompt);
191:             $line = fgets(STDIN, 1024);
192:             $line = (!$line && strlen($line) == 0) ? false : rtrim($line);
193:         }
194: 
195:         return $line;
196:     }
197: 
198:     public function getProcessIsolation()
199:     {
200:         return $this->processIsolation;
201:     }
202: 
203:     public function setProcessIsolation($processIsolation)
204:     {
205:         $this->processIsolation = (Boolean) $processIsolation;
206: 
207:         if ($this->processIsolation && !class_exists('Symfony\\Component\\Process\\Process')) {
208:             throw new \RuntimeException('Unable to isolate processes as the Symfony Process Component is not installed.');
209:         }
210:     }
211: }
212: 
php-coveralls API documentation generated by ApiGen 2.8.0