Verzeichnisstruktur phpBB-3.2.0


Veröffentlicht
06.01.2017

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

QuestionHelper.php

Zuletzt modifiziert: 09.10.2024, 12:56 - Dateigröße: 13.35 KiB


 001  <?php
 002   
 003  /*
 004   * This file is part of the Symfony package.
 005   *
 006   * (c) Fabien Potencier <fabien@symfony.com>
 007   *
 008   * For the full copyright and license information, please view the LICENSE
 009   * file that was distributed with this source code.
 010   */
 011   
 012  namespace Symfony\Component\Console\Helper;
 013   
 014  use Symfony\Component\Console\Exception\InvalidArgumentException;
 015  use Symfony\Component\Console\Exception\RuntimeException;
 016  use Symfony\Component\Console\Input\InputInterface;
 017  use Symfony\Component\Console\Output\ConsoleOutputInterface;
 018  use Symfony\Component\Console\Output\OutputInterface;
 019  use Symfony\Component\Console\Formatter\OutputFormatterStyle;
 020  use Symfony\Component\Console\Question\Question;
 021  use Symfony\Component\Console\Question\ChoiceQuestion;
 022   
 023  /**
 024   * The QuestionHelper class provides helpers to interact with the user.
 025   *
 026   * @author Fabien Potencier <fabien@symfony.com>
 027   */
 028  class QuestionHelper extends Helper
 029  {
 030      private $inputStream;
 031      private static $shell;
 032      private static $stty;
 033   
 034      /**
 035       * Asks a question to the user.
 036       *
 037       * @param InputInterface  $input    An InputInterface instance
 038       * @param OutputInterface $output   An OutputInterface instance
 039       * @param Question        $question The question to ask
 040       *
 041       * @return string The user answer
 042       *
 043       * @throws RuntimeException If there is no data to read in the input stream
 044       */
 045      public function ask(InputInterface $input, OutputInterface $output, Question $question)
 046      {
 047          if ($output instanceof ConsoleOutputInterface) {
 048              $output = $output->getErrorOutput();
 049          }
 050   
 051          if (!$input->isInteractive()) {
 052              return $question->getDefault();
 053          }
 054   
 055          if (!$question->getValidator()) {
 056              return $this->doAsk($output, $question);
 057          }
 058   
 059          $that = $this;
 060   
 061          $interviewer = function () use ($output, $question, $that) {
 062              return $that->doAsk($output, $question);
 063          };
 064   
 065          return $this->validateAttempts($interviewer, $output, $question);
 066      }
 067   
 068      /**
 069       * Sets the input stream to read from when interacting with the user.
 070       *
 071       * This is mainly useful for testing purpose.
 072       *
 073       * @param resource $stream The input stream
 074       *
 075       * @throws InvalidArgumentException In case the stream is not a resource
 076       */
 077      public function setInputStream($stream)
 078      {
 079          if (!is_resource($stream)) {
 080              throw new InvalidArgumentException('Input stream must be a valid resource.');
 081          }
 082   
 083          $this->inputStream = $stream;
 084      }
 085   
 086      /**
 087       * Returns the helper's input stream.
 088       *
 089       * @return resource
 090       */
 091      public function getInputStream()
 092      {
 093          return $this->inputStream;
 094      }
 095   
 096      /**
 097       * {@inheritdoc}
 098       */
 099      public function getName()
 100      {
 101          return 'question';
 102      }
 103   
 104      /**
 105       * Asks the question to the user.
 106       *
 107       * This method is public for PHP 5.3 compatibility, it should be private.
 108       *
 109       * @param OutputInterface $output
 110       * @param Question        $question
 111       *
 112       * @return bool|mixed|null|string
 113       *
 114       * @throws \Exception
 115       * @throws \RuntimeException
 116       */
 117      public function doAsk(OutputInterface $output, Question $question)
 118      {
 119          $this->writePrompt($output, $question);
 120   
 121          $inputStream = $this->inputStream ?: STDIN;
 122          $autocomplete = $question->getAutocompleterValues();
 123   
 124          if (null === $autocomplete || !$this->hasSttyAvailable()) {
 125              $ret = false;
 126              if ($question->isHidden()) {
 127                  try {
 128                      $ret = trim($this->getHiddenResponse($output, $inputStream));
 129                  } catch (\RuntimeException $e) {
 130                      if (!$question->isHiddenFallback()) {
 131                          throw $e;
 132                      }
 133                  }
 134              }
 135   
 136              if (false === $ret) {
 137                  $ret = fgets($inputStream, 4096);
 138                  if (false === $ret) {
 139                      throw new RuntimeException('Aborted');
 140                  }
 141                  $ret = trim($ret);
 142              }
 143          } else {
 144              $ret = trim($this->autocomplete($output, $question, $inputStream));
 145          }
 146   
 147          $ret = strlen($ret) > 0 ? $ret : $question->getDefault();
 148   
 149          if ($normalizer = $question->getNormalizer()) {
 150              return $normalizer($ret);
 151          }
 152   
 153          return $ret;
 154      }
 155   
 156      /**
 157       * Outputs the question prompt.
 158       *
 159       * @param OutputInterface $output
 160       * @param Question        $question
 161       */
 162      protected function writePrompt(OutputInterface $output, Question $question)
 163      {
 164          $message = $question->getQuestion();
 165   
 166          if ($question instanceof ChoiceQuestion) {
 167              $maxWidth = max(array_map(array($this, 'strlen'), array_keys($question->getChoices())));
 168   
 169              $messages = (array) $question->getQuestion();
 170              foreach ($question->getChoices() as $key => $value) {
 171                  $width = $maxWidth - $this->strlen($key);
 172                  $messages[] = '  [<info>'.$key.str_repeat(' ', $width).'</info>] '.$value;
 173              }
 174   
 175              $output->writeln($messages);
 176   
 177              $message = $question->getPrompt();
 178          }
 179   
 180          $output->write($message);
 181      }
 182   
 183      /**
 184       * Outputs an error message.
 185       *
 186       * @param OutputInterface $output
 187       * @param \Exception      $error
 188       */
 189      protected function writeError(OutputInterface $output, \Exception $error)
 190      {
 191          if (null !== $this->getHelperSet() && $this->getHelperSet()->has('formatter')) {
 192              $message = $this->getHelperSet()->get('formatter')->formatBlock($error->getMessage(), 'error');
 193          } else {
 194              $message = '<error>'.$error->getMessage().'</error>';
 195          }
 196   
 197          $output->writeln($message);
 198      }
 199   
 200      /**
 201       * Autocompletes a question.
 202       *
 203       * @param OutputInterface $output
 204       * @param Question        $question
 205       * @param resource        $inputStream
 206       *
 207       * @return string
 208       */
 209      private function autocomplete(OutputInterface $output, Question $question, $inputStream)
 210      {
 211          $autocomplete = $question->getAutocompleterValues();
 212          $ret = '';
 213   
 214          $i = 0;
 215          $ofs = -1;
 216          $matches = $autocomplete;
 217          $numMatches = count($matches);
 218   
 219          $sttyMode = shell_exec('stty -g');
 220   
 221          // Disable icanon (so we can fread each keypress) and echo (we'll do echoing here instead)
 222          shell_exec('stty -icanon -echo');
 223   
 224          // Add highlighted text style
 225          $output->getFormatter()->setStyle('hl', new OutputFormatterStyle('black', 'white'));
 226   
 227          // Read a keypress
 228          while (!feof($inputStream)) {
 229              $c = fread($inputStream, 1);
 230   
 231              // Backspace Character
 232              if ("\177" === $c) {
 233                  if (0 === $numMatches && 0 !== $i) {
 234                      --$i;
 235                      // Move cursor backwards
 236                      $output->write("\033[1D");
 237                  }
 238   
 239                  if ($i === 0) {
 240                      $ofs = -1;
 241                      $matches = $autocomplete;
 242                      $numMatches = count($matches);
 243                  } else {
 244                      $numMatches = 0;
 245                  }
 246   
 247                  // Pop the last character off the end of our string
 248                  $ret = substr($ret, 0, $i);
 249              } elseif ("\033" === $c) {
 250                  // Did we read an escape sequence?
 251                  $c .= fread($inputStream, 2);
 252   
 253                  // A = Up Arrow. B = Down Arrow
 254                  if (isset($c[2]) && ('A' === $c[2] || 'B' === $c[2])) {
 255                      if ('A' === $c[2] && -1 === $ofs) {
 256                          $ofs = 0;
 257                      }
 258   
 259                      if (0 === $numMatches) {
 260                          continue;
 261                      }
 262   
 263                      $ofs += ('A' === $c[2]) ? -1 : 1;
 264                      $ofs = ($numMatches + $ofs) % $numMatches;
 265                  }
 266              } elseif (ord($c) < 32) {
 267                  if ("\t" === $c || "\n" === $c) {
 268                      if ($numMatches > 0 && -1 !== $ofs) {
 269                          $ret = $matches[$ofs];
 270                          // Echo out remaining chars for current match
 271                          $output->write(substr($ret, $i));
 272                          $i = strlen($ret);
 273                      }
 274   
 275                      if ("\n" === $c) {
 276                          $output->write($c);
 277                          break;
 278                      }
 279   
 280                      $numMatches = 0;
 281                  }
 282   
 283                  continue;
 284              } else {
 285                  $output->write($c);
 286                  $ret .= $c;
 287                  ++$i;
 288   
 289                  $numMatches = 0;
 290                  $ofs = 0;
 291   
 292                  foreach ($autocomplete as $value) {
 293                      // If typed characters match the beginning chunk of value (e.g. [AcmeDe]moBundle)
 294                      if (0 === strpos($value, $ret) && $i !== strlen($value)) {
 295                          $matches[$numMatches++] = $value;
 296                      }
 297                  }
 298              }
 299   
 300              // Erase characters from cursor to end of line
 301              $output->write("\033[K");
 302   
 303              if ($numMatches > 0 && -1 !== $ofs) {
 304                  // Save cursor position
 305                  $output->write("\0337");
 306                  // Write highlighted text
 307                  $output->write('<hl>'.substr($matches[$ofs], $i).'</hl>');
 308                  // Restore cursor position
 309                  $output->write("\0338");
 310              }
 311          }
 312   
 313          // Reset stty so it behaves normally again
 314          shell_exec(sprintf('stty %s', $sttyMode));
 315   
 316          return $ret;
 317      }
 318   
 319      /**
 320       * Gets a hidden response from user.
 321       *
 322       * @param OutputInterface $output      An Output instance
 323       * @param resource        $inputStream The handler resource
 324       *
 325       * @return string The answer
 326       *
 327       * @throws RuntimeException In case the fallback is deactivated and the response cannot be hidden
 328       */
 329      private function getHiddenResponse(OutputInterface $output, $inputStream)
 330      {
 331          if ('\\' === DIRECTORY_SEPARATOR) {
 332              $exe = __DIR__.'/../Resources/bin/hiddeninput.exe';
 333   
 334              // handle code running from a phar
 335              if ('phar:' === substr(__FILE__, 0, 5)) {
 336                  $tmpExe = sys_get_temp_dir().'/hiddeninput.exe';
 337                  copy($exe, $tmpExe);
 338                  $exe = $tmpExe;
 339              }
 340   
 341              $value = rtrim(shell_exec($exe));
 342              $output->writeln('');
 343   
 344              if (isset($tmpExe)) {
 345                  unlink($tmpExe);
 346              }
 347   
 348              return $value;
 349          }
 350   
 351          if ($this->hasSttyAvailable()) {
 352              $sttyMode = shell_exec('stty -g');
 353   
 354              shell_exec('stty -echo');
 355              $value = fgets($inputStream, 4096);
 356              shell_exec(sprintf('stty %s', $sttyMode));
 357   
 358              if (false === $value) {
 359                  throw new RuntimeException('Aborted');
 360              }
 361   
 362              $value = trim($value);
 363              $output->writeln('');
 364   
 365              return $value;
 366          }
 367   
 368          if (false !== $shell = $this->getShell()) {
 369              $readCmd = $shell === 'csh' ? 'set mypassword = $<' : 'read -r mypassword';
 370              $command = sprintf("/usr/bin/env %s -c 'stty -echo; %s; stty echo; echo \$mypassword'", $shell, $readCmd);
 371              $value = rtrim(shell_exec($command));
 372              $output->writeln('');
 373   
 374              return $value;
 375          }
 376   
 377          throw new RuntimeException('Unable to hide the response.');
 378      }
 379   
 380      /**
 381       * Validates an attempt.
 382       *
 383       * @param callable        $interviewer A callable that will ask for a question and return the result
 384       * @param OutputInterface $output      An Output instance
 385       * @param Question        $question    A Question instance
 386       *
 387       * @return string The validated response
 388       *
 389       * @throws \Exception In case the max number of attempts has been reached and no valid response has been given
 390       */
 391      private function validateAttempts($interviewer, OutputInterface $output, Question $question)
 392      {
 393          $error = null;
 394          $attempts = $question->getMaxAttempts();
 395          while (null === $attempts || $attempts--) {
 396              if (null !== $error) {
 397                  $this->writeError($output, $error);
 398              }
 399   
 400              try {
 401                  return call_user_func($question->getValidator(), $interviewer());
 402              } catch (RuntimeException $e) {
 403                  throw $e;
 404              } catch (\Exception $error) {
 405              }
 406          }
 407   
 408          throw $error;
 409      }
 410   
 411      /**
 412       * Returns a valid unix shell.
 413       *
 414       * @return string|bool The valid shell name, false in case no valid shell is found
 415       */
 416      private function getShell()
 417      {
 418          if (null !== self::$shell) {
 419              return self::$shell;
 420          }
 421   
 422          self::$shell = false;
 423   
 424          if (file_exists('/usr/bin/env')) {
 425              // handle other OSs with bash/zsh/ksh/csh if available to hide the answer
 426              $test = "/usr/bin/env %s -c 'echo OK' 2> /dev/null";
 427              foreach (array('bash', 'zsh', 'ksh', 'csh') as $sh) {
 428                  if ('OK' === rtrim(shell_exec(sprintf($test, $sh)))) {
 429                      self::$shell = $sh;
 430                      break;
 431                  }
 432              }
 433          }
 434   
 435          return self::$shell;
 436      }
 437   
 438      /**
 439       * Returns whether Stty is available or not.
 440       *
 441       * @return bool
 442       */
 443      private function hasSttyAvailable()
 444      {
 445          if (null !== self::$stty) {
 446              return self::$stty;
 447          }
 448   
 449          exec('stty 2>&1', $output, $exitcode);
 450   
 451          return self::$stty = $exitcode === 0;
 452      }
 453  }
 454