Passed
Pull Request — master (#7)
by
unknown
02:04
created

ShellWord::setNameUppercase()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 2
c 1
b 0
f 0
dl 0
loc 4
rs 10
cc 1
nc 1
nop 1
1
<?php
2
3
declare(strict_types=1);
4
5
namespace PHPSu\ShellCommandBuilder\Literal;
6
7
use PHPSu\ShellCommandBuilder\Definition\Pattern;
8
use PHPSu\ShellCommandBuilder\Exception\ShellBuilderException;
9
use PHPSu\ShellCommandBuilder\ShellInterface;
10
11
/**
12
 * Representing the basic element of a Shell Command, a single literal aka "word"
13
 * @internal
14
 * @psalm-internal PHPSu\ShellCommandBuilder\Literal
15
 * @package PHPSu\ShellCommandBuilder\Literal
16
 */
17
class ShellWord implements ShellInterface
18
{
19
    protected const OPTION_CONTROL = '--';
20
    protected const SHORT_OPTION_CONTROL = '-';
21
    protected const EQUAL_CONTROL = '=';
22
23
    /** @var bool */
24
    protected $isShortOption = false;
25
    /** @var bool */
26
    protected $isOption = false;
27
    /** @var bool */
28
    protected $isArgument = false;
29
    /** @var bool */
30
    protected $isEnvironmentVariable = false;
31
    /** @var bool */
32
    protected $isEscaped = true;
33
    /** @var bool */
34
    protected $spaceAfterValue = true;
35
    /** @var bool */
36
    protected $useAssignOperator = false;
37
    /** @var bool */
38
    protected $nameUpperCase = false;
39
    /** @var string */
40
    protected $prefix = '';
41
    /** @var string */
42
    protected $suffix = ' ';
43
    /** @var string */
44
    protected $delimiter = ' ';
45
    /** @var string */
46
    protected $argument;
47
    /** @var string|ShellInterface */
48
    protected $value;
49
50
    /**
51
     * The constructor is protected, you must choose one of the children
52
     * @param string $argument
53
     * @param string|ShellInterface $value
54
     * @throws ShellBuilderException
55
     */
56
    protected function __construct(string $argument, $value = '')
57
    {
58
        if (!empty($argument) && !$this->validShellWord($argument)) {
59
            throw new ShellBuilderException('A Shell Argument has to be a valid Shell word and cannot contain e.g whitespace');
60
        }
61
        $this->argument = $argument;
62
        $this->value = $value;
63
    }
64
65
    public function setEscape(bool $isEscaped): self
66
    {
67
        $this->isEscaped = $isEscaped;
68
        return $this;
69
    }
70
71
    public function setSpaceAfterValue(bool $spaceAfterValue): self
72
    {
73
        $this->spaceAfterValue = $spaceAfterValue;
74
        return $this;
75
    }
76
77
    public function setAssignOperator(bool $useAssignOperator): self
78
    {
79
        $this->useAssignOperator = $useAssignOperator;
80
        return $this;
81
    }
82
83
    public function setNameUppercase(bool $uppercaseName): self
84
    {
85
        $this->nameUpperCase = $uppercaseName;
86
        return $this;
87
    }
88
89
    protected function validate(): void
90
    {
91
        /** @psalm-suppress DocblockTypeContradiction */
92
        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...
93
            throw new ShellBuilderException('Value must be an instance of ShellInterface or a string');
94
        }
95
    }
96
97
    /**
98
     * @psalm-pure
99
     * @param string $word
100
     * @return bool
101
     * @throws ShellBuilderException
102
     */
103
    private function validShellWord(string $word): bool
104
    {
105
        return count(Pattern::split($word)) === 1;
106
    }
107
108
    private function prepare(): void
109
    {
110
        $this->validate();
111
        if (!$this->spaceAfterValue) {
112
            $this->suffix = '';
113
        }
114
        if ($this->useAssignOperator) {
115
            $this->delimiter = self::EQUAL_CONTROL;
116
        }
117
        if (!empty($this->argument) && $this->nameUpperCase) {
118
            $this->argument = strtoupper($this->argument);
119
        }
120
    }
121
122
    /**
123
     * @param bool $debug
124
     * @return array<mixed>|string
125
     */
126
    private function getValue(bool $debug = false)
127
    {
128
        $word = $this->value;
129
        if ($word instanceof ShellInterface) {
130
            if ($debug) {
131
                return $word->__toArray();
132
            }
133
            $word = (string)$word;
134
        }
135
        if ($this->isEscaped && !empty($word)) {
136
            $word = escapeshellarg($word);
137
        }
138
        return $word;
139
    }
140
141
    /**
142
     * @return array<string, mixed>
143
     */
144
    public function __toArray(): array
145
    {
146
        $this->prepare();
147
        return [
148
            'isArgument' => $this->isArgument,
149
            'isShortOption' => $this->isShortOption,
150
            'isOption' => $this->isOption,
151
            'isEnvironmentVariable' => $this->isEnvironmentVariable,
152
            'escaped' => $this->isEscaped,
153
            'withAssign' => $this->useAssignOperator,
154
            'spaceAfterValue' => $this->spaceAfterValue,
155
            'value' => $this->getValue(true),
156
            'argument' => $this->argument,
157
        ];
158
    }
159
160
    public function __toString(): string
161
    {
162
        $this->prepare();
163
        /** @var string $value */
164
        $value = $this->getValue();
165
        return sprintf(
166
            '%s%s%s%s%s',
167
            $this->prefix,
168
            $this->argument,
169
            $this->delimiter,
170
            $value,
171
            $this->suffix
172
        );
173
    }
174
}
175