Completed
Pull Request — master (#3)
by
unknown
02:26
created

ShellBuilder::__toArray()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 7
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

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