Passed
Branch master (68f47c)
by Nils
03:49 queued 01:24
created

InitCommand::getServerName()   A

Complexity

Conditions 3
Paths 2

Size

Total Lines 22
Code Lines 13

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 3
eloc 13
c 1
b 0
f 0
nc 2
nop 2
dl 0
loc 22
rs 9.8333
1
<?php
2
3
namespace Startwind\Inventorio\Command;
4
5
use GuzzleHttp\Client;
6
use GuzzleHttp\Exception\ClientException;
7
use GuzzleHttp\RequestOptions;
8
use Symfony\Component\Console\Command\Command;
9
use Symfony\Component\Console\Input\InputArgument;
10
use Symfony\Component\Console\Input\InputInterface;
11
use Symfony\Component\Console\Input\InputOption;
12
use Symfony\Component\Console\Output\OutputInterface;
13
use Symfony\Component\Console\Style\SymfonyStyle;
14
15
class InitCommand extends InventorioCommand
16
{
17
    protected static $defaultName = 'init';
18
    protected static $defaultDescription = 'Initialize Inventorio';
19
20
    private const ENDPOINT_INIT = '/inventory/server/{serverId}';
21
22
    private const SERVER_ID_PREFIX = 'inv-srv-';
23
24
    protected function configure(): void
25
    {
26
        parent::configure();
27
28
        $this->addArgument('userId', InputArgument::REQUIRED, 'The inventorio user id.');
29
        $this->addOption('serverName', 's', InputOption::VALUE_OPTIONAL, 'The server name');
30
    }
31
32
    protected function execute(InputInterface $input, OutputInterface $output): int
33
    {
34
        $this->initConfiguration($input->getOption('configFile'));
35
36
        if ($this->isInitialized()) {
37
            $output->writeln('<info>System is already initialized.</info>');
38
            return Command::SUCCESS;
39
        }
40
41
        $serverName = $this->getServerName();
0 ignored issues
show
Bug introduced by
The call to Startwind\Inventorio\Com...ommand::getServerName() has too few arguments starting with input. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

41
        /** @scrutinizer ignore-call */ 
42
        $serverName = $this->getServerName();

This check compares calls to functions or methods with their respective definitions. If the call has less arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress. Please note the @ignore annotation hint above.

Loading history...
42
43
        $configFile = $this->getConfigFile();
44
        $serverId = $this->createServerId();
45
46
        $userId = $input->getArgument('userId');
47
48
        $client = new Client();
49
50
        $payload = [
51
            'userId' => $userId,
52
            'serverId' => $serverId,
53
            'serverName' => $serverName
54
        ];
55
56
        try {
57
            $client->post($this->getPreparedEndpoint($serverId), [
58
                RequestOptions::JSON => $payload
59
            ]);
60
        } catch (ClientException $exception) {
61
            $result = json_decode((string)$exception->getResponse()->getBody(), true);
62
            $output->writeln('<error>Unable to initialize: ' . $result['message'] . '</error>');
63
            return Command::FAILURE;
64
        }
65
66
        $config = [
67
            'serverId' => $serverId,
68
            'userId' => $userId
69
        ];
70
71
        if (!file_exists(dirname($configFile))) {
72
            mkdir(dirname($configFile), 0777, true);
73
        }
74
75
        file_put_contents($configFile, json_encode($config), JSON_PRETTY_PRINT);
76
77
        $output->writeln('<info>Server registered. Please run the following command to set up  the cron job:</info>');
78
        $output->writeln('');
79
        $output->writeln('<comment>(crontab -l 2>/dev/null; echo "' . rand(0, 59) . ' * * * * /usr/local/bin/inventorio collect >> /var/log/inventorio.log 2>&1") | crontab -</comment>');
80
81
        return Command::SUCCESS;
82
    }
83
84
    /**
85
     * Ask the user for the server name if not set a parameter.
86
     */
87
    private function getServerName(InputInterface $input, OutputInterface $output): string
88
    {
89
        if (!$input->getOption('serverName')) {
90
            $io = new SymfonyStyle($input, $output);
91
92
            $defaultName = gethostname();
93
94
            $serverName = $io->ask(
95
                'Please provide the name of the server (default: ' . $defaultName . ')',
96
                $defaultName,
97
                function (?string $value) {
98
                    if (strlen($value ?? '') < 3) {
99
                        throw new \RuntimeException('The server name has to be at least three characters long.');
100
                    }
101
                    return $value;
102
                }
103
            );
104
        } else {
105
            $serverName = $input->getOption('serverName');
106
        }
107
108
        return $serverName;
109
    }
110
111
    /**
112
     * Return the final endpoint where the collected data should be sent to.
113
     */
114
    private function getPreparedEndpoint($serverId): string
115
    {
116
        return str_replace('{serverId}', $serverId, $this->config->getInventorioServer() . self::ENDPOINT_INIT);
117
    }
118
119
    private function createServerId(): string
120
    {
121
        $data = random_bytes(16);
122
123
        $data[6] = chr(ord($data[6]) & 0x0f | 0x40);
124
        $data[8] = chr(ord($data[8]) & 0x3f | 0x80);
125
126
        return self::SERVER_ID_PREFIX . vsprintf('%s%s-%s-%s-%s-%s%s%s', str_split(bin2hex($data), 4));
0 ignored issues
show
Bug introduced by
It seems like str_split(bin2hex($data), 4) can also be of type true; however, parameter $values of vsprintf() does only seem to accept array, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

126
        return self::SERVER_ID_PREFIX . vsprintf('%s%s-%s-%s-%s-%s%s%s', /** @scrutinizer ignore-type */ str_split(bin2hex($data), 4));
Loading history...
127
    }
128
}
129