1 <?php
2
3 namespace Docoflow;
4
5 use Exception;
6 use CDbCriteria;
7 use Carbon\Carbon;
8 use Docoflow\Entity\Step;
9 use Docoflow\Entity\Group;
10 use Docolight\Support\Fluent;
11 use Docoflow\Models\Workflow;
12 use Docoflow\Entity\Verificator;
13 use Docoflow\Models\WorkflowStep;
14 use Docoflow\Models\WorkflowGroups;
15 use Docoflow\Models\WorkflowVerificator;
16 use Docoflow\Contracts\ValidationStatus;
17
18 19 20 21 22
23 class Flo extends Fluent implements ValidationStatus
24 {
25 26 27 28 29
30 protected $validUntil;
31 32 33 34 35
36 protected $workflow;
37
38 39 40 41 42
43 protected $steps;
44
45 46 47 48 49
50 protected $jsonAble;
51
52 53 54 55 56
57 protected $groups;
58
59 60 61 62 63
64 protected $verificators;
65
66 67 68 69 70
71 protected $groupedVerificators;
72
73 74 75 76 77
78 protected $bootstrapped;
79
80 81 82 83 84
85 public function __construct($id)
86 {
87 $this->workflow = Workflow::model()->findByPk($id);
88 $this->bootstrapped = fluent();
89
90 if (! $this->workflow) {
91 return;
92 }
93
94 $this->bootstrapped->set('workflow', true);
95
96 $this->fill($this->workflow->attributes);
97 }
98
99 protected function makeInternalSteps()
100 {
101 $this->bootstrapped->set('steps', true);
102
103 if ($this->workflow) {
104 $this->steps = new Step($this->workflow->getRelated('steps'));
105 }
106 }
107
108 protected function makeInternalGroups()
109 {
110 $this->bootstrapped->set('groups', true);
111
112 if (! $this->steps) {
113 if (! $this->bootstrapped->steps) {
114 $this->makeInternalSteps();
115 } else {
116 return;
117 }
118 }
119
120 $this->groups = new Group();
121
122 foreach ($this->steps as $step) {
123 foreach ($step->getRelated('groups') as $group) {
124 $this->groups->push($group);
125 }
126 }
127 }
128
129 protected function makeInternalVerificators()
130 {
131 $this->bootstrapped->set('verificators', true);
132
133 if (! $this->groups) {
134 if (! $this->bootstrapped->groups) {
135 $this->makeInternalGroups();
136 } else {
137 return;
138 }
139 }
140
141 $this->verificators = new Verificator();
142
143 foreach ($this->groups as $group) {
144 foreach ($group->getRelated('verificators') as $verificator) {
145 $this->verificators->push($verificator);
146 }
147 }
148 }
149
150 151 152 153 154 155 156
157 public static function fetch($id)
158 {
159 return new static($id);
160 }
161
162 163 164 165 166
167 public function steps()
168 {
169 if (! $this->bootstrapped->steps) {
170 $this->makeInternalSteps();
171 }
172
173 return $this->steps ?: [];
174 }
175
176 177 178 179 180 181 182 183 184 185 186
187 public function step($step)
188 {
189 if (! $this->bootstrapped->steps) {
190 $this->makeInternalSteps();
191 }
192
193 return ($this->steps) ? (($this->steps->offsetExists((int) $step - 1)) ? $this->steps->offsetGet((int) $step - 1)
194 : null)
195 : null;
196 }
197
198 199 200 201 202
203 public function groups()
204 {
205 if (! $this->bootstrapped->groups) {
206 $this->makeInternalGroups();
207 }
208
209 return $this->groups ?: [];
210 }
211
212 213 214 215 216 217 218 219 220 221 222
223 public function groupsInStep($step)
224 {
225 if (! $this->bootstrapped->groups) {
226 $this->makeInternalGroups();
227 }
228
229 return ($this->step($step)) ? new Group($this->step($step)->groups) : [];
230 }
231
232 233 234 235 236
237 public function verificators()
238 {
239 if (! $this->bootstrapped->verificators) {
240 $this->makeInternalVerificators();
241 }
242
243 return $this->verificators ?: [];
244 }
245
246 247 248 249 250 251 252 253 254 255 256
257 public function verificatorsInStep($step)
258 {
259 if (isset($this->groupedVerificators[$step])) {
260 return $this->groupedVerificators[$step];
261 }
262
263 if (! $this->bootstrapped->steps) {
264 $this->makeInternalSteps();
265 }
266 $steps = $this->step($step);
267 if (empty($steps)) {
268 return [];
269 }
270
271 return $this->groupedVerificators[$step] = Group::make($steps->getRelated('groups'))->gatherVerificators();
272 }
273
274 275 276 277 278 279 280
281 public function toArray($returnModel = false)
282 {
283 if ($this->jsonAble) {
284 return $this->jsonAble;
285 }
286
287 if (! $this->workflow) {
288 $this->jsonAble = fluent();
289
290 return;
291 }
292
293 $this->jsonAble = fluent($this->workflow->attributes);
294
295 $this->jsonAble->steps = collect();
296
297 foreach ($this->steps as $step) {
298 $stepFluent = fluent(array_except($step->attributes, ['workflow_id']));
299
300 $stepFluent->groups = collect();
301
302 foreach ($step->getRelated('groups') as $group) {
303 $groupFluent = fluent(array_except($group->attributes, ['workflow_step_id']));
304
305 $groupFluent->verificators = collect();
306
307 foreach ($group->getRelated('verificators') as $verificator) {
308 $fluentVerificator = fluent(array_except($verificator->attributes, ['workflow_groups_id']));
309
310 if ($verificator->hasMutator('user')) {
311 container()->instance('workflow.verificator', $verificator);
312 unset($fluentVerificator['user_id']);
313 $fluentVerificator->user = $verificator->callMutator('user', [container('workflow.verificator')]);
314 }
315
316 $groupFluent->verificators->push($fluentVerificator);
317 }
318
319 $stepFluent->groups->push($groupFluent);
320 }
321
322 $this->jsonAble->steps->push($stepFluent);
323 }
324
325 return ($returnModel) ? $this->jsonAble : $this->jsonAble->toArray();
326 }
327
328 329 330 331 332
333 public function validUntil()
334 {
335 if ($this->workflow) {
336 return $this->workflow->validUntil();
337 }
338 }
339
340 341 342 343 344
345 public function valid()
346 {
347 if ($this->workflow) {
348 return $this->workflow->valid();
349 }
350
351 return false;
352 }
353
354 355 356 357 358
359 public function reset()
360 {
361 if ($this->workflow) {
362 $this->workflow->reset();
363
364 if (($verificators = $this->verificators()) instanceof Verificator) {
365 $verificators->reset();
366 }
367
368 if (($steps = $this->steps()) instanceof Step) {
369 $steps->reset();
370 }
371 }
372
373 return $this;
374 }
375
376 377 378 379 380
381 public function resetIf()
382 {
383 if ($this->workflow) {
384 $this->workflow->resetIf();
385
386 if (($verificators = $this->verificators()) instanceof Verificator) {
387 $verificators->resetIf();
388 }
389
390 if (($steps = $this->steps()) instanceof Step) {
391 $steps->resetIf();
392 }
393 }
394
395 return $this;
396 }
397
398 399 400 401 402
403 public function reject()
404 {
405 if ($this->workflow) {
406 $this->workflow->reject();
407
408 if (($verificators = $this->verificators()) instanceof Verificator) {
409 $verificators->reject();
410 }
411
412 if (($steps = $this->steps()) instanceof Step) {
413 $steps->reject();
414 }
415 }
416
417 return $this;
418 }
419
420 421 422 423 424
425 public function rejectIf()
426 {
427 if ($this->workflow) {
428 $this->workflow->rejectIf();
429
430 if (($verificators = $this->verificators()) instanceof Verificator) {
431 $verificators->rejectIf();
432 }
433
434 if (($steps = $this->steps()) instanceof Step) {
435 $steps->rejectIf();
436 }
437 }
438
439 return $this;
440 }
441
442 443 444 445 446
447 public function approve()
448 {
449 if ($this->workflow) {
450 $this->workflow->approve();
451
452 if (($verificators = $this->verificators()) instanceof Verificator) {
453 $verificators->approve();
454 }
455
456 if (($steps = $this->steps()) instanceof Step) {
457 $steps->approve();
458 }
459 }
460
461 return $this;
462 }
463
464 465 466 467 468
469 public function approveIf()
470 {
471 if ($this->workflow) {
472 $this->workflow->approveIf();
473
474 if (($verificators = $this->verificators()) instanceof Verificator) {
475 $verificators->approveIf();
476 }
477
478 if (($steps = $this->steps()) instanceof Step) {
479 $steps->approveIf();
480 }
481 }
482
483 return $this;
484 }
485
486 487 488 489 490
491 public function save()
492 {
493 if ($this->workflow) {
494 $transaction = transaction(container('docoflow.connection'));
495
496 try {
497 $this->workflow->save();
498
499 if (($steps = $this->steps()) instanceof Step) {
500 $steps->save();
501 }
502
503 if (($groups = $this->groups()) instanceof Group) {
504 $groups->save();
505 }
506
507 if (($verificators = $this->verificators()) instanceof Verificator) {
508 $verificators->save();
509 }
510
511 $transaction->commit();
512 } catch (Exception $e) {
513 $transaction->rollback();
514
515 throw $e;
516 }
517 }
518 }
519 }
520