izzum\statemachine\StateMachine::addTransition PHP Method

addTransition() public method

It is possible to add transition that have 'regex' states: states that have a name in the format of 'regex://' or 'not-regex://'. When adding a transition with a regex state, it will be matched against all currently known states if there is a match. If you just want to use regex transitions, it might be preferable to store some states via 'addState' first, so the Self transitions for regex states are disallowed by default since you would probably only want to do that explicitly. Regex states can be both the 'to' and the 'from' state of a transition. Transitions from a 'final' type of state are not allowed. the order in which transitions are added matters insofar that when a StateMachine::run() is called, the first Transition for the current State will be tried first. Since a transition has complete knowledge about it's states, the addition of a transition will also trigger the adding of the to and from state on this class. this method can also be used to add a Transition directly (instead of via a loader). Make sure that transitions that share a common State use the same instance of that State object and vice versa.
public addTransition ( Transition $transition, boolean $allow_self_transition_by_regex = false ) : integer
$transition Transition
$allow_self_transition_by_regex boolean optional: to allow regexes to set a self transition.
return integer a count of how many transitions were added. In case of a regex transition this might be multiple and in case a transition already exists it might be 0.
    public function addTransition(Transition $transition, $allow_self_transition_by_regex = false)
    {
        $from = $transition->getStateFrom();
        $to = $transition->getStateTo();
        $all_states = $this->getStates();
        // check if we have regex states in the transition and get either the
        // original state back if it's not a regex, or all currently known
        // states that match the regex.
        $all_from = Utils::getAllRegexMatchingStates($from, $all_states);
        $all_to = Utils::getAllRegexMatchingStates($to, $all_states);
        $contains_regex = $from->isRegex() || $to->isRegex();
        $non_regex_transition = $transition;
        $count = 0;
        // loop trought all possible 'from' states
        foreach ($all_from as $from) {
            // loop through all possible 'to' states
            foreach ($all_to as $to) {
                if ($contains_regex && $from->getName() === $to->getName() && !$allow_self_transition_by_regex) {
                    // disallow self transition for regexes and from final states unless it is explicitely allowed.
                    continue;
                }
                if ($contains_regex) {
                    /*
                     * get a copy of the current transition that has a regex (so
                     * we have a non-regex state) and delegate to $transition to
                     * get that copy in case it's a subclass of transition and
                     * we need to copy specific fields
                     */
                    $non_regex_transition = $transition->getCopy($from, $to);
                }
                if ($this->addTransitionWithoutRegex($non_regex_transition)) {
                    $count++;
                }
            }
        }
        return $count;
    }

Usage Example

 /**
  * @test
  */
 public function shouldBeAbleToStoreAndRetrieveData()
 {
     $redis = new Redis();
     $redis->setDatabase(15);
     //clear the redis database for testing
     $redis->flushdb();
     $machine = new StateMachine(new Context(new Identifier('1', 'test-machine'), null, $redis));
     //create the loader
     //get the configuration from the json file
     $configuration = file_get_contents(__DIR__ . '/../loader/fixture-example.json');
     //set it. normally, this would be done by a seperate process that has already loaded the configuration
     $redis->set(Redis::KEY_CONFIGURATION, $configuration);
     //load the machine
     $count = $redis->load($machine);
     //add the machine to the backend system
     $this->assertTrue($machine->add('this is the first addition'));
     $this->assertFalse($machine->add(), 'returns false, already added');
     $this->assertTrue($machine->run('this is a test run message'), 'succesful transitions so it returns true');
     $this->assertEquals('b', $machine->getCurrentState());
     $this->assertContains('1', $redis->getEntityIds('test-machine'));
     $this->assertTrue($machine->hasEvent('goToC'));
     try {
         $machine->goToC();
         $this->fail('should not come here');
     } catch (Exception $e) {
         $this->assertEquals(Exception::RULE_APPLY_FAILURE, $e->getCode());
     }
     $this->assertEquals('b', $machine->getCurrentState());
     //create new instance of same machine
     $machine2 = new StateMachine(new Context(new Identifier('1', 'test-machine'), null, $redis));
     $this->assertNotSame($machine2, $machine);
     $redis->load($machine2);
     $this->assertEquals('b', $machine2->getCurrentState(), 'should retrieve the same value');
     //create new instance of other machine
     $machine3 = new StateMachine(new Context(new Identifier('2', 'test-machine'), null, $redis));
     $this->assertNotSame($machine2, $machine3);
     $redis->load($machine3);
     $this->assertTrue($machine3->add());
     $this->assertNotEquals('b', $machine3->getCurrentState()->getName(), 'should not retrieve the same value as the other machine');
     $this->assertEquals('a', $machine3->getCurrentState()->getName(), 'initial state');
     //echo $machine3->toString(true);
     $this->assertEquals(2, $machine3->runToCompletion("go to the final state"));
     $this->assertEquals('done', $machine3->getCurrentState()->getName(), 'final state');
     $machine4 = new StateMachine(new Context(new Identifier('3', 'another-machine'), null, $redis));
     $a = new State('begin', State::TYPE_INITIAL);
     $b = new State('enter', State::TYPE_NORMAL);
     $c = new State('leave', State::TYPE_FINAL);
     $machine4->addTransition(new Transition($a, $b));
     $machine4->addTransition(new Transition($b, $c));
     $machine4->add('creating another machine to see that all goes well storing the data for multiple machines in redis');
     $this->assertEquals(2, $machine4->runToCompletion('running the machine to completion'));
     $ids = $redis->getEntityIds('test-machine');
     $this->assertEquals(array('1', '2'), $ids);
     $ids = $redis->getEntityIds('another-machine');
     $this->assertEquals(array('3'), $ids);
     $ids = $redis->getEntityIds('test-machine', 'done');
     $this->assertEquals(array('2'), $ids, 'only 2 was run to completion and in state done');
     $ids = $redis->getEntityIds('another-machine', 'leave');
     $this->assertEquals(array('3'), $ids, 'only 3 was run to completion and in state leave');
     //$redis->hmset("key" , array("name1" => "value1", "name2" => "value2"));
 }
All Usage Examples Of izzum\statemachine\StateMachine::addTransition