Passed
Pull Request — master (#26)
by David
02:11
created

Question::yesNoQuestion()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
nc 1
nop 0
dl 0
loc 4
rs 10
c 0
b 0
f 0
1
<?php
2
namespace TheAentMachine\Helper;
3
4
5
use Symfony\Component\Console\Helper\QuestionHelper;
6
use Symfony\Component\Console\Input\InputInterface;
7
use Symfony\Component\Console\Output\OutputInterface;
8
9
/**
10
 * A helper class to easily create questions.
11
 */
12
class Question
13
{
14
    /**
15
     * @var QuestionHelper
16
     */
17
    private $helper;
18
    /**
19
     * @var InputInterface
20
     */
21
    private $input;
22
    /**
23
     * @var OutputInterface
24
     */
25
    private $output;
26
    /**
27
     * @var string
28
     */
29
    private $question;
30
    /**
31
     * @var string|null
32
     */
33
    private $default;
34
    /**
35
     * @var bool
36
     */
37
    private $compulsory = false;
38
    /**
39
     * @var callable
40
     */
41
    private $validator;
42
    /**
43
     * @var string|null
44
     */
45
    private $helpText;
46
    /**
47
     * @var bool
48
     */
49
    private $yesNoQuestion = false;
50
51
    public function __construct(QuestionHelper $helper, InputInterface $input, OutputInterface $output, string $question)
52
    {
53
        $this->helper = $helper;
54
        $this->input = $input;
55
        $this->output = $output;
56
        $this->question = $question;
57
    }
58
59
    public function compulsory(): self
60
    {
61
        $this->compulsory = true;
62
        return $this;
63
    }
64
65
    public function setValidator(callable $validator): self
66
    {
67
        $this->validator = $validator;
68
        return $this;
69
    }
70
71
    public function setHelpText(string $helpText): self
72
    {
73
        $this->helpText = $helpText;
74
        return $this;
75
    }
76
77
    public function setDefault(string $default): self
78
    {
79
        $this->default = $default;
80
        return $this;
81
    }
82
83
    public function yesNoQuestion(): self
84
    {
85
        $this->yesNoQuestion = true;
86
        return $this;
87
    }
88
89
    public function ask()
90
    {
91
        $text = $this->question;
92
        if ($this->helpText) {
93
            $text .= ' (? for help)';
94
        }
95
        if ($this->default) {
96
            if (!$this->yesNoQuestion) {
97
                $text .= ' ['.$this->default.']';
98
            } elseif ($this->default === 'y') {
99
                $text .= ' [Y/n]';
100
            } elseif ($this->default === 'n') {
101
                $text .= ' [y/N]';
102
            } else {
103
                $text .= ' [y/n]';
104
            }
105
        }
106
        $text .= ': ';
107
108
        $question = new \Symfony\Component\Console\Question\Question($text, $this->default);
109
110
        $validator = $this->validator;
111
112
        if ($this->yesNoQuestion) {
113
            $validator = function(?string $response) use ($validator) {
114
                $response = trim(\strtolower($response));
115
                if (!\in_array($response, ['y', 'n', 'yes', 'no'])) {
116
                    throw new \InvalidArgumentException('Answer must be "y" or "n"');
117
                }
118
                $response = \in_array($response, ['y', 'yes']) ? '1' : '';
119
                return $validator ? $validator($response) : $response;
120
            };
121
        }
122
123
        if ($this->helpText) {
124
            $validator = function(?string $response) use ($validator) {
125
                if (trim($response) === '?') {
126
                    $this->output->writeln($this->helpText);
127
                    return '?';
128
                }
129
                return $validator ? $validator($response) : $response;
130
            };
131
        }
132
133
        if ($this->compulsory) {
134
            $validator = function(?string $response) use ($validator) {
135
                if (trim($response) === '') {
136
                    throw new \InvalidArgumentException('This field is compulsory.');
137
                }
138
                return $validator ? $validator($response) : $response;
139
            };
140
        }
141
142
        $question->setValidator($validator);
143
144
        do {
145
            $answer = $this->helper->ask($this->input, $this->output, $question);
146
        } while ($this->helpText !== null && $answer === '?');
147
148
        return $answer;
149
    }
150
}
151