/**
* Add a fully configured transition to the machine.
*
* It is possible to add transition that have 'regex' states: states that
* have a name in the format of 'regex:/<regex-here>/' or 'not-regex:/<regex-here>/'.
* 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.
*
* @param Transition $transition
* @param boolean $allow_self_transition_by_regex optional: to allow regexes to set a self transition.
* @return int 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;
}