This project does not seem to handle request data directly as such no vulnerable execution paths were found.
include
, or for example
via PHP's auto-loading mechanism.
These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more
1 | <?php |
||
2 | |||
3 | namespace app\backgroundtasks\models; |
||
4 | |||
5 | use app\backend\models\Notification; |
||
6 | use app\backgroundtasks\traits\SearchModelTrait; |
||
7 | use app\modules\user\models\User; |
||
8 | use yii\data\ActiveDataProvider; |
||
9 | use yii\db\ActiveRecord; |
||
10 | use yii\helpers\Json; |
||
11 | |||
12 | /** |
||
13 | * This is the model class for table "backgroundtasks_task". |
||
14 | * |
||
15 | * @property integer $id |
||
16 | * @property string $action |
||
17 | * @property string $type |
||
18 | * @property integer $initiator |
||
19 | * @property string $name |
||
20 | * @property string $description |
||
21 | * @property string $params |
||
22 | * @property string $data |
||
23 | * @property string $init_event |
||
24 | * @property string $cron_expression |
||
25 | * @property string $status |
||
26 | * @property integer $fail_counter |
||
27 | * @property string $ts |
||
28 | * @property string $options |
||
29 | */ |
||
30 | class Task extends ActiveRecord |
||
31 | { |
||
32 | use SearchModelTrait; |
||
33 | |||
34 | public $username; |
||
35 | |||
36 | const MAX_FAIL_COUNT = 5; |
||
37 | |||
38 | const STATUS_ACTIVE = 'ACTIVE'; |
||
39 | const STATUS_STOPPED = 'STOPPED'; |
||
40 | const STATUS_RUNNING = 'RUNNING'; |
||
41 | const STATUS_PROCESS = 'PROCESS'; |
||
42 | const STATUS_COMPLETED = 'COMPLETED'; |
||
43 | const STATUS_FAILED = 'FAILED'; |
||
44 | |||
45 | const TYPE_EVENT = 'EVENT'; |
||
46 | const TYPE_REPEAT = 'REPEAT'; |
||
47 | |||
48 | private $logname = ''; |
||
49 | private $task_options = []; |
||
50 | |||
51 | /** |
||
52 | * @inheritdoc |
||
53 | */ |
||
54 | public static function tableName() |
||
55 | { |
||
56 | return '{{%backgroundtasks_task}}'; |
||
57 | } |
||
58 | |||
59 | /** |
||
60 | * Return array of statuses |
||
61 | * @param string $type |
||
62 | * @return array |
||
0 ignored issues
–
show
|
|||
63 | */ |
||
64 | public static function getStatuses($type = '') |
||
65 | { |
||
66 | switch ($type) { |
||
67 | View Code Duplication | case Task::TYPE_EVENT: |
|
68 | return [ |
||
69 | self::STATUS_ACTIVE => self::STATUS_ACTIVE, |
||
70 | self::STATUS_COMPLETED => self::STATUS_COMPLETED, |
||
71 | self::STATUS_FAILED => self::STATUS_FAILED, |
||
72 | self::STATUS_RUNNING => self::STATUS_RUNNING, |
||
73 | ]; |
||
74 | View Code Duplication | case Task::TYPE_REPEAT: |
|
75 | return [ |
||
76 | self::STATUS_ACTIVE => self::STATUS_ACTIVE, |
||
77 | self::STATUS_STOPPED => self::STATUS_STOPPED, |
||
78 | self::STATUS_FAILED => self::STATUS_FAILED, |
||
79 | self::STATUS_RUNNING => self::STATUS_RUNNING, |
||
80 | self::STATUS_PROCESS => self::STATUS_PROCESS, |
||
81 | ]; |
||
82 | default: |
||
83 | return [ |
||
84 | self::STATUS_ACTIVE => self::STATUS_ACTIVE, |
||
85 | self::STATUS_STOPPED => self::STATUS_STOPPED, |
||
86 | self::STATUS_RUNNING => self::STATUS_RUNNING, |
||
87 | self::STATUS_PROCESS => self::STATUS_PROCESS, |
||
88 | self::STATUS_COMPLETED => self::STATUS_COMPLETED, |
||
89 | self::STATUS_FAILED => self::STATUS_FAILED, |
||
90 | ]; |
||
91 | } |
||
92 | } |
||
93 | |||
94 | /** |
||
95 | * Return array of types |
||
96 | * @return array |
||
0 ignored issues
–
show
|
|||
97 | */ |
||
98 | public static function getTypes() |
||
99 | { |
||
100 | return [ |
||
101 | self::TYPE_EVENT => self::TYPE_EVENT, |
||
102 | self::TYPE_REPEAT => self::TYPE_REPEAT, |
||
103 | ]; |
||
104 | } |
||
105 | |||
106 | /** |
||
107 | * @inheritdoc |
||
108 | */ |
||
109 | public function rules() |
||
110 | { |
||
111 | return [ |
||
112 | [['action', 'initiator', 'name'], 'required', 'except' => 'search'], |
||
113 | [['cron_expression'], 'required', 'on' => 'repeat'], |
||
114 | [['init_event'], 'required', 'on' => 'event'], |
||
115 | [['type', 'description', 'params', 'data', 'status', 'options'], 'string'], |
||
116 | [['initiator'], 'integer'], |
||
117 | [['ts', 'username', 'fail_counter'], 'safe'], |
||
118 | [['action', 'name', 'init_event', 'cron_expression'], 'string', 'max' => 255], |
||
119 | [['status'], 'default', 'value' => self::STATUS_ACTIVE], |
||
120 | ]; |
||
121 | } |
||
122 | |||
123 | /** |
||
124 | * @inheritdoc |
||
125 | */ |
||
126 | public function attributeLabels() |
||
127 | { |
||
128 | return [ |
||
129 | 'id' => \Yii::t('app', 'ID'), |
||
130 | 'action' => \Yii::t('app', 'Action'), |
||
131 | 'type' => \Yii::t('app', 'Type'), |
||
132 | 'initiator' => \Yii::t('app', 'Initiator'), |
||
133 | 'name' => \Yii::t('app', 'Name'), |
||
134 | 'description' => \Yii::t('app', 'Description'), |
||
135 | 'params' => \Yii::t('app', 'Parameters'), |
||
136 | 'data' => \Yii::t('app', 'Data'), |
||
137 | 'init_event' => \Yii::t('app', 'Event'), |
||
138 | 'cron_expression' => \Yii::t('app', 'Condition'), |
||
139 | 'ts' => \Yii::t('app', 'Date Modify'), |
||
140 | 'status' => \Yii::t('app', 'Status'), |
||
141 | 'fail_counter' => \Yii::t('app', 'Fail Status Count'), |
||
142 | 'username' => \Yii::t('app', 'Initiator'), |
||
143 | 'options' => \Yii::t('app', 'Options'), |
||
144 | ]; |
||
145 | } |
||
146 | |||
147 | /** |
||
148 | * Return attribute hints |
||
149 | * @return array |
||
0 ignored issues
–
show
|
|||
150 | */ |
||
151 | public function attributeHints() |
||
152 | { |
||
153 | return [ |
||
154 | 'action' => \Yii::t('app', '[route to the action module/controller/action]'), |
||
155 | 'params' => \Yii::t('app', '[action parameters separated by spaces]'), |
||
156 | ]; |
||
157 | } |
||
158 | |||
159 | /** |
||
160 | * Users relation |
||
161 | * @return mixed |
||
0 ignored issues
–
show
|
|||
162 | */ |
||
163 | public function getUsers() |
||
164 | { |
||
165 | return $this->hasMany(User::className(), ['id' => 'user_id']) |
||
0 ignored issues
–
show
The method
yii\base\BaseObject::className() has been deprecated with message: since 2.0.14. On PHP >=5.5, use `::class` instead.
This method has been deprecated. The supplier of the class has supplied an explanatory message. The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead. ![]() |
|||
166 | ->viaTable('Notification', ['task_id' => 'id']); |
||
167 | } |
||
168 | |||
169 | /** |
||
170 | * Initiator user relation |
||
171 | * @return \yii\db\ActiveQueryInterface |
||
172 | */ |
||
173 | public function getInitiatorUser() |
||
174 | { |
||
175 | return $this->hasOne(User::className(), ['id' => 'initiator']); |
||
0 ignored issues
–
show
The method
yii\base\BaseObject::className() has been deprecated with message: since 2.0.14. On PHP >=5.5, use `::class` instead.
This method has been deprecated. The supplier of the class has supplied an explanatory message. The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead. ![]() |
|||
176 | } |
||
177 | |||
178 | /** |
||
179 | * Set running status |
||
180 | * @return bool |
||
0 ignored issues
–
show
|
|||
181 | */ |
||
182 | public function setRunning() |
||
183 | { |
||
184 | return $this->setStatus(self::STATUS_RUNNING); |
||
185 | } |
||
186 | |||
187 | /** |
||
188 | * Set process status |
||
189 | * @return bool |
||
0 ignored issues
–
show
|
|||
190 | */ |
||
191 | public function setProcess() |
||
192 | { |
||
193 | return $this->setStatus(self::STATUS_PROCESS); |
||
194 | } |
||
195 | |||
196 | /** |
||
197 | * Set stopped status |
||
198 | * @return bool |
||
0 ignored issues
–
show
|
|||
199 | */ |
||
200 | public function setStopped() |
||
201 | { |
||
202 | return $this->setStatus(self::STATUS_STOPPED); |
||
203 | } |
||
204 | |||
205 | /** |
||
206 | * Set completed status |
||
207 | * @return bool |
||
0 ignored issues
–
show
|
|||
208 | */ |
||
209 | public function setCompleted() |
||
210 | { |
||
211 | return $this->setStatus(self::STATUS_COMPLETED); |
||
212 | } |
||
213 | |||
214 | /** |
||
215 | * Set active status |
||
216 | * @return bool |
||
0 ignored issues
–
show
|
|||
217 | */ |
||
218 | public function setActive() |
||
219 | { |
||
220 | return $this->setStatus(self::STATUS_ACTIVE); |
||
221 | } |
||
222 | |||
223 | /** |
||
224 | * Set failed status |
||
225 | * @return bool |
||
0 ignored issues
–
show
|
|||
226 | */ |
||
227 | public function setFailed() |
||
228 | { |
||
229 | return $this->setStatus(self::STATUS_FAILED); |
||
230 | } |
||
231 | |||
232 | /** |
||
233 | * Set status |
||
234 | * @param $status |
||
235 | * @return bool |
||
0 ignored issues
–
show
|
|||
236 | */ |
||
237 | public function setStatus($status) |
||
238 | { |
||
239 | $this->status = $status; |
||
240 | return $this->update(false, ['status']); |
||
241 | } |
||
242 | |||
243 | /** |
||
244 | * @return array |
||
245 | */ |
||
246 | public function getOptions() |
||
247 | { |
||
248 | return $this->task_options; |
||
249 | } |
||
250 | |||
251 | /** |
||
252 | * @param $options |
||
253 | */ |
||
254 | public function setOptions($options) |
||
255 | { |
||
256 | if (is_array($options)) { |
||
257 | $this->task_options = $options; |
||
258 | } |
||
259 | } |
||
260 | |||
261 | /** |
||
262 | * Set failed status counter |
||
263 | * @return bool |
||
264 | */ |
||
265 | private function incrementCounter() |
||
266 | { |
||
267 | return $this->updateCounters(['fail_counter' => 1]); |
||
268 | } |
||
269 | |||
270 | /** |
||
271 | * Refresh failed status counter |
||
272 | * @return bool |
||
0 ignored issues
–
show
|
|||
273 | */ |
||
274 | private function refreshCounter() |
||
275 | { |
||
276 | $this->fail_counter = 0; |
||
277 | return $this->update(false, ['fail_counter']); |
||
278 | } |
||
279 | |||
280 | /** |
||
281 | * Run task |
||
282 | */ |
||
283 | public function run() |
||
284 | { |
||
285 | $oldts = $this->ts; |
||
286 | $this->refresh(); |
||
287 | if (($this->status == self::STATUS_ACTIVE || $this->status == self::STATUS_PROCESS) && $this->ts == $oldts) { |
||
288 | $this->setRunning(); |
||
289 | $message = new NotifyMessage(); |
||
290 | $message->task_id = $this->id; |
||
291 | \Yii::trace($this->name.' is running', $this->getLogname()); |
||
0 ignored issues
–
show
The method
yii\BaseYii::trace() has been deprecated with message: since 2.0.14. Use [[debug()]] instead.
This method has been deprecated. The supplier of the class has supplied an explanatory message. The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead. ![]() |
|||
292 | $args = ' ' . escapeshellarg($this->action); |
||
293 | /* isJson validate*/ |
||
294 | $params = preg_match('/^{[^}]+}$/iu',$this->params) ? [$this->params]: [$this->params]; |
||
295 | |||
296 | if (!empty($params)) { |
||
297 | foreach ($params as $param) { |
||
298 | $args .= ' ' . escapeshellarg($param); |
||
299 | } |
||
300 | } |
||
301 | exec(\Yii::getAlias('@app/yii') . $args . ' 2>&1', $output, $return_val); |
||
302 | $message->result = $this->printCommandResult($output); |
||
303 | |||
304 | if ($return_val === 0) { |
||
305 | switch ($this->type) { |
||
306 | case self::TYPE_EVENT: |
||
307 | $this->setCompleted(); |
||
308 | \Yii::trace($this->name.' completed', $this->getLogname()); |
||
0 ignored issues
–
show
The method
yii\BaseYii::trace() has been deprecated with message: since 2.0.14. Use [[debug()]] instead.
This method has been deprecated. The supplier of the class has supplied an explanatory message. The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead. ![]() |
|||
309 | break; |
||
310 | case self::TYPE_REPEAT: |
||
311 | $this->setActive(); |
||
312 | $this->refreshCounter(); |
||
313 | \Yii::trace($this->name.' completed', $this->getLogname()); |
||
0 ignored issues
–
show
The method
yii\BaseYii::trace() has been deprecated with message: since 2.0.14. Use [[debug()]] instead.
This method has been deprecated. The supplier of the class has supplied an explanatory message. The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead. ![]() |
|||
314 | break; |
||
315 | default: |
||
316 | $this->setFailed(); |
||
317 | \Yii::error($this->name.' failed', $this->getLogname()); |
||
318 | break; |
||
319 | } |
||
320 | $message->result_status = NotifyMessage::STATUS_SUCCESS; |
||
321 | } else { |
||
322 | switch ($this->type) { |
||
323 | case self::TYPE_EVENT: |
||
324 | $this->setFailed(); |
||
325 | \Yii::trace($this->name.' failed', $this->getLogname()); |
||
0 ignored issues
–
show
The method
yii\BaseYii::trace() has been deprecated with message: since 2.0.14. Use [[debug()]] instead.
This method has been deprecated. The supplier of the class has supplied an explanatory message. The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead. ![]() |
|||
326 | break; |
||
327 | case self::TYPE_REPEAT: |
||
328 | $this->incrementCounter(); |
||
329 | if ($this->fail_counter >= self::MAX_FAIL_COUNT) { |
||
330 | $this->setFailed(); |
||
331 | } else { |
||
332 | $this->setActive(); |
||
333 | } |
||
334 | \Yii::trace($this->name.' failed', $this->getLogname()); |
||
0 ignored issues
–
show
The method
yii\BaseYii::trace() has been deprecated with message: since 2.0.14. Use [[debug()]] instead.
This method has been deprecated. The supplier of the class has supplied an explanatory message. The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead. ![]() |
|||
335 | break; |
||
336 | default: |
||
337 | $this->setFailed(); |
||
338 | \Yii::error($this->name.' failed', $this->getLogname()); |
||
339 | break; |
||
340 | } |
||
341 | $message->result_status = NotifyMessage::STATUS_FAULT; |
||
342 | } |
||
343 | $message->save(); |
||
344 | } |
||
345 | } |
||
346 | |||
347 | /** |
||
348 | * Logging script output and return string representation |
||
349 | * @param $output |
||
350 | * @return string |
||
351 | */ |
||
352 | private function printCommandResult($output) |
||
353 | { |
||
354 | $result = ''; |
||
355 | foreach ($output as $line) { |
||
356 | \Yii::trace($line, $this->getLogname()); |
||
0 ignored issues
–
show
The method
yii\BaseYii::trace() has been deprecated with message: since 2.0.14. Use [[debug()]] instead.
This method has been deprecated. The supplier of the class has supplied an explanatory message. The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead. ![]() |
|||
357 | $result .= "$line\n"; |
||
358 | } |
||
359 | return strlen($result) > 0 ? $result : '(no message)'; |
||
360 | } |
||
361 | |||
362 | /** |
||
363 | * Get log category |
||
364 | * @return string |
||
365 | */ |
||
366 | private function getLogname() |
||
367 | { |
||
368 | if ($this->logname == '') { |
||
369 | $this->logname = 'background\task:' |
||
370 | . ($this->name ? $this->name : 'undefined') |
||
371 | . '\action:' |
||
372 | . ($this->action ? $this->action : 'undefined'); |
||
373 | } |
||
374 | return $this->logname; |
||
375 | } |
||
376 | |||
377 | /** |
||
378 | * @inheritdoc |
||
379 | */ |
||
380 | public function scenarios() |
||
381 | { |
||
382 | return [ |
||
383 | 'default' => [ |
||
384 | 'id', |
||
385 | 'type', |
||
386 | 'name', |
||
387 | 'description', |
||
388 | 'action', |
||
389 | 'params', |
||
390 | 'initiator', |
||
391 | 'init_event', |
||
392 | 'cron_expression', |
||
393 | 'ts', |
||
394 | 'status' |
||
395 | ], |
||
396 | 'repeat' => [ |
||
397 | 'id', |
||
398 | 'type', |
||
399 | 'name', |
||
400 | 'description', |
||
401 | 'action', |
||
402 | 'params', |
||
403 | 'initiator', |
||
404 | 'cron_expression', |
||
405 | 'ts', |
||
406 | 'status' |
||
407 | ], |
||
408 | 'event' => [ |
||
409 | 'id', |
||
410 | 'type', |
||
411 | 'name', |
||
412 | 'description', |
||
413 | 'action', |
||
414 | 'params', |
||
415 | 'initiator', |
||
416 | 'init_event', |
||
417 | 'ts', |
||
418 | 'status' |
||
419 | ], |
||
420 | 'search' => [ |
||
421 | 'id', |
||
422 | 'name', |
||
423 | 'description', |
||
424 | 'action', |
||
425 | 'params', |
||
426 | 'cron_expression', |
||
427 | 'ts', |
||
428 | 'status', |
||
429 | 'username' |
||
430 | ], |
||
431 | ]; |
||
432 | } |
||
433 | |||
434 | /** |
||
435 | * Search tasks |
||
436 | * @param $params |
||
437 | * @return ActiveDataProvider |
||
438 | */ |
||
439 | public function search($params) |
||
440 | { |
||
441 | /* @var $query \yii\db\ActiveQuery */ |
||
442 | $query = self::find(); |
||
443 | $query->joinWith('initiatorUser'); |
||
444 | |||
445 | $dataProvider = new ActiveDataProvider( |
||
446 | [ |
||
447 | 'query' => $query, |
||
448 | 'pagination' => [ |
||
449 | 'pageSize' => 10, |
||
450 | ], |
||
451 | ] |
||
452 | ); |
||
453 | |||
454 | $dataProvider->sort->attributes['username'] = [ |
||
455 | 'asc' => [User::tableName().'.username' => SORT_ASC], |
||
456 | 'desc' => [User::tableName().'.username' => SORT_DESC], |
||
457 | ]; |
||
458 | |||
459 | $query->andWhere($this->tableName().'.type = :type', [':type' => 'REPEAT']); |
||
460 | |||
461 | if (!($this->load($params) && $this->validate())) { |
||
462 | return $dataProvider; |
||
463 | } |
||
464 | |||
465 | $this->addCondition($query, $this->tableName(), 'id'); |
||
466 | $this->addCondition($query, $this->tableName(), 'name', true); |
||
467 | $this->addCondition($query, $this->tableName(), 'description', true); |
||
468 | $this->addCondition($query, $this->tableName(), 'action', true); |
||
469 | $this->addCondition($query, $this->tableName(), 'params', true); |
||
470 | $this->addCondition($query, $this->tableName(), 'cron_expression', true); |
||
471 | $this->addCondition($query, $this->tableName(), 'ts', true); |
||
472 | $this->addCondition($query, $this->tableName(), 'status'); |
||
473 | $this->addCondition($query, User::tableName(), 'username', true); |
||
474 | |||
475 | return $dataProvider; |
||
476 | } |
||
477 | |||
478 | /** |
||
479 | * @param bool $insert |
||
480 | * @return bool |
||
481 | */ |
||
482 | public function beforeSave($insert) |
||
483 | { |
||
484 | $result = parent::beforeSave($insert); |
||
485 | |||
486 | $this->options = Json::encode($this->task_options); |
||
487 | |||
488 | return $result; |
||
489 | } |
||
490 | |||
491 | |||
492 | /** |
||
493 | * @param bool $insert |
||
494 | * @param array $changedAttributes |
||
495 | */ |
||
496 | public function afterSave($insert, $changedAttributes) |
||
497 | { |
||
498 | parent::afterSave($insert, $changedAttributes); |
||
499 | |||
500 | if (empty($changedAttributes)) { |
||
501 | return ; |
||
502 | } |
||
503 | |||
504 | if (!isset($this->task_options['create_notification']) || (false == $this->task_options['create_notification'])) { |
||
505 | return ; |
||
506 | } |
||
507 | |||
508 | if (self::STATUS_ACTIVE === $this->status) { |
||
509 | Notification::addNotification( |
||
510 | $this->initiator, |
||
511 | 'Задание "'.$this->description.'" добавлено в очередь.', |
||
512 | 'Задание', |
||
513 | 'info' |
||
514 | ); |
||
515 | } else if (self::STATUS_RUNNING === $this->status) { |
||
516 | Notification::addNotification( |
||
517 | $this->initiator, |
||
518 | 'Задание "'.$this->description.'" выполняется.', |
||
519 | 'Задание', |
||
520 | 'info' |
||
521 | ); |
||
522 | } else if (self::STATUS_COMPLETED === $this->status) { |
||
523 | Notification::addNotification( |
||
524 | $this->initiator, |
||
525 | 'Задание "'.$this->description.'" успешно выполнено.', |
||
526 | 'Задание', |
||
527 | 'success' |
||
528 | ); |
||
529 | } else if (self::STATUS_FAILED === $this->status) { |
||
530 | Notification::addNotification( |
||
531 | $this->initiator, |
||
532 | 'Задание "'.$this->description.'" завершилось с ошибкой.', |
||
533 | 'Задание', |
||
534 | 'danger' |
||
535 | ); |
||
536 | } |
||
537 | } |
||
538 | |||
539 | /** |
||
540 | * |
||
541 | */ |
||
542 | public function afterFind() |
||
543 | { |
||
544 | parent::afterFind(); |
||
545 | |||
546 | $options = []; |
||
547 | try { |
||
548 | $options = Json::decode($this->options); |
||
549 | } catch(\Exception $e) { |
||
0 ignored issues
–
show
Coding Style
Comprehensibility
introduced
by
|
|||
550 | } |
||
551 | |||
552 | $this->task_options = $options; |
||
0 ignored issues
–
show
It seems like
$options of type * is incompatible with the declared type array of property $task_options .
Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property. Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property.. ![]() |
|||
553 | } |
||
554 | } |
||
555 |
This check looks for the generic type
array
as a return type and suggests a more specific type. This type is inferred from the actual code.