LFT
  • Namespace
  • Class
  • Tree

Namespaces

  • Docoflow
    • Contracts
    • Entity
    • Facades
    • Models
    • Traits
  • Docolight
    • Agno
      • Traits
    • Container
    • Http
      • Contracts
    • Rest
      • Handler
      • Http
    • Support
      • Debug
      • Traits
  • Docotory
    • Traits
  • None

Classes

  • Docoflow\Docoflow
  • Docoflow\Entity\Group
  • Docoflow\Entity\Step
  • Docoflow\Entity\Verificator
  • Docoflow\Facades\Action
  • Docoflow\Facades\Activity
  • Docoflow\Facades\Flo
  • Docoflow\Facades\StateActivity
  • Docoflow\Flo
  • Docoflow\Models\Workflow
  • Docoflow\Models\WorkflowAction
  • Docoflow\Models\WorkflowActivity
  • Docoflow\Models\WorkflowGroups
  • Docoflow\Models\WorkflowNotification
  • Docoflow\Models\WorkflowState
  • Docoflow\Models\WorkflowStateActivity
  • Docoflow\Models\WorkflowStep
  • Docoflow\Models\WorkflowVerificator
  • Docolight
  • Docolight\Agno\AgnoModule
  • Docolight\Container\Container
  • Docolight\Http\Headers
  • Docolight\Http\JsonResponse
  • Docolight\Http\MimeResponse
  • Docolight\Http\Response
  • Docolight\Http\ResponseFactory
  • Docolight\Rest\Handler\RestfulErrorHandler
  • Docolight\Rest\Http\RestFulController
  • Docolight\Support\ActiveRecordWrapper
  • Docolight\Support\Arr
  • Docolight\Support\Carbonate
  • Docolight\Support\ClassLoader
  • Docolight\Support\Collection
  • Docolight\Support\CollectionDataProvider
  • Docolight\Support\Debug\Dumper
  • Docolight\Support\Debug\HtmlDumper
  • Docolight\Support\Facade
  • Docolight\Support\Factory
  • Docolight\Support\Fluent
  • Docolight\Support\Html
  • Docolight\Support\IterablePager
  • Docolight\Support\Repository
  • Docolight\Support\Set
  • Docolight\Support\Str
  • Docotory\Factory

Interfaces

  • Docoflow\Contracts\DocoflowContract
  • Docoflow\Contracts\ValidationStatus
  • Docolight\Http\Contracts\Arrayable

Traits

  • Docoflow\Traits\BulkValidator
  • Docoflow\Traits\Entity
  • Docoflow\Traits\HasMutator
  • Docoflow\Traits\Validable
  • Docolight\Agno\Traits\HasAssetsUrl
  • Docolight\Agno\Traits\HasAutoload
  • Docolight\Support\Traits\Macroable
  • Docotory\Traits\HasFactories

Exceptions

  • Docolight\Container\BindingResolutionException
  • Docotory\ResolvingTypeException

Functions

  • array_add
  • array_build
  • array_collapse
  • array_divide
  • array_dot
  • array_except
  • array_first
  • array_flatten
  • array_forget
  • array_get
  • array_has
  • array_last
  • array_only
  • array_pluck
  • array_pull
  • array_replace_value
  • array_set
  • array_sort
  • array_sort_recursive
  • array_where
  • cache
  • camel_case
  • class_basename
  • class_uses_recursive
  • collect
  • container
  • data_get
  • dd
  • def
  • dump
  • e
  • ends_with
  • fluent
  • get
  • head
  • input
  • last
  • object_get
  • preg_replace_sub
  • request
  • response
  • session
  • snake_case
  • starts_with
  • str_contains
  • str_finish
  • str_is
  • str_limit
  • str_random
  • str_replace_array
  • str_slug
  • studly_case
  • title_case
  • trait_uses_recursive
  • transaction
  • trimtolower
  • value
  • with
  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  * Workflow fetcher. It helps you to manage your workflow, such as get the verificators, groups, step, etc.
 20  *
 21  * @author Krisan Alfa Timur <krisanalfa@docotel.co.id>
 22  */
 23 class Flo extends Fluent implements ValidationStatus
 24 {
 25     /**
 26      * Workflow date validity.
 27      *
 28      * @var \Carbon\Carbon
 29      */
 30     protected $validUntil;
 31     /**
 32      * Workflow Model
 33      *
 34      * @var \Docoflow\Models\Workflow
 35      */
 36     protected $workflow;
 37 
 38     /**
 39      * Step entities
 40      *
 41      * @var \Docoflow\Entity\Step
 42      */
 43     protected $steps;
 44 
 45     /**
 46      * Array that frendly with json representation.
 47      *
 48      * @var array
 49      */
 50     protected $jsonAble;
 51 
 52     /**
 53      * Group entities
 54      *
 55      * @var \Docoflow\Entity\Group
 56      */
 57     protected $groups;
 58 
 59     /**
 60      * Verificator entities
 61      *
 62      * @var \Docoflow\Entity\Verificator
 63      */
 64     protected $verificators;
 65 
 66     /**
 67      * A 'cache' to store grouped verificators based on their step
 68      *
 69      * @var array
 70      */
 71     protected $groupedVerificators;
 72 
 73     /**
 74      * Boostrapped entities
 75      *
 76      * @var array
 77      */
 78     protected $bootstrapped;
 79 
 80     /**
 81      * Flo constructor
 82      *
 83      * @param int $id Workflow id in database.
 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      * Statically create new Flo implementation
152      *
153      * @param int $id Workflow id in database
154      *
155      * @return \Docoflow\Flo
156      */
157     public static function fetch($id)
158     {
159         return new static($id);
160     }
161 
162     /**
163      * Get all steps in current workflow. Return an empty array if there's no step in it.
164      *
165      * @return array|\Docoflow\Entity\Step
166      */
167     public function steps()
168     {
169         if (! $this->bootstrapped->steps) {
170             $this->makeInternalSteps();
171         }
172 
173         return $this->steps ?: [];
174     }
175 
176     /**
177      * Get a single step. Let's say you have 4 steps in this workflow. You can call the 4th step entity by call:
178      *
179      * ```php
180      * Flo::fetch($id)->step(4);
181      * ```
182      *
183      * @param int $step Step you want to return
184      *
185      * @return null|\Docoflow\Models\WorkflowStep
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      * Get current group entities. Return an empty array if there's no group in it.
200      *
201      * @return array|\Docoflow\Entity\Group
202      */
203     public function groups()
204     {
205         if (! $this->bootstrapped->groups) {
206             $this->makeInternalGroups();
207         }
208 
209         return $this->groups ?: [];
210     }
211 
212     /**
213      * Get group based on your step. If you have 4 steps in current workflow, and you want to get a group only in the second step, you may call:
214      *
215      * ```php
216      * Flo::fetch(1)->groupsInStep(2);
217      * ```
218      *
219      * @param int $step Step you want to return.
220      *
221      * @return array|\Docoflow\Entity\Group
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      * Get all verificators in your workflow. Will return empty array if there's no verificator in your current workflow.
234      *
235      * @return array|\Docoflow\Entity\Verificator
236      */
237     public function verificators()
238     {
239         if (! $this->bootstrapped->verificators) {
240             $this->makeInternalVerificators();
241         }
242 
243         return $this->verificators ?: [];
244     }
245 
246     /**
247      * Get verificators in certain step. If you have 4 steps in your workflow, and you want to get a list of verificators only in 3rd step:
248      *
249      * ```php
250      * Flo::fetch(1)->verificatorsInStep(3);
251      * ```
252      *
253      * @param int $step Step you want to return
254      *
255      * @return array|\Docoflow\Entity\Verificator
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      * Convert this implementation to a standard PHP array.
276      *
277      * @param boolean $returnModel Set to true if you want to return an object, instead of array.
278      *
279      * @return array|\Docolight\Support\Collection
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      * Get workflow date validity.
330      *
331      * @return null|\Carbon\Carbon
332      */
333     public function validUntil()
334     {
335         if ($this->workflow) {
336             return $this->workflow->validUntil();
337         }
338     }
339 
340     /**
341      * Determine if workflow stil valid to be validated.
342      *
343      * @return bool
344      */
345     public function valid()
346     {
347         if ($this->workflow) {
348             return $this->workflow->valid();
349         }
350 
351         return false;
352     }
353 
354     /**
355      * Reset workflow, also all of it's steps and verificators status.
356      *
357      * @return \Docoflow\Flo
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      * Reset workflow, also all of it's steps and verificators status if only it's not expired.
378      *
379      * @return \Docoflow\Flo
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      * Reject workflow, also all of it's steps and verificators status.
400      *
401      * @return \Docoflow\Flo
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      * Reject workflow, also all of it's steps and verificators status if only it's not expired.
422      *
423      * @return \Docoflow\Flo
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      * Approve workflow, also all of it's steps and verificators status.
444      *
445      * @return \Docoflow\Flo
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      * Approve workflow, also all of it's steps and verificators status if only it's not expired.
466      *
467      * @return \Docoflow\Flo
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      * Save all data in workflow, include all of it's steps, groups, and verificators.
488      *
489      * @return void
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 
LFT API documentation generated by ApiGen