Passed
Pull Request — master (#17)
by Harry
02:26
created

CallbackRun   A

Complexity

Total Complexity 24

Size/Duplication

Total Lines 186
Duplicated Lines 0 %

Test Coverage

Coverage 100%

Importance

Changes 0
Metric Value
wmc 24
eloc 54
dl 0
loc 186
ccs 59
cts 59
cp 1
rs 10
c 0
b 0
f 0

14 Methods

Rating   Name   Duplication   Size   Complexity  
A handleOutput() 0 12 6
A getExceptions() 0 6 2
A getDuration() 0 6 3
A poll() 0 4 1
A __construct() 0 4 1
A isSuccessful() 0 3 1
A getTags() 0 3 1
A getEventNames() 0 7 1
A hasStarted() 0 3 1
A getLastMessageType() 0 3 1
A getLastMessage() 0 3 1
A getProgress() 0 3 1
A isRunning() 0 3 1
A start() 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;
15
16
use Exception;
17
use Graze\ParallelProcess\Event\EventDispatcherTrait;
18
use Graze\ParallelProcess\Event\RunEvent;
19
use Throwable;
20
21
class CallbackRun implements RunInterface, OutputterInterface
22
{
23
    use EventDispatcherTrait;
24
25
    /** @var callable */
26
    private $callback;
27
    /** @var float */
28
    private $started = 0;
29
    /** @var float */
30
    private $finished = 0;
31
    /** @var bool */
32
    private $successful = false;
33
    /** @var string[] */
34
    private $tags;
35
    /** @var Exception|null */
36
    private $exception = null;
37
    /** @var string */
38
    private $last;
39
40
    /**
41
     * Run constructor.
42
     *
43
     * @param callable $callback A callback to run, if this returns a string, it can be accessed from the
44
     *                           `->getLastMessage()` calls
45
     * @param string[] $tags     List of key value tags associated with this run
46
     */
47 8
    public function __construct(callable $callback, array $tags = [])
48
    {
49 8
        $this->callback = $callback;
50 8
        $this->tags = $tags;
51 8
    }
52
53
    /**
54
     * @return string[]
55
     */
56 6
    protected function getEventNames()
57
    {
58
        return [
59 6
            RunEvent::STARTED,
60 6
            RunEvent::COMPLETED,
61 6
            RunEvent::FAILED,
62 6
            RunEvent::UPDATED,
63
        ];
64
    }
65
66
    /**
67
     * Start the process
68
     *
69
     * @return $this
70
     */
71 6
    public function start()
72
    {
73 6
        if ($this->started == 0) {
74 6
            $this->started = microtime(true);
75 6
            $this->dispatch(RunEvent::STARTED, new RunEvent($this));
76
            try {
77 6
                $output = call_user_func($this->callback);
78 5
                $this->handleOutput($output);
79 5
                $this->finished = microtime(true);
80 5
                $this->successful = true;
81 5
                $this->dispatch(RunEvent::COMPLETED, new RunEvent($this));
82 1
            } catch (Exception $e) {
83 1
                $this->finished = microtime(true);
84 1
                $this->successful = false;
85 1
                $this->exception = $e;
86 1
                $this->dispatch(RunEvent::FAILED, new RunEvent($this));
87
            }
88
        }
89
90 6
        return $this;
91
    }
92
93
    /**
94
     * @param mixed $output The output from the callback, if you want to send this back, return a string|string[]
95
     */
96 5
    private function handleOutput($output)
97
    {
98 5
        if (is_string($output)) {
99 1
            $output = explode("\n", $output);
100
        }
101 5
        if (is_array($output)) {
102 2
            foreach ($output as $line) {
103 2
                if (is_string($line)) {
104 2
                    $line = rtrim($line);
105 2
                    if (mb_strlen($line) > 0) {
106 2
                        $this->last = $line;
107 2
                        $this->dispatch(RunEvent::UPDATED, new RunEvent($this));
108
                    }
109
                }
110
            }
111
        }
112 5
    }
113
114
    /**
115
     * Poll to see if the callback is still running (hint: it is not)
116
     *
117
     * @return bool
118
     */
119 6
    public function poll()
120
    {
121
        // non async process, so it will have finished when calling start
122 6
        return false;
123
    }
124
125
    /**
126
     * Return if the underlying process is running
127
     *
128
     * @return bool
129
     */
130 2
    public function isRunning()
131
    {
132 2
        return false;
133
    }
134
135
    /**
136
     * @return bool
137
     */
138 2
    public function isSuccessful()
139
    {
140 2
        return $this->successful;
141
    }
142
143
    /**
144
     * @return bool
145
     */
146 2
    public function hasStarted()
147
    {
148 2
        return $this->started > 0;
149
    }
150
151
    /**
152
     * @return array
153
     */
154 1
    public function getTags()
155
    {
156 1
        return $this->tags;
157
    }
158
159
    /**
160
     * @return float number of seconds this run has been running for (0 for not started)
161
     */
162 3
    public function getDuration()
163
    {
164 3
        if ($this->finished > 0) {
165 1
            return $this->finished - $this->started;
166
        }
167 2
        return $this->started > 0 ? microtime(true) - $this->started : 0;
168
    }
169
170
    /**
171
     * @return float[]|null the process between 0 and 1 if the run supports it, otherwise null
172
     */
173 1
    public function getProgress()
174
    {
175 1
        return null;
176
    }
177
178
    /**
179
     * If the run was unsuccessful, get the error if applicable
180
     *
181
     * @return Exception[]|Throwable[]
182
     */
183 2
    public function getExceptions()
184
    {
185 2
        if ($this->exception !== null) {
186 1
            return [$this->exception];
187
        }
188 1
        return [];
189
    }
190
191
    /**
192
     * Get the last message that this thing produced
193
     *
194
     * @return string
195
     */
196 3
    public function getLastMessage()
197
    {
198 3
        return $this->last;
199
    }
200
201
    /**
202
     * @return string
203
     */
204 1
    public function getLastMessageType()
205
    {
206 1
        return '';
207
    }
208
}
209