/** * Creates a new Piece_Flow_Continuation_Server object and configure it. * * @return Piece_Flow_Continuation_Server * @throws PIECE_UNITY_ERROR_INVALID_CONFIGURATION */ function &_createContinuationServer() { $continuationServer =& new Piece_Flow_Continuation_Server($this->_getConfiguration('enableSingleFlowMode'), $this->_getConfiguration('enableGC'), $this->_getConfiguration('gcExpirationTime')); $continuationServer->setCacheDirectory($this->_getConfiguration('cacheDirectory')); $continuationServer->setEventNameCallback(array(__CLASS__, 'getEventName')); $continuationServer->setFlowExecutionTicketCallback(array(__CLASS__, 'getFlowExecutionTicket')); $continuationServer->setFlowIDCallback(array(__CLASS__, 'getFlowID')); if ($this->_getConfiguration('useFlowMappings')) { $continuationServer->setConfigDirectory($this->_getConfiguration('configDirectory')); $continuationServer->setConfigExtension($this->_getConfiguration('configExtension')); foreach ($this->_getConfiguration('flowMappings') as $flowMapping) { if (array_key_exists('url', $flowMapping)) { $flowMapping['uri'] = $flowMapping['url']; } Piece_Flow_Error::disableCallback(); $continuationServer->addFlow($flowMapping['uri'], $flowMapping['flowName'], $flowMapping['isExclusive']); Piece_Flow_Error::enableCallback(); if (Piece_Flow_Error::hasErrors()) { Piece_Unity_Error::push(PIECE_UNITY_ERROR_INVALID_CONFIGURATION, "Failed to configure the plugin [ {$this->_name}.", 'exception', array(), Piece_Flow_Error::pop()); $return = null; return $return; } } } else { foreach ($this->_getConfiguration('flowDefinitions') as $flowDefinition) { Piece_Flow_Error::disableCallback(); $continuationServer->addFlow($flowDefinition['name'], $flowDefinition['file'], $flowDefinition['isExclusive']); Piece_Flow_Error::enableCallback(); if (Piece_Flow_Error::hasErrors()) { Piece_Unity_Error::push(PIECE_UNITY_ERROR_INVALID_CONFIGURATION, "Failed to configure the plugin [ {$this->_name}.", 'exception', array(), Piece_Flow_Error::pop()); $return = null; return $return; } } } return $continuationServer; }
/** * Configures action states. * * @param array $states * @throws PIECE_FLOW_ERROR_PROTECTED_STATE */ function _configureActionStates($states) { foreach ($states as $key => $state) { if ($this->_fsm->isProtectedState($state['name'])) { Piece_Flow_Error::push(PIECE_FLOW_ERROR_PROTECTED_STATE, "The state [ {$state['name']} ] cannot be used in flow definitions."); return; } $this->_configureState($state); if (Piece_Flow_Error::hasErrors()) { return; } } }
/** * Reads configuration from the given source and creates * a Piece_Flow_Config object. * * @param mixed $source * @param string $driverName * @param string $cacheDirectory * @param string $configDirectory * @param string $configExtension * @return Piece_Flow_Config * @throws PIECE_FLOW_ERROR_NOT_FOUND * @static */ function &read($source, $driverName, $cacheDirectory, $configDirectory, $configExtension) { if (!is_callable($source)) { $flowName = $source; if (!is_null($configDirectory)) { $source = str_replace('_', '/', $source); $source = "{$configDirectory}/{$source}{$configExtension}"; } if (is_null($driverName)) { $driverName = strtoupper(substr(strrchr($source, '.'), 1)); if ($driverName != 'YAML' && $driverName != 'XML') { $driverName = 'YAML'; } } if ($driverName == 'XML') { if (version_compare(phpversion(), '5.0.0', '>=')) { $driverName = 'XML5'; } else { $driverName = 'XML4'; } } } else { $driverName = 'PHPArray'; } $class = "Piece_Flow_ConfigReader_{$driverName}"; if (!Piece_Flow_ClassLoader::loaded($class)) { Piece_Flow_ClassLoader::load($class); if (Piece_Flow_Error::hasErrors()) { $return = null; return $return; } if (!Piece_Flow_ClassLoader::loaded($class)) { Piece_Flow_Error::push(PIECE_FLOW_ERROR_NOT_FOUND, "The class [ {$class} ] not found in the loaded file."); $return = null; return $return; } } $driver =& new $class($source, $cacheDirectory); $config =& $driver->read(); if (Piece_Flow_Error::hasErrors()) { $return = null; return $return; } if (!is_callable($source)) { if (is_null($configDirectory)) { $flowName = basename($source); $positionOfExtension = strrpos($flowName, '.'); if ($positionOfExtension !== false) { $flowName = substr($flowName, 0, $positionOfExtension); } } $config->setName($flowName); } return $config; }
/** * Starts a flow execution. * * @param mixed &$payload * @return string * @throws PIECE_FLOW_ERROR_NOT_FOUND */ function _start(&$payload) { if (!array_key_exists($this->_activeFlowID, $this->_flowDefinitions)) { Piece_Flow_Error::push(PIECE_FLOW_ERROR_NOT_FOUND, "The flow ID [ {$this->_activeFlowID} ] not found in the flow definitions."); return; } $flow =& new Piece_Flow(); $flow->configure($this->_flowDefinitions[$this->_activeFlowID]['source'], null, $this->_cacheDirectory, $this->_actionDirectory, $this->_configDirectory, $this->_configExtension); if (Piece_Flow_Error::hasErrors()) { return; } while (true) { $flowExecutionTicket = $this->_generateFlowExecutionTicket(); if (!$this->_flowExecution->hasFlowExecution($flowExecutionTicket)) { $this->_flowExecution->addFlowExecution($flowExecutionTicket, $flow, $this->_activeFlowID); if ($this->_isExclusive()) { $this->_flowExecution->markFlowExecutionAsExclusive($flowExecutionTicket, $this->_activeFlowID); } break; } } $this->_flowExecution->activateFlowExecution($flowExecutionTicket, $this->_activeFlowID); $this->_activeFlowExecutionTicket = $flowExecutionTicket; $flow->setPayload($payload); $this->_prepareContext(); $flow->start(); if (Piece_Flow_Error::hasErrors()) { return; } return $flowExecutionTicket; }
/** * Starts a flow execution. * * @param mixed &$payload * @return string * @throws PIECE_FLOW_ERROR_NOT_FOUND */ function _start(&$payload) { if (!array_key_exists($this->_currentFlowName, $this->_flowDefinitions)) { Piece_Flow_Error::push(PIECE_FLOW_ERROR_NOT_FOUND, "The flow name [ {$this->_currentFlowName} ] not found in the flow definitions."); return; } $flow =& new Piece_Flow(); $flow->configure($this->_flowDefinitions[$this->_currentFlowName]['file'], null, $this->_cacheDirectory); if (Piece_Flow_Error::hasErrors()) { return; } while (true) { $flowExecutionTicket = $this->_generateFlowExecutionTicket(); if (!$this->_hasFlowExecutionTicket($flowExecutionTicket)) { $this->_flowExecutions[$flowExecutionTicket] =& $flow; break; } } $this->_currentFlowExecutionTicket = $flowExecutionTicket; $this->_activated = true; $flow->setPayload($payload); $flow->start(); if (Piece_Flow_Error::hasErrors()) { return; } if ($this->_isExclusive()) { $this->_exclusiveFlowExecutionTicketsByFlowName[$this->_currentFlowName] = $flowExecutionTicket; $this->_exclusiveFlowNamesByFlowExecutionTicket[$flowExecutionTicket] = $this->_currentFlowName; } return $flowExecutionTicket; }
/** * Loads an action class corresponding to the given class name. * * @param string $class * @throws PIECE_FLOW_ERROR_NOT_GIVEN * @throws PIECE_FLOW_ERROR_NOT_FOUND */ function load($class) { if (!Piece_Flow_ClassLoader::loaded($class)) { if (is_null($GLOBALS['PIECE_FLOW_Action_Directory'])) { Piece_Flow_Error::push(PIECE_FLOW_ERROR_NOT_GIVEN, 'The action directory is not given.'); return; } Piece_Flow_ClassLoader::load($class, $GLOBALS['PIECE_FLOW_Action_Directory']); if (Piece_Flow_Error::hasErrors()) { return; } if (!Piece_Flow_ClassLoader::loaded($class)) { Piece_Flow_Error::push(PIECE_FLOW_ERROR_NOT_FOUND, "The class [ {$class} ] not found in the loaded file."); } } }
/** * Builds a FSM with the given configuration. * * @param mixed $source * @param string $driverName * @param string $cacheDirectory * @param string $actionDirectory * @param string $configDirectory * @param string $configExtension */ function configure($source, $driverName = null, $cacheDirectory = null, $actionDirectory = null, $configDirectory = null, $configExtension = null) { $config =& Piece_Flow_ConfigReader::read($source, $driverName, $cacheDirectory, $configDirectory, $configExtension); if (Piece_Flow_Error::hasErrors()) { return; } $this->_name = $config->getName(); $fsmBuilder =& new Piece_Flow_FSMBuilder($this, $actionDirectory); $fsm =& $fsmBuilder->build($config); if (Piece_Flow_Error::hasErrors()) { return; } $this->_fsm =& $fsm; $lastState = $config->getLastState(); if (!is_null($lastState)) { $this->_lastState = $lastState; } foreach ($config->getViewStates() as $key => $state) { $this->_views[$state['name']] = $state['view']; } $this->_actionDirectory = $actionDirectory; }
/** * Invokes an event handler in an action. * * @param string $eventName * @param mixed &$payload * @return string * @throws PIECE_FLOW_ERROR_NOT_FOUND */ function _invokeEventHandler($eventName, &$payload) { if (!is_null($this->_actionDirectory)) { Piece_Flow_Action_Factory::setActionDirectory($this->_actionDirectory); } $action =& Piece_Flow_Action_Factory::factory($this->_class); if (Piece_Flow_Error::hasErrors()) { return; } if (!method_exists($action, $this->_method)) { Piece_Flow_Error::push(PIECE_FLOW_ERROR_NOT_FOUND, "The method [ {$this->_method} ] does not exist in the action class [ {$this->_class} ]."); return; } if (method_exists($action, 'setFlow')) { $action->setFlow($this->_flow); } if (method_exists($action, 'setPayload')) { $action->setPayload($payload); } if (method_exists($action, 'setEvent')) { $action->setEvent($eventName); } if (method_exists($action, 'prepare')) { $action->prepare(); } $result = call_user_func(array(&$action, $this->_method)); if (method_exists($action, 'clear')) { $action->clear(); } return $result; }
/** * Parses the given source and returns a Piece_Flow_Config object. * * @return Piece_Flow_Config * @since Method available since Release 1.11.0 */ function &_createConfigurationFromSource() { $flow = $this->_parseSource(); if (Piece_Flow_Error::hasErrors()) { $return = null; return $return; } $this->_config =& new Piece_Flow_Config(); $this->_configureFirstState(@$flow['firstState']); if (Piece_Flow_Error::hasErrors()) { $return = null; return $return; } $this->_configureLastState(@$flow['lastState']); if (Piece_Flow_Error::hasErrors()) { $return = null; return $return; } $this->_configureViewStates(@$flow['viewState']); if (Piece_Flow_Error::hasErrors()) { $return = null; return $return; } $this->_configureActionStates(@$flow['actionState']); if (Piece_Flow_Error::hasErrors()) { $return = null; return $return; } $this->_configureInitialAction(@$flow['initial']); if (Piece_Flow_Error::hasErrors()) { $return = null; return $return; } $this->_configureFinalAction(@$flow['final']); if (Piece_Flow_Error::hasErrors()) { $return = null; return $return; } return $this->_config; }