| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355 | 
							- <?php
 
- /**
 
-  * Finite state machine writer.
 
-  *
 
-  * Keeping the FSM writer (generation) functions out of the root class minimize
 
-  * the code volume for FSM readers, which should represent the majority of FSM
 
-  * users.
 
-  *
 
-  * @copyright  (c) 2007 OSI
 
-  * @author     Frédéric G. MARAND
 
-  * @license    Licensed under the CeCILL 2.0
 
-  * @version    CVS: $Id: Fsm_Writer.php,v 1.1 2007-06-10 19:42:35 marand Exp $
 
-  * @link       http://wiki.audean.com/fsm/fsm
 
-  * @since      Not applicable yet
 
-  * @package    fsm
 
-  * @subpackage fsm.core
 
-  */
 
- /**
 
-  * needed notably for autoload and func_name()
 
-  */
 
- require_once('misc.php');
 
- $erFiniteStateMachine = error_reporting(E_ALL|E_STRICT);
 
- /**
 
-  * Read/Write concrete FSM class.
 
-  *
 
-  * This (concrete) class extends the default abstract
 
-  * Finite_State_Machine to add write behaviours. It is to be used by
 
-  * applications wishing to write FSM files. Other applications should not
 
-  * use it to avoid code bloat.
 
-  * @package    fsm
 
-  * @subpackage fsm.core
 
-  */
 
- class Fsm_Writer extends Finite_State_Machine
 
-   {
 
-   const VERSION = '$Id: Fsm_Writer.php,v 1.1 2007-06-10 19:42:35 marand Exp $';
 
-   public function __construct()
 
-     {
 
-     $this->f_transitions = array();
 
-     parent::__construct();
 
-     }
 
-   /**
 
-    * Return the initial and final states from an abstract FSM graph
 
-    *
 
-    * @param array $graph Abstract FSM
 
-    * @return array
 
-    */
 
-   protected function getSpecialStates($graph)
 
-     {
 
-     $ret[0] = NULL;
 
-     $ret[1] = NULL;
 
-     foreach ($graph['states'] as $state)
 
-       {
 
-       if (isset($state['type']) && $state['type'] == 'initial')
 
-         {
 
-         $ret[0]  = $state['name'];
 
-         }
 
-       if (isset($state['type']) && $state['type'] == 'final')
 
-         {
 
-         $ret[1]  = $state['name'];
 
-         }
 
-       if (isset($ret[0]) && isset($ret[1]))
 
-         {
 
-         break;
 
-         }
 
-       }
 
-     return $ret;
 
-     }
 
-   /**
 
-    * Return the transitions (triggers) available from a given state
 
-    *
 
-    * @param array $graph Abstract FSM
 
-    * @param string $id State id in the abstract graph (not id in the XML FSM)
 
-    */
 
-   protected function getTransitionsForState($graph, $id)
 
-     {
 
-     $ret = array();
 
-     foreach ($graph['transitions'] as $txid => $transition)
 
-       {
 
-       // echo "id = $id, txid = $txid from = " . $transition['from'] . PHP_EOL;
 
-       if ($transition['from'] == $id)
 
-         {
 
-         $ret[] = $txid;
 
-         }
 
-       }
 
-     return $ret;
 
-     }
 
-   /**
 
-    * Generate the XML FSM file and optionally PHP stubs file from an abstract
 
-    * FSM representation as an array of states and transitions
 
-    *
 
-    * @param array $graph
 
-    * @param string $prefix
 
-    * @param boolean $php
 
-    * @param boolean $overwrite
 
-    * @todo take $overwrite and $php into account
 
-    * @deprecated
 
-    */
 
-   public function old_save_fsm($graph, $prefix = 'fsm', $php = FALSE, $overwrite = FALSE)
 
-     {
 
-     echo "This is a dump for FSM $prefix"
 
-       . ', ' . ($php ? 'with' : 'without') . ' PHP generation'
 
-       . ', ' . ($overwrite ? 'with' : 'without') . ' overwrite mode'
 
-       . ".\n";
 
-     $doc = new DOMDocument('1.0', 'utf-8');
 
-     $comment = new DOMComment(' Generated by '
 
-       . basename(__FILE__, '.php')
 
-       . " version " . Fsm_Writer::VERSION
 
-       . " ");
 
-     $doc->appendChild($comment);
 
-     $fsm = new DOMElement('fsm');
 
-     $doc->appendChild($fsm);
 
-     $fsm->setAttribute('fsm_version',   "1.3");
 
-     $fsm->setAttribute('idle_work',     "1");
 
-     $fsm->setAttribute('allow_actions', "1");
 
-     list($init, $final) = $this->getSpecialStates($graph);
 
-     $fsm->setAttribute('init', $init);
 
-     $fsm->setAttribute('final', $final);
 
-     foreach ($graph['states'] as $id => $state)
 
-       {
 
-       $state_node = new DOMElement('state');
 
-       $fsm->appendChild($state_node);
 
-       $state_node->setAttribute('id', $state['name']); // setIdAttribute not yet implemented in php 5.1
 
-       $transitions = $this->getTransitionsForState($graph, $id);
 
-       /**
 
-        * FGM on ne peut pas simplement boucler ainsi: on a dans le graphe
 
-        * abstrait une transition par évènement, alors que dans la FSM les
 
-        * transitions partant du même état sont groupées. En se contentant
 
-        * de boucler ainsi, on crée un "event" pour chaque transition alors
 
-        * qu'il faut créer 1 event et "n" next.
 
-        */
 
-       foreach ($transitions as $transition_id)
 
-         {
 
-         $event_node = new DOMElement('event');
 
-         $state_node->appendChild($event_node);
 
-         $transition = $graph['transitions'][$transition_id];
 
-         $event_node->setAttribute('name', $transition['trigger']);
 
-         /**
 
-          * @todo support other event types
 
-          */
 
-         $event_node->setAttribute('type', 'string');
 
-         }
 
-       }
 
-     $doc->save("$prefix.xml");
 
-     print_r($graph['transitions']);
 
-     }
 
-   /**
 
-    * Add a new state to the transitions table
 
-    *
 
-    * @param string $name
 
-    * @return integer 0 on success, < 0 on failure
 
-    */
 
-   public function addState($name)
 
-     {
 
-     // echo func_name() . "($name)";
 
-     if (array_key_exists($name, $this->f_transitions))
 
-       {
 
-       $ret = -1;
 
-       }
 
-     else
 
-       {
 
-       $this->f_transitions[$name] = array();
 
-       $ret = 0;
 
-       }
 
-     // echo ", ret = $ret\n";
 
-     return $ret;
 
-     }
 
-   /**
 
-    * Add an event definition (name + optional type of handler) to an existing state
 
-    *
 
-    * @param string $state
 
-    * @param string $event
 
-    * @param string $type
 
-    * @return integer 0 on success, < 0 on failure
 
-    */
 
-   public function addEvent($state, $event, $type = 'string')
 
-     {
 
-     if (!array_key_exists($state, $this->f_transitions))
 
-       {
 
-       $ret = -1;
 
-       }
 
-     elseif (array_key_exists($event, $this->f_transitions[$state]))
 
-       {
 
-       $ret = -2;
 
-       }
 
-     else // state exists, event doesn't: OK
 
-       {
 
-       $this->f_transitions[$state][$event] = array();
 
-       $this->f_transitions[$state][$event]["#type"] = $type;
 
-       $ret = 0;
 
-       }
 
-     return $ret;
 
-     }
 
-   /**
 
-    * Add an outcome definition to an existing event:
 
-    * - event handler result
 
-    * - next state
 
-    * - event to fire after transition to next state
 
-    * All outcome fields are optional
 
-    *
 
-    * @param name $state
 
-    * @param name $event
 
-    * @return integer 0 on success, < 0 on failure
 
-    */
 
-   public function addOutcome($state, $event,
 
-     $result     = NULL,  // if null, single possible outcome; only possible on void events
 
-     $next_state = NULL,  // if null, stay on same state
 
-     $action     = NULL)  // if null, do not send an event after transitioning
 
-     {
 
-     $t = &$this->f_transitions;
 
-     if (!array_key_exists($state, $t))
 
-       {
 
-       $ret = -1;
 
-       }
 
-     elseif (!array_key_exists($event, $t[$state]))
 
-       {
 
-       $ret = -2;
 
-       }
 
-     elseif (($result == NULL) && ($t[$state][$event]['#type'] <> 'void'))
 
-       {
 
-       $ret = -3; // Undefined, single, results are only available for void events
 
-       }
 
-     elseif (($result != NULL) && array_key_exists($result, $t[$state][$event]))
 
-       {
 
-       $ret = -4; // results must be unique per event
 
-       }
 
-     else
 
-       {
 
-       $t[$state][$event][$result] = array($next_state, $action);
 
-       $ret = 0;
 
-       }
 
-     return $ret;
 
-     }
 
-   /**
 
-    * Defines the special states in the FSM
 
-    *
 
-    * @param string $kind Finite_State_Machine::INIT_STATE or ..FINAL_STATE
 
-    * @param string $name
 
-    */
 
-   public function setSpecialState($kind, $name)
 
-     {
 
-     // echo func_name() . "($kind, $name)\n";
 
-     if (($kind != Finite_State_Machine::INIT_STATE) && ($kind != Finite_State_Machine::FINAL_STATE))
 
-       {
 
-       $ret = -1; // unknown special state
 
-       }
 
-     elseif (!array_key_exists($name, $this->f_transitions))
 
-       {
 
-       $ret = -2; // non existent state declared as special
 
-       }
 
-     else
 
-       {
 
-       $this->f_transitions["#$kind"] = $name;
 
-       $ret = 0;
 
-       }
 
-     return $ret;
 
-     }
 
-   /*
 
-    * Generate the XML FSM file and optionally PHP stubs file from a valid
 
-    * instanc of Finite_State_Machine
 
-    *
 
-    * @param string $prefix
 
-    * @param boolean $php
 
-    * @param boolean $overwrite
 
-    * @todo take $overwrite and $php into account
 
-    * @throws Exception from within _check_transitions
 
-    */
 
-   public function save_fsm($prefix = 'fsm', $php = FALSE, $overwrite = FALSE)
 
-     {
 
-     $this->_check_transitions();
 
-     $t = &$this->f_transitions;
 
-     echo "This is a dump for FSM $prefix"
 
-       . ', ' . ($php ? 'with' : 'without') . ' PHP generation'
 
-       . ', ' . ($overwrite ? 'with' : 'without') . ' overwrite mode'
 
-       . ".\n";
 
-     $doc = new DOMDocument('1.0', 'utf-8');
 
-     $comment = new DOMComment(' Generated by '
 
-       . basename(__FILE__, '.php')
 
-       . " version " . Fsm_Writer::VERSION
 
-       . " on FSM version " . Finite_State_Machine::VERSION
 
-       . " ");
 
-     $doc->appendChild($comment);
 
-     $fsm = new DOMElement('fsm');
 
-     $doc->appendChild($fsm);
 
-     $fsm->setAttribute('fsm_version',   "1.3");
 
-     $fsm->setAttribute('idle_work',     "1");
 
-     $fsm->setAttribute('allow_actions', "1");
 
-     $fsm->setAttribute('init',  $t['#' . Finite_State_Machine::INIT_STATE]);
 
-     $fsm->setAttribute('final', $t['#' . Finite_State_Machine::FINAL_STATE]);
 
-     foreach ($this->f_transitions as $state_name => $state)
 
-       {
 
-       if ($state_name[0] == '#')
 
-         {
 
-         continue; // ignore special state definitions
 
-         }
 
-       $state_node = new DOMElement('state', "\n");
 
-       $fsm->appendChild($state_node);
 
-       $state_node->setAttribute('id', $state_name);
 
-       foreach ($state as $event_name => $event)
 
-         {
 
-         $event_node = new DOMElement('event', "\n");
 
-         $state_node->appendChild($event_node);
 
-         $event_node->setAttribute('name', $event_name);
 
-         $event_node->setAttribute('type', $event['#type']);
 
-         foreach ($event as $outcome_name => $outcome)
 
-           {
 
-           if ($outcome_name[0] == '#')
 
-             {
 
-             continue; // ignore special outcome definitions (event type)
 
-             }
 
-           $outcome_node = new DOMElement('next', "\n");
 
-           $event_node->appendChild($outcome_node);
 
-           /**
 
-            * Generated FSMs currently always use the "string" event handler type,
 
-            * meaning they always have outcome results. This will not always be
 
-            * the case, hence this test (think ftp.xml)
 
-            */
 
-           if (!empty($outcome_name))
 
-             {
 
-             $outcome_node->setAttribute('result', $outcome_name);
 
-             }
 
-           if (!empty($outcome[0]))
 
-             {
 
-             $outcome_node->setAttribute('state', $outcome[0]);
 
-             }
 
-           if (!empty($outcome[1]))
 
-             {
 
-             $outcome_node->setAttribute('action', $outcome[1]);
 
-             }
 
-           }
 
-         }
 
-       }
 
-     $doc->save("$prefix.xml");
 
-     }
 
-   }
 
 
  |