SimpleStateMachine - A very simple State Machine
, (*1)
- A Simple State Machine without timeouts.
- States can modify a Data object which will be injected in the initial State.
- The State Machine graph can be visualised in a UML diagram generated in different formats.
Table of Contents
Installation
Simple State Machine is installable via Composer
as cosma/simple-state-machine., (*2)
{
"require": {
"cosma/simple-state-machine": "1.0.*"
}
}
Usage
Let's follow the example of a simple price calculator state machine., (*3)
namespace \MyProject;
/**
* Simple State Machine
*/
$priceStateMachine = \Cosma\SimpleStateMachine\StateMachine('Price Calculator State Machine');
/**
* Your Data object which can be modify by the State Machines
* Has to implement the interface \Cosma\SimpleStateMachine\InterfaceData
*/
$price = new \YourProject\Price();
/**
* Start State of the State Machine
* Has to extends the abstract \Cosma\SimpleStateMachine\AbstractState
*/
$initialPriceState = \YourProject\PriceStateMachine\States\InitialPrice($price);
/**
* Simple State Machine cannot run without setting the start State
*/
$priceStateMachine->setState($initialPriceState);
/**
* Running the State Machine
* During this process the Data object will be modified depending on teh configuration of the Machine
*/
$priceStateMachine->run();
/**
* Retrieve the Data object at the end of the process
*/
$finalPrice = $priceStateMachine->getState()->getData();
/**
* Generate the Diagram of the State Machine.
* Choose the format
*/
$graphic = new Graphic('svg');
$diagramSVG = $priceStateMachine->draw($graphic);
echo $diagramSVG;
Reference
Defining Data Object
The Data object can be modify by the State Machines transitions and State., (*4)
The Data class must implement the interface \Cosma\SimpleStateMachine\InterfaceData., (*5)
InterfaceData is a empty interface but is used to force Type hinting., (*6)
namespace \MyProject\PriceStateMachine;
class Price implements \Cosma\SimpleStateMachine\InterfaceData
{
/**
* @var float
*/
private $value;
public function __constructor()
{
$this->value = $this->getPriceFromDB();
}
/**
* getters, setters and other functions
*/
...
}
Defining States
All states must extend the class \Cosma\SimpleStateMachine\AbstractState, (*7)
namespace \MyProject\PriceStateMachine\States;
class AddVATState extends \Cosma\SimpleStateMachine\AbstractState
{
/**
* Set the label for this State used in State Machine diagram
*/
public function getLabel()
{
return 'Add VAT Tax';
}
/**
* Modify the Data object
*/
protected function process()
{
$price = $this->getData();
$price->setValue($price->getValue() * 1.19);
...
}
/**
* Configure the Transitions from this State to another States or itself in case of a loop
* You may set in what Condition that Transition takes place
* The order to check upon the validity of conditions and forward to next State is from up to down
*/
protected function configureAvailableTransitions()
{
$this->addTransition(
'\YourProject\PriceStateMachine\States\AddDiscount',
'\YourProject\PriceStateMachine\Conditions\IfGreaterThan1000'
);
$this->addTransition('NewStateClass', 'ConditionClass');
$this->addTransition('\YourProject\PriceStateMachine\States\AddDiscount');
...
}
}
Defining Conditions
A Transition between states is possible directly when there is no condition or,
if there is a condition, only when that condition is true., (*8)
All Conditions must extend \Cosma\SimpleStateMachine\AbstractCondition class, (*9)
namespace namespace \MyProject\PriceStateMachine\Conditions;
class SomeWildCondition extends \Cosma\SimpleStateMachine\AbstractCondition
{
/**
* @return string
*/
public function getLabel()
{
return "Some Wild Condition";
}
/**
* @return bool
*/
public function isTrue()
{
$data = $this->getData();
return $this->checkSomething($data);
}
...
}
Graph Diagram
You can easily visualise the State Machine Diagram, (*10)
namespace \MyProject;
/**
* Generate the Diagram of the State Machine.
* Choose the format
*/
$graphic = new Graphic('svg');
$diagramSVG = $priceStateMachine->draw($graphic);
echo $diagramSVG;
The output is delivered in various formats., (*11)
The most used export formats are:
- PNG
- PDF
- SVG
- DOT
- EPS
- TIFF
- JPG (low quality)
- GIF (low quality)
- BMP (low quality), (*12)
All supported formats are the DOT output formats: bmp, canon, cgimage, cmap, cmapx, cmapx_np, dot, eps, exr, fig, gif, gv, icns,
ico, imap, imap_np, ismap, jp2, jpe, jpeg, jpg, pct, pdf, pic, pict, plain, plain-ext, png, pov, ps, ps2, psd, sgi, svg, svgz,
tga, tif, tiff, tk, vml, vmlz, x11, xdot, xdot1.2, xdot1.4, xlib, (*13)
DOT Language
Stands for graph description language and you can read more here, (*14)
To take fully advantage of style attributes you need to know DOT language., (*15)
When defining a Condition or a State, you can easily modify the protected $styleAttributes property
and overwrite the default style for a State or a Condition., (*16)
By this you can manipulate the color, font and shape of States and Conditions, (*17)
namespace \MyProject\PriceStateMachine\States;
class MyState extends \Cosma\SimpleStateMachine\AbstractState
{
...
/**
* An array of DOT attributes to overwrite the default style of a State/Condition
*/
protected $styleAttributes = array(
'fillcolor' => '#A8CE9F',
'style' => 'filled',
'fontcolor' => '#000000',
'fontsize' => 12,
'penwidth' => 1,
);
...
}
DOT Useful Links:, (*18)
-
Drawing graphs with DOT - download a pdf, (*19)
-
Node Shapes - shapes of a node, (*20)
Tests
vendor/phpunit/phpunit/phpunit --coverage-text --coverage-html=tests/coverage tests
License
Released under the MIT License, see LICENSE., (*21)