Completed
Pull Request — master (#12)
by Harry
11:21
created

Lines::updateRowKeyLengths()   B

Complexity

Conditions 5
Paths 3

Size

Total Lines 14
Code Lines 7

Duplication

Lines 14
Ratio 100 %

Code Coverage

Tests 3
CRAP Score 5

Importance

Changes 0
Metric Value
dl 14
loc 14
ccs 3
cts 3
cp 1
rs 8.8571
c 0
b 0
f 0
cc 5
eloc 7
nc 3
nop 1
crap 5
1
<?php
2
3
namespace Graze\ParallelProcess;
4
5
use Graze\DiffRenderer\DiffConsoleOutput;
6
use Graze\DiffRenderer\Terminal\TerminalInterface;
7
use Symfony\Component\Console\Output\OutputInterface;
8
use Symfony\Component\Process\Exception\ProcessFailedException;
9
use Symfony\Component\Process\Process;
10
11
class Lines
12
{
13
    /** @var OutputInterface */
14
    private $output;
15
    /** @var TerminalInterface */
16
    private $terminal;
17
    /** @var Pool */
18
    private $processPool;
19
    /** @var int[] */
20
    private $maxLengths = [];
21
    /** @var bool */
22
    private $showDuration = true;
23
    /** @var bool */
24
    private $showType = true;
25
    /** @var bool */
26
    private $colourProcesses = true;
27
    /** @var string[] */
28
    private $colours = ['red', 'green', 'blue', 'yellow', 'magenta', 'white', 'cyan'];
29
30
    /**
31
     * Stream constructor.
32
     *
33
     * @param OutputInterface $output
34
     * @param Pool|null       $pool
35
     */
36 8 View Code Duplication
    public function __construct(OutputInterface $output, Pool $pool = null)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
37
    {
38 5
        $this->output = $output;
39 5
        if (!$output instanceof DiffConsoleOutput) {
40
            $this->output = new DiffConsoleOutput($output);
41
            $this->output->setTrim(false);
42
        } else {
43 8
            $this->output = $output;
44 3
        }
45
        $this->terminal = $this->output->getTerminal();
46 5
        $this->processPool = $pool ?: new Pool();
47
    }
48
49
    /**
50
     * Show the running duration of each process
51
     *
52
     * @param bool $showDuration
53
     *
54
     * @return $this
55
     */
56 1
    public function setShowDuration($showDuration)
57
    {
58 1
        $this->showDuration = $showDuration;
59 1
        return $this;
60
    }
61
62
    /**
63
     * @return bool
64
     */
65
    public function isShowDuration()
66
    {
67
        return $this->showDuration;
68
    }
69
70
    /**
71
     * Show the type of each output (`out` or `err`)
72
     *
73
     * @param bool $showType
74
     *
75
     * @return $this
76
     */
77 2
    public function setShowType($showType)
78
    {
79 2
        $this->showType = $showType;
80 2
        return $this;
81
    }
82
83
    /**
84
     * @return bool
85
     */
86
    public function isShowType()
87
    {
88
        return $this->showType;
89
    }
90
91
    /**
92
     * Set weather this should colour each process with a different colour
93
     *
94
     * @param bool $colourProcesses
95
     *
96
     * @return $this
97
     */
98 2
    public function setColourProcesses($colourProcesses)
99
    {
100 2
        $this->colourProcesses = $colourProcesses;
101 2
        return $this;
102
    }
103
104
    /**
105
     * Does this colour each process with a different colour
106
     *
107
     * @return bool
108
     */
109
    public function isColourProcesses()
110
    {
111
        return $this->colourProcesses;
112
    }
113
114
    /**
115
     * @param Process $process
116
     * @param array   $data
117
     */
118 4
    public function add(Process $process, array $data = [])
119
    {
120
        $index = $this->processPool->count();
121
        $onProgress = function (Process $process, $duration, $last, $lastType) use ($index, $data) {
122 1
            $message = ($this->showType ? sprintf('(%s) %s', $lastType, $last) : $last);
123
            $this->output->writeln($this->format($index, $data, $duration, $message));
124
        };
125
126
        $run = new Run(
127
            $process,
128
            function (Process $process, $duration) use ($index, $data) {
129
                $this->output->writeln($this->format($index, $data, $duration, "<info>✓ Succeeded</info>"));
130 1
            },
131
            function (Process $process, $duration) use ($index, $data) {
132 1
                $this->output->writeln(
133 1
                    $this->format(
134
                        $index,
135
                        $data,
136
                        $duration,
137
                        sprintf(
138 1
                            "<error>x Failed</error> (code: %d) %s",
139 1
                            $process->getExitCode(),
140 1
                            $process->getExitCodeText()
141
                        )
142
                    )
143
                );
144
                $this->output->writeln((new ProcessFailedException($process))->getMessage());
145 4
            },
146
            $onProgress,
147
            function (Process $process, $duration) use ($index, $data) {
148
                $this->output->writeln($this->format($index, $data, $duration, "<fg=blue>→ Started</>"));
149
            }
150
        );
151
        $run->setUpdateOnPoll(false);
152
        $this->processPool->add($run);
153
154
        $this->updateRowKeyLengths($data);
155
    }
156
157
    /**
158
     * Parses the rows to determine the key lengths to make a pretty table
159
     *
160
     * @param array $data
161
     */
162 5 View Code Duplication
    private function updateRowKeyLengths(array $data = [])
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
163
    {
164
        $lengths = array_map('mb_strlen', $data);
165
166
        $keys = array_merge(array_keys($lengths), array_keys($this->maxLengths));
167
168
        foreach ($keys as $key) {
169 5
            if (!isset($this->maxLengths[$key])
170
                || (isset($lengths[$key]) && $lengths[$key] > $this->maxLengths[$key])
171
            ) {
172 5
                $this->maxLengths[$key] = $lengths[$key];
173
            }
174
        }
175
    }
176
177
    /**
178
     * @param int    $index
179
     * @param array  $data
180
     * @param float  $duration
181
     * @param string $message
182
     *
183
     * @return string
184
     */
185
    private function format($index, array $data, $duration, $message = '')
186
    {
187
        $info = [];
188
        foreach ($data as $key => $value) {
189
            $length = isset($this->maxLengths[$key]) ? '-' . $this->maxLengths[$key] : '';
190
            if ($this->colourProcesses) {
191
                $colour = $this->colours[$index % count($this->colours)];
192
                $valueFormat = sprintf("<options=bold;fg=%s>%{$length}s</>", $colour, $value);
193
            } else {
194
                $valueFormat = sprintf("%{$length}s", $value);
195
            }
196
            if (is_int($key)) {
197
                $info[] = $valueFormat;
198
            } else {
199
                $info[] = sprintf("<info>%s</info>: %s", $key, $valueFormat);
200
            }
201
        }
202
        $output = implode(' ', $info);
203
        if ($this->showDuration) {
204
            $output .= sprintf(' (<comment>%6.2fs</comment>)', $duration);
205
        }
206
207
        return sprintf("%s %s", $output, $this->terminal->filter($message));
208
    }
209
210
    /**
211
     * @param float $checkInterval
212
     *
213
     * @return bool true if all processes were successful
214
     */
215
    public function run($checkInterval = Pool::CHECK_INTERVAL)
216
    {
217
        return $this->processPool->run($checkInterval);
218
    }
219
}
220