Ejemplo n.º 1
0
 /**
  * @param SimpleXMLElement $xml
  * @param StateMachine $sm
  * @return static
  */
 public static function fromXml(SimpleXMLElement $xml, StateMachine $sm)
 {
     $rVal = new static();
     // Attach the statemachine
     $rVal->sm = $sm;
     // Value and Label
     $rVal->value = (string) $xml->attributes()->value;
     $rVal->label = (string) $xml->attributes()->label;
     // Load events
     foreach ($xml->event as $eventXml) {
         $rVal->events[] = Event::fromXml($eventXml, $sm, $rVal);
     }
     // Load timeouts
     foreach ($xml->timeout as $timeoutXml) {
         $rVal->timeouts[] = Timeout::fromXml($timeoutXml, $sm, $rVal);
     }
     // Enter Commands XML fragments
     $enterXml = !empty($xml->enter) ? $xml->enter[0]->command : [];
     foreach ($enterXml as $item) {
         $rVal->enter[] = $item;
     }
     // Exit Commands XML fragments
     $exitXml = !empty($xml->exit) ? $xml->exit[0]->command : [];
     foreach ($exitXml as $item) {
         $rVal->exit[] = $item;
     }
     $rVal->isInitial = $sm->getInitialStateValue() === $rVal->value;
     $rVal->isFinal = empty($rVal->events);
     return $rVal;
 }
Ejemplo n.º 2
0
 /**
  * @param StateMachineEvent $event
  * @param StateMachineContext $context
  * @return bool
  * @throws Exception
  * @throws \yii\db\Exception
  */
 public function transition(StateMachineEvent $event, StateMachineContext $context)
 {
     // Let the context know which event triggered the transition
     $context->setEvent($event);
     /** @var yii\db\Transaction|false $txn */
     $txn = $this->useTransactions ? $context->getModel()->getDb()->beginTransaction() : false;
     try {
         // Leaving current state...
         foreach ($event->getState()->getExitCommands() as $command) {
             if (!$command->execute($context)) {
                 $txn && $txn->rollBack();
                 return false;
             }
         }
         // Cleanup old timeouts
         Timeout::cleanUp($context);
         // Entering new state...
         $context->getModel()->{$context->getAttr()} = $event->getTarget();
         foreach ($event->getTargetState()->getEnterCommands() as $command) {
             if (!$command->execute($context)) {
                 $txn && $txn->rollBack();
                 return false;
             }
         }
         // Register the new timeouts
         foreach ($event->getTargetState()->getTimeOuts() as $timeout) {
             $timeout->register($context);
         }
         // Persist the context's model data
         $context->getModel()->save();
         // Update Journal - if applicable
         if ($this->modelJournal) {
             $journal = $this->modelJournal;
             /** @var StateMachineJournal $journal */
             $journal::nu($context, $event);
         }
         $txn && $txn->commit();
         // transition completed successfully
         return true;
     } catch (Exception $e) {
         $txn && $txn->rollBack();
         $context->attachException($e);
         throw $e;
     }
 }