Completed
Push — master ( e1c388...7bf58d )
by
unknown
12:55 queued 10:58
created

ShellBuilder::runAsynchronously()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 2
c 0
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;
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
        $this->commandList[] = ShellList::addAnd($this->parseCommand($command));
65
        return $this;
66
    }
67
68
    /**
69
     * @param string|ShellInterface $command
70
     * @return $this
71
     * @throws ShellBuilderException
72
     */
73
    public function or($command): self
74
    {
75
        $this->commandList[] = ShellList::addOr($this->parseCommand($command));
76
        return $this;
77
    }
78
79
    /**
80
     * @param string|ShellInterface $command
81
     * @return $this
82
     * @throws ShellBuilderException
83
     */
84
    public function async($command): self
85
    {
86
        $this->commandList[] = ShellList::async($this->parseCommand($command));
87
        return $this;
88
    }
89
90
    /**
91
     * @param string|ShellInterface $command
92
     * @return $this
93
     * @throws ShellBuilderException
94
     */
95
    public function pipe($command): self
96
    {
97
        $this->commandList[] = Pipeline::pipe($this->parseCommand($command));
98
        return $this;
99
    }
100
101
    /**
102
     * @param string|ShellInterface $command
103
     * @return $this
104
     * @throws ShellBuilderException
105
     */
106
    public function pipeWithForward($command): self
107
    {
108
        $this->commandList[] = Pipeline::pipeErrorForward($this->parseCommand($command));
109
        return $this;
110
    }
111
112
    /**
113
     * @param string|ShellInterface $command
114
     * @param bool $append
115
     * @return $this
116
     * @throws ShellBuilderException
117
     */
118
    public function redirectOutput($command, bool $append = false): self
119
    {
120
        $command = $this->parseCommand($command);
121
        $this->commandList[] = Redirection::redirectOutput($command, $append);
122
        return $this;
123
    }
124
125
    /**
126
     * @param string|ShellInterface $command
127
     * @return $this
128
     * @throws ShellBuilderException
129
     */
130
    public function redirectInput($command): self
131
    {
132
        $command = $this->parseCommand($command);
133
        $this->commandList[] = Redirection::redirectInput($command);
134
        return $this;
135
    }
136
137
    /**
138
     * @param string|ShellInterface $command
139
     * @return $this
140
     * @throws ShellBuilderException
141
     */
142
    public function redirectError($command): self
143
    {
144
        $command = $this->parseCommand($command);
145
        $this->commandList[] = Redirection::redirectError($command);
146
        return $this;
147
    }
148
149
    /**
150
     * @param string|ShellInterface $command
151
     * @param bool $toLeft
152
     * @return $this
153
     * @throws ShellBuilderException
154
     */
155
    public function redirect($command, bool $toLeft = true): self
156
    {
157
        $command = $this->parseCommand($command);
158
        $this->commandList[] = Redirection::redirectBetweenFiles($command, $toLeft);
159
        return $this;
160
    }
161
162
    public function redirectErrorToOutput(): self
163
    {
164
        $this->commandList[] = Redirection::redirectErrorToOutput();
165
        return $this;
166
    }
167
168
    public function createGroup(bool $inSameShell = false): self
169
    {
170
        return new self($inSameShell ? GroupType::SAMESHELL_GROUP : GroupType::SUBSHELL_GROUP);
171
    }
172
173
    /**
174
     * @param string|ShellInterface $command
175
     * @param bool $allowEmpty
176
     * @return ShellInterface
177
     * @throws ShellBuilderException
178
     */
179
    private function parseCommand($command, bool $allowEmpty = false): ShellInterface
180
    {
181
        if (is_string($command)) {
182
            $command = $this->createCommand($command);
183
        }
184
        try {
185
            $this->validateCommand($command, $allowEmpty);
186
        } catch (TypeError $typeError) {
187
            throw new ShellBuilderException('Provided the wrong type - only ShellCommand and ShellBuilder allowed');
188
        }
189
        return $command;
190
    }
191
192
    /** @noinspection PhpUnusedParameterInspection */
193
    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

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