/** * Creates and returns workflow event sequence or scenario for the pending transition. * * Being given the current status and the status value passed as argument * this method returns the event sequence that will occur in the workflow or an empty array if no event is found.<br/> * A "event sequence" is an array containing an ordered set of WorkflowEvents instances. * Possible events sequences are : * * <ul> * <li>[enterWorkflow, enterStatus] : when the current Workflow status is null and $status contains the id of an initial status</li> * <li>[leaveStatus,leaveWorkflow] : when the current Workflow status is not null, and $status is null</li> * <li>[leaveStatus,changeStatus,enterStatus] : when a transition exists between the current workflow status and $status</li> * </ul> * * Note that if the current workflow status and $status are refering to the same status, then a <b>changeStatus event</b> is returned * <b>only if a reflexive transition exists</b> for this status, otherwise no event is returned. * * @param mixed | null $status a status Id or a IStatus instance considered as the target status to reach * @param $scenarioNames * @param $eventSequence * @return array * @throws Exception * @throws WorkflowException */ public function createTransitionItems($status, $scenarioNames, $eventSequence) { $start = $this->getWorkflowStatus(); $end = $status; $scenario = []; $events = []; $newStatus = null; if ($start === null && $end !== null) { // (potential) entering workflow ----------------------------------- $end = $this->ensureStatusInstance($end, true); $workflow = $this->_workflowFactory->getWorkflow($end->getWorkflowId(), $this->owner); $initialStatusId = $workflow->getInitialStatusId(); if ($end->getId() !== $initialStatusId) { throw new WorkflowException('Not an initial status : ' . $end->getId() . ' ("' . $initialStatusId . '" expected)'); } if ($scenarioNames) { $scenario = [WorkflowScenario::enterWorkflow($end->getWorkflowId()), WorkflowScenario::enterStatus($end->getId())]; } if ($eventSequence && $this->_eventSequence !== null) { /** @var Object|ActiveWorkflowBehavior $this */ $events = $this->_eventSequence->createEnterWorkflowSequence($end, $this); } $newStatus = $end; } elseif ($start !== null && $end == null) { // leaving workflow ------------------------------------------------- if ($scenarioNames) { $scenario = [WorkflowScenario::leaveWorkflow($start->getWorkflowId()), WorkflowScenario::leaveStatus($start->getId())]; } if ($eventSequence && $this->_eventSequence !== null) { /** @var Object|ActiveWorkflowBehavior $this */ $events = $this->_eventSequence->createLeaveWorkflowSequence($start, $this); } $newStatus = $end; } elseif ($start !== null && $end !== null) { // change status --------------------------------------- $end = $this->ensureStatusInstance($end, true); $transition = $this->_workflowFactory->getTransition($start->getId(), $end->getId(), $this->selectDefaultWorkflowId(), $this->owner); if ($transition === null && $start->getId() != $end->getId()) { throw new WorkflowException('No transition found between status ' . $start->getId() . ' and ' . $end->getId()); } if ($transition != null) { if ($scenarioNames) { $scenario = [WorkflowScenario::leaveStatus($start->getId()), WorkflowScenario::changeStatus($start->getId(), $end->getId()), WorkflowScenario::enterStatus($end->getId())]; } if ($eventSequence && $this->_eventSequence !== null) { /** @var Object|ActiveWorkflowBehavior $this */ $events = $this->_eventSequence->createChangeStatusSequence($transition, $this); } } $newStatus = $end; } if (count($events) != 0 && (!isset($events['before']) || !isset($events['after']))) { throw new Exception('Invalid event sequence format : "before" and "after" keys are mandatory'); } return [$newStatus, $scenario, $events]; }
public function rules() { return [[['status'], '\\fproject\\workflow\\validators\\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')]]; }
/** * Checks if a validator is active for the workflow event passed as argument. * * @param Validator $validator The validator instance to test * @param $currentScenario * @return bool */ private function _isActiveValidator($validator, $currentScenario) { foreach ($validator->on as $scenario) { if (WorkflowScenario::match($scenario, $currentScenario)) { return true; } } return false; }