/** * Checks if a validator is active for the workflow event passed as argument. * * @param yii\validators\Validator $validator The validator instance to test * @param WorklflowEvent $event The workflow event for which the validator is tested * @return boolean */ private function _isActiveValidator($validator, $currentScenario) { foreach ($validator->on as $scenario) { if (WorkflowScenario::match($scenario, $currentScenario)) { return true; } } return false; }
/** * Creates and returns workflow event sequence and/or scenario for the pending transition. * * Being given the current status and the status value passed as argument this method returns the corresponding * event sequence and the scenario names. * * The returned array contains up to 3 elements : * - index = 0 : the Status instance corresponding to the $status passed as argument * - index = 1 : an array of [[\raoul2000\workflow\events\WorkflowEvent]] instances (the event sequence) that * may contain no element if no event sequence component is configured or if event sequence are not requested ($withEventSequence = false) * - index = 2 : an array of scenario names (string) that may be empty if scenario names are not requested ($WithScenarioNames= false) * * @param mixed $status a status Id or a Status instance considered as the target status to reach * @param boolean $WithScenarioNames When TRUE scenario names are requested, FALSE otherwise * @param boolean $withEventSequence When TRUE the event sequence is requested, FALSE otherwise * @throws WorkflowException * @return array Three elements : Status intance, scenario names, event sequence. * */ public function createTransitionItems($status, $WithScenarioNames, $withEventSequence) { $start = $this->getWorkflowStatus(); $end = $status; $scenario = []; $events = ['before' => [], 'after' => []]; $defaultEventCfg = $newStatus = null; $emptyStart = empty($start); $emptyEnd = empty($end); if ($emptyStart && !$emptyEnd) { // (potential) entering workflow ----------------------------------- $end = $this->ensureStatusInstance($end, true); $workflow = $this->_wfSource->getWorkflow($end->getWorkflowId()); $initialStatusId = $workflow->getInitialStatusId(); if ($end->getId() !== $initialStatusId) { throw new WorkflowException('Not an initial status : ' . $end->getId() . ' ("' . $initialStatusId . '" expected)'); } if ($WithScenarioNames) { $scenario = [WorkflowScenario::enterWorkflow($end->getWorkflowId()), WorkflowScenario::enterStatus($end->getId())]; } if ($withEventSequence && $this->_eventSequence !== null) { $events = $this->_eventSequence->createEnterWorkflowSequence($end, $this); } if ($this->fireDefaultEvent) { $defaultEventCfg = ['end' => $end, 'sender' => $this]; } $newStatus = $end; } elseif (!$emptyStart && $emptyEnd) { // leaving workflow ------------------------------------------------- if ($WithScenarioNames) { $scenario = [WorkflowScenario::leaveWorkflow($start->getWorkflowId()), WorkflowScenario::leaveStatus($start->getId())]; } if ($withEventSequence && $this->_eventSequence !== null) { $events = $this->_eventSequence->createLeaveWorkflowSequence($start, $this); } if ($this->fireDefaultEvent) { $defaultEventCfg = ['start' => $start, 'sender' => $this]; } $newStatus = $end; } elseif (!$emptyStart && !$emptyEnd) { // change status --------------------------------------- $end = $this->ensureStatusInstance($end, true); $transition = $this->_wfSource->getTransition($start->getId(), $end->getId(), $this->selectDefaultWorkflowId()); // TODO : replace $this->owner with defaultWorkflowId if ($transition === null && $start->getId() != $end->getId()) { throw new WorkflowException('No transition found between status ' . $start->getId() . ' and ' . $end->getId()); } if ($transition != null) { if ($WithScenarioNames) { $scenario = [WorkflowScenario::leaveStatus($start->getId()), WorkflowScenario::changeStatus($start->getId(), $end->getId()), WorkflowScenario::enterStatus($end->getId())]; } if ($withEventSequence && $this->_eventSequence !== null) { $events = $this->_eventSequence->createChangeStatusSequence($transition, $this); } if ($this->fireDefaultEvent) { $defaultEventCfg = ['start' => $transition->getStartStatus(), 'end' => $transition->getEndStatus(), 'transition' => $transition, 'sender' => $this]; } } $newStatus = $end; } if (count($events) != 0 && (!isset($events['before']) || !isset($events['after']))) { throw new WorkflowException('Invalid event sequence format : "before" and "after" keys are mandatory'); } if ($this->fireDefaultEvent && $defaultEventCfg != null) { array_unshift($events['before'], new WorkflowEvent(self::EVENT_BEFORE_CHANGE_STATUS, $defaultEventCfg)); array_unshift($events['after'], new WorkflowEvent(self::EVENT_AFTER_CHANGE_STATUS, $defaultEventCfg)); } return [$newStatus, $scenario, $events]; }
public function rules() { return [[['status'], '\\raoul2000\\workflow\\validation\\WorkflowValidator'], ['name', 'required', 'on' => WorkflowScenario::changeStatus('Item05Workflow/new', 'Item05Workflow/correction')], ['category', 'required', 'on' => WorkflowScenario::enterWorkflow('Item05Workflow')], ['category', 'compare', 'compareValue' => 'done', 'on' => WorkflowScenario::leaveWorkflow()], ['tags', 'required', 'on' => WorkflowScenario::leaveStatus('Item05Workflow/correction')], ['author', 'required', 'on' => WorkflowScenario::enterStatus('Item05Workflow/published')]]; }