コード例 #1
0
 /**
  * Wake the given execution up using the given signal / variables.
  * 
  * @param Execution $execution
  * @param string $signal
  * @param array $variables
  * @param array $delegation
  */
 public function __construct(Execution $execution, $signal = NULL, array $variables = [], array $delegation = [])
 {
     $this->executionId = (string) $execution->getId();
     $this->signal = $signal === NULL ? NULL : (string) $signal;
     $this->variables = serialize($variables);
     $this->delegation = serialize($delegation);
 }
コード例 #2
0
 /**
  * {@inheritdoc}
  */
 public function execute(Execution $execution)
 {
     $engine = $execution->getEngine();
     $activityId = $execution->getNode()->getId();
     $engine->notify(new ActivityStartedEvent($activityId, $execution, $engine));
     parent::execute($execution);
     $engine->notify(new ActivityCompletedEvent($activityId, $execution, $engine));
 }
コード例 #3
0
 /**
  * {@inheritdoc}
  */
 public function signal(Execution $execution, $signal, array $variables = [], array $delegation = [])
 {
     foreach ($variables as $k => $v) {
         $execution->setVariable($k, $v);
     }
     if ($signal === NULL) {
         return $execution->takeAll(NULL, [$execution]);
     }
     return $execution->take($signal);
 }
コード例 #4
0
ファイル: TestEngine.php プロジェクト: koolkode/process
 protected function collectExecutions(Execution $execution, Node $node = NULL)
 {
     $executions = [$execution];
     foreach ($execution->findChildExecutions($node) as $child) {
         foreach ($this->collectExecutions($child, $node) as $exec) {
             $executions[] = $exec;
         }
     }
     return $executions;
 }
コード例 #5
0
 /**
  * {@inheritdoc}
  */
 public function execute(Execution $execution)
 {
     $execution->getEngine()->notify(new ActivityStartedEvent($this->activityId, $execution, $execution->getEngine()));
     $execution->getEngine()->info('ENTER: scope <{scope}> at level {level} using {execution}', ['scope' => $this->activityId, 'level' => $execution->getExecutionDepth(), 'execution' => (string) $execution]);
     $root = $execution->createNestedExecution($execution->getProcessModel(), $execution->getNode(), true);
     $root->waitForSignal();
     $this->createEventSubscriptions($root, $this->activityId, $execution->getNode());
     $this->enter($root->createExecution(false));
 }
コード例 #6
0
 public function signal(Execution $execution, $signal, array $variables = [], array $delegation = [])
 {
     $sub = $execution->getEngine()->findExecution($delegation['executionId']);
     if (!$sub instanceof Execution) {
         throw new \RuntimeException('Missing reference to nested execution');
     }
     foreach ($this->outputs as $target => $source) {
         if ($sub->hasVariable($source)) {
             $execution->setVariable($target, $sub->getVariable($source));
         }
     }
     $execution->takeAll(NULL, [$execution]);
 }
コード例 #7
0
 /**
  * {@inheritdoc}
  */
 public function execute(Execution $execution)
 {
     foreach ($execution->getProcessModel()->findOutgoingTransitions($execution->getNode()->getId()) as $trans) {
         if ($trans->getId() === $this->defaultTransition) {
             continue;
         }
         if ($trans->isEnabled($execution)) {
             return $execution->take($trans);
         }
     }
     if ($this->defaultTransition !== NULL) {
         return $execution->take($this->defaultTransition);
     }
     $message = sprintf('Execution %s about to get stuck in exclusive choice within node "%s"', $execution->getId(), $execution->getNode()->getId());
     throw new StuckException($message);
 }
コード例 #8
0
 protected function isReachable(Node $source, Node $target, Execution $execution, \SplObjectStorage $visited)
 {
     if ($source === $target) {
         return true;
     }
     $model = $execution->getProcessModel();
     $out = $model->findOutgoingTransitions($source->getId());
     $visited->attach($source);
     foreach ($out as $transition) {
         $tmp = $model->findNode($transition->getTo());
         if (!$visited->contains($tmp) && $this->isReachable($tmp, $target, $execution, $visited)) {
             return true;
         }
     }
     return false;
 }
コード例 #9
0
ファイル: SyncBehavior.php プロジェクト: koolkode/process
 /**
  * {@inheritdoc}
  */
 public function execute(Execution $execution)
 {
     $execution->setActive(false);
     $numberExecutions = count($execution->getProcessModel()->findIncomingTransitions($execution->getNode()->getId()));
     // Collect recycled executions, initialize with current execution:
     $recycle = [$execution->getTransition()->getId() => $execution];
     foreach ($execution->findInactiveConcurrentExecutions($execution->getNode()) as $concurrent) {
         // Collect at most 1 execution per incoming transition.
         $transId = $concurrent->getTransition()->getId();
         if (empty($recycle[$transId]) || $concurrent->getTimestamp() < $recycle[$transId]->getTimestamp()) {
             $recycle[$transId] = $concurrent;
         }
     }
     if (count($recycle) !== $numberExecutions) {
         return;
     }
     return $execution->takeAll(NULL, $recycle);
 }
コード例 #10
0
ファイル: ProcessEngine.php プロジェクト: Lesspion/bpmn
 protected function computeVarDelta(Execution $execution, array $syncData)
 {
     $result = [0 => [], 1 => []];
     $data = $execution->getSyncData();
     $vars = empty($data['variables']) ? [] : $data['variables'];
     $syncData = empty($syncData['variables']) ? [] : $syncData['variables'];
     foreach ($vars as $k => $v) {
         if (!array_key_exists($k, $syncData)) {
             $result[0][$k] = true;
             continue;
         }
         if ($v !== $syncData[$k]) {
             $result[1][$k] = true;
         }
         unset($syncData[$k]);
     }
     foreach ($syncData as $k => $v) {
         $result[1][$k] = true;
     }
     return [Execution::SYNC_STATE_REMOVED => array_unique(array_keys(array_merge($result[0], $result[1]))), Execution::SYNC_STATE_MODIFIED => array_keys($result[1])];
     return array_map('array_keys', $result);
 }
コード例 #11
0
ファイル: PassBehavior.php プロジェクト: koolkode/process
 /**
  * {@inheritdoc}
  */
 public function execute(Execution $execution)
 {
     $execution->takeAll();
 }
コード例 #12
0
 public function isEnabled(Execution $execution)
 {
     return call_user_func($this->expression, $execution->getExpressionContext()) ? true : false;
 }
コード例 #13
0
ファイル: Execution.php プロジェクト: koolkode/process
 /**
  * Take all given transitions (or every transition when given NULL) recycling the given
  * executions in the process.
  * 
  * @param array<string> $transitions
  * @param array<Execution> $recycle
  * 
  * @throws \RuntimeException When the execution has been terminated.
  */
 public function takeAll(array $transitions = NULL, array $recycle = [])
 {
     if ($this->isTerminated()) {
         throw new \RuntimeException(sprintf('Cannot take transition in terminated %s', $this));
     }
     $this->engine->pushCommand(new CallbackCommand(function () use($transitions, $recycle) {
         if ($this->isConcurrent()) {
             if (1 === count($this->findConcurrentExecutions())) {
                 foreach ($recycle as $rec) {
                     foreach ($recycle as $rec) {
                         if ($rec !== $this) {
                             $rec->terminate(false);
                         }
                     }
                 }
                 foreach ($this->findChildExecutions() as $child) {
                     $this->parentExecution->registerChildExecution($child);
                 }
                 $this->parentExecution->node = $this->node;
                 $this->parentExecution->transition = $this->transition;
                 $this->parentExecution->setActive(true);
                 $this->engine->debug('Merged concurrent {execution} into {root}', ['execution' => (string) $this, 'root' => (string) $this->parentExecution]);
                 $this->terminate(false);
                 return $this->parentExecution->takeAll($transitions);
             }
         }
         if ($transitions === NULL) {
             $transitions = $this->getProcessModel()->findOutgoingTransitions($this->node->getId());
         } else {
             $transitions = array_map(function ($trans) {
                 return $trans instanceof Transition ? $trans : $this->getProcessModel()->findTransition($trans);
             }, $transitions);
         }
         $transitions = array_filter($transitions, function (Transition $trans) {
             return $trans->isEnabled($this);
         });
         if (!in_array($this, $recycle, true)) {
             array_unshift($recycle, $this);
         }
         if (empty($transitions)) {
             foreach ($recycle as $rec) {
                 if ($rec !== $this) {
                     $rec->terminate(false);
                 }
             }
             if ($this->isConcurrent() && 0 == count($this->findConcurrentExecutions())) {
                 $this->parentExecution->setActive(true);
                 $this->terminate(false);
                 return $this->parentExecution->terminate();
             }
             $this->terminate();
             return;
         }
         $root = $this->isConcurrent() ? $this->parentExecution : $this;
         $merge = count($root->findChildExecutions()) == count($root->findChildExecutions($this->node));
         $active = [];
         foreach ($root->findChildExecutions() as $exec) {
             if ($exec->isActive()) {
                 $active[] = $exec;
             }
         }
         $recycle = array_filter($recycle, function (Execution $execution) use($root) {
             return $execution !== $root;
         });
         if (count($transitions) == 1 && empty($active) && $merge) {
             $terminated = 0;
             foreach ($recycle as $rec) {
                 if (!$rec->isTerminated()) {
                     $rec->terminate(false);
                     $terminated++;
                 }
             }
             $this->setState(self::STATE_CONCURRENT, false);
             $root->setNode($this->node);
             $root->setActive(true);
             if ($terminated > 0) {
                 $this->engine->debug('Merged {count} concurrent executions into {execution}', ['count' => $terminated, 'execution' => (string) $root]);
             }
             $this->markModified(true);
             return $root->take(array_shift($transitions));
         }
         $outgoing = [];
         while (!empty($transitions)) {
             $transition = array_shift($transitions);
             if (empty($recycle)) {
                 $exec = $root->createExecution(true);
             } else {
                 $exec = array_shift($recycle);
             }
             $exec->setActive(true);
             $exec->setNode($this->node);
             $exec->setState(self::STATE_CONCURRENT, true);
             $outgoing[] = [$exec, $transition];
         }
         $root->setActive(false);
         foreach ($recycle as $rec) {
             $rec->terminate(false);
         }
         foreach ($outgoing as $out) {
             $out[0]->take($out[1]);
         }
     }));
 }
コード例 #14
0
ファイル: AbstractActivity.php プロジェクト: Lesspion/bpmn
 /**
  * {@inheritdoc}
  */
 public function execute(Execution $execution)
 {
     $execution->getEngine()->notify(new ActivityStartedEvent($execution->getNode()->getId(), $execution, $execution->getEngine()));
     $this->createEventSubscriptions($execution, $execution->getNode()->getId());
     $this->enter($execution);
 }
コード例 #15
0
ファイル: VirtualExecution.php プロジェクト: Lesspion/bpmn
 /**
  * Get the BPMN process engine instance.
  * 
  * @return ProcessEngine
  */
 public function getEngine()
 {
     return parent::getEngine();
 }
コード例 #16
0
ファイル: AbstractEngine.php プロジェクト: koolkode/process
 protected function syncRemovedExecution(Execution $execution)
 {
     unset($this->executions[(string) $execution->getId()]);
     $this->debug('Sync removed {execution}', ['execution' => (string) $execution]);
 }
コード例 #17
0
 /**
  * Have the given execution execute execute the node's behavior.
  * 
  * @param Execution $execution
  * @param Node $node
  */
 public function __construct(Execution $execution, Node $node)
 {
     $this->executionId = $execution->getId();
     $this->nodeId = (string) $node->getId();
 }
コード例 #18
0
 /**
  * Find the outgoing transition to be taken by the given execution.
  * 
  * @param Execution $execution
  * @throws \RuntimeException
  * @return Transition
  */
 protected function findTransition(Execution $execution)
 {
     $out = (array) $execution->getProcessModel()->findOutgoingTransitions($execution->getNode()->getId());
     $trans = NULL;
     if ($this->transitionId === NULL) {
         if (count($out) != 1) {
             throw new \RuntimeException(sprintf('No single outgoing transition found at node "%s"', $execution->getNode()->getId()));
         }
         return array_pop($out);
     }
     foreach ($out as $tmp) {
         if ($tmp->getId() === $this->transitionId) {
             $trans = $tmp;
             break;
         }
     }
     if ($trans === NULL) {
         throw new \RuntimeException(sprintf('Transition "%s" not connected to node "%s"', $this->transitionId, $execution->getNode()->getId()));
     }
     return $trans;
 }