| Code Coverage | ||||||||||
| Classes and Traits | Functions and Methods | Lines | ||||||||
| Total |  | 0.00% | 0 / 1 |  | 26.92% | 7 / 26 | CRAP |  | 61.11% | 55 / 90 | 
| TaskState |  | 0.00% | 0 / 1 |  | 40.62% | 13 / 32 | 271.73 |  | 61.11% | 55 / 90 | 
| getState |  | 100.00% | 1 / 1 | 2 |  | 100.00% | 5 / 5 | |||
| getStatusItems |  | 0.00% | 0 / 1 | 2 |  | 0.00% | 0 / 4 | |||
| getStatusLabel |  | 0.00% | 0 / 1 | 30 |  | 0.00% | 0 / 9 | |||
| proceed |  | 0.00% | 0 / 1 | 5.05 |  | 87.50% | 7 / 8 | |||
| reset |  | 0.00% | 0 / 1 | 2.06 |  | 75.00% | 3 / 4 | |||
| canProceed |  | 0.00% | 0 / 1 | 4.07 |  | 83.33% | 5 / 6 | |||
| getProceedStatuses |  | 100.00% | 1 / 1 | 1 |  | 100.00% | 1 / 1 | |||
| getProceedConfig |  | 100.00% | 1 / 1 | 3 |  | 100.00% | 6 / 6 | |||
| getDefaultProceedStatusId |  | 100.00% | 1 / 1 | 2 |  | 100.00% | 3 / 3 | |||
| getDefaultProceedState |  | 0.00% | 0 / 1 | 2 |  | 0.00% | 0 / 1 | |||
| revert |  | 0.00% | 0 / 1 | 5.39 |  | 75.00% | 6 / 8 | |||
| canRevert |  | 0.00% | 0 / 1 | 4.07 |  | 83.33% | 5 / 6 | |||
| getRevertStatuses |  | 100.00% | 1 / 1 | 1 |  | 100.00% | 1 / 1 | |||
| getRevertConfig |  | 100.00% | 1 / 1 | 2 |  | 100.00% | 4 / 4 | |||
| getDefaultRevertStatusId |  | 0.00% | 0 / 1 | 2.15 |  | 66.67% | 2 / 3 | |||
| getDefaultRevertState |  | 0.00% | 0 / 1 | 2 |  | 0.00% | 0 / 1 | |||
| changeStatus |  | 100.00% | 1 / 1 | 1 |  | 100.00% | 3 / 3 | |||
| getStateInstance |  | 0.00% | 0 / 1 | 2.03 |  | 80.00% | 4 / 5 | |||
| getCheckUrl |  | 0.00% | 0 / 1 | 12 |  | 0.00% | 0 / 5 | |||
| getProceedUrl |  | 0.00% | 0 / 1 | 2 |  | 0.00% | 0 / 1 | |||
| getRevertUrl |  | 0.00% | 0 / 1 | 2 |  | 0.00% | 0 / 1 | |||
| isPending |  | 0.00% | 0 / 1 | 2 |  | 0.00% | 0 / 1 | |||
| isInProgress |  | 0.00% | 0 / 1 | 2 |  | 0.00% | 0 / 1 | |||
| isPendingReview |  | 0.00% | 0 / 1 | 2 |  | 0.00% | 0 / 1 | |||
| isCompleted |  | 0.00% | 0 / 1 | 2 |  | 0.00% | 0 / 1 | |||
| getStatusId |  | 0.00% | 0 / 1 | 2 |  | 0.00% | 0 / 1 | |||
| proceedConfig |  | 100.00% | 1 / 1 | 1 | n/a | 0 / 0 | ||||
| revertConfig |  | 100.00% | 1 / 1 | 1 | n/a | 0 / 0 | ||||
| checkRevertRules |  | 100.00% | 1 / 1 | 1 | n/a | 0 / 0 | ||||
| checkProceedRules |  | 100.00% | 1 / 1 | 1 | n/a | 0 / 0 | ||||
| afterProceed |  | 100.00% | 1 / 1 | 1 | n/a | 0 / 0 | ||||
| afterRevert |  | 100.00% | 1 / 1 | 1 | n/a | 0 / 0 | ||||
| <?php | |
| namespace humhub\modules\tasks\models\state; | |
| use humhub\modules\tasks\helpers\TaskUrl; | |
| use humhub\modules\tasks\models\Task; | |
| use Yii; | |
| use yii\base\Component; | |
| /** | |
| * Class TaskState | |
| * @todo change base class back to BaseObject after v1.3 stable | |
| * @package humhub\modules\tasks\models\state | |
| */ | |
| abstract class TaskState extends Component | |
| { | |
| const STATES = [ | |
| Task::STATUS_PENDING => PendingState::class, | |
| Task::STATUS_IN_PROGRESS => InProgressState::class, | |
| Task::STATUS_PENDING_REVIEW => PendingReviewState::class, | |
| Task::STATUS_COMPLETED => CompletedState::class | |
| ]; | |
| public static $status; | |
| public static $defaultProceedStatus; | |
| public static $defaultRevertStatus; | |
| /** | |
| * @var Task | |
| */ | |
| public $task; | |
| public static function getState($task) | |
| { | |
| $states = static::STATES; | |
| $stateClass = isset($states[$task->status]) ? $states[$task->status] : $states[Task::STATUS_PENDING]; | |
| return Yii::createObject([ | |
| 'class' => $stateClass, | |
| 'task' => $task | |
| ]); | |
| } | |
| /** | |
| * Returns an array of statusItems. | |
| * Primary used in TaskFilter | |
| * | |
| * @return array | |
| */ | |
| public static function getStatusItems() | |
| { | |
| return [ | |
| Task::STATUS_PENDING => Yii::t('TasksModule.views_index_index', 'Pending'), | |
| Task::STATUS_IN_PROGRESS => Yii::t('TasksModule.views_index_index', 'In Progress'), | |
| Task::STATUS_PENDING_REVIEW => Yii::t('TasksModule.views_index_index', 'In Review'), | |
| Task::STATUS_COMPLETED => Yii::t('TasksModule.views_index_index', 'Completed'), | |
| ]; | |
| } | |
| /** | |
| * send label for change-status button | |
| * @return string $statusLabel | |
| */ | |
| public function getStatusLabel() | |
| { | |
| switch ($this->status) { | |
| case Task::STATUS_PENDING: | |
| $statusLabel = Yii::t('TasksModule.base', 'Begin Task'); | |
| break; | |
| case Task::STATUS_IN_PROGRESS: | |
| return $this->review ? Yii::t('TasksModule.base', 'Let Task Review') | |
| : Yii::t('TasksModule.base', 'Finish Task'); | |
| break; | |
| case Task::STATUS_PENDING_REVIEW: | |
| $statusLabel = Yii::t('TasksModule.base', 'Finish Task'); | |
| break; | |
| default : | |
| $statusLabel = ''; | |
| } | |
| return $statusLabel; | |
| } | |
| public function proceed($newStatus = null) | |
| { | |
| if($newStatus instanceof TaskState) { | |
| $newStatus = $newStatus->getStatusId(); | |
| } else { | |
| $newStatus = ($newStatus) ? $newStatus : $this->getDefaultProceedStatusId(); | |
| } | |
| if(!array_key_exists($newStatus, static::STATES) || !$this->canProceed($newStatus)) { | |
| return false; | |
| } | |
| $this->changeStatus($newStatus); | |
| $this->task->state->afterProceed($this); | |
| return true; | |
| } | |
| public function reset() | |
| { | |
| if($this->canRevert(Task::STATUS_PENDING)) { | |
| $this->revert(Task::STATUS_PENDING); | |
| return true; | |
| } | |
| return false; | |
| } | |
| public function canProceed($newStatus = null, $user = null) { | |
| if($newStatus instanceof TaskState) { | |
| $newStatus = $newStatus->getStatusId(); | |
| } else { | |
| $newStatus = ($newStatus) ? $newStatus : $this->getDefaultProceedStatusId(); | |
| } | |
| if(!in_array($newStatus, $this->getProceedStatuses($user))) { | |
| return false; | |
| } | |
| return $this->checkProceedRules($newStatus, $user); | |
| } | |
| public function getProceedStatuses($user = null) | |
| { | |
| return array_keys($this->getProceedConfig($user)); | |
| } | |
| public function getProceedConfig($user = null) | |
| { | |
| $result = $this->proceedConfig($user); | |
| if(!$this->task->review) { | |
| unset($result[Task::STATUS_PENDING_REVIEW]); | |
| } | |
| if(!$this->getStateInstance(Task::STATUS_COMPLETED)->canCompleteTask($user)) { | |
| unset($result[Task::STATUS_COMPLETED]); | |
| } | |
| return $result; | |
| } | |
| protected function getDefaultProceedStatusId() | |
| { | |
| if(static::$defaultProceedStatus) { | |
| return static::$defaultProceedStatus; | |
| } | |
| return null; | |
| } | |
| /** | |
| * @return TaskState | |
| */ | |
| public function getDefaultProceedState() | |
| { | |
| return $this->getStateInstance($this->getDefaultProceedStatusId()); | |
| } | |
| public function revert($newStatus = null) | |
| { | |
| if($newStatus instanceof TaskState) { | |
| $newStatus = $newStatus->getStatusId(); | |
| } else { | |
| $newStatus = ($newStatus) ? $newStatus : $this->getDefaultRevertStatusId(); | |
| } | |
| if(!array_key_exists($newStatus, static::STATES) || !$this->canRevert($newStatus)) { | |
| return false; | |
| } | |
| $this->changeStatus($newStatus); | |
| $this->task->state->afterRevert($this); | |
| return true; | |
| } | |
| public function canRevert($newStatus = null, $user = null) | |
| { | |
| if($newStatus instanceof TaskState) { | |
| $newStatus = $newStatus->getStatusId(); | |
| } else { | |
| $newStatus = ($newStatus) ? $newStatus : $this->getDefaultRevertStatusId(); | |
| } | |
| if(!in_array($newStatus, $this->getRevertStatuses($user))) { | |
| return false; | |
| } | |
| return $this->checkRevertRules($newStatus, $user); | |
| } | |
| public function getRevertStatuses($user = null) | |
| { | |
| return array_keys($this->getRevertConfig($user)); | |
| } | |
| public function getRevertConfig($user = null) | |
| { | |
| $result = $this->revertConfig($user); | |
| if(!$this->task->review) { | |
| unset($result[Task::STATUS_PENDING_REVIEW]); | |
| } | |
| return $result; | |
| } | |
| protected function getDefaultRevertStatusId() | |
| { | |
| if(static::$defaultRevertStatus) { | |
| return static::$defaultRevertStatus; | |
| } | |
| return null; | |
| } | |
| public function getDefaultRevertState() | |
| { | |
| return $this->getStateInstance($this->getDefaultRevertStatusId()); | |
| } | |
| protected function changeStatus($status) | |
| { | |
| $this->task->status = $status; | |
| $this->task->save(); | |
| } | |
| /** | |
| * @param $newState | |
| * @return TaskState | |
| */ | |
| public function getStateInstance($newState) | |
| { | |
| if($newState) { | |
| return Yii::createObject([ | |
| 'class' => static::STATES[$newState], | |
| 'task' => $this->task | |
| ]); | |
| } | |
| return null; | |
| } | |
| public function getCheckUrl() | |
| { | |
| if($this->canProceed(Task::STATUS_COMPLETED)) { | |
| return $this->getStateInstance(Task::STATUS_COMPLETED)->getProceedUrl(); | |
| } else if ($this->canProceed(Task::STATUS_PENDING_REVIEW)) { | |
| return $this->getStateInstance(Task::STATUS_PENDING_REVIEW)->getProceedUrl(); | |
| } | |
| return null; | |
| } | |
| public function getProceedUrl() | |
| { | |
| return TaskUrl::proceedTask($this->task, static::$status); | |
| } | |
| public function getRevertUrl() | |
| { | |
| return TaskUrl::revertTask($this->task, static::$status); | |
| } | |
| public function isPending() | |
| { | |
| return ($this->task->status === Task::STATUS_PENDING); | |
| } | |
| public function isInProgress() | |
| { | |
| return ($this->task->status === Task::STATUS_IN_PROGRESS); | |
| } | |
| public function isPendingReview() | |
| { | |
| return ($this->task->status === Task::STATUS_PENDING_REVIEW); | |
| } | |
| public function isCompleted() | |
| { | |
| return ($this->task->status === Task::STATUS_COMPLETED); | |
| } | |
| public function getStatusId() | |
| { | |
| return static::$status; | |
| } | |
| protected abstract function proceedConfig($user = null); | |
| protected abstract function revertConfig($user = null); | |
| public abstract function checkRevertRules($newStatus = null, $user = null); | |
| public abstract function checkProceedRules($newStatus = null, $user = null); | |
| public abstract function afterProceed(TaskState $oldState); | |
| public abstract function afterRevert(TaskState $oldState); | |
| } |