Passed
Pull Request — master (#6)
by
unknown
01:45
created

ShellBuilder::add()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 9
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Importance

Changes 2
Bugs 0 Features 0
Metric Value
eloc 6
c 2
b 0
f 0
dl 0
loc 9
rs 10
cc 2
nc 2
nop 1
1
<?php
2
3
declare(strict_types=1);
4
5
namespace PHPSu\ShellCommandBuilder;
6
7
use PHPSu\ShellCommandBuilder\Collection\CollectionTuple;
8
use PHPSu\ShellCommandBuilder\Collection\Pipeline;
9
use PHPSu\ShellCommandBuilder\Collection\Redirection;
10
use PHPSu\ShellCommandBuilder\Collection\ShellList;
11
use PHPSu\ShellCommandBuilder\Definition\ControlOperator;
12
use PHPSu\ShellCommandBuilder\Definition\GroupType;
13
use PHPSu\ShellCommandBuilder\Exception\ShellBuilderException;
14
use TypeError;
15
16
final class ShellBuilder implements ShellInterface
17
{
18
    /** @var array<ShellInterface|CollectionTuple>  */
19
    private $commandList = [];
20
    /** @var int */
21
    private $groupType;
22
    /** @var bool */
23
    private $asynchronously = false;
24
25
    public function __construct(int $groupType = GroupType::NO_GROUP)
26
    {
27
        $this->groupType = $groupType;
28
    }
29
30
    public function createCommand(string $name, bool $withNewBuilder = false): ShellCommand
31
    {
32
        return new ShellCommand($name, $withNewBuilder ? new self() : $this);
33
    }
34
35
    public function runAsynchronously(bool $isAsync = true): self
36
    {
37
        $this->asynchronously = $isAsync;
38
        return $this;
39
    }
40
41
    /**
42
     * @param string|ShellInterface $command
43
     * @return $this
44
     * @throws ShellBuilderException
45
     */
46
    public function add($command): self
47
    {
48
        $command = $this->parseCommand($command, true);
49
        if (empty($this->commandList)) {
50
            $this->commandList[] = $command;
51
            return $this;
52
        }
53
        $this->commandList[] = ShellList::add($command);
54
        return $this;
55
    }
56
57
    /**
58
     * @param string|ShellInterface $command
59
     * @return $this
60
     * @throws ShellBuilderException
61
     */
62
    public function and($command): self
63
    {
64
        if (is_string($command)) {
65
            $command = $this->createCommand($command);
66
        }
67
        $this->commandList[] = ShellList::addAnd($this->parseCommand($command));
68
        return $this;
69
    }
70
71
    /**
72
     * @param string|ShellInterface $command
73
     * @return $this
74
     * @throws ShellBuilderException
75
     */
76
    public function or($command): self
77
    {
78
        if (is_string($command)) {
79
            $command = $this->createCommand($command);
80
        }
81
        $this->commandList[] = ShellList::addOr($this->parseCommand($command));
82
        return $this;
83
    }
84
85
    /**
86
     * @param string|ShellInterface $command
87
     * @return $this
88
     * @throws ShellBuilderException
89
     */
90
    public function pipe($command): self
91
    {
92
        if (is_string($command)) {
93
            $command = $this->createCommand($command);
94
        }
95
        $this->commandList[] = Pipeline::pipe($this->parseCommand($command));
96
        return $this;
97
    }
98
99
    /**
100
     * @param string|ShellInterface $command
101
     * @return $this
102
     * @throws ShellBuilderException
103
     */
104
    public function pipeWithForward($command): self
105
    {
106
        if (is_string($command)) {
107
            $command = $this->createCommand($command);
108
        }
109
        $this->commandList[] = Pipeline::pipeErrorForward($this->parseCommand($command));
110
        return $this;
111
    }
112
113
    /**
114
     * @param string|ShellInterface $command
115
     * @param bool $append
116
     * @return $this
117
     * @throws ShellBuilderException
118
     */
119
    public function redirectOutput($command, bool $append = false): self
120
    {
121
        $command = $this->parseCommand($command);
122
        $this->commandList[] = Redirection::redirectOutput($command, $append);
123
        return $this;
124
    }
125
126
    /**
127
     * @param string|ShellInterface $command
128
     * @return $this
129
     * @throws ShellBuilderException
130
     */
131
    public function redirectInput($command): self
132
    {
133
        $command = $this->parseCommand($command);
134
        $this->commandList[] = Redirection::redirectInput($command);
135
        return $this;
136
    }
137
138
    /**
139
     * @param string|ShellInterface $command
140
     * @return $this
141
     * @throws ShellBuilderException
142
     */
143
    public function redirectError($command): self
144
    {
145
        $command = $this->parseCommand($command);
146
        $this->commandList[] = Redirection::redirectError($command);
147
        return $this;
148
    }
149
150
    /**
151
     * @param string|ShellInterface $command
152
     * @param bool $toLeft
153
     * @return $this
154
     * @throws ShellBuilderException
155
     */
156
    public function redirect($command, bool $toLeft = true): self
157
    {
158
        $command = $this->parseCommand($command);
159
        $this->commandList[] = Redirection::redirectBetweenFiles($command, $toLeft);
160
        return $this;
161
    }
162
163
    public function redirectErrorToOutput(): self
164
    {
165
        $this->commandList[] = Redirection::redirectErrorToOutput();
166
        return $this;
167
    }
168
169
    public function createGroup(bool $inSameShell = false): self
170
    {
171
        return new self($inSameShell ? GroupType::SAMESHELL_GROUP : GroupType::SUBSHELL_GROUP);
172
    }
173
174
    /**
175
     * @param string|ShellInterface $command
176
     * @param bool $allowEmpty
177
     * @return ShellInterface
178
     * @throws ShellBuilderException
179
     */
180
    private function parseCommand($command, bool $allowEmpty = false): ShellInterface
181
    {
182
        if (is_string($command)) {
183
            $command = $this->createCommand($command);
184
        }
185
        try {
186
            $this->validateCommand($command, $allowEmpty);
187
        } catch (TypeError $typeError) {
188
            throw new ShellBuilderException('Provided the wrong type - only ShellCommand and ShellBuilder allowed');
189
        }
190
        return $command;
191
    }
192
193
    /** @noinspection PhpUnusedParameterInspection */
194
    private function validateCommand(ShellInterface $command, bool $allowEmpty): void
0 ignored issues
show
Unused Code introduced by
The parameter $command is not used and could be removed. ( Ignorable by Annotation )

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

194
    private function validateCommand(/** @scrutinizer ignore-unused */ ShellInterface $command, bool $allowEmpty): void

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
195
    {
196
        if (!$allowEmpty && empty($this->commandList)) {
197
            throw new ShellBuilderException('You have to first add a command before you can combine it');
198
        }
199
    }
200
201
    /**
202
     * @return array<mixed>
203
     */
204
    public function __toArray(): array
205
    {
206
        $commands = [];
207
        foreach ($this->commandList as $item) {
208
            $commands[] = $item instanceof ShellInterface ? $item->__toArray() : $item;
209
        }
210
        return $commands;
211
    }
212
213
    public function __toString(): string
214
    {
215
        $result = '';
216
        if ($this->asynchronously) {
217
            $result = 'coproc ';
218
        }
219
        foreach ($this->commandList as $command) {
220
            $result .= $command;
221
        }
222
        if ($this->groupType === GroupType::SAMESHELL_GROUP) {
223
            return sprintf(
224
                '%s%s;%s',
225
                ControlOperator::CURLY_BLOCK_DEFINITON_OPEN,
226
                $result,
227
                ControlOperator::CURLY_BLOCK_DEFINITON_CLOSE
228
            );
229
        }
230
        if ($this->groupType === GroupType::SUBSHELL_GROUP) {
231
            return sprintf(
232
                '%s%s%s',
233
                ControlOperator::BLOCK_DEFINITON_OPEN,
234
                $result,
235
                ControlOperator::BLOCK_DEFINITON_CLOSE
236
            );
237
        }
238
        return $result;
239
    }
240
}
241