Passed
Push — master ( f833b1...244bf6 )
by Timm
02:07
created

Cmd::extend()

Size

Total Lines 2
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 2
Bugs 0 Features 0
Metric Value
eloc 1
c 2
b 0
f 0
nc 1
nop 1
dl 0
loc 2
ccs 0
cts 0
cp 0
1
<?php
2
3
namespace Stefaminator\Cli;
4
5
use Exception;
6
use GetOptionKit\OptionCollection;
7
use GetOptionKit\OptionResult;
8
9
10
class Cmd {
11
12
    /**
13
     * @var Cmd
14
     */
15
    public $parent;
16
17
    /**
18
     * @var string
19
     */
20
    public $cmd;
21
22
    /**
23
     * @var string
24
     */
25
    public $descr;
26
27
    /**
28
     * @var array
29
     */
30
    public $optionSpecs = [];
31
32
    /**
33
     * @var OptionCollection
34
     */
35
    private $optionCollection;
36
37
    /**
38
     * @var OptionResult|null
39
     */
40
    public $optionResult;
41
42
    /**
43
     * @var Exception
44
     */
45
    public $optionParseException;
46
47
    /**
48
     * @var array
49
     */
50
    public $argumentSpecs = [];
51
52
    /**
53
     * @var string[]
54
     */
55
    public $arguments = [];
56
57
    /**
58
     * @var Cmd[]
59
     */
60
    public $subcommands = [];
61
62
    /**
63
     * @var CmdRunner|null
64
     */
65
    private $runner;
66
67
68 20
    public function __construct(string $cmd) {
69 20
        $this->cmd = $cmd;
70 20
    }
71
72 20
    public function addOption(string $specString, array $config): self {
73
74 20
        $this->optionSpecs[$specString] = $config;
75
76 20
        return $this;
77
    }
78
79 15
    public function addArgument(string $specString, array $config): self {
80
81 15
        foreach ($this->argumentSpecs as $k => $v) {
82 15
            if (array_key_exists('multiple', $v)) {
83
                unset($this->argumentSpecs[$k]['multiple']);
84
            }
85
        }
86
87 15
        $config['index'] = count($this->argumentSpecs);
88
89 15
        $this->argumentSpecs[$specString] = $config;
90
91 15
        return $this;
92
    }
93
94 15
    public function addSubCmd(Cmd $cmd): self {
95
96 15
        $cmd->parent = $this;
97 15
        $this->subcommands[$cmd->cmd] = $cmd;
98
99 15
        return $this;
100
    }
101
102 15
    public function setDescription(string $descr): self {
103
104 15
        $this->descr = $descr;
105
106 15
        return $this;
107
    }
108
109 20
    public function setRunner(CmdRunner $runner): self {
110
111 20
        $runner->setCmd($this);
112
113 20
        $this->runner = $runner;
114
115 20
        return $this;
116
    }
117
118 16
    public function hasSubCmd(string $cmd): bool {
119 16
        return array_key_exists($cmd, $this->subcommands);
120
    }
121
122 2
    public function hasProvidedOption(string $key): bool {
123 2
        return $this->optionResult !== null && $this->optionResult->has($key);
124
    }
125
126 2
    public function getProvidedOption(string $key) {
127 2
        if ($this->optionResult !== null) {
128 2
            return $this->optionResult->get($key);
129
        }
130
        return null;
131
    }
132
133
    public function getAllProvidedOptions(): array {
134
        $r = [];
135
        if ($this->optionResult !== null) {
136
            $keys = array_keys($this->optionResult->keys);
137
            foreach($keys as $key) {
138
                $r[$key] = $this->getProvidedOption($key);
139
            }
140
        }
141
        return $r;
142
    }
143
144
    public function getAllProvidedArguments(): array {
145
        return $this->arguments;
146
    }
147
148 10
    public function getSubCmd(string $cmd): ?Cmd {
149 10
        if ($this->hasSubCmd($cmd)) {
150 10
            return $this->subcommands[$cmd];
151
        }
152
        return null;
153
    }
154
155 7
    public function getMethodName(): string {
156 7
        $cmd = $this;
157 7
        $pwd = [];
158
159 7
        while ($cmd !== null) {
160 7
            $pwd[] = $cmd->parent !== null ? $cmd->cmd : 'cmd';
161 7
            $cmd = $cmd->parent;
162
        }
163
164 7
        $pwd = array_reverse($pwd);
165
166 7
        $pwd_str = '';
167 7
        foreach ($pwd as $p) {
168 7
            $pwd_str .= ucfirst(strtolower($p));
169
        }
170
171 7
        return lcfirst($pwd_str);
172
    }
173
174 4
    public function getRunner(): ?CmdRunner {
175 4
        return $this->runner;
176
    }
177
178 20
    public function getOptionCollection(): OptionCollection {
179
180 20
        if ($this->optionCollection !== null) {
181 3
            return $this->optionCollection;
182
        }
183
184 20
        $specs = (array)$this->optionSpecs;
185
186 20
        $collection = new OptionCollection();
187
188 20
        foreach ($specs as $k => $v) {
189 20
            $opt = $collection->add($k, $v['description']);
190 20
            if (array_key_exists('isa', $v)) {
191 10
                $opt->isa($v['isa']);
192
            }
193 20
            if (array_key_exists('default', $v)) {
194 8
                $opt->defaultValue($v['default']);
195
            }
196
        }
197
198 20
        $this->optionCollection = $collection;
199 20
        return $this->optionCollection;
200
    }
201
202 5
    public function handleOptionParseException(): bool {
203
204 5
        if ($this->optionParseException === null) {
205 4
            return false;
206
        }
207
208 1
        CmdRunner::eol();
209 1
        CmdRunner::echo('Uups, something went wrong!', Color::FOREGROUND_COLOR_RED);
210 1
        CmdRunner::eol();
211 1
        CmdRunner::echo($this->optionParseException->getMessage(), Color::FOREGROUND_COLOR_RED);
212 1
        CmdRunner::eol();
213
214 1
        $this->help();
215
216 1
        return true;
217
    }
218
219 3
    public function help(): void {
220 3
        (new HelpRunner($this))->run();
221 3
    }
222
223
    public static function extend(string $cmd): Cmd {
224
        return new class($cmd) extends Cmd {
225
        };
226
    }
227
228 20
    public static function root(): Cmd {
229 20
        return self::extend('__root');
230
    }
231
}