1: <?php
2:
3: /*
4: * This file is part of the Symfony package.
5: *
6: * (c) Fabien Potencier <fabien@symfony.com>
7: *
8: * For the full copyright and license information, please view the LICENSE
9: * file that was distributed with this source code.
10: */
11:
12: namespace Symfony\Component\Console\Helper;
13:
14: use Symfony\Component\Console\Output\OutputInterface;
15:
16: /**
17: * The Dialog class provides helpers to interact with the user.
18: *
19: * @author Fabien Potencier <fabien@symfony.com>
20: */
21: class DialogHelper extends Helper
22: {
23: private $inputStream;
24:
25: /**
26: * Asks a question to the user.
27: *
28: * @param OutputInterface $output An Output instance
29: * @param string|array $question The question to ask
30: * @param string $default The default answer if none is given by the user
31: *
32: * @return string The user answer
33: *
34: * @throws \RuntimeException If there is no data to read in the input stream
35: */
36: public function ask(OutputInterface $output, $question, $default = null)
37: {
38: $output->write($question);
39:
40: $ret = fgets($this->inputStream ?: STDIN, 4096);
41: if (false === $ret) {
42: throw new \RuntimeException('Aborted');
43: }
44: $ret = trim($ret);
45:
46: return strlen($ret) > 0 ? $ret : $default;
47: }
48:
49: /**
50: * Asks a confirmation to the user.
51: *
52: * The question will be asked until the user answers by nothing, yes, or no.
53: *
54: * @param OutputInterface $output An Output instance
55: * @param string|array $question The question to ask
56: * @param Boolean $default The default answer if the user enters nothing
57: *
58: * @return Boolean true if the user has confirmed, false otherwise
59: */
60: public function askConfirmation(OutputInterface $output, $question, $default = true)
61: {
62: $answer = 'z';
63: while ($answer && !in_array(strtolower($answer[0]), array('y', 'n'))) {
64: $answer = $this->ask($output, $question);
65: }
66:
67: if (false === $default) {
68: return $answer && 'y' == strtolower($answer[0]);
69: }
70:
71: return !$answer || 'y' == strtolower($answer[0]);
72: }
73:
74: /**
75: * Asks for a value and validates the response.
76: *
77: * The validator receives the data to validate. It must return the
78: * validated data when the data is valid and throw an exception
79: * otherwise.
80: *
81: * @param OutputInterface $output An Output instance
82: * @param string|array $question The question to ask
83: * @param callback $validator A PHP callback
84: * @param integer $attempts Max number of times to ask before giving up (false by default, which means infinite)
85: * @param string $default The default answer if none is given by the user
86: *
87: * @return mixed
88: *
89: * @throws \Exception When any of the validators return an error
90: */
91: public function askAndValidate(OutputInterface $output, $question, $validator, $attempts = false, $default = null)
92: {
93: $error = null;
94: while (false === $attempts || $attempts--) {
95: if (null !== $error) {
96: $output->writeln($this->getHelperSet()->get('formatter')->formatBlock($error->getMessage(), 'error'));
97: }
98:
99: $value = $this->ask($output, $question, $default);
100:
101: try {
102: return call_user_func($validator, $value);
103: } catch (\Exception $error) {
104: }
105: }
106:
107: throw $error;
108: }
109:
110: /**
111: * Sets the input stream to read from when interacting with the user.
112: *
113: * This is mainly useful for testing purpose.
114: *
115: * @param resource $stream The input stream
116: */
117: public function setInputStream($stream)
118: {
119: $this->inputStream = $stream;
120: }
121:
122: /**
123: * Returns the helper's input stream
124: *
125: * @return string
126: */
127: public function getInputStream()
128: {
129: return $this->inputStream;
130: }
131:
132: /**
133: * Returns the helper's canonical name.
134: */
135: public function getName()
136: {
137: return 'dialog';
138: }
139: }
140: