Browse Source

Added new post-event action feature based on the work done on 14/04/07-15/04/07
- introduced fsm_result class
- apply_event now returns an fsm_result
- apply_simple_event replaces apply_event for 1.1-like events

Frederic G. Marand 17 years ago
parent
commit
bb76ef1a2e
1 changed files with 62 additions and 9 deletions
  1. 62 9
      u_fsm.php

+ 62 - 9
u_fsm.php

@@ -5,10 +5,43 @@
  * (c) 2006 Ouest Systèmes Informatiques (OSI)
  * Licensed under the CeCILL 2.0 license
  *
- * $Id: u_fsm.php,v 1.1 2006-12-03 23:20:08 marand Exp $
+ * $Id: u_fsm.php,v 1.2 2007-04-28 20:02:50 marand Exp $
  */
 require_once('misc.php'); // for func_name()
 
+/**
+ * This class defines a possible outcome for a given FSM transition
+ *
+ */
+class fsm_result
+  {
+  /**
+   * The name of the state to which the FSM must change. If NULL, do not change
+   * the current state.
+   *
+   * @var string
+   */
+  public $fsm_state;
+
+  /**
+   * The name of an event to be fired after the state change has been applied
+   *
+   * @var string
+   */
+  public $fsm_action;
+
+  /**
+   * @param string $state
+   * @param string $action
+   * @return void
+   */
+  public function __construct($state = NULL, $action = NULL)
+    {
+    $this->fsm_state = $state;
+    $this->fsm_action = $action;
+    }
+  }
+
 abstract class fsm
   {
   /**
@@ -22,7 +55,7 @@ abstract class fsm
    * state1
    *   event1
    *     result1
-   *     action1
+   *     state_name|fsm_result
    *   event2
    *     ...
    *   ..
@@ -133,7 +166,7 @@ abstract class fsm
     }
 
   /**
-   * apply an event
+   * apply an event, and the resulting event chain if needed
    *
    * @param string $event_name
    * @param array $params the
@@ -143,6 +176,25 @@ abstract class fsm
     {
     //echo func_name() . "\n";
 
+    do {
+      $result = $this->apply_simple_event($event_name);
+      $event_name = $result->fsm_action; // can be NULL
+      } while($event_name);
+
+    return $result;
+    }
+
+  /**
+   * Helper for apply_event that does not implement the post-transition action
+   *
+   * @param string $event_name
+   * @return fsm_result
+   * @see apply_event()
+   */
+  private function apply_simple_event($event_name)
+    {
+    //echo func_name() . "\n";
+
     if (! $this->is_event_allowed($event_name))
       throw new Exception(func_name()
         . ":  Event \"$event_name\" not accepted in current state \"$this->f_state\"");
@@ -151,17 +203,18 @@ abstract class fsm
     $outcomes = $this->get_accepted_outcomes($event_name);
 
     $result = $this->$method_name();
-
-    if (!in_array($result, $outcomes))
+    if (!is_object($result))
+      {
+      $result = new fsm_result($result, NULL);
+      }
+    if (!in_array($result->fsm_state, $outcomes))
       throw new Exception(func_name()
         . ": event guard. Transition on \"$event_name\" return invalid result: "
         . var_dump($result)
         . "\n");
 
-    $this->f_state = $this->f_transitions[$this->f_state][$event_name][$result];
-    // echo "new state: $this->f_state\n";
-
+    $this->f_state = $this->f_transitions[$this->f_state][$event_name][$result->fsm_state];
+    // echo func_name() . ", new state: $this->f_state, action: $result->fsm_action\n";
     return $result;
     }
-
   }