Lines   A
last analyzed

Complexity

Total Complexity 25

Size/Duplication

Total Lines 241
Duplicated Lines 0 %

Test Coverage

Coverage 100%

Importance

Changes 0
Metric Value
wmc 25
eloc 95
dl 0
loc 241
ccs 113
cts 113
cp 1
rs 10
c 0
b 0
f 0

12 Methods

Rating   Name   Duplication   Size   Complexity  
A run() 0 3 1
A isShowDuration() 0 3 1
A setShowType() 0 4 1
A setShowDuration() 0 4 1
A setShowProgress() 0 4 1
A isColourProcesses() 0 3 1
A isShowType() 0 3 1
A isShowProgress() 0 3 1
A setColourProcesses() 0 4 1
B add() 0 61 7
A format() 0 21 6
A __construct() 0 20 3
1
<?php
2
/**
3
 * This file is part of graze/parallel-process.
4
 *
5
 * Copyright © 2018 Nature Delivered Ltd. <https://www.graze.com>
6
 *
7
 * For the full copyright and license information, please view the LICENSE
8
 * file that was distributed with this source code.
9
 *
10
 * @license https://github.com/graze/parallel-process/blob/master/LICENSE.md
11
 * @link    https://github.com/graze/parallel-process
12
 */
13
14
namespace Graze\ParallelProcess\Display;
15
16
use Graze\DiffRenderer\DiffConsoleOutput;
17
use Graze\DiffRenderer\Terminal\TerminalInterface;
18
use Graze\ParallelProcess\Event\PoolRunEvent;
19
use Graze\ParallelProcess\Event\RunEvent;
20
use Graze\ParallelProcess\OutputterInterface;
21
use Graze\ParallelProcess\PoolInterface;
22
use Graze\ParallelProcess\PriorityPool;
23
use Graze\ParallelProcess\ProcessRun;
24
use Graze\ParallelProcess\RunInterface;
25
use Symfony\Component\Console\Output\OutputInterface;
26
27
class Lines
28
{
29
    use TagsTrait;
30
31
    /** @var OutputInterface */
32
    private $output;
33
    /** @var TerminalInterface */
34
    private $terminal;
35
    /** @var PoolInterface */
36
    private $pool;
37
    /** @var bool */
38
    private $showDuration = true;
39
    /** @var bool */
40
    private $showType = true;
41
    /** @var bool */
42
    private $showProgress = true;
43
    /** @var bool */
44
    private $colourProcesses = true;
45
    /** @var string[] */
46
    private $colours = ['red', 'green', 'blue', 'yellow', 'magenta', 'white', 'cyan'];
47
    /** @var TinyProgressBar|null */
48
    private $bar = null;
49
    /** @var int */
50
    private $counter = 0;
51
52
    /**
53
     * Lines constructor.
54
     *
55
     * @param OutputInterface    $output
56
     * @param PoolInterface|null $pool
57
     */
58 13
    public function __construct(OutputInterface $output, PoolInterface $pool = null)
59
    {
60 13
        $this->output = $output;
61 13
        if (!$output instanceof DiffConsoleOutput) {
62 3
            $this->output = new DiffConsoleOutput($output);
63 3
            $this->output->setTrim(false);
0 ignored issues
show
Bug introduced by
The method setTrim() does not exist on Symfony\Component\Console\Output\OutputInterface. It seems like you code against a sub-type of Symfony\Component\Console\Output\OutputInterface such as Graze\DiffRenderer\DiffConsoleOutput. ( Ignorable by Annotation )

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

63
            $this->output->/** @scrutinizer ignore-call */ 
64
                           setTrim(false);
Loading history...
64 3
        } else {
65 13
            $this->output = $output;
66
        }
67 13
        $this->terminal = $this->output->getTerminal();
0 ignored issues
show
Bug introduced by
The method getTerminal() does not exist on Symfony\Component\Console\Output\OutputInterface. It seems like you code against a sub-type of Symfony\Component\Console\Output\OutputInterface such as Graze\DiffRenderer\DiffConsoleOutput. ( Ignorable by Annotation )

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

67
        /** @scrutinizer ignore-call */ 
68
        $this->terminal = $this->output->getTerminal();
Loading history...
68 13
        $this->pool = $pool ?: new PriorityPool();
69
70 13
        $this->pool->addListener(
71 13
            PoolRunEvent::POOL_RUN_ADDED,
72
            function (PoolRunEvent $event) {
73 10
                $this->add($event->getRun());
74 10
            }
75 13
        );
76
77 13
        array_map([$this, 'add'], $this->pool->getAll());
78 13
    }
79
80
    /**
81
     * Show the running duration of each process
82
     *
83
     * @param bool $showDuration
84
     *
85
     * @return $this
86
     */
87 2
    public function setShowDuration($showDuration)
88
    {
89 2
        $this->showDuration = $showDuration;
90 2
        return $this;
91
    }
92
93
    /**
94
     * @return bool
95
     */
96 1
    public function isShowDuration()
97
    {
98 1
        return $this->showDuration;
99
    }
100
101
    /**
102
     * @return bool
103
     */
104 1
    public function isShowProgress()
105
    {
106 1
        return $this->showProgress;
107
    }
108
109
    /**
110
     * @param bool $showProgress
111
     *
112
     * @return Lines
113
     */
114 2
    public function setShowProgress($showProgress)
115
    {
116 2
        $this->showProgress = $showProgress;
117 2
        return $this;
118
    }
119
120
    /**
121
     * Show the type of each output (`out` or `err`)
122
     *
123
     * @param bool $showType
124
     *
125
     * @return $this
126
     */
127 2
    public function setShowType($showType)
128
    {
129 2
        $this->showType = $showType;
130 2
        return $this;
131
    }
132
133
    /**
134
     * @return bool
135
     */
136 1
    public function isShowType()
137
    {
138 1
        return $this->showType;
139
    }
140
141
    /**
142
     * Set weather this should colour each process with a different colour
143
     *
144
     * @param bool $colourProcesses
145
     *
146
     * @return $this
147
     */
148 2
    public function setColourProcesses($colourProcesses)
149
    {
150 2
        $this->colourProcesses = $colourProcesses;
151 2
        return $this;
152
    }
153
154
    /**
155
     * Does this colour each process with a different colour
156
     *
157
     * @return bool
158
     */
159 1
    public function isColourProcesses()
160
    {
161 1
        return $this->colourProcesses;
162
    }
163
164
    /**
165
     * @param RunInterface $run
166
     */
167 10
    public function add(RunInterface $run)
168
    {
169 10
        $index = $this->counter++;
170 10
        $run->addListener(
171 10
            RunEvent::UPDATED,
172
            function (RunEvent $event) use ($index) {
173 8
                $run = $event->getRun();
174 8
                $message = '';
175 8
                if ($run instanceof OutputterInterface) {
176 8
                    $message = ($this->showType && $run->getLastMessageType() !== '')
177 8
                        ? sprintf('(%s) %s', $run->getLastMessageType(), $run->getLastMessage())
178 8
                        : $run->getLastMessage();
179 8
                }
180 8
                $this->output->writeln($this->format($index, $run, $message));
181 8
            }
182 10
        );
183 10
        $run->addListener(
184 10
            RunEvent::STARTED,
185
            function (RunEvent $event) use ($index) {
186 10
                $run = $event->getRun();
187 10
                $this->output->writeln(
188 10
                    $this->format($index, $run, "<fg=blue>→ Started</>")
189 10
                );
190 10
            }
191 10
        );
192 10
        $run->addListener(
193 10
            RunEvent::SUCCESSFUL,
194
            function (RunEvent $event) use ($index) {
195 7
                $run = $event->getRun();
196 7
                $this->output->writeln(
197 7
                    $this->format($index, $run, "<info>✓ Succeeded</info>")
198 7
                );
199 7
            }
200 10
        );
201 10
        $run->addListener(
202 10
            RunEvent::FAILED,
203 3
            function (RunEvent $event) use ($index) {
204 3
                $run = $event->getRun();
205 3
                $exceptions = $run->getExceptions();
206 3
                $exception = null;
207 3
                if (count($exceptions) > 0) {
208 2
                    $exception = reset($exceptions);
209 2
                    $error = sprintf(
210 2
                        "<error>x Failed</error> (%d) %s",
211 2
                        $exception->getCode(),
212 2
                        $exception->getMessage()
213 2
                    );
214 2
                } else {
215 1
                    $error = "<error>x Failed</error>";
216
                }
217 3
                $this->output->writeln($this->format($index, $run, $error));
218 3
                if ($exception) {
219 2
                    $this->output->writeln($exception->getMessage());
220 2
                }
221 3
            }
222 10
        );
223
224 10
        if ($run instanceof ProcessRun) {
225 8
            $run->setUpdateOnPoll(false);
226 8
        }
227 10
        $this->updateRowKeyLengths($run->getTags());
228 10
    }
229
230
    /**
231
     * @param int          $index
232
     * @param RunInterface $run
233
     * @param string       $message
234
     *
235
     * @return string
236
     */
237 10
    private function format($index, RunInterface $run, $message = '')
238
    {
239 10
        $output = $this->formatTags(
240 10
            $run->getTags(),
241 10
            ($this->colourProcesses ? $this->colours[$index % count($this->colours)] : null)
242 10
        );
243 10
        if ($this->showDuration) {
244 9
            $output .= sprintf(' (<comment>%6.2fs</comment>)', $run->getDuration());
245 9
        }
246 10
        $progress = $run->getProgress();
247 10
        if ($this->showProgress && !is_null($progress)) {
248 1
            if (is_null($this->bar)) {
249 1
                $this->bar = new TinyProgressBar(2, TinyProgressBar::FORMAT_SHORT, 1);
250 1
            }
251 1
            $output .= $this->bar->setPosition($progress[2])
252 1
                                 ->setPosition($progress[0])
253 1
                                 ->setMax($progress[1])
254 1
                                 ->render();
255 1
        }
256
257 10
        return sprintf("%s %s", $output, $this->terminal->filter($message));
258
    }
259
260
    /**
261
     * @param float $checkInterval
262
     *
263
     * @return bool true if all processes were successful
264
     */
265 10
    public function run($checkInterval = PriorityPool::CHECK_INTERVAL)
266
    {
267 10
        return $this->pool->run($checkInterval);
268
    }
269
}
270