Verzeichnisstruktur phpBB-3.1.0


Veröffentlicht
27.10.2014

So funktioniert es


Auf das letzte Element klicken. Dies geht jeweils ein Schritt zurück

Auf das Icon klicken, dies öffnet das Verzeichnis. Nochmal klicken schließt das Verzeichnis.
Auf den Verzeichnisnamen klicken, dies zeigt nur das Verzeichnis mit Inhalt an

(Beispiel Datei-Icons)

Auf das Icon klicken um den Quellcode anzuzeigen

Application.php

Zuletzt modifiziert: 09.10.2024, 12:58 - Dateigröße: 36.77 KiB


0001  <?php
0002   
0003  /*
0004   * This file is part of the Symfony package.
0005   *
0006   * (c) Fabien Potencier <fabien@symfony.com>
0007   *
0008   * For the full copyright and license information, please view the LICENSE
0009   * file that was distributed with this source code.
0010   */
0011   
0012  namespace Symfony\Component\Console;
0013   
0014  use Symfony\Component\Console\Descriptor\TextDescriptor;
0015  use Symfony\Component\Console\Descriptor\XmlDescriptor;
0016  use Symfony\Component\Console\Input\InputInterface;
0017  use Symfony\Component\Console\Input\ArgvInput;
0018  use Symfony\Component\Console\Input\ArrayInput;
0019  use Symfony\Component\Console\Input\InputDefinition;
0020  use Symfony\Component\Console\Input\InputOption;
0021  use Symfony\Component\Console\Input\InputArgument;
0022  use Symfony\Component\Console\Output\OutputInterface;
0023  use Symfony\Component\Console\Output\ConsoleOutput;
0024  use Symfony\Component\Console\Output\ConsoleOutputInterface;
0025  use Symfony\Component\Console\Command\Command;
0026  use Symfony\Component\Console\Command\HelpCommand;
0027  use Symfony\Component\Console\Command\ListCommand;
0028  use Symfony\Component\Console\Helper\HelperSet;
0029  use Symfony\Component\Console\Helper\FormatterHelper;
0030  use Symfony\Component\Console\Helper\DialogHelper;
0031  use Symfony\Component\Console\Helper\ProgressHelper;
0032  use Symfony\Component\Console\Helper\TableHelper;
0033  use Symfony\Component\Console\Event\ConsoleCommandEvent;
0034  use Symfony\Component\Console\Event\ConsoleExceptionEvent;
0035  use Symfony\Component\Console\Event\ConsoleTerminateEvent;
0036  use Symfony\Component\EventDispatcher\EventDispatcherInterface;
0037   
0038  /**
0039   * An Application is the container for a collection of commands.
0040   *
0041   * It is the main entry point of a Console application.
0042   *
0043   * This class is optimized for a standard CLI environment.
0044   *
0045   * Usage:
0046   *
0047   *     $app = new Application('myapp', '1.0 (stable)');
0048   *     $app->add(new SimpleCommand());
0049   *     $app->run();
0050   *
0051   * @author Fabien Potencier <fabien@symfony.com>
0052   *
0053   * @api
0054   */
0055  class Application
0056  {
0057      private $commands;
0058      private $wantHelps = false;
0059      private $runningCommand;
0060      private $name;
0061      private $version;
0062      private $catchExceptions;
0063      private $autoExit;
0064      private $definition;
0065      private $helperSet;
0066      private $dispatcher;
0067   
0068      /**
0069       * Constructor.
0070       *
0071       * @param string $name    The name of the application
0072       * @param string $version The version of the application
0073       *
0074       * @api
0075       */
0076      public function __construct($name = 'UNKNOWN', $version = 'UNKNOWN')
0077      {
0078          $this->name = $name;
0079          $this->version = $version;
0080          $this->catchExceptions = true;
0081          $this->autoExit = true;
0082          $this->commands = array();
0083          $this->helperSet = $this->getDefaultHelperSet();
0084          $this->definition = $this->getDefaultInputDefinition();
0085   
0086          foreach ($this->getDefaultCommands() as $command) {
0087              $this->add($command);
0088          }
0089      }
0090   
0091      public function setDispatcher(EventDispatcherInterface $dispatcher)
0092      {
0093          $this->dispatcher = $dispatcher;
0094      }
0095   
0096      /**
0097       * Runs the current application.
0098       *
0099       * @param InputInterface  $input  An Input instance
0100       * @param OutputInterface $output An Output instance
0101       *
0102       * @return int 0 if everything went fine, or an error code
0103       *
0104       * @throws \Exception When doRun returns Exception
0105       *
0106       * @api
0107       */
0108      public function run(InputInterface $input = null, OutputInterface $output = null)
0109      {
0110          if (null === $input) {
0111              $input = new ArgvInput();
0112          }
0113   
0114          if (null === $output) {
0115              $output = new ConsoleOutput();
0116          }
0117   
0118          $this->configureIO($input, $output);
0119   
0120          try {
0121              $exitCode = $this->doRun($input, $output);
0122          } catch (\Exception $e) {
0123              if (!$this->catchExceptions) {
0124                  throw $e;
0125              }
0126   
0127              if ($output instanceof ConsoleOutputInterface) {
0128                  $this->renderException($e, $output->getErrorOutput());
0129              } else {
0130                  $this->renderException($e, $output);
0131              }
0132   
0133              $exitCode = $e->getCode();
0134              if (is_numeric($exitCode)) {
0135                  $exitCode = (int) $exitCode;
0136                  if (0 === $exitCode) {
0137                      $exitCode = 1;
0138                  }
0139              } else {
0140                  $exitCode = 1;
0141              }
0142          }
0143   
0144          if ($this->autoExit) {
0145              if ($exitCode > 255) {
0146                  $exitCode = 255;
0147              }
0148              // @codeCoverageIgnoreStart
0149              exit($exitCode);
0150              // @codeCoverageIgnoreEnd
0151          }
0152   
0153          return $exitCode;
0154      }
0155   
0156      /**
0157       * Runs the current application.
0158       *
0159       * @param InputInterface  $input  An Input instance
0160       * @param OutputInterface $output An Output instance
0161       *
0162       * @return int 0 if everything went fine, or an error code
0163       */
0164      public function doRun(InputInterface $input, OutputInterface $output)
0165      {
0166          if (true === $input->hasParameterOption(array('--version', '-V'))) {
0167              $output->writeln($this->getLongVersion());
0168   
0169              return 0;
0170          }
0171   
0172          $name = $this->getCommandName($input);
0173          if (true === $input->hasParameterOption(array('--help', '-h'))) {
0174              if (!$name) {
0175                  $name = 'help';
0176                  $input = new ArrayInput(array('command' => 'help'));
0177              } else {
0178                  $this->wantHelps = true;
0179              }
0180          }
0181   
0182          if (!$name) {
0183              $name = 'list';
0184              $input = new ArrayInput(array('command' => 'list'));
0185          }
0186   
0187          // the command name MUST be the first element of the input
0188          $command = $this->find($name);
0189   
0190          $this->runningCommand = $command;
0191          $exitCode = $this->doRunCommand($command, $input, $output);
0192          $this->runningCommand = null;
0193   
0194          return $exitCode;
0195      }
0196   
0197      /**
0198       * Set a helper set to be used with the command.
0199       *
0200       * @param HelperSet $helperSet The helper set
0201       *
0202       * @api
0203       */
0204      public function setHelperSet(HelperSet $helperSet)
0205      {
0206          $this->helperSet = $helperSet;
0207      }
0208   
0209      /**
0210       * Get the helper set associated with the command.
0211       *
0212       * @return HelperSet The HelperSet instance associated with this command
0213       *
0214       * @api
0215       */
0216      public function getHelperSet()
0217      {
0218          return $this->helperSet;
0219      }
0220   
0221      /**
0222       * Set an input definition set to be used with this application
0223       *
0224       * @param InputDefinition $definition The input definition
0225       *
0226       * @api
0227       */
0228      public function setDefinition(InputDefinition $definition)
0229      {
0230          $this->definition = $definition;
0231      }
0232   
0233      /**
0234       * Gets the InputDefinition related to this Application.
0235       *
0236       * @return InputDefinition The InputDefinition instance
0237       */
0238      public function getDefinition()
0239      {
0240          return $this->definition;
0241      }
0242   
0243      /**
0244       * Gets the help message.
0245       *
0246       * @return string A help message.
0247       */
0248      public function getHelp()
0249      {
0250          $messages = array(
0251              $this->getLongVersion(),
0252              '',
0253              '<comment>Usage:</comment>',
0254              '  [options] command [arguments]',
0255              '',
0256              '<comment>Options:</comment>',
0257          );
0258   
0259          foreach ($this->getDefinition()->getOptions() as $option) {
0260              $messages[] = sprintf('  %-29s %s %s',
0261                  '<info>--'.$option->getName().'</info>',
0262                  $option->getShortcut() ? '<info>-'.$option->getShortcut().'</info>' : '  ',
0263                  $option->getDescription()
0264              );
0265          }
0266   
0267          return implode(PHP_EOL, $messages);
0268      }
0269   
0270      /**
0271       * Sets whether to catch exceptions or not during commands execution.
0272       *
0273       * @param bool $boolean Whether to catch exceptions or not during commands execution
0274       *
0275       * @api
0276       */
0277      public function setCatchExceptions($boolean)
0278      {
0279          $this->catchExceptions = (bool) $boolean;
0280      }
0281   
0282      /**
0283       * Sets whether to automatically exit after a command execution or not.
0284       *
0285       * @param bool $boolean Whether to automatically exit after a command execution or not
0286       *
0287       * @api
0288       */
0289      public function setAutoExit($boolean)
0290      {
0291          $this->autoExit = (bool) $boolean;
0292      }
0293   
0294      /**
0295       * Gets the name of the application.
0296       *
0297       * @return string The application name
0298       *
0299       * @api
0300       */
0301      public function getName()
0302      {
0303          return $this->name;
0304      }
0305   
0306      /**
0307       * Sets the application name.
0308       *
0309       * @param string $name The application name
0310       *
0311       * @api
0312       */
0313      public function setName($name)
0314      {
0315          $this->name = $name;
0316      }
0317   
0318      /**
0319       * Gets the application version.
0320       *
0321       * @return string The application version
0322       *
0323       * @api
0324       */
0325      public function getVersion()
0326      {
0327          return $this->version;
0328      }
0329   
0330      /**
0331       * Sets the application version.
0332       *
0333       * @param string $version The application version
0334       *
0335       * @api
0336       */
0337      public function setVersion($version)
0338      {
0339          $this->version = $version;
0340      }
0341   
0342      /**
0343       * Returns the long version of the application.
0344       *
0345       * @return string The long application version
0346       *
0347       * @api
0348       */
0349      public function getLongVersion()
0350      {
0351          if ('UNKNOWN' !== $this->getName() && 'UNKNOWN' !== $this->getVersion()) {
0352              return sprintf('<info>%s</info> version <comment>%s</comment>', $this->getName(), $this->getVersion());
0353          }
0354   
0355          return '<info>Console Tool</info>';
0356      }
0357   
0358      /**
0359       * Registers a new command.
0360       *
0361       * @param string $name The command name
0362       *
0363       * @return Command The newly created command
0364       *
0365       * @api
0366       */
0367      public function register($name)
0368      {
0369          return $this->add(new Command($name));
0370      }
0371   
0372      /**
0373       * Adds an array of command objects.
0374       *
0375       * @param Command[] $commands An array of commands
0376       *
0377       * @api
0378       */
0379      public function addCommands(array $commands)
0380      {
0381          foreach ($commands as $command) {
0382              $this->add($command);
0383          }
0384      }
0385   
0386      /**
0387       * Adds a command object.
0388       *
0389       * If a command with the same name already exists, it will be overridden.
0390       *
0391       * @param Command $command A Command object
0392       *
0393       * @return Command The registered command
0394       *
0395       * @api
0396       */
0397      public function add(Command $command)
0398      {
0399          $command->setApplication($this);
0400   
0401          if (!$command->isEnabled()) {
0402              $command->setApplication(null);
0403   
0404              return;
0405          }
0406   
0407          $this->commands[$command->getName()] = $command;
0408   
0409          foreach ($command->getAliases() as $alias) {
0410              $this->commands[$alias] = $command;
0411          }
0412   
0413          return $command;
0414      }
0415   
0416      /**
0417       * Returns a registered command by name or alias.
0418       *
0419       * @param string $name The command name or alias
0420       *
0421       * @return Command A Command object
0422       *
0423       * @throws \InvalidArgumentException When command name given does not exist
0424       *
0425       * @api
0426       */
0427      public function get($name)
0428      {
0429          if (!isset($this->commands[$name])) {
0430              throw new \InvalidArgumentException(sprintf('The command "%s" does not exist.', $name));
0431          }
0432   
0433          $command = $this->commands[$name];
0434   
0435          if ($this->wantHelps) {
0436              $this->wantHelps = false;
0437   
0438              $helpCommand = $this->get('help');
0439              $helpCommand->setCommand($command);
0440   
0441              return $helpCommand;
0442          }
0443   
0444          return $command;
0445      }
0446   
0447      /**
0448       * Returns true if the command exists, false otherwise.
0449       *
0450       * @param string $name The command name or alias
0451       *
0452       * @return bool true if the command exists, false otherwise
0453       *
0454       * @api
0455       */
0456      public function has($name)
0457      {
0458          return isset($this->commands[$name]);
0459      }
0460   
0461      /**
0462       * Returns an array of all unique namespaces used by currently registered commands.
0463       *
0464       * It does not returns the global namespace which always exists.
0465       *
0466       * @return array An array of namespaces
0467       */
0468      public function getNamespaces()
0469      {
0470          $namespaces = array();
0471          foreach ($this->commands as $command) {
0472              $namespaces[] = $this->extractNamespace($command->getName());
0473   
0474              foreach ($command->getAliases() as $alias) {
0475                  $namespaces[] = $this->extractNamespace($alias);
0476              }
0477          }
0478   
0479          return array_values(array_unique(array_filter($namespaces)));
0480      }
0481   
0482      /**
0483       * Finds a registered namespace by a name or an abbreviation.
0484       *
0485       * @param string $namespace A namespace or abbreviation to search for
0486       *
0487       * @return string A registered namespace
0488       *
0489       * @throws \InvalidArgumentException When namespace is incorrect or ambiguous
0490       */
0491      public function findNamespace($namespace)
0492      {
0493          $allNamespaces = $this->getNamespaces();
0494          $found = '';
0495          foreach (explode(':', $namespace) as $i => $part) {
0496              // select sub-namespaces matching the current namespace we found
0497              $namespaces = array();
0498              foreach ($allNamespaces as $n) {
0499                  if ('' === $found || 0 === strpos($n, $found)) {
0500                      $namespaces[$n] = explode(':', $n);
0501                  }
0502              }
0503   
0504              $abbrevs = static::getAbbreviations(array_unique(array_values(array_filter(array_map(function ($p) use ($i) { return isset($p[$i]) ? $p[$i] : ''; }, $namespaces)))));
0505   
0506              if (!isset($abbrevs[$part])) {
0507                  $message = sprintf('There are no commands defined in the "%s" namespace.', $namespace);
0508   
0509                  if (1 <= $i) {
0510                      $part = $found.':'.$part;
0511                  }
0512   
0513                  if ($alternatives = $this->findAlternativeNamespace($part, $abbrevs)) {
0514                      if (1 == count($alternatives)) {
0515                          $message .= "\n\nDid you mean this?\n    ";
0516                      } else {
0517                          $message .= "\n\nDid you mean one of these?\n    ";
0518                      }
0519   
0520                      $message .= implode("\n    ", $alternatives);
0521                  }
0522   
0523                  throw new \InvalidArgumentException($message);
0524              }
0525   
0526              // there are multiple matches, but $part is an exact match of one of them so we select it
0527              if (in_array($part, $abbrevs[$part])) {
0528                  $abbrevs[$part] = array($part);
0529              }
0530   
0531              if (count($abbrevs[$part]) > 1) {
0532                  throw new \InvalidArgumentException(sprintf('The namespace "%s" is ambiguous (%s).', $namespace, $this->getAbbreviationSuggestions($abbrevs[$part])));
0533              }
0534   
0535              $found .= $found ? ':'.$abbrevs[$part][0] : $abbrevs[$part][0];
0536          }
0537   
0538          return $found;
0539      }
0540   
0541      /**
0542       * Finds a command by name or alias.
0543       *
0544       * Contrary to get, this command tries to find the best
0545       * match if you give it an abbreviation of a name or alias.
0546       *
0547       * @param string $name A command name or a command alias
0548       *
0549       * @return Command A Command instance
0550       *
0551       * @throws \InvalidArgumentException When command name is incorrect or ambiguous
0552       *
0553       * @api
0554       */
0555      public function find($name)
0556      {
0557          // namespace
0558          $namespace = '';
0559          $searchName = $name;
0560          if (false !== $pos = strrpos($name, ':')) {
0561              $namespace = $this->findNamespace(substr($name, 0, $pos));
0562              $searchName = $namespace.substr($name, $pos);
0563          }
0564   
0565          // name
0566          $commands = array();
0567          foreach ($this->commands as $command) {
0568              $extractedNamespace = $this->extractNamespace($command->getName());
0569              if ($extractedNamespace === $namespace
0570                 || !empty($namespace) && 0 === strpos($extractedNamespace, $namespace)
0571              ) {
0572                  $commands[] = $command->getName();
0573              }
0574          }
0575   
0576          $abbrevs = static::getAbbreviations(array_unique($commands));
0577          if (isset($abbrevs[$searchName]) && 1 == count($abbrevs[$searchName])) {
0578              return $this->get($abbrevs[$searchName][0]);
0579          }
0580   
0581          if (isset($abbrevs[$searchName]) && in_array($searchName, $abbrevs[$searchName])) {
0582              return $this->get($searchName);
0583          }
0584   
0585          if (isset($abbrevs[$searchName]) && count($abbrevs[$searchName]) > 1) {
0586              $suggestions = $this->getAbbreviationSuggestions($abbrevs[$searchName]);
0587   
0588              throw new \InvalidArgumentException(sprintf('Command "%s" is ambiguous (%s).', $name, $suggestions));
0589          }
0590   
0591          // aliases
0592          $aliases = array();
0593          foreach ($this->commands as $command) {
0594              foreach ($command->getAliases() as $alias) {
0595                  $extractedNamespace = $this->extractNamespace($alias);
0596                  if ($extractedNamespace === $namespace
0597                     || !empty($namespace) && 0 === strpos($extractedNamespace, $namespace)
0598                  ) {
0599                      $aliases[] = $alias;
0600                  }
0601              }
0602          }
0603   
0604          $aliases = static::getAbbreviations(array_unique($aliases));
0605          if (!isset($aliases[$searchName])) {
0606              $message = sprintf('Command "%s" is not defined.', $name);
0607   
0608              if ($alternatives = $this->findAlternativeCommands($searchName, $abbrevs)) {
0609                  if (1 == count($alternatives)) {
0610                      $message .= "\n\nDid you mean this?\n    ";
0611                  } else {
0612                      $message .= "\n\nDid you mean one of these?\n    ";
0613                  }
0614                  $message .= implode("\n    ", $alternatives);
0615              }
0616   
0617              throw new \InvalidArgumentException($message);
0618          }
0619   
0620          if (count($aliases[$searchName]) > 1) {
0621              throw new \InvalidArgumentException(sprintf('Command "%s" is ambiguous (%s).', $name, $this->getAbbreviationSuggestions($aliases[$searchName])));
0622          }
0623   
0624          return $this->get($aliases[$searchName][0]);
0625      }
0626   
0627      /**
0628       * Gets the commands (registered in the given namespace if provided).
0629       *
0630       * The array keys are the full names and the values the command instances.
0631       *
0632       * @param string $namespace A namespace name
0633       *
0634       * @return Command[] An array of Command instances
0635       *
0636       * @api
0637       */
0638      public function all($namespace = null)
0639      {
0640          if (null === $namespace) {
0641              return $this->commands;
0642          }
0643   
0644          $commands = array();
0645          foreach ($this->commands as $name => $command) {
0646              if ($namespace === $this->extractNamespace($name, substr_count($namespace, ':') + 1)) {
0647                  $commands[$name] = $command;
0648              }
0649          }
0650   
0651          return $commands;
0652      }
0653   
0654      /**
0655       * Returns an array of possible abbreviations given a set of names.
0656       *
0657       * @param array $names An array of names
0658       *
0659       * @return array An array of abbreviations
0660       */
0661      public static function getAbbreviations($names)
0662      {
0663          $abbrevs = array();
0664          foreach ($names as $name) {
0665              for ($len = strlen($name); $len > 0; --$len) {
0666                  $abbrev = substr($name, 0, $len);
0667                  $abbrevs[$abbrev][] = $name;
0668              }
0669          }
0670   
0671          return $abbrevs;
0672      }
0673   
0674      /**
0675       * Returns a text representation of the Application.
0676       *
0677       * @param string $namespace An optional namespace name
0678       * @param bool   $raw       Whether to return raw command list
0679       *
0680       * @return string A string representing the Application
0681       *
0682       * @deprecated Deprecated since version 2.3, to be removed in 3.0.
0683       */
0684      public function asText($namespace = null, $raw = false)
0685      {
0686          $descriptor = new TextDescriptor();
0687   
0688          return $descriptor->describe($this, array('namespace' => $namespace, 'raw_text' => $raw));
0689      }
0690   
0691      /**
0692       * Returns an XML representation of the Application.
0693       *
0694       * @param string $namespace An optional namespace name
0695       * @param bool   $asDom     Whether to return a DOM or an XML string
0696       *
0697       * @return string|\DOMDocument An XML string representing the Application
0698       *
0699       * @deprecated Deprecated since version 2.3, to be removed in 3.0.
0700       */
0701      public function asXml($namespace = null, $asDom = false)
0702      {
0703          $descriptor = new XmlDescriptor();
0704   
0705          return $descriptor->describe($this, array('namespace' => $namespace, 'as_dom' => $asDom));
0706      }
0707   
0708      /**
0709       * Renders a caught exception.
0710       *
0711       * @param \Exception      $e      An exception instance
0712       * @param OutputInterface $output An OutputInterface instance
0713       */
0714      public function renderException($e, $output)
0715      {
0716          do {
0717              $title = sprintf('  [%s]  ', get_class($e));
0718   
0719              $len = $this->stringWidth($title);
0720   
0721              $width = $this->getTerminalWidth() ? $this->getTerminalWidth() - 1 : PHP_INT_MAX;
0722              // HHVM only accepts 32 bits integer in str_split, even when PHP_INT_MAX is a 64 bit integer: https://github.com/facebook/hhvm/issues/1327
0723              if (defined('HHVM_VERSION') && $width > 1 << 31) {
0724                  $width = 1 << 31;
0725              }
0726              $formatter = $output->getFormatter();
0727              $lines = array();
0728              foreach (preg_split('/\r?\n/', $e->getMessage()) as $line) {
0729                  foreach ($this->splitStringByWidth($line, $width - 4) as $line) {
0730                      // pre-format lines to get the right string length
0731                      $lineLength = $this->stringWidth(preg_replace('/\[[^m]*m/', '', $formatter->format($line))) + 4;
0732                      $lines[] = array($line, $lineLength);
0733   
0734                      $len = max($lineLength, $len);
0735                  }
0736              }
0737   
0738              $messages = array('', '');
0739              $messages[] = $emptyLine = $formatter->format(sprintf('<error>%s</error>', str_repeat(' ', $len)));
0740              $messages[] = $formatter->format(sprintf('<error>%s%s</error>', $title, str_repeat(' ', max(0, $len - $this->stringWidth($title)))));
0741              foreach ($lines as $line) {
0742                  $messages[] = $formatter->format(sprintf('<error>  %s  %s</error>', $line[0], str_repeat(' ', $len - $line[1])));
0743              }
0744              $messages[] = $emptyLine;
0745              $messages[] = '';
0746              $messages[] = '';
0747   
0748              $output->writeln($messages, OutputInterface::OUTPUT_RAW);
0749   
0750              if (OutputInterface::VERBOSITY_VERBOSE <= $output->getVerbosity()) {
0751                  $output->writeln('<comment>Exception trace:</comment>');
0752   
0753                  // exception related properties
0754                  $trace = $e->getTrace();
0755                  array_unshift($trace, array(
0756                      'function' => '',
0757                      'file'     => $e->getFile() != null ? $e->getFile() : 'n/a',
0758                      'line'     => $e->getLine() != null ? $e->getLine() : 'n/a',
0759                      'args'     => array(),
0760                  ));
0761   
0762                  for ($i = 0, $count = count($trace); $i < $count; $i++) {
0763                      $class = isset($trace[$i]['class']) ? $trace[$i]['class'] : '';
0764                      $type = isset($trace[$i]['type']) ? $trace[$i]['type'] : '';
0765                      $function = $trace[$i]['function'];
0766                      $file = isset($trace[$i]['file']) ? $trace[$i]['file'] : 'n/a';
0767                      $line = isset($trace[$i]['line']) ? $trace[$i]['line'] : 'n/a';
0768   
0769                      $output->writeln(sprintf(' %s%s%s() at <info>%s:%s</info>', $class, $type, $function, $file, $line));
0770                  }
0771   
0772                  $output->writeln("");
0773                  $output->writeln("");
0774              }
0775          } while ($e = $e->getPrevious());
0776   
0777          if (null !== $this->runningCommand) {
0778              $output->writeln(sprintf('<info>%s</info>', sprintf($this->runningCommand->getSynopsis(), $this->getName())));
0779              $output->writeln("");
0780              $output->writeln("");
0781          }
0782      }
0783   
0784      /**
0785       * Tries to figure out the terminal width in which this application runs
0786       *
0787       * @return int|null
0788       */
0789      protected function getTerminalWidth()
0790      {
0791          $dimensions = $this->getTerminalDimensions();
0792   
0793          return $dimensions[0];
0794      }
0795   
0796      /**
0797       * Tries to figure out the terminal height in which this application runs
0798       *
0799       * @return int|null
0800       */
0801      protected function getTerminalHeight()
0802      {
0803          $dimensions = $this->getTerminalDimensions();
0804   
0805          return $dimensions[1];
0806      }
0807   
0808      /**
0809       * Tries to figure out the terminal dimensions based on the current environment
0810       *
0811       * @return array Array containing width and height
0812       */
0813      public function getTerminalDimensions()
0814      {
0815          if (defined('PHP_WINDOWS_VERSION_BUILD')) {
0816              // extract [w, H] from "wxh (WxH)"
0817              if (preg_match('/^(\d+)x\d+ \(\d+x(\d+)\)$/', trim(getenv('ANSICON')), $matches)) {
0818                  return array((int) $matches[1], (int) $matches[2]);
0819              }
0820              // extract [w, h] from "wxh"
0821              if (preg_match('/^(\d+)x(\d+)$/', $this->getConsoleMode(), $matches)) {
0822                  return array((int) $matches[1], (int) $matches[2]);
0823              }
0824          }
0825   
0826          if ($sttyString = $this->getSttyColumns()) {
0827              // extract [w, h] from "rows h; columns w;"
0828              if (preg_match('/rows.(\d+);.columns.(\d+);/i', $sttyString, $matches)) {
0829                  return array((int) $matches[2], (int) $matches[1]);
0830              }
0831              // extract [w, h] from "; h rows; w columns"
0832              if (preg_match('/;.(\d+).rows;.(\d+).columns/i', $sttyString, $matches)) {
0833                  return array((int) $matches[2], (int) $matches[1]);
0834              }
0835          }
0836   
0837          return array(null, null);
0838      }
0839   
0840      /**
0841       * Configures the input and output instances based on the user arguments and options.
0842       *
0843       * @param InputInterface  $input  An InputInterface instance
0844       * @param OutputInterface $output An OutputInterface instance
0845       */
0846      protected function configureIO(InputInterface $input, OutputInterface $output)
0847      {
0848          if (true === $input->hasParameterOption(array('--ansi'))) {
0849              $output->setDecorated(true);
0850          } elseif (true === $input->hasParameterOption(array('--no-ansi'))) {
0851              $output->setDecorated(false);
0852          }
0853   
0854          if (true === $input->hasParameterOption(array('--no-interaction', '-n'))) {
0855              $input->setInteractive(false);
0856          } elseif (function_exists('posix_isatty') && $this->getHelperSet()->has('dialog')) {
0857              $inputStream = $this->getHelperSet()->get('dialog')->getInputStream();
0858              if (!@posix_isatty($inputStream)) {
0859                  $input->setInteractive(false);
0860              }
0861          }
0862   
0863          if (true === $input->hasParameterOption(array('--quiet', '-q'))) {
0864              $output->setVerbosity(OutputInterface::VERBOSITY_QUIET);
0865          } else {
0866              if ($input->hasParameterOption('-vvv') || $input->hasParameterOption('--verbose=3') || $input->getParameterOption('--verbose') === 3) {
0867                  $output->setVerbosity(OutputInterface::VERBOSITY_DEBUG);
0868              } elseif ($input->hasParameterOption('-vv') || $input->hasParameterOption('--verbose=2') || $input->getParameterOption('--verbose') === 2) {
0869                  $output->setVerbosity(OutputInterface::VERBOSITY_VERY_VERBOSE);
0870              } elseif ($input->hasParameterOption('-v') || $input->hasParameterOption('--verbose=1') || $input->hasParameterOption('--verbose') || $input->getParameterOption('--verbose')) {
0871                  $output->setVerbosity(OutputInterface::VERBOSITY_VERBOSE);
0872              }
0873          }
0874      }
0875   
0876      /**
0877       * Runs the current command.
0878       *
0879       * If an event dispatcher has been attached to the application,
0880       * events are also dispatched during the life-cycle of the command.
0881       *
0882       * @param Command         $command A Command instance
0883       * @param InputInterface  $input   An Input instance
0884       * @param OutputInterface $output  An Output instance
0885       *
0886       * @return int 0 if everything went fine, or an error code
0887       *
0888       * @throws \Exception when the command being run threw an exception
0889       */
0890      protected function doRunCommand(Command $command, InputInterface $input, OutputInterface $output)
0891      {
0892          if (null === $this->dispatcher) {
0893              return $command->run($input, $output);
0894          }
0895   
0896          $event = new ConsoleCommandEvent($command, $input, $output);
0897          $this->dispatcher->dispatch(ConsoleEvents::COMMAND, $event);
0898   
0899          try {
0900              $exitCode = $command->run($input, $output);
0901          } catch (\Exception $e) {
0902              $event = new ConsoleTerminateEvent($command, $input, $output, $e->getCode());
0903              $this->dispatcher->dispatch(ConsoleEvents::TERMINATE, $event);
0904   
0905              $event = new ConsoleExceptionEvent($command, $input, $output, $e, $event->getExitCode());
0906              $this->dispatcher->dispatch(ConsoleEvents::EXCEPTION, $event);
0907   
0908              throw $event->getException();
0909          }
0910   
0911          $event = new ConsoleTerminateEvent($command, $input, $output, $exitCode);
0912          $this->dispatcher->dispatch(ConsoleEvents::TERMINATE, $event);
0913   
0914          return $event->getExitCode();
0915      }
0916   
0917      /**
0918       * Gets the name of the command based on input.
0919       *
0920       * @param InputInterface $input The input interface
0921       *
0922       * @return string The command name
0923       */
0924      protected function getCommandName(InputInterface $input)
0925      {
0926          return $input->getFirstArgument();
0927      }
0928   
0929      /**
0930       * Gets the default input definition.
0931       *
0932       * @return InputDefinition An InputDefinition instance
0933       */
0934      protected function getDefaultInputDefinition()
0935      {
0936          return new InputDefinition(array(
0937              new InputArgument('command', InputArgument::REQUIRED, 'The command to execute'),
0938   
0939              new InputOption('--help',           '-h', InputOption::VALUE_NONE, 'Display this help message.'),
0940              new InputOption('--quiet',          '-q', InputOption::VALUE_NONE, 'Do not output any message.'),
0941              new InputOption('--verbose',        '-v|vv|vvv', InputOption::VALUE_NONE, 'Increase the verbosity of messages: 1 for normal output, 2 for more verbose output and 3 for debug.'),
0942              new InputOption('--version',        '-V', InputOption::VALUE_NONE, 'Display this application version.'),
0943              new InputOption('--ansi',           '',   InputOption::VALUE_NONE, 'Force ANSI output.'),
0944              new InputOption('--no-ansi',        '',   InputOption::VALUE_NONE, 'Disable ANSI output.'),
0945              new InputOption('--no-interaction', '-n', InputOption::VALUE_NONE, 'Do not ask any interactive question.'),
0946          ));
0947      }
0948   
0949      /**
0950       * Gets the default commands that should always be available.
0951       *
0952       * @return Command[] An array of default Command instances
0953       */
0954      protected function getDefaultCommands()
0955      {
0956          return array(new HelpCommand(), new ListCommand());
0957      }
0958   
0959      /**
0960       * Gets the default helper set with the helpers that should always be available.
0961       *
0962       * @return HelperSet A HelperSet instance
0963       */
0964      protected function getDefaultHelperSet()
0965      {
0966          return new HelperSet(array(
0967              new FormatterHelper(),
0968              new DialogHelper(),
0969              new ProgressHelper(),
0970              new TableHelper(),
0971          ));
0972      }
0973   
0974      /**
0975       * Runs and parses stty -a if it's available, suppressing any error output
0976       *
0977       * @return string
0978       */
0979      private function getSttyColumns()
0980      {
0981          if (!function_exists('proc_open')) {
0982              return;
0983          }
0984   
0985          $descriptorspec = array(1 => array('pipe', 'w'), 2 => array('pipe', 'w'));
0986          $process = proc_open('stty -a | grep columns', $descriptorspec, $pipes, null, null, array('suppress_errors' => true));
0987          if (is_resource($process)) {
0988              $info = stream_get_contents($pipes[1]);
0989              fclose($pipes[1]);
0990              fclose($pipes[2]);
0991              proc_close($process);
0992   
0993              return $info;
0994          }
0995      }
0996   
0997      /**
0998       * Runs and parses mode CON if it's available, suppressing any error output
0999       *
1000       * @return string <width>x<height> or null if it could not be parsed
1001       */
1002      private function getConsoleMode()
1003      {
1004          if (!function_exists('proc_open')) {
1005              return;
1006          }
1007   
1008          $descriptorspec = array(1 => array('pipe', 'w'), 2 => array('pipe', 'w'));
1009          $process = proc_open('mode CON', $descriptorspec, $pipes, null, null, array('suppress_errors' => true));
1010          if (is_resource($process)) {
1011              $info = stream_get_contents($pipes[1]);
1012              fclose($pipes[1]);
1013              fclose($pipes[2]);
1014              proc_close($process);
1015   
1016              if (preg_match('/--------+\r?\n.+?(\d+)\r?\n.+?(\d+)\r?\n/', $info, $matches)) {
1017                  return $matches[2].'x'.$matches[1];
1018              }
1019          }
1020      }
1021   
1022      /**
1023       * Returns abbreviated suggestions in string format.
1024       *
1025       * @param array $abbrevs Abbreviated suggestions to convert
1026       *
1027       * @return string A formatted string of abbreviated suggestions
1028       */
1029      private function getAbbreviationSuggestions($abbrevs)
1030      {
1031          return sprintf('%s, %s%s', $abbrevs[0], $abbrevs[1], count($abbrevs) > 2 ? sprintf(' and %d more', count($abbrevs) - 2) : '');
1032      }
1033   
1034      /**
1035       * Returns the namespace part of the command name.
1036       *
1037       * This method is not part of public API and should not be used directly.
1038       *
1039       * @param string $name  The full name of the command
1040       * @param string $limit The maximum number of parts of the namespace
1041       *
1042       * @return string The namespace of the command
1043       */
1044      public function extractNamespace($name, $limit = null)
1045      {
1046          $parts = explode(':', $name);
1047          array_pop($parts);
1048   
1049          return implode(':', null === $limit ? $parts : array_slice($parts, 0, $limit));
1050      }
1051   
1052      /**
1053       * Finds alternative commands of $name
1054       *
1055       * @param string $name    The full name of the command
1056       * @param array  $abbrevs The abbreviations
1057       *
1058       * @return array A sorted array of similar commands
1059       */
1060      private function findAlternativeCommands($name, $abbrevs)
1061      {
1062          $callback = function ($item) {
1063              return $item->getName();
1064          };
1065   
1066          return $this->findAlternatives($name, $this->commands, $abbrevs, $callback);
1067      }
1068   
1069      /**
1070       * Finds alternative namespace of $name
1071       *
1072       * @param string $name    The full name of the namespace
1073       * @param array  $abbrevs The abbreviations
1074       *
1075       * @return array A sorted array of similar namespace
1076       */
1077      private function findAlternativeNamespace($name, $abbrevs)
1078      {
1079          return $this->findAlternatives($name, $this->getNamespaces(), $abbrevs);
1080      }
1081   
1082      /**
1083       * Finds alternative of $name among $collection,
1084       * if nothing is found in $collection, try in $abbrevs
1085       *
1086       * @param string               $name       The string
1087       * @param array|\Traversable   $collection The collection
1088       * @param array                $abbrevs    The abbreviations
1089       * @param Closure|string|array $callback   The callable to transform collection item before comparison
1090       *
1091       * @return array A sorted array of similar string
1092       */
1093      private function findAlternatives($name, $collection, $abbrevs, $callback = null)
1094      {
1095          $alternatives = array();
1096   
1097          foreach ($collection as $item) {
1098              if (null !== $callback) {
1099                  $item = call_user_func($callback, $item);
1100              }
1101   
1102              $lev = levenshtein($name, $item);
1103              if ($lev <= strlen($name) / 3 || false !== strpos($item, $name)) {
1104                  $alternatives[$item] = $lev;
1105              }
1106          }
1107   
1108          if (!$alternatives) {
1109              foreach ($abbrevs as $key => $values) {
1110                  $lev = levenshtein($name, $key);
1111                  if ($lev <= strlen($name) / 3 || false !== strpos($key, $name)) {
1112                      foreach ($values as $value) {
1113                          $alternatives[$value] = $lev;
1114                      }
1115                  }
1116              }
1117          }
1118   
1119          asort($alternatives);
1120   
1121          return array_keys($alternatives);
1122      }
1123   
1124      private function stringWidth($string)
1125      {
1126          if (!function_exists('mb_strwidth')) {
1127              return strlen($string);
1128          }
1129   
1130          if (false === $encoding = mb_detect_encoding($string)) {
1131              return strlen($string);
1132          }
1133   
1134          return mb_strwidth($string, $encoding);
1135      }
1136   
1137      private function splitStringByWidth($string, $width)
1138      {
1139          // str_split is not suitable for multi-byte characters, we should use preg_split to get char array properly.
1140          // additionally, array_slice() is not enough as some character has doubled width.
1141          // we need a function to split string not by character count but by string width
1142   
1143          if (!function_exists('mb_strwidth')) {
1144              return str_split($string, $width);
1145          }
1146   
1147          if (false === $encoding = mb_detect_encoding($string)) {
1148              return str_split($string, $width);
1149          }
1150   
1151          $utf8String = mb_convert_encoding($string, 'utf8', $encoding);
1152          $lines = array();
1153          $line = '';
1154          foreach (preg_split('//u', $utf8String) as $char) {
1155              // test if $char could be appended to current line
1156              if (mb_strwidth($line.$char, 'utf8') <= $width) {
1157                  $line .= $char;
1158                  continue;
1159              }
1160              // if not, push current line to array and make new line
1161              $lines[] = str_pad($line, $width);
1162              $line = $char;
1163          }
1164          if (strlen($line)) {
1165              $lines[] = count($lines) ? str_pad($line, $width) : $line;
1166          }
1167   
1168          mb_convert_variables($encoding, 'utf8', $lines);
1169   
1170          return $lines;
1171      }
1172  }
1173