Esempio n. 1
1
 /**
  * Will return the script required by GraphViz (dot) to render the graph
  *
  * @param StateMachine $sm
  * @return string
  */
 public function render(StateMachine $sm)
 {
     $graph = new Digraph('G');
     $graph->set('truecolor', true);
     foreach ($sm->getStates() as $state) {
         $graph->node($state->getValue(), $this->renderState($state, $this->profile['states']));
     }
     foreach ($sm->getStates() as $state) {
         /** @var Event[] $connectors */
         $connectors = array_merge($state->getEvents(), $state->getTimeOuts());
         foreach ($connectors as $event) {
             $p = $this->profile['events']['default'];
             foreach ($this->profile['events']['exclusiveRoles'] as $exclusiveRole => $roleProfile) {
                 if ($event->isExclusiveTo($exclusiveRole)) {
                     $p = array_merge($p, $roleProfile);
                     break;
                 }
             }
             if ($event instanceof Timeout) {
                 $p = array_merge($p, $this->profile['events']['timeout']);
             } elseif ($event->isRefresh()) {
                 $p = array_merge($p, $this->profile['events']['refresh']);
             }
             $fontcolor = $p['fontcolor'];
             $fillcolor = $p['fillcolor'];
             $color = $p['color'];
             $style = $p['style'];
             $graph->edge([$state->getValue(), $event->getTarget()], ['label' => chr(1) . '<<table border="0" cellspacing="0" cellpadding="2"><tr><td>' . $event->getLabel() . '</td></tr></table>>', 'margin' => 10, 'arrowsize' => 0.6, 'fontsize' => 9, 'fontname' => 'Helvetica Neue', 'fontcolor' => $fontcolor, 'fillcolor' => $fillcolor, 'color' => $color, 'style' => $style]);
         }
     }
     return $graph->render();
 }
 /**
  * @param string $name
  * @param mixed $value
  * @throws CannotGuessEventException
  * @throws EventNotFoundException
  * @throws InvalidSchemaException
  * @throws TransitionException
  * @throws \yii\base\UnknownPropertyException
  * @throws exceptions\StateNotFoundException
  * @throws null
  */
 public function __set($name, $value)
 {
     if ($name === $this->virtAttr) {
         $m = $this->owner;
         // Value did not change - ignore
         if ($m->{$this->attr} === $value) {
             return;
         }
         // First time? Initialize SM for $value state
         if ($m->{$this->attr} === null && $m->getIsNewRecord()) {
             if ($value !== $this->sm->getInitialStateValue()) {
                 throw new InvalidValueException("This attribute is just entering the State Machine and must be set to {$this->sm->getInitialStateValue()}");
             }
             $context = $this->initStateMachine();
         } else {
             // Not first time, try to trigger for $value
             $state = $this->sm->getState($m->{$this->attr});
             if (!$state) {
                 throw new InvalidSchemaException("Cannot load current state {$m->{$this->attr}}");
             }
             $event = $state->guessEvent($value, $this->internalGetUserRole(Yii::$app->user->identity));
             $context = $this->trigger($event);
         }
         // Migrate the context errors to the virtual attribute
         foreach ($context->errors as $attr => $error) {
             $m->addError($this->virtAttr, $error);
         }
     } else {
         parent::__set($name, $value);
     }
 }
Esempio n. 3
0
 /**
  * @return State
  * @throws exceptions\InvalidSchemaException
  * @throws exceptions\StateNotFoundException
  */
 public function getTargetState()
 {
     return $this->sm->getState($this->target);
 }
Esempio n. 4
0
 /**
  * @return interfaces\StateMachineEvent[]
  */
 public function getPossibleEvents()
 {
     return $this->sm->getState($this->model->{$this->attr})->getEvents($this->role, $this);
 }