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

DialogHelper.php

Zuletzt modifiziert: 09.10.2024, 12:58 - Dateigröße: 15.99 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\Output\OutputInterface;
 015  use Symfony\Component\Console\Formatter\OutputFormatterStyle;
 016   
 017  /**
 018   * The Dialog class provides helpers to interact with the user.
 019   *
 020   * @author Fabien Potencier <fabien@symfony.com>
 021   */
 022  class DialogHelper extends Helper
 023  {
 024      private $inputStream;
 025      private static $shell;
 026      private static $stty;
 027   
 028      /**
 029       * Asks the user to select a value.
 030       *
 031       * @param OutputInterface $output       An Output instance
 032       * @param string|array    $question     The question to ask
 033       * @param array           $choices      List of choices to pick from
 034       * @param bool|string     $default      The default answer if the user enters nothing
 035       * @param bool|int        $attempts Max number of times to ask before giving up (false by default, which means infinite)
 036       * @param string          $errorMessage Message which will be shown if invalid value from choice list would be picked
 037       * @param bool            $multiselect  Select more than one value separated by comma
 038       *
 039       * @return int|string|array     The selected value or values (the key of the choices array)
 040       *
 041       * @throws \InvalidArgumentException
 042       */
 043      public function select(OutputInterface $output, $question, $choices, $default = null, $attempts = false, $errorMessage = 'Value "%s" is invalid', $multiselect = false)
 044      {
 045          $width = max(array_map('strlen', array_keys($choices)));
 046   
 047          $messages = (array) $question;
 048          foreach ($choices as $key => $value) {
 049              $messages[] = sprintf("  [<info>%-${width}s</info>] %s", $key, $value);
 050          }
 051   
 052          $output->writeln($messages);
 053   
 054          $result = $this->askAndValidate($output, '> ', function ($picked) use ($choices, $errorMessage, $multiselect) {
 055              // Collapse all spaces.
 056              $selectedChoices = str_replace(" ", "", $picked);
 057   
 058              if ($multiselect) {
 059                  // Check for a separated comma values
 060                  if (!preg_match('/^[a-zA-Z0-9_-]+(?:,[a-zA-Z0-9_-]+)*$/', $selectedChoices, $matches)) {
 061                      throw new \InvalidArgumentException(sprintf($errorMessage, $picked));
 062                  }
 063                  $selectedChoices = explode(",", $selectedChoices);
 064              } else {
 065                  $selectedChoices = array($picked);
 066              }
 067   
 068              $multiselectChoices = array();
 069   
 070              foreach ($selectedChoices as $value) {
 071                  if (empty($choices[$value])) {
 072                      throw new \InvalidArgumentException(sprintf($errorMessage, $value));
 073                  }
 074                  array_push($multiselectChoices, $value);
 075              }
 076   
 077              if ($multiselect) {
 078                  return $multiselectChoices;
 079              }
 080   
 081              return $picked;
 082          }, $attempts, $default);
 083   
 084          return $result;
 085      }
 086   
 087      /**
 088       * Asks a question to the user.
 089       *
 090       * @param OutputInterface $output       An Output instance
 091       * @param string|array    $question     The question to ask
 092       * @param string          $default      The default answer if none is given by the user
 093       * @param array           $autocomplete List of values to autocomplete
 094       *
 095       * @return string The user answer
 096       *
 097       * @throws \RuntimeException If there is no data to read in the input stream
 098       */
 099      public function ask(OutputInterface $output, $question, $default = null, array $autocomplete = null)
 100      {
 101          $output->write($question);
 102   
 103          $inputStream = $this->inputStream ?: STDIN;
 104   
 105          if (null === $autocomplete || !$this->hasSttyAvailable()) {
 106              $ret = fgets($inputStream, 4096);
 107              if (false === $ret) {
 108                  throw new \RuntimeException('Aborted');
 109              }
 110              $ret = trim($ret);
 111          } else {
 112              $ret = '';
 113   
 114              $i = 0;
 115              $ofs = -1;
 116              $matches = $autocomplete;
 117              $numMatches = count($matches);
 118   
 119              $sttyMode = shell_exec('stty -g');
 120   
 121              // Disable icanon (so we can fread each keypress) and echo (we'll do echoing here instead)
 122              shell_exec('stty -icanon -echo');
 123   
 124              // Add highlighted text style
 125              $output->getFormatter()->setStyle('hl', new OutputFormatterStyle('black', 'white'));
 126   
 127              // Read a keypress
 128              while (!feof($inputStream)) {
 129                  $c = fread($inputStream, 1);
 130   
 131                  // Backspace Character
 132                  if ("\177" === $c) {
 133                      if (0 === $numMatches && 0 !== $i) {
 134                          $i--;
 135                          // Move cursor backwards
 136                          $output->write("\033[1D");
 137                      }
 138   
 139                      if ($i === 0) {
 140                          $ofs = -1;
 141                          $matches = $autocomplete;
 142                          $numMatches = count($matches);
 143                      } else {
 144                          $numMatches = 0;
 145                      }
 146   
 147                      // Pop the last character off the end of our string
 148                      $ret = substr($ret, 0, $i);
 149                  } elseif ("\033" === $c) {
 150                      // Did we read an escape sequence?
 151                      $c .= fread($inputStream, 2);
 152   
 153                      // A = Up Arrow. B = Down Arrow
 154                      if (isset($c[2]) && ('A' === $c[2] || 'B' === $c[2])) {
 155                          if ('A' === $c[2] && -1 === $ofs) {
 156                              $ofs = 0;
 157                          }
 158   
 159                          if (0 === $numMatches) {
 160                              continue;
 161                          }
 162   
 163                          $ofs += ('A' === $c[2]) ? -1 : 1;
 164                          $ofs = ($numMatches + $ofs) % $numMatches;
 165                      }
 166                  } elseif (ord($c) < 32) {
 167                      if ("\t" === $c || "\n" === $c) {
 168                          if ($numMatches > 0 && -1 !== $ofs) {
 169                              $ret = $matches[$ofs];
 170                              // Echo out remaining chars for current match
 171                              $output->write(substr($ret, $i));
 172                              $i = strlen($ret);
 173                          }
 174   
 175                          if ("\n" === $c) {
 176                              $output->write($c);
 177                              break;
 178                          }
 179   
 180                          $numMatches = 0;
 181                      }
 182   
 183                      continue;
 184                  } else {
 185                      $output->write($c);
 186                      $ret .= $c;
 187                      $i++;
 188   
 189                      $numMatches = 0;
 190                      $ofs = 0;
 191   
 192                      foreach ($autocomplete as $value) {
 193                          // If typed characters match the beginning chunk of value (e.g. [AcmeDe]moBundle)
 194                          if (0 === strpos($value, $ret) && $i !== strlen($value)) {
 195                              $matches[$numMatches++] = $value;
 196                          }
 197                      }
 198                  }
 199   
 200                  // Erase characters from cursor to end of line
 201                  $output->write("\033[K");
 202   
 203                  if ($numMatches > 0 && -1 !== $ofs) {
 204                      // Save cursor position
 205                      $output->write("\0337");
 206                      // Write highlighted text
 207                      $output->write('<hl>'.substr($matches[$ofs], $i).'</hl>');
 208                      // Restore cursor position
 209                      $output->write("\0338");
 210                  }
 211              }
 212   
 213              // Reset stty so it behaves normally again
 214              shell_exec(sprintf('stty %s', $sttyMode));
 215          }
 216   
 217          return strlen($ret) > 0 ? $ret : $default;
 218      }
 219   
 220      /**
 221       * Asks a confirmation to the user.
 222       *
 223       * The question will be asked until the user answers by nothing, yes, or no.
 224       *
 225       * @param OutputInterface $output   An Output instance
 226       * @param string|array    $question The question to ask
 227       * @param bool            $default  The default answer if the user enters nothing
 228       *
 229       * @return bool    true if the user has confirmed, false otherwise
 230       */
 231      public function askConfirmation(OutputInterface $output, $question, $default = true)
 232      {
 233          $answer = 'z';
 234          while ($answer && !in_array(strtolower($answer[0]), array('y', 'n'))) {
 235              $answer = $this->ask($output, $question);
 236          }
 237   
 238          if (false === $default) {
 239              return $answer && 'y' == strtolower($answer[0]);
 240          }
 241   
 242          return !$answer || 'y' == strtolower($answer[0]);
 243      }
 244   
 245      /**
 246       * Asks a question to the user, the response is hidden
 247       *
 248       * @param OutputInterface $output   An Output instance
 249       * @param string|array    $question The question
 250       * @param bool            $fallback In case the response can not be hidden, whether to fallback on non-hidden question or not
 251       *
 252       * @return string         The answer
 253       *
 254       * @throws \RuntimeException In case the fallback is deactivated and the response can not be hidden
 255       */
 256      public function askHiddenResponse(OutputInterface $output, $question, $fallback = true)
 257      {
 258          if (defined('PHP_WINDOWS_VERSION_BUILD')) {
 259              $exe = __DIR__.'/../Resources/bin/hiddeninput.exe';
 260   
 261              // handle code running from a phar
 262              if ('phar:' === substr(__FILE__, 0, 5)) {
 263                  $tmpExe = sys_get_temp_dir().'/hiddeninput.exe';
 264                  copy($exe, $tmpExe);
 265                  $exe = $tmpExe;
 266              }
 267   
 268              $output->write($question);
 269              $value = rtrim(shell_exec($exe));
 270              $output->writeln('');
 271   
 272              if (isset($tmpExe)) {
 273                  unlink($tmpExe);
 274              }
 275   
 276              return $value;
 277          }
 278   
 279          if ($this->hasSttyAvailable()) {
 280              $output->write($question);
 281   
 282              $sttyMode = shell_exec('stty -g');
 283   
 284              shell_exec('stty -echo');
 285              $value = fgets($this->inputStream ?: STDIN, 4096);
 286              shell_exec(sprintf('stty %s', $sttyMode));
 287   
 288              if (false === $value) {
 289                  throw new \RuntimeException('Aborted');
 290              }
 291   
 292              $value = trim($value);
 293              $output->writeln('');
 294   
 295              return $value;
 296          }
 297   
 298          if (false !== $shell = $this->getShell()) {
 299              $output->write($question);
 300              $readCmd = $shell === 'csh' ? 'set mypassword = $<' : 'read -r mypassword';
 301              $command = sprintf("/usr/bin/env %s -c 'stty -echo; %s; stty echo; echo \$mypassword'", $shell, $readCmd);
 302              $value = rtrim(shell_exec($command));
 303              $output->writeln('');
 304   
 305              return $value;
 306          }
 307   
 308          if ($fallback) {
 309              return $this->ask($output, $question);
 310          }
 311   
 312          throw new \RuntimeException('Unable to hide the response');
 313      }
 314   
 315      /**
 316       * Asks for a value and validates the response.
 317       *
 318       * The validator receives the data to validate. It must return the
 319       * validated data when the data is valid and throw an exception
 320       * otherwise.
 321       *
 322       * @param OutputInterface $output       An Output instance
 323       * @param string|array    $question     The question to ask
 324       * @param callable        $validator    A PHP callback
 325       * @param int|false       $attempts     Max number of times to ask before giving up (false by default, which means infinite)
 326       * @param string          $default      The default answer if none is given by the user
 327       * @param array           $autocomplete List of values to autocomplete
 328       *
 329       * @return mixed
 330       *
 331       * @throws \Exception When any of the validators return an error
 332       */
 333      public function askAndValidate(OutputInterface $output, $question, $validator, $attempts = false, $default = null, array $autocomplete = null)
 334      {
 335          $that = $this;
 336   
 337          $interviewer = function () use ($output, $question, $default, $autocomplete, $that) {
 338              return $that->ask($output, $question, $default, $autocomplete);
 339          };
 340   
 341          return $this->validateAttempts($interviewer, $output, $validator, $attempts);
 342      }
 343   
 344      /**
 345       * Asks for a value, hide and validates the response.
 346       *
 347       * The validator receives the data to validate. It must return the
 348       * validated data when the data is valid and throw an exception
 349       * otherwise.
 350       *
 351       * @param OutputInterface $output    An Output instance
 352       * @param string|array    $question  The question to ask
 353       * @param callable        $validator A PHP callback
 354       * @param int|false       $attempts  Max number of times to ask before giving up (false by default, which means infinite)
 355       * @param bool            $fallback  In case the response can not be hidden, whether to fallback on non-hidden question or not
 356       *
 357       * @return string         The response
 358       *
 359       * @throws \Exception        When any of the validators return an error
 360       * @throws \RuntimeException In case the fallback is deactivated and the response can not be hidden
 361       *
 362       */
 363      public function askHiddenResponseAndValidate(OutputInterface $output, $question, $validator, $attempts = false, $fallback = true)
 364      {
 365          $that = $this;
 366   
 367          $interviewer = function () use ($output, $question, $fallback, $that) {
 368              return $that->askHiddenResponse($output, $question, $fallback);
 369          };
 370   
 371          return $this->validateAttempts($interviewer, $output, $validator, $attempts);
 372      }
 373   
 374      /**
 375       * Sets the input stream to read from when interacting with the user.
 376       *
 377       * This is mainly useful for testing purpose.
 378       *
 379       * @param resource $stream The input stream
 380       */
 381      public function setInputStream($stream)
 382      {
 383          $this->inputStream = $stream;
 384      }
 385   
 386      /**
 387       * Returns the helper's input stream
 388       *
 389       * @return string
 390       */
 391      public function getInputStream()
 392      {
 393          return $this->inputStream;
 394      }
 395   
 396      /**
 397       * {@inheritdoc}
 398       */
 399      public function getName()
 400      {
 401          return 'dialog';
 402      }
 403   
 404      /**
 405       * Return a valid Unix shell
 406       *
 407       * @return string|bool     The valid shell name, false in case no valid shell is found
 408       */
 409      private function getShell()
 410      {
 411          if (null !== self::$shell) {
 412              return self::$shell;
 413          }
 414   
 415          self::$shell = false;
 416   
 417          if (file_exists('/usr/bin/env')) {
 418              // handle other OSs with bash/zsh/ksh/csh if available to hide the answer
 419              $test = "/usr/bin/env %s -c 'echo OK' 2> /dev/null";
 420              foreach (array('bash', 'zsh', 'ksh', 'csh') as $sh) {
 421                  if ('OK' === rtrim(shell_exec(sprintf($test, $sh)))) {
 422                      self::$shell = $sh;
 423                      break;
 424                  }
 425              }
 426          }
 427   
 428          return self::$shell;
 429      }
 430   
 431      private function hasSttyAvailable()
 432      {
 433          if (null !== self::$stty) {
 434              return self::$stty;
 435          }
 436   
 437          exec('stty 2>&1', $output, $exitcode);
 438   
 439          return self::$stty = $exitcode === 0;
 440      }
 441   
 442      /**
 443       * Validate an attempt
 444       *
 445       * @param callable         $interviewer  A callable that will ask for a question and return the result
 446       * @param OutputInterface  $output       An Output instance
 447       * @param callable         $validator    A PHP callback
 448       * @param int|false        $attempts     Max number of times to ask before giving up ; false will ask infinitely
 449       *
 450       * @return string   The validated response
 451       *
 452       * @throws \Exception In case the max number of attempts has been reached and no valid response has been given
 453       */
 454      private function validateAttempts($interviewer, OutputInterface $output, $validator, $attempts)
 455      {
 456          $error = null;
 457          while (false === $attempts || $attempts--) {
 458              if (null !== $error) {
 459                  $output->writeln($this->getHelperSet()->get('formatter')->formatBlock($error->getMessage(), 'error'));
 460              }
 461   
 462              try {
 463                  return call_user_func($validator, $interviewer());
 464              } catch (\Exception $error) {
 465              }
 466          }
 467   
 468          throw $error;
 469      }
 470  }
 471