Stdin::getArgument()   A
last analyzed

Complexity

Conditions 3
Paths 3

Size

Total Lines 8
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 3
eloc 4
c 1
b 0
f 0
nc 3
nop 1
dl 0
loc 8
rs 10
1
<?php
2
3
namespace pjpawel\LightApi\Command\Input;
4
5
use Exception;
6
use pjpawel\LightApi\Exception\KernelException;
7
8
class Stdin implements InputInterface
9
{
10
11
    /**
12
     * @var Option[]
13
     */
14
    public array $options = [];
15
    /**
16
     * @var Argument[]
17
     */
18
    public array $arguments = [];
19
20
    /**
21
     * @return void
22
     * @throws KernelException
23
     * @throws Exception
24
     */
25
    public function load(): void
26
    {
27
        $loadedArguments = [];
28
        $loadedOptions = [];
29
        $argv = $_SERVER['argv'];
30
        $argvCount = count($argv);
31
        for ($i = 2; $i <= $argvCount; $i++) {
32
            if (!isset($argv[$i])) {
33
                continue;
34
            }
35
            if (str_contains($argv[$i], '=')) {
36
                [$optionName, $value] = explode('=', $argv[$i], 2);
37
                if (empty($value)) {
38
                    throw new Exception('Missing value for option: ' . $optionName);
39
                }
40
                if (str_starts_with($optionName, '--')) {
41
                    $loadedOptions[] = [
42
                        'shortName' => null,
43
                        'longName' => substr($optionName, 2),
44
                        'value' => $value
45
                    ];
46
                } elseif (str_starts_with($optionName, '-')) {
47
                    $loadedOptions[] = [
48
                        'shortName' => substr($optionName, 1),
49
                        'longName' => null,
50
                        'value' => $value
51
                    ];
52
                } else {
53
                    throw new KernelException('Uncovered option ' . $argv[$i]);
54
                }
55
            } elseif (str_starts_with($argv[$i], '--')) {
56
                if (!isset($argv[$i+1])) {
57
                    throw new Exception('Missing value for option: ' . substr($argv[$i], 2));
58
                }
59
                $loadedOptions[] = [
60
                    'shortName' => null,
61
                    'longName' => substr($argv[$i], 2),
62
                    'value' => $argv[$i+1]
63
                ];
64
                unset($argv[$i+1]);
65
            } elseif (str_starts_with($argv[$i], '-')) {
66
                if (!isset($argv[$i+1])) {
67
                    throw new Exception('Missing value for option: ' . substr($argv[$i], 1));
68
                }
69
                $loadedOptions[] = [
70
                    'shortName' => substr($argv[$i], 1),
71
                    'longName' => null,
72
                    'value' => $argv[$i+1]
73
                ];
74
                unset($argv[$i+1]);
75
            } else {
76
                $loadedArguments[] = $argv[$i];
77
            }
78
        }
79
        foreach ($this->arguments as $argument) {
80
            $argument->setValue(array_shift($loadedArguments));
81
            if ($argument->type == Argument::REQUIRED && $argument->value == null) {
82
                throw new Exception('Missing required argument: ' . $argument->name);
83
            }
84
        }
85
        foreach ($this->options as $option) {
86
            $loadedOption = $this->optionExists($loadedOptions, $option->shortcut, $option->name);
87
            if ($loadedOption !== false) {
88
                $option->setValue($loadedOption['value']);
89
            }
90
            if ($option->type == Option::REQUIRED && $option->value == null) {
91
                throw new Exception('Missing required option: ' . $option->name);
92
            }
93
        }
94
    }
95
96
    /**
97
     * @param array $options
98
     * @param string $shortName
99
     * @param string $longName
100
     * @return array|false
101
     */
102
    private function optionExists(array $options, string $shortName, string $longName): array|false
103
    {
104
        foreach ($options as $option) {
105
            if ($shortName == $option['shortName']) {
106
                return $option;
107
            }
108
            if ($longName == $option['longName']) {
109
                return $option;
110
            }
111
        }
112
        return false;
113
    }
114
115
    public function addOption(
116
        string $name,
117
        ?string $shortcut = null,
118
        int $type = Option::OPTIONAL,
119
        mixed $default = null,
120
        string $description = null
121
    ): void
122
    {
123
        $this->options[] = new Option($name, $shortcut, $type, $default, $description);
124
    }
125
126
    public function addArgument(
127
        string $name,
128
        int $type = Argument::REQUIRED,
129
        string $description = null
130
    ): void
131
    {
132
        $this->arguments[] = new Argument($name, $type, $description);
133
    }
134
135
    /**
136
     * @param string $name
137
     * @return int|string|null
138
     * @throws Exception
139
     */
140
    public function getOption(string $name): int|string|null
141
    {
142
        foreach ($this->options as $option) {
143
            if ($option->name === $name) {
144
                return $option->value ?? $option->default;
145
            }
146
        }
147
        throw new Exception("Option $name wasn't found");
148
    }
149
150
    /**
151
     * @param string $name
152
     * @return int|string|null
153
     * @throws Exception
154
     */
155
    public function getArgument(string $name): int|string|null
156
    {
157
        foreach ($this->arguments as $argument) {
158
            if ($argument->name === $name) {
159
                return $argument->value;
160
            }
161
        }
162
        throw new Exception("Argument $name wasn't found");
163
    }
164
}