Code Coverage |
||||||||||
Classes and Traits |
Functions and Methods |
Lines |
||||||||
| Total | |
0.00% |
0 / 1 |
|
21.05% |
4 / 19 |
CRAP | |
33.71% |
30 / 89 |
| TaskList | |
0.00% |
0 / 1 |
|
21.05% |
4 / 19 |
370.78 | |
33.71% |
30 / 89 |
| afterSave | |
100.00% |
1 / 1 |
2 | |
100.00% |
6 / 6 |
|||
| getTasks | |
100.00% |
1 / 1 |
1 | |
100.00% |
1 / 1 |
|||
| load | |
0.00% |
0 / 1 |
2 | |
0.00% |
0 / 2 |
|||
| getNonCompletedTasks | |
100.00% |
1 / 1 |
1 | |
100.00% |
1 / 1 |
|||
| getShowMoreCompletedTasks | |
0.00% |
0 / 1 |
2 | |
0.00% |
0 / 1 |
|||
| getCompletedTasks | |
0.00% |
0 / 1 |
2 | |
0.00% |
0 / 1 |
|||
| getTasksByStatus | |
0.00% |
0 / 1 |
2 | |
0.00% |
0 / 1 |
|||
| findById | |
0.00% |
0 / 1 |
2 | |
0.00% |
0 / 1 |
|||
| findByFilter | |
0.00% |
0 / 1 |
42 | |
0.00% |
0 / 15 |
|||
| findOverviewLists | |
100.00% |
1 / 1 |
1 | |
100.00% |
10 / 10 |
|||
| findHiddenLists | |
0.00% |
0 / 1 |
2 | |
0.00% |
0 / 11 |
|||
| deleteByModule | |
0.00% |
0 / 1 |
12 | |
0.00% |
0 / 6 |
|||
| deleteByType | |
0.00% |
0 / 1 |
12 | |
0.00% |
0 / 6 |
|||
| afterDelete | |
0.00% |
0 / 1 |
2 | |
0.00% |
0 / 3 |
|||
| moveItemIndex | |
0.00% |
0 / 1 |
8.30 | |
60.00% |
12 / 20 |
|||
| isHideIfCompleted | |
0.00% |
0 / 1 |
2 | |
0.00% |
0 / 1 |
|||
| getId | |
0.00% |
0 / 1 |
2 | |
0.00% |
0 / 1 |
|||
| getTitle | |
0.00% |
0 / 1 |
2 | |
0.00% |
0 / 1 |
|||
| getColor | |
0.00% |
0 / 1 |
2 | |
0.00% |
0 / 1 |
|||
| <?php | |
| /** | |
| * @link https://www.humhub.org/ | |
| * @copyright Copyright (c) 2018 HumHub GmbH & Co. KG | |
| * @license https://www.humhub.com/licences | |
| * | |
| */ | |
| namespace humhub\modules\tasks\models\lists; | |
| use humhub\modules\content\components\ActiveQueryContent; | |
| use humhub\modules\content\components\ContentContainerActiveRecord; | |
| use humhub\modules\content\models\ContentContainer; | |
| use humhub\modules\content\models\ContentTag; | |
| use humhub\modules\tasks\models\Sortable; | |
| use humhub\modules\tasks\models\Task; | |
| use yii\db\ActiveQuery; | |
| use yii\db\Expression; | |
| /** | |
| * Class TaskList | |
| * @property int $id | |
| * @property TaskListSettings $addition | |
| */ | |
| class TaskList extends ContentTag implements TaskListInterface, Sortable | |
| { | |
| public $moduleId = 'tasks'; | |
| public $additionClass = TaskListSettings::class; | |
| const FILTER_STATUS_INCLUDE = 'status'; | |
| const FILTER_STATUS_EXCLUDE = 'status'; | |
| public function afterSave($insert, $changedAttributes) | |
| { | |
| // TODO: this can be removed after v1.2.6 | |
| $this->addition->setTag($this); | |
| if($insert) { | |
| $root = new TaskListRoot(['contentContainer' => $this->getContainer()]); | |
| $root->moveItemIndex($this->id, 0); | |
| } | |
| parent::afterSave($insert, $changedAttributes); | |
| } | |
| /** | |
| * @return ActiveQueryContent | |
| */ | |
| public function getTasks() | |
| { | |
| return Task::find()->andWhere(['task_list_id' => $this->id])->readable(); | |
| } | |
| public function load($data, $formName = null) | |
| { | |
| // TODO: this can be removed after v1.2.6 | |
| $this->addition->load($data); | |
| return parent::load($data, $formName); // TODO: Change the autogenerated stub | |
| } | |
| /** | |
| * @return ActiveQueryContent | |
| */ | |
| public function getNonCompletedTasks() | |
| { | |
| return $this->getTasks()->where(['!=', 'task.status', Task::STATUS_COMPLETED])->orderBy(['sort_order' => SORT_ASC, 'updated_at' => SORT_DESC]); | |
| } | |
| /** | |
| * @param $offset int | |
| * @param $limit int | |
| * @return static[] | |
| */ | |
| public function getShowMoreCompletedTasks($offset, $limit) | |
| { | |
| return $this->getCompletedTasks()->orderBy(['task.updated_at' => SORT_DESC])->offset($offset)->limit($limit)->all(); | |
| } | |
| /** | |
| * @return ActiveQuery | |
| */ | |
| public function getCompletedTasks() | |
| { | |
| return $this->getTasksByStatus(Task::STATUS_COMPLETED)->orderBy(['task.updated_at' => SORT_DESC]); | |
| } | |
| /** | |
| * @param $status | |
| * @return ActiveQuery | |
| */ | |
| public function getTasksByStatus($status) | |
| { | |
| return $this->getTasks()->where(['task.status' => $status]); | |
| } | |
| /** | |
| * @param $id | |
| * @param $container | |
| * @return TaskList|null | |
| */ | |
| public static function findById($id, $container) | |
| { | |
| return static::findByContainer($container)->andWhere(['id' => $id])->one(); | |
| } | |
| /** | |
| * @param $container | |
| * @param array $filters | |
| * @return ActiveQuery | |
| */ | |
| public static function findByFilter($container, $filters = []) | |
| { | |
| $query = static::findByContainer($container); | |
| if(isset($filters[static::FILTER_STATUS_EXCLUDE])) { | |
| $includes = Task::$statuses; | |
| $excludes = is_array($filters[static::FILTER_STATUS_EXCLUDE]) ? $filters[static::FILTER_STATUS_EXCLUDE] : [$filters[static::FILTER_STATUS_EXCLUDE]]; | |
| foreach ($excludes as $exclude) { | |
| unset($includes[$exclude]); | |
| } | |
| $filters[static::FILTER_STATUS_INCLUDE] = $includes; | |
| } | |
| if(isset($filters[static::FILTER_STATUS_INCLUDE])) { | |
| $query->leftJoin('task', 'task.task_list_id=content_tag.id'); | |
| $includes = is_array($filters[static::FILTER_STATUS_INCLUDE]) ? $filters[static::FILTER_STATUS_INCLUDE] : [$filters[static::FILTER_STATUS_INCLUDE]]; | |
| $query->andWhere( | |
| ['OR', | |
| ['IS', 'task.id', new Expression("NULL")], | |
| ['IN', 'task.status', $includes] | |
| ]); | |
| } | |
| return $query; | |
| } | |
| /** | |
| * @param $container | |
| * @return ActiveQuery | |
| */ | |
| public static function findOverviewLists(ContentContainerActiveRecord $container) | |
| { | |
| $query = static::findByContainer($container); | |
| $query->leftJoin('task', 'task.task_list_id=content_tag.id'); | |
| $query->leftJoin('task_list_setting', 'task_list_setting.tag_id=content_tag.id'); | |
| $includes = [Task::STATUS_IN_PROGRESS, Task::STATUS_PENDING_REVIEW, Task::STATUS_PENDING]; | |
| $query->andWhere( | |
| ['OR', | |
| ['IN', 'task.status', $includes], | |
| ['IS', 'task.id', new Expression("NULL")], | |
| ['task_list_setting.hide_if_completed' => '0'] | |
| ] | |
| ); | |
| $query->orderBy(['task_list_setting.sort_order' => SORT_ASC]); | |
| return $query; | |
| } | |
| public static function findHiddenLists(ContentContainerActiveRecord $container) | |
| { | |
| $query = static::findByContainer($container); | |
| $query->leftJoin('task t', 't.task_list_id=content_tag.id'); | |
| $query->leftJoin('task_list_setting', 'task_list_setting.tag_id=content_tag.id'); | |
| $includes = [Task::STATUS_IN_PROGRESS, Task::STATUS_PENDING_REVIEW, Task::STATUS_PENDING]; | |
| $subQuery = Task::find()->where(['task_list_id' => new Expression('content_tag.id')])->andWhere(['IN', 'task.status', $includes]); | |
| $query->andWhere( | |
| ['AND', | |
| ['NOT EXISTS', $subQuery], | |
| ['IS NOT', 't.id', new Expression("NULL")], | |
| ['task_list_setting.hide_if_completed' => '1'] | |
| ] | |
| ); | |
| $query->orderBy(['task_list_setting.updated_at' => SORT_ASC]); | |
| return $query; | |
| } | |
| /** | |
| * Deletes all tags by module id | |
| * @param ContentContainerActiveRecord|int $contentContainer | |
| */ | |
| public static function deleteByModule($contentContainer = null) | |
| { | |
| $instance = new static(); | |
| if($contentContainer) { | |
| $container_id = $contentContainer instanceof ContentContainerActiveRecord ? $contentContainer->contentcontainer_id : $contentContainer; | |
| static::deleteAll(['module_id' => $instance->module_id, 'contentcontainer_id' => $container_id]); | |
| } else { | |
| static::deleteAll(['module_id' => $instance->module_id]); | |
| } | |
| } | |
| /** | |
| * Deletes all tags by type | |
| * @param ContentContainerActiveRecord|int $contentContainer | |
| */ | |
| public static function deleteByType($contentContainer = null) | |
| { | |
| $instance = new static(); | |
| if($contentContainer) { | |
| $container_id = $contentContainer instanceof ContentContainerActiveRecord ? $contentContainer->contentcontainer_id : $contentContainer; | |
| static::deleteAll(['type' => $instance->type, 'contentcontainer_id' => $container_id]); | |
| } else { | |
| static::deleteAll(['type' => $instance->type]); | |
| } | |
| } | |
| /** | |
| * @inheritdoc | |
| */ | |
| public function afterDelete() | |
| { | |
| // Workaround for non foreign key support | |
| Task::updateAll(['task_list_id' => new Expression('NULL')], ['task_list_id' => $this->id]); | |
| parent::afterDelete(); | |
| } | |
| public function moveItemIndex($taskId, $newIndex) | |
| { | |
| /** @var $task Task */ | |
| $transaction = Task::getDb()->beginTransaction(); | |
| try { | |
| $task = Task::findOne(['id' => $taskId]); | |
| $tasks = $this->getNonCompletedTasks()->andWhere(['!=', 'task.id', $task->id])->all(); | |
| $task->updateAttributes(['task_list_id' => $this->id]); | |
| // make sure no invalid index is given | |
| if ($newIndex < 0) { | |
| $newIndex = 0; | |
| } else if ($newIndex >= count($tasks) + 1) { | |
| $newIndex = count($tasks) - 1; | |
| } | |
| array_splice($tasks, $newIndex, 0, [$task]); | |
| foreach ($tasks as $index => $item) { | |
| $item->updateAttributes(['sort_order' => $index]); | |
| } | |
| $transaction->commit(); | |
| } catch (\Exception $e) { | |
| $transaction->rollBack(); | |
| throw $e; | |
| } catch (\Throwable $e) { | |
| $transaction->rollBack(); | |
| throw $e; | |
| } | |
| $this->refresh(); | |
| } | |
| public function isHideIfCompleted() | |
| { | |
| return $this->addition->hide_if_completed; | |
| } | |
| public function getId() | |
| { | |
| return $this->id; | |
| } | |
| public function getTitle() | |
| { | |
| return $this->name; | |
| } | |
| public function getColor() | |
| { | |
| return $this->color; | |
| } | |
| } |