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