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

DialogHelper.php

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