1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
namespace Graze\ParallelProcess; |
4
|
|
|
|
5
|
|
|
use Symfony\Component\Process\Process; |
6
|
|
|
|
7
|
|
|
class Run implements RunInterface |
8
|
|
|
{ |
9
|
|
|
const ON_SUCCESS = 1; |
10
|
|
|
const ON_FAILURE = 2; |
11
|
|
|
const ON_PROGRESS = 3; |
12
|
|
|
|
13
|
|
|
/** @var Process */ |
14
|
|
|
private $process; |
15
|
|
|
/** @var callable|null */ |
16
|
|
|
private $onSuccess; |
17
|
|
|
/** @var callable|null */ |
18
|
|
|
private $onFailure; |
19
|
|
|
/** @var callable|null */ |
20
|
|
|
private $onProgress; |
21
|
|
|
/** @var callable|null */ |
22
|
|
|
private $onStart; |
23
|
|
|
/** @var float */ |
24
|
|
|
private $started; |
25
|
|
|
/** @var bool */ |
26
|
|
|
private $successful = false; |
27
|
|
|
/** @var bool */ |
28
|
|
|
private $completed = false; |
29
|
|
|
/** @var string */ |
30
|
|
|
private $last = ''; |
31
|
|
|
/** @var string */ |
32
|
|
|
private $lastType = 'std'; |
33
|
|
|
/** @var bool */ |
34
|
|
|
private $updateOnPoll = true; |
35
|
|
|
/** @var bool */ |
36
|
|
|
private $updateOnProcessOutput = true; |
37
|
|
|
|
38
|
|
|
/** |
39
|
|
|
* Run constructor. |
40
|
|
|
* |
41
|
|
|
* @param Process $process |
42
|
|
|
* @param callable|null $onSuccess When the process finishes and is successful |
43
|
|
|
* function (Process $process, float $duration, string $last, string $lastType) : |
44
|
|
|
* void |
45
|
|
|
* @param callable|null $onFailure When the process finishes and failed |
46
|
|
|
* function (Process $process, float $duration, string $last, string $lastType) : |
47
|
|
|
* void |
48
|
|
|
* @param callable|null $onProgress Called every check period or a message is returned from the process |
49
|
|
|
* function (Process $process, float $duration, string $last, string $lastType) : |
50
|
|
|
* void |
51
|
|
|
* @param callable|null $onStart When the process starts |
52
|
|
|
* function (Process $process, float $duration, string $last, string $lastType) : |
53
|
|
|
* void |
54
|
|
|
*/ |
55
|
43 |
View Code Duplication |
public function __construct( |
|
|
|
|
56
|
|
|
Process $process, |
57
|
|
|
callable $onSuccess = null, |
58
|
|
|
callable $onFailure = null, |
59
|
|
|
callable $onProgress = null, |
60
|
|
|
callable $onStart = null |
61
|
|
|
) { |
62
|
43 |
|
$this->process = $process; |
63
|
43 |
|
$this->onSuccess = $onSuccess; |
64
|
43 |
|
$this->onFailure = $onFailure; |
65
|
43 |
|
$this->onProgress = $onProgress; |
66
|
43 |
|
$this->onStart = $onStart; |
67
|
43 |
|
} |
68
|
|
|
|
69
|
|
|
/** |
70
|
|
|
* Start the process |
71
|
|
|
* |
72
|
|
|
* @return $this |
73
|
|
|
*/ |
74
|
36 |
|
public function start() |
75
|
|
|
{ |
76
|
36 |
|
if (!$this->process->isRunning()) { |
77
|
35 |
|
$this->started = microtime(true); |
78
|
35 |
|
$this->update($this->onStart); |
79
|
35 |
|
$this->process->start( |
80
|
18 |
|
function ($type, $data) { |
81
|
18 |
|
$this->lastType = $type; |
82
|
18 |
|
$this->last = rtrim($data); |
83
|
18 |
|
if ($this->updateOnProcessOutput) { |
84
|
7 |
|
$this->update($this->onProgress); |
85
|
7 |
|
} |
86
|
18 |
|
} |
87
|
35 |
|
); |
88
|
35 |
|
$this->completed = false; |
89
|
35 |
|
} |
90
|
|
|
|
91
|
36 |
|
return $this; |
92
|
|
|
} |
93
|
|
|
|
94
|
|
|
/** |
95
|
|
|
* Poll the process to see if it is still running, and trigger events |
96
|
|
|
* |
97
|
|
|
* @return bool true if the process is currently running (started and not terminated) |
98
|
|
|
*/ |
99
|
33 |
|
public function poll() |
100
|
|
|
{ |
101
|
33 |
|
if ($this->completed || !$this->hasStarted()) { |
102
|
1 |
|
return false; |
103
|
|
|
} |
104
|
|
|
|
105
|
32 |
|
if ($this->process->isRunning()) { |
106
|
24 |
|
if ($this->updateOnPoll) { |
107
|
17 |
|
$this->update($this->onProgress); |
108
|
17 |
|
} |
109
|
24 |
|
return true; |
110
|
|
|
} |
111
|
|
|
|
112
|
32 |
|
$this->completed = true; |
113
|
|
|
|
114
|
32 |
|
if ($this->process->isSuccessful()) { |
115
|
23 |
|
$this->successful = true; |
116
|
23 |
|
$this->update($this->onSuccess); |
117
|
23 |
|
} else { |
118
|
10 |
|
$this->update($this->onFailure); |
119
|
|
|
} |
120
|
32 |
|
return false; |
121
|
|
|
} |
122
|
|
|
|
123
|
|
|
/** |
124
|
|
|
* Return if the underlying process is running |
125
|
|
|
* |
126
|
|
|
* @return bool |
127
|
|
|
*/ |
128
|
32 |
|
public function isRunning() |
129
|
|
|
{ |
130
|
32 |
|
return $this->process->isRunning(); |
131
|
|
|
} |
132
|
|
|
|
133
|
|
|
/** |
134
|
|
|
* Call an event callback |
135
|
|
|
* |
136
|
|
|
* @param callable|null $func |
137
|
|
|
*/ |
138
|
35 |
|
protected function update($func) |
139
|
|
|
{ |
140
|
35 |
|
if (!is_null($func)) { |
141
|
29 |
|
call_user_func( |
142
|
29 |
|
$func, |
143
|
29 |
|
$this->process, |
144
|
29 |
|
microtime(true) - $this->started, |
145
|
29 |
|
$this->last, |
146
|
29 |
|
$this->lastType |
147
|
29 |
|
); |
148
|
29 |
|
} |
149
|
35 |
|
} |
150
|
|
|
|
151
|
|
|
/** |
152
|
|
|
* @return bool |
153
|
|
|
*/ |
154
|
28 |
|
public function isSuccessful() |
155
|
|
|
{ |
156
|
28 |
|
return $this->successful; |
157
|
|
|
} |
158
|
|
|
|
159
|
|
|
/** |
160
|
|
|
* @return bool |
161
|
|
|
*/ |
162
|
36 |
|
public function hasStarted() |
163
|
|
|
{ |
164
|
36 |
|
return $this->process->isStarted(); |
165
|
|
|
} |
166
|
|
|
|
167
|
|
|
/** |
168
|
|
|
* @return Process |
169
|
|
|
*/ |
170
|
3 |
|
public function getProcess() |
171
|
|
|
{ |
172
|
3 |
|
return $this->process; |
173
|
|
|
} |
174
|
|
|
|
175
|
|
|
/** |
176
|
|
|
* @param bool $updateOnPoll |
177
|
|
|
* |
178
|
|
|
* @return $this |
179
|
|
|
*/ |
180
|
8 |
|
public function setUpdateOnPoll($updateOnPoll) |
181
|
|
|
{ |
182
|
8 |
|
$this->updateOnPoll = $updateOnPoll; |
183
|
8 |
|
return $this; |
184
|
|
|
} |
185
|
|
|
|
186
|
|
|
/** |
187
|
|
|
* @return bool |
188
|
|
|
*/ |
189
|
2 |
|
public function isUpdateOnPoll() |
190
|
|
|
{ |
191
|
2 |
|
return $this->updateOnPoll; |
192
|
|
|
} |
193
|
|
|
|
194
|
|
|
/** |
195
|
|
|
* @param bool $updateOnProcessOutput |
196
|
|
|
* |
197
|
|
|
* @return $this |
198
|
|
|
*/ |
199
|
14 |
|
public function setUpdateOnProcessOutput($updateOnProcessOutput) |
|
|
|
|
200
|
|
|
{ |
201
|
14 |
|
$this->updateOnProcessOutput = $updateOnProcessOutput; |
202
|
14 |
|
return $this; |
203
|
|
|
} |
204
|
|
|
|
205
|
|
|
/** |
206
|
|
|
* @return bool |
207
|
|
|
*/ |
208
|
2 |
|
public function isUpdateOnProcessOutput() |
209
|
|
|
{ |
210
|
2 |
|
return $this->updateOnProcessOutput; |
211
|
|
|
} |
212
|
|
|
} |
213
|
|
|
|
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.