1 <?php
2
3 namespace Docoflow;
4
5 use Yii;
6 use Datetime;
7 use Exception;
8 use Docoflow\Entity\Step;
9 use Docoflow\Entity\Group;
10 use Docoflow\Entity\Verificator;
11 use Docoflow\Models\Workflow;
12 use Docoflow\Models\WorkflowStep;
13 use Docoflow\Models\WorkflowGroups;
14 use Docoflow\Models\WorkflowVerificator;
15
16 17 18 19 20
21 class Docoflow
22 {
23 24 25 26 27
28 protected $prepared;
29
30 31 32 33 34
35 protected $workflow;
36
37 38 39 40 41
42 protected $step;
43
44 45 46 47 48
49 protected $group;
50
51 52 53 54 55
56 protected $verificator;
57
58 59 60 61 62
63 protected $expiredDate;
64
65 66 67 68 69 70 71 72
73 public function __construct($name, Step $step = null, Group $group = null, Verificator $verificator = null)
74 {
75 $this->name = $name;
76 $this->step = $step;
77 $this->group = $group;
78 $this->verificator = $verificator;
79 }
80
81 82 83 84 85 86 87 88
89 public static function make($name, Step $step = null, Group $group = null, Verificator $verificator = null)
90 {
91 return new static($name, $step, $group, $verificator);
92 }
93
94 95 96 97 98 99 100
101 public function withStep(Step $step)
102 {
103 $this->step = $step;
104
105 return $this;
106 }
107
108 109 110 111 112 113 114
115 public function withGroup(Group $group)
116 {
117 $this->group = $group;
118
119 return $this;
120 }
121
122 123 124 125 126 127 128
129 public function withVerificator(Verificator $verificator)
130 {
131 $this->verificator = $verificator;
132
133 return $this;
134 }
135
136 137 138 139 140 141 142
143 public function validUntil(Datetime $expiredDate)
144 {
145 $this->expiredDate = $expiredDate;
146
147 return $this;
148 }
149
150 151 152 153 154
155 public function save()
156 {
157 if (!$this->prepared) {
158 $this->prepare();
159 }
160
161 $transaction = transaction(container('docoflow.connection'));
162
163 try {
164 $newWorkFlowId = $this->createNewWorkFlow();
165
166 $this->createWorkflowDefinition($newWorkFlowId);
167
168 $transaction->commit();
169
170 return $this->workflow;
171 } catch (Exception $e) {
172 $transaction->rollback();
173
174 throw $e;
175 }
176 }
177
178 179 180 181 182
183 public function prepare()
184 {
185 if (!$this->step) {
186 throw new Exception('Cannot create workflow, steps are empty.');
187 }
188
189 $steps = $this->step->rebuild();
190
191 if (!$this->group) {
192 throw new Exception('Cannot create workflow, groups are empty.');
193 }
194
195 $this->group->rebuild($steps);
196
197 if (!$this->verificator) {
198 throw new Exception('Cannot create workflow, verificators are empty.');
199 }
200
201 $this->verificator->rebuild($steps);
202
203 $this->prepared = $steps;
204
205 return $this;
206 }
207
208 209 210 211 212
213 public function getPreparedData()
214 {
215 if (!$this->prepared) {
216 $this->prepare();
217 }
218
219 return $this->prepared;
220 }
221
222 223 224
225 protected function createNewWorkFlow()
226 {
227 $workflowModel = new Workflow();
228
229 $workflowModel->name = $this->name;
230
231 if ($this->expiredDate instanceof Datetime) {
232 $workflowModel->expired_at = $this->expiredDate->format('Y-m-d H:i:s');
233 }
234
235 if (!$workflowModel->save()) {
236 throw new Exception("Cannot save Workflow: ".json_encode($workflowModel->getErrors()));
237 }
238
239 $this->workflow = $workflowModel;
240
241 return $workflowModel->{$workflowModel->tableSchema->primaryKey};
242 }
243
244 245 246 247 248 249 250
251 protected function createWorkflowDefinition($newWorkFlowId)
252 {
253 foreach ($this->prepared as $step) {
254 $stepModel = new WorkflowStep();
255
256 $stepModel->workflow_id = $newWorkFlowId;
257 $stepModel->name = $step->name;
258
259 if ($step->expired_at instanceof Datetime) {
260 $stepModel->expired_at = $step->expired_at->format('Y-m-d H:i:s');
261 }
262
263 if ($stepModel->save()) {
264 $this->createWorkflowGroup($step->groups, $stepModel->{$stepModel->tableSchema->primaryKey});
265 } else {
266 throw new Exception("Cannot save Step: ".json_encode($stepModel->getErrors()));
267 }
268 }
269
270 return $newWorkFlowId;
271 }
272
273 274 275 276 277 278
279 protected function createWorkflowGroup(Group $groups, $newStepId)
280 {
281 foreach ($groups as $group) {
282 $groupModel = new WorkflowGroups();
283
284 $groupModel->workflow_step_id = $newStepId;
285 $groupModel->name = $group->name;
286
287 if ($groupModel->save()) {
288 $this->createWorkflowVerificator($group->verificator, $groupModel->{$groupModel->tableSchema->primaryKey});
289 } else {
290 throw new Exception("Cannot save Group: ".json_encode($groupModel->getErrors()));
291 }
292 }
293 }
294
295 296 297 298 299 300
301 protected function createWorkflowVerificator(Verificator $verificators, $newGroupId)
302 {
303 foreach ($verificators as $verificator) {
304 $verificatorModel = new WorkflowVerificator();
305
306 $verificatorModel->workflow_groups_id = $newGroupId;
307 $verificatorModel->user_id = $verificator->user_id;
308
309 if (!$verificatorModel->save()) {
310 throw new Exception("Cannot save Verificator: ".json_encode($verificatorModel->getErrors()));
311 }
312 }
313 }
314 }
315