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