/**
  * 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];
 }
Example #2
0
 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;
 }