/** * Invokes the action. * * @param Stagehand_FSM &$fsm * @throws STAGEHAND_FSM_ERROR_NOT_CALLABLE */ function invokeAction(&$fsm) { if (is_null($this->_action)) { return; } if (!is_callable($this->_action)) { Stagehand_FSM_Error::push(STAGEHAND_FSM_ERROR_NOT_CALLABLE, 'The action is not callable.'); return; } $payload =& $fsm->getPayload(); call_user_func_array($this->_action, array(&$fsm, &$this, &$payload)); }
/** * Triggers the given event. * * @param string $eventName * @param boolean $transitionToHistoryMarker * @return Stagehand_FSM_State * @throws PIECE_FLOW_ERROR_INVALID_OPERATION * @throws PIECE_FLOW_ERROR_CANNOT_INVOKE */ function &triggerEvent($eventName, $transitionToHistoryMarker = false) { if (!$this->_started()) { Piece_Flow_Error::push(PIECE_FLOW_ERROR_INVALID_OPERATION, __FUNCTION__ . ' method must be called after starting flows.'); $return = null; return $return; } if ($eventName == PIECE_FLOW_PROTECTED_EVENT || $this->_fsm->isProtectedEvent($eventName)) { trigger_error("The event [ {$eventName} ] cannot be called directly. The current state [ " . $this->getCurrentStateName() . ' ] will only be updated.', E_USER_WARNING); $eventName = PIECE_FLOW_PROTECTED_EVENT; } $this->_lastEventIsValid = $this->_fsm->hasEvent($eventName); Stagehand_FSM_Error::disableCallback(); $state =& $this->_fsm->triggerEvent($eventName, $transitionToHistoryMarker); Stagehand_FSM_Error::enableCallback(); if (Stagehand_FSM_Error::hasErrors()) { Piece_Flow_Error::push(PIECE_FLOW_ERROR_CANNOT_INVOKE, 'Failed to invoke Stagehand_FSM::triggerEvent() for any reasons.', 'exception', array(), Stagehand_FSM_Error::pop()); $return = null; return $return; } if (!is_null($this->_lastState) && $state->getName() == $this->_lastState) { Stagehand_FSM_Error::disableCallback(); $state =& $this->_fsm->triggerEvent(STAGEHAND_FSM_EVENT_END); Stagehand_FSM_Error::enableCallback(); if (Stagehand_FSM_Error::hasErrors()) { Piece_Flow_Error::push(PIECE_FLOW_ERROR_CANNOT_INVOKE, 'Failed to invoke Stagehand_FSM::triggerEvent() for any reasons.', 'exception', array(), Stagehand_FSM_Error::pop()); $return = null; return $return; } } return $state; }
/** * Processes an event. * * @param string $eventName * @param boolean $transitionToHistoryMarker * @return Stagehand_FSM_State * @throws STAGEHAND_FSM_ERROR_ALREADY_SHUTDOWN * @since Method available since Release 1.7.0 */ function &_processEvent($eventName, $transitionToHistoryMarker = false) { if ($this->_currentState->getName() == STAGEHAND_FSM_STATE_FINAL && !$this->_isSpecialEvent($eventName)) { Stagehand_FSM_Error::push(STAGEHAND_FSM_ERROR_ALREADY_SHUTDOWN, 'The FSM was already shutdown.'); $return = null; return $return; } $event =& $this->_currentState->getEvent($eventName); if (!is_null($event)) { if (!$this->_isSpecialEvent($eventName)) { $result = $event->evaluateGuard($this); if (Stagehand_FSM_Error::hasErrors()) { $return = null; return $return; } if (!$result) { $eventName = STAGEHAND_FSM_EVENT_DO; $event =& $this->_currentState->getEvent(STAGEHAND_FSM_EVENT_DO); } } } else { $eventName = STAGEHAND_FSM_EVENT_DO; $event =& $this->_currentState->getEvent(STAGEHAND_FSM_EVENT_DO); } if (!$this->_isSpecialEvent($eventName)) { $this->_processEvent(STAGEHAND_FSM_EVENT_EXIT, $transitionToHistoryMarker); if (Stagehand_FSM_Error::hasErrors()) { $return = null; return $return; } } if (!$this->_isSpecialEvent($eventName)) { $nextStateName = $event->getNextState(); $this->_transition($nextStateName); } $event->invokeAction($this); if (Stagehand_FSM_Error::hasErrors()) { $return = null; return $return; } if ($this->_isEntryEvent($eventName) && is_a($this->_currentState, __CLASS__) && !$transitionToHistoryMarker) { $this->_currentState->start(); if (Stagehand_FSM_Error::hasErrors()) { $return = null; return $return; } } if (!$this->_isSpecialEvent($eventName)) { $this->_processEvent(STAGEHAND_FSM_EVENT_ENTRY, $event->getTransitionToHistoryMarker()); if (Stagehand_FSM_Error::hasErrors()) { $return = null; return $return; } } if (!$this->_isSpecialEvent($eventName)) { $this->_processEvent(STAGEHAND_FSM_EVENT_DO, $event->getTransitionToHistoryMarker()); if (Stagehand_FSM_Error::hasErrors()) { $return = null; return $return; } } return $this->_currentState; }
/** * Enables the last callback. * * @since Method available since Release 1.10.0 */ function enableCallback() { Stagehand_FSM_Error::popCallback(); }