Passed
Push — master ( 1157cf...cd5eb5 )
by Melech
01:25
created

QuestionWriter::write()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 8
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 2
eloc 4
c 1
b 0
f 0
nc 2
nop 2
dl 0
loc 8
rs 10
1
<?php
2
3
declare(strict_types=1);
4
5
/*
6
 * This file is part of the Valkyrja Framework package.
7
 *
8
 * (c) Melech Mizrachi <[email protected]>
9
 *
10
 * For the full copyright and license information, please view the LICENSE
11
 * file that was distributed with this source code.
12
 */
13
14
namespace Valkyrja\Cli\Interaction\Writer;
15
16
use Override;
0 ignored issues
show
Bug introduced by
The type Override was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
17
use Valkyrja\Cli\Interaction\Formatter\HighlightedTextFormatter;
18
use Valkyrja\Cli\Interaction\Message\Contract\AnswerContract;
19
use Valkyrja\Cli\Interaction\Message\Contract\MessageContract;
20
use Valkyrja\Cli\Interaction\Message\Contract\QuestionContract;
21
use Valkyrja\Cli\Interaction\Message\Message as MessageMessage;
22
use Valkyrja\Cli\Interaction\Message\NewLine;
23
use Valkyrja\Cli\Interaction\Output\Contract\OutputContract;
24
use Valkyrja\Cli\Interaction\Throwable\Exception\InvalidArgumentException;
25
use Valkyrja\Cli\Interaction\Writer\Contract\WriterContract;
26
27
use function array_map;
28
use function implode;
29
30
class QuestionWriter implements WriterContract
31
{
32
    /**
33
     * @inheritDoc
34
     */
35
    #[Override]
36
    public function shouldWriteMessage(MessageContract $message): bool
37
    {
38
        return $message instanceof QuestionContract;
39
    }
40
41
    /**
42
     * @inheritDoc
43
     *
44
     * @template O of OutputContract
45
     *
46
     * @param O $output The output
0 ignored issues
show
Bug introduced by
The type Valkyrja\Cli\Interaction\Writer\O was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
47
     *
48
     * @return O
49
     */
50
    #[Override]
51
    public function write(OutputContract $output, MessageContract $message): OutputContract
52
    {
53
        if (! $message instanceof QuestionContract) {
54
            throw new InvalidArgumentException('This writer expects only questions');
55
        }
56
57
        return $this->askQuestion($output, $message);
58
    }
59
60
    /**
61
     * Ask a question.
62
     *
63
     * @template O of OutputContract
64
     *
65
     * @param O $output The output
66
     *
67
     * @return O
68
     */
69
    protected function askQuestion(OutputContract $output, QuestionContract $question): OutputContract
70
    {
71
        $output = $this->writeQuestion($output, $question);
72
73
        $answer = $question->getAnswer();
74
75
        if ($output->isInteractive() && ! $output->isQuiet() && ! $output->isSilent()) {
76
            $answer = $question->ask();
77
78
            if (! $answer->isValidResponse()) {
79
                // For posterity add the answer with the invalid user response to the written messages list
80
                $output = $this->writeAnswerAfterResponse($output, $answer);
81
82
                // Re-ask the question
83
                return $this->askQuestion($output, $question);
84
            }
85
        }
86
87
        $output = $this->writeAnswerAfterResponse($output, $answer);
88
89
        $callable = $question->getCallable();
90
91
        /** @var O $output */
92
        $output = $callable($output, $answer);
93
94
        return $output;
95
    }
96
97
    /**
98
     * Write a question.
99
     *
100
     * @template O of OutputContract
101
     *
102
     * @param O $output The output
103
     *
104
     * @return O
105
     */
106
    protected function writeQuestion(OutputContract $output, QuestionContract $question): OutputContract
107
    {
108
        // Write the question text
109
        $output = $output->writeMessage($question);
110
111
        $answer = $question->getAnswer();
112
113
        $validResponses = $answer->getAllowedResponses();
114
115
        if ($validResponses !== []) {
116
            // (`valid` or `also valid` or `another valid value`)
117
            $output = $output->writeMessage(new MessageMessage(' ('));
118
            $output = $output->writeMessage(new MessageMessage(implode(' or ', array_map(static fn (string $value) => "`$value`", $validResponses))));
119
            $output = $output->writeMessage(new MessageMessage(')'));
120
        }
121
122
        // [default: "defaultResponse"]
123
        $output = $output->writeMessage(new MessageMessage(' [default: "'));
124
        $output = $output->writeMessage(new MessageMessage($answer->getDefaultResponse(), new HighlightedTextFormatter()));
125
        $output = $output->writeMessage(new MessageMessage('"]'));
126
127
        // :
128
        // > response will be typed here
129
        $output = $output->writeMessage(new MessageMessage(':'));
130
        $output = $output->writeMessage(new NewLine());
131
        $output = $output->writeMessage(new MessageMessage('> '));
132
133
        return $output;
134
    }
135
136
    /**
137
     * Write an answer after it has been answered.
138
     *
139
     * @template O of OutputContract
140
     *
141
     * @param O $output The output
142
     *
143
     * @return O
144
     */
145
    protected function writeAnswerAfterResponse(OutputContract $output, AnswerContract $answer): OutputContract
146
    {
147
        $output = $output->writeMessage($answer);
148
        $output = $output->writeMessage(new NewLine());
149
150
        return $output;
151
    }
152
}
153