Passed
Pull Request — master (#6)
by
unknown
02:22
created

ShellWord::asShortOption()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 1
Metric Value
eloc 3
c 1
b 0
f 1
dl 0
loc 5
rs 10
cc 1
nc 1
nop 0
1
<?php
2
3
declare(strict_types=1);
4
5
namespace PHPSu\ShellCommandBuilder;
6
7
use PHPSu\ShellCommandBuilder\Exception\ShellBuilderException;
8
9
final class ShellWord implements ShellInterface
10
{
11
    private const OPTION_CONTROL = '--';
12
    private const SHORT_OPTION_CONTROL = '-';
13
    private const EQUAL_CONTROL = '=';
14
15
    /** @var bool  */
16
    private $isShortOption = false;
17
    /** @var bool  */
18
    private $isOption = false;
19
    /** @var bool  */
20
    private $isArgument = false;
21
    /** @var bool  */
22
    private $isSubcommand = false;
23
    /** @var bool  */
24
    private $isEnvironmentVariable = false;
25
    /** @var bool  */
26
    private $isEscaped = true;
27
    /** @var bool  */
28
    private $spaceAfterValue = true;
29
    /** @var bool  */
30
    private $useAssignOperator = false;
31
32
    /** @var string */
33
    private $prefix = '';
34
    /** @var string */
35
    private $suffix = ' ';
36
    /** @var string */
37
    private $delimiter = ' ';
38
    /** @var string|ShellInterface */
39
    private $argument;
40
    /** @var string|ShellInterface */
41
    private $value;
42
43
    /**
44
     * ShellWord constructor.
45
     * @param string|ShellInterface $argument
46
     * @param string|ShellInterface $value
47
     */
48
    public function __construct($argument, $value = '')
49
    {
50
        $this->argument = $argument;
51
        $this->value = $value;
52
    }
53
54
    public function asOption(): self
55
    {
56
        $this->reset();
57
        $this->isOption = true;
58
        return $this;
59
    }
60
61
    public function asShortOption(): self
62
    {
63
        $this->reset();
64
        $this->isShortOption = true;
65
        return $this;
66
    }
67
68
    public function asArgument(): self
69
    {
70
        $this->reset();
71
        $this->isArgument = true;
72
        return $this;
73
    }
74
75
    public function asSubCommand(): self
76
    {
77
        $this->reset();
78
        $this->isSubcommand = true;
79
        return $this;
80
    }
81
82
    public function asEnvironmentVariable(): self
83
    {
84
        $this->reset();
85
        $this->isEnvironmentVariable = true;
86
        return $this;
87
    }
88
89
    public function setEscape(bool $isEscaped): self
90
    {
91
        $this->isEscaped = $isEscaped;
92
        return $this;
93
    }
94
95
    public function setSpaceAfterValue(bool $spaceAfterValue): self
96
    {
97
        $this->spaceAfterValue = $spaceAfterValue;
98
        return $this;
99
    }
100
101
    public function setAssignOperator(bool $useAssignOperator): self
102
    {
103
        $this->useAssignOperator = $useAssignOperator;
104
        return $this;
105
    }
106
107
    private function reset(): void
108
    {
109
        $this->isOption = false;
110
        $this->isShortOption = false;
111
        $this->isArgument = false;
112
        $this->isSubcommand = false;
113
    }
114
115
    private function validate(): void
116
    {
117
        if ($this->argument === null || (is_string($this->argument) && empty($this->argument))) {
118
            throw new ShellBuilderException('Argument cant be empty');
119
        }
120
        if (!(is_string($this->value) || $this->value instanceof ShellInterface)) {
0 ignored issues
show
introduced by
$this->value is always a sub-type of PHPSu\ShellCommandBuilder\ShellInterface.
Loading history...
121
            throw new ShellBuilderException('Value must be an instance of ShellInterface or a string');
122
        }
123
        if (!(is_string($this->argument) || $this->argument instanceof ShellInterface)) {
0 ignored issues
show
introduced by
$this->argument is always a sub-type of PHPSu\ShellCommandBuilder\ShellInterface.
Loading history...
124
            throw new ShellBuilderException('Argument must be an instance of ShellInterface or a string');
125
        }
126
        if (!($this->isOption || $this->isShortOption || $this->isSubcommand || $this->isArgument || $this->isEnvironmentVariable)) {
127
            throw new ShellBuilderException('No ShellWord-Type defined - use e.g. asArgument() to define it');
128
        }
129
        if (($this->isArgument || $this->isSubcommand) && is_string($this->value) && !empty($this->value)) {
130
            throw new ShellBuilderException('An argument cant have a value');
131
        }
132
        if (($this->isArgument || $this->isSubcommand) && $this->value instanceof ShellInterface) {
133
            throw new ShellBuilderException('An argument cant have a value');
134
        }
135
        if ($this->isEnvironmentVariable && !(is_string($this->value) && is_string($this->argument))) {
136
            throw new ShellBuilderException('EnvironmentVariables must be string only');
137
        }
138
    }
139
140
    private function prepare(): void
141
    {
142
        if ($this->isOption) {
143
            $this->prefix = self::OPTION_CONTROL;
144
        }
145
        if ($this->isShortOption) {
146
            $this->prefix = self::SHORT_OPTION_CONTROL;
147
        }
148
        if (!$this->spaceAfterValue) {
149
            $this->suffix = '';
150
        }
151
        if ($this->useAssignOperator) {
152
            $this->delimiter = self::EQUAL_CONTROL;
153
        }
154
        if ($this->isSubcommand || $this->isArgument) {
155
            $this->delimiter = '';
156
        }
157
        if (($this->isShortOption || $this->isOption) && empty($this->value)) {
158
            $this->delimiter = '';
159
        }
160
        if ($this->isEnvironmentVariable) {
161
            $this->argument = strtoupper($this->argument);
162
        }
163
    }
164
165
    /**
166
     * @param bool $debug
167
     * @return array<mixed>|string
168
     */
169
    private function getArgument(bool $debug = false)
170
    {
171
        $word = $this->argument;
172
        if ($word instanceof ShellInterface) {
173
            if ($debug) {
174
                return $word->__toArray();
175
            }
176
            $word = (string)$word;
177
        }
178
        if ($this->isEscaped && ($this->isArgument || $this->isSubcommand) && !empty($word)) {
179
            $word = escapeshellarg($word);
180
        }
181
        return $word;
182
    }
183
184
    /**
185
     * @param bool $debug
186
     * @return array<mixed>|string
187
     */
188
    private function getValue(bool $debug = false)
189
    {
190
        $word = $this->value;
191
        if ($word instanceof ShellInterface) {
192
            if ($debug) {
193
                return $word->__toArray();
194
            }
195
            $word = (string)$word;
196
        }
197
        if ($this->isEscaped && !empty($word)) {
198
            $word = escapeshellarg($word);
199
        }
200
        return $word;
201
    }
202
203
    /**
204
     * @return array<string, mixed>
205
     * @throws ShellBuilderException
206
     */
207
    public function __toArray(): array
208
    {
209
        $this->validate();
210
        return [
211
            'isArgument' => $this->isArgument,
212
            'isSubcommand' => $this->isSubcommand,
213
            'isShortOption' => $this->isShortOption,
214
            'isOption' => $this->isOption,
215
            'isEnvironmentVariable' => $this->isEnvironmentVariable,
216
            'escaped' => $this->isEscaped,
217
            'withAssign' => $this->useAssignOperator,
218
            'spaceAfterValue' => $this->spaceAfterValue,
219
            'value' => $this->getValue(true),
220
            'argument' => $this->getArgument(true),
221
        ];
222
    }
223
224
    public function __toString(): string
225
    {
226
        $this->validate();
227
        $this->prepare();
228
        /** @var string $argument */
229
        $argument = $this->getArgument();
230
        /** @var string $value */
231
        $value = $this->getValue();
232
        return sprintf(
233
            '%s%s%s%s%s',
234
            $this->prefix,
235
            $argument,
236
            $this->delimiter,
237
            $value,
238
            $this->suffix
239
        );
240
    }
241
}
242