2424 *
2525 * @package eftec\statemachineone
2626 * @author Jorge Patricio Castro Castillo <jcastro arroba eftec dot cl>
27- * @version 2.24 2024-07-18
27+ * @version 2.25 2024-07-19
2828 * @license LGPL-3.0 (you could use in a comercial-close-source product but any change to this library must be shared)
2929 * @link https://github.com/EFTEC/StateMachineOne
3030 */
3131class StateMachineOne
3232{
33- public const VERSION = '2.24 ' ;
33+ public const VERSION = '2.25 ' ;
3434 /** @var int NODB constants indicate that NO DB would be used */
3535 public const NODB = 0 ;
3636 /** @var int PDODB constants indicate that PdoOne database would be used */
3737 public const PDODB = 1 ;
3838 /** @var int PDODB constants indicate that DocumentStoreOne database would be used */
3939 public const DOCDB = 2 ;
40-
4140 /**
4241 * @var array Possible states. It must be an associative array.<br>
4342 * <p>$statemachine->states=['State1'=>'name of the state','State2'=>'another name'];</p>
@@ -54,7 +53,7 @@ class StateMachineOne
5453 /** @var string The name of the table to store the jobs */
5554 public string $ tableJobs = 'stm_jobs ' ;
5655 /** @var string The name of the table to store the logs per job. If it's empty then it is not used */
57- public string $ tableJobLogs = '' ;
56+ public string $ tableJobLogs = 'stm_logs ' ;
5857 /** @var array The list of database columns used by the job */
5958 public array $ columnJobs = ['idjob ' , 'idparentjob ' , 'idactive ' , 'idstate ' , 'dateinit ' , 'datelastchange '
6059 , 'dateexpired ' , 'dateend ' ];
@@ -83,7 +82,7 @@ class StateMachineOne
8382 /** @var MiniLang */
8483 public $ miniLang ;
8584 /** @var null|object It is the service class (optional) */
86- public ?object $ serviceObject= null ;
85+ public ?object $ serviceObject = null ;
8786 /** @var string =['after','before','instead'][$i] */
8887 public string $ pauseTriggerWhen ; // none
8988 /** @var callable|null It is used to replace the current method used to store the logs */
@@ -111,7 +110,7 @@ class StateMachineOne
111110 private string $ dbSchema = '' ;
112111 // callbacks
113112 /** @var PdoOne|null */
114- private ?PdoOne $ pdoOne= null ;
113+ private ?PdoOne $ pdoOne = null ;
115114 /** @var DocumentStoreOne */
116115 private DocumentStoreOne $ docOne ;
117116 /** @var callable it's called when we change state (by default it returns true) */
@@ -131,6 +130,10 @@ class StateMachineOne
131130 /** @var callable This function increased in 1 the next id of the job. It is only called if we are not using a database */
132131 private $ getNumberTrigger ;
133132 public string $ zeroDate = '1970-01-01 00:00:01 ' ;
133+ /**
134+ * @var callable|null
135+ */
136+ private $ timeFunction ;
134137
135138 /**
136139 * Constructor of the class. By default, the construct set default triggers.
@@ -921,9 +924,13 @@ public function addLog(Job $job, string $type, string $subtype, string $descript
921924 }
922925
923926 /**
924- * It returns the current timestamp. If exists a universal timer function (a global function called universaltime),
925- * then it is uses. Why? It is because sometimes we want the same time across different services.
926- *
927+ * It returns the current timestamp using the microtime function. It is used internally.<br>
928+ * If exists a universal timer function (a global function called universaltime),then it is uses.<br>
929+ * If setTime() is set, then it uses the value set there.<br>
930+ * **Example**
931+ * ```
932+ * $time=$this->getTime();
933+ * ```
927934 * @param bool $microtime if true then it returns the microtime as float
928935 *
929936 * @return int|float
@@ -933,9 +940,40 @@ public function getTime(bool $microtime = false)
933940 if (function_exists ('universaltime ' )) {
934941 return universaltime ($ microtime );
935942 }
943+ if ($ this ->timeFunction !== null ) {
944+ $ fn = $ this ->timeFunction ;
945+ return $ fn ($ microtime );
946+ }
936947 return $ microtime ? microtime (true ) : time ();
937948 }
938949
950+ /**
951+ * It sets the way to determine the current time (timestamp). If it is not set, then it uses microtime()<br>
952+ * **Example**<br>
953+ * ```
954+ * $this->setTime(10); // GMT: Thursday, 1 January 1970 0:00:10
955+ * $this->setTime(new DateTime("2024-01-01 11:12:14"));
956+ * $this->setTime(function($microtime=false) { return microtime($microtime); });
957+ * ```
958+ * @param callable|DateTime|numeric|null $newTime if callable, then it uses a funcion to determine the current time
959+ * if DateTime, then it is converted to timestamp
960+ * If int, then it is used as the current timestamp
961+ * @return void
962+ */
963+ public function setTime ($ newTime ): void
964+ {
965+ if (is_callable ($ newTime )) {
966+ $ this ->timeFunction = $ newTime ;
967+ } else {
968+ if ($ newTime instanceof DateTime) {
969+ $ newTime = $ newTime ->getTimestamp ();
970+ }
971+ $ this ->timeFunction = static function ($ arg = null ) use ($ newTime ) {
972+ return $ newTime ;
973+ };
974+ }
975+ }
976+
939977 /**
940978 * @param mixed $time timestamp with microseconds. If "now", then it returns the current time.
941979 *
@@ -1412,9 +1450,9 @@ public function callEvent($name, ?Job $job = null): void
14121450 return ;
14131451 }
14141452 $ this ->events [$ name ]->setDict ($ jobExec ->fields );
1415- $ this ->events [$ name ]->setDictEntry ('_idjob ' , $ job ->idJob );
1453+ $ this ->events [$ name ]->setDictEntry ('_idjob ' , $ job !== null ? $ job ->idJob : null );
14161454 $ this ->events [$ name ]->setDictEntry ('_time ' , $ this ->getTime ());
1417- $ this ->events [$ name ]->setDictEntry ('_state0 ' , $ job ->state );
1455+ $ this ->events [$ name ]->setDictEntry ('_state0 ' , $ job !== null ? $ job ->state : null );
14181456 $ this ->events [$ name ]->evalSet ();
14191457 $ this ->checkJob ($ jobExec );
14201458 if ($ this ->dbActive != self ::NODB ) {
0 commit comments