Passed
Push — master ( b05304...84ccec )
by Harry
02:04
created

CallbackRun::isRunning()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

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