Completed
Push — master ( 02bfd3...3a9941 )
by David
05:43 queued 01:40
created

AentHelper::askForServiceName()   A

Complexity

Conditions 2
Paths 1

Size

Total Lines 19

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
nc 1
nop 2
dl 0
loc 19
rs 9.6333
c 0
b 0
f 0
1
<?php
2
3
4
namespace TheAentMachine;
5
6
use Symfony\Component\Console\Formatter\OutputFormatterStyle;
7
use Symfony\Component\Console\Helper\FormatterHelper;
8
use Symfony\Component\Console\Helper\QuestionHelper;
9
use Symfony\Component\Console\Input\InputInterface;
10
use Symfony\Component\Console\Output\OutputInterface;
11
use Symfony\Component\Console\Question\Question;
12
use TheAentMachine\Registry\RegistryClient;
13
use TheAentMachine\Registry\TagsAnalyzer;
14
15
/**
16
 * A helper class for the most common questions asked in the console.
17
 */
18
class AentHelper
19
{
20
    /**
21
     * @var InputInterface
22
     */
23
    private $input;
24
    /**
25
     * @var OutputInterface
26
     */
27
    private $output;
28
    /**
29
     * @var QuestionHelper
30
     */
31
    private $questionHelper;
32
    /**
33
     * @var FormatterHelper
34
     */
35
    private $formatterHelper;
36
37
    public function __construct(InputInterface $input, OutputInterface $output, QuestionHelper $questionHelper, FormatterHelper $formatterHelper)
38
    {
39
40
        $this->input = $input;
41
        $this->output = $output;
42
        $this->questionHelper = $questionHelper;
43
        $this->formatterHelper = $formatterHelper;
44
    }
45
46
    private function registerStyle(): void
47
    {
48
        $outputStyle = new OutputFormatterStyle('black', 'cyan', ['bold']);
49
        $this->output->getFormatter()->setStyle('title', $outputStyle);
50
    }
51
52
    /**
53
     * Displays text in a big block
54
     */
55
    public function title(string $title): void
56
    {
57
        $this->registerStyle();
58
        $this->output->writeln($this->formatterHelper->formatBlock($title, 'title', true));
59
    }
60
61
    /**
62
     * Displays text in a small block
63
     */
64
    public function subTitle(string $title): void
65
    {
66
        $this->registerStyle();
67
        $this->output->writeln($this->formatterHelper->formatBlock($title, 'title', false));
68
    }
69
70
    public function askForServiceName(string $serviceName, string $applicationName = ''): string
71
    {
72
        $answer = $this->question("$applicationName service name")
73
            ->setDefault($serviceName)
74
            ->compulsory()
75
            ->setHelpText('The "service name" is used as an identifier for the container you are creating. It is also bound in Docker internal network DNS and can be used from other containers to reference your container.')
76
            ->setValidator(function (string $value) {
77
                $value = trim($value);
78
                if (!\preg_match('/^[a-zA-Z0-9_.-]+$/', $value)) {
79
                    throw new \InvalidArgumentException('Invalid service name "'.$value.'". Service names can contain alphanumeric characters, and "_", ".", "-".');
80
                }
81
                return $value;
82
            })
83
            ->ask();
84
85
        $this->output->writeln("<info>Service name: $answer</info>");
86
        $this->spacer();
87
88
        return $answer;
89
    }
90
91
    public function spacer(): void
92
    {
93
        $this->output->writeln('');
94
    }
95
96
    public function askForTag(string $dockerHubImage, string $applicationName = ''): string
97
    {
98
        $registryClient = new RegistryClient();
99
        $availableVersions = $registryClient->getImageTagsOnDockerHub($dockerHubImage);
100
101
        $tagsAnalyzer = new TagsAnalyzer();
102
        $proposedTags = $tagsAnalyzer->filterBestTags($availableVersions);
103
        $default = $proposedTags[0] ?? null;
104
        $this->output->writeln("Please choose your $applicationName version.");
105
        if (!empty($proposedTags)) {
106
            $this->output->writeln('Possible values include: <info>'.\implode('</info>, <info>', $proposedTags).'</info>');
107
        }
108
        $this->output->writeln('Enter "v" to view all available versions, "?" for help');
109
        $question = new Question(
110
            "Select your $applicationName version [$default]: ",
111
            $default
112
        );
113
        $question->setAutocompleterValues($availableVersions);
114
        $question->setValidator(function (string $value) use ($availableVersions, $dockerHubImage) {
115
            $value = trim($value);
116
117
            if ($value === 'v') {
118
                $this->output->writeln('Available versions: <info>'.\implode('</info>, <info>', $availableVersions).'</info>');
119
                return 'v';
120
            }
121
122
            if ($value === '?') {
123
                $this->output->writeln("Please choose the version (i.e. the tag) of the $dockerHubImage image you are about to install. Press 'v' to view the list of available tags.");
124
                return '?';
125
            }
126
127
            if (!\in_array($value, $availableVersions)) {
128
                throw new \InvalidArgumentException("Version '$value' is invalid.");
129
            }
130
131
            return $value;
132
        });
133
        do {
134
            $version = $this->questionHelper->ask($this->input, $this->output, $question);
135
        } while ($version === 'v' || $version === '?');
136
137
        $this->output->writeln("<info>Selected version: $version</info>");
138
        $this->spacer();
139
140
        return $version;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $version 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...
141
    }
142
143
    public function question(string $question): \TheAentMachine\Helper\Question
144
    {
145
        return new \TheAentMachine\Helper\Question($this->questionHelper, $this->input, $this->output, $question);
146
    }
147
}
148