1: <?php
2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27:
28:
29: namespace Mothership\StateMachine;
30:
31:
32: use Mothership\StateMachine\StatusInterface;
33: use Mothership\Exception\StateMachine\StatusException;
34: use Mothership\StateMachine\TransitionInterface;
35: use Mothership\StateMachine\WorkflowInterface;
36: use Mothership\StateMachine\Transition;
37:
38: class Status implements StatusInterface
39: {
40:
41: 42: 43:
44: protected $properties;
45: protected $types = ['initial', 'normal', 'final'];
46: private $workflow;
47: protected $internalState;
48:
49: protected $transitions = array();
50:
51:
52: public function __construct(WorkflowInterface $workflow, array $properties = [])
53: {
54: $this->workflow = $workflow;
55: $this->properties = $properties;
56: $this->transitions = $this->getTransitions();
57: }
58:
59: 60: 61: 62:
63: public function getName()
64: {
65: if (!$this->has('name')) {
66: throw new StatusException("Status without a name", 100, null,
67: $this->getWorkflow()->getOutput());
68: }
69: return $this->properties['name'];
70: }
71:
72: 73: 74: 75:
76: public function getType()
77: {
78: if (!$this->has('type')) {
79: throw new StatusException("Status without a type", 100, null,
80: $this->getWorkflow()->getOutput());
81: }
82: if (!in_array($this->properties['type'], $this->types)) {
83: throw new StatusException("The type specified is invalid", 100, null,
84: $this->getWorkflow()->getOutput());
85: }
86: return $this->properties['type'];
87: }
88:
89: 90: 91: 92: 93:
94: protected function isInitialType()
95: {
96: return $this->getType() == 'initial';
97: }
98:
99: 100: 101: 102: 103:
104: public function getTransitions()
105: {
106: if (count($this->transitions) == 0 && !$this->isInitialType()) {
107: if (!$this->has('transitions_to')) {
108: throw new StatusException("Status " . $this->getName() . " without transitions_to property", 80, null,
109: $this->getWorkflow()->getOutput());
110: }
111: if (!$this->has('transitions_from')) {
112: throw new StatusException("Status " . $this->getName() . " without transitions_from property", 81, null,
113: $this->getWorkflow()->getOutput());
114: }
115:
116: foreach ($this->properties['transitions_from'] as $transition) {
117: array_push($this->transitions, new Transition($this, $transition));
118: }
119:
120: if (count($this->transitions) == 0) {
121: throw new StatusException("Status " . $this->getName() . " has transition_from property not maching the name",
122: 85, null,
123: $this->getWorkflow()->getOutput());
124: }
125: } else if ($this->isInitialType()) {
126: $this->transitions = [];
127: }
128: return $this->transitions;
129: }
130:
131: 132: 133: 134: 135: 136: 137:
138: public function execute($transition_name, StatusInterface $current_status)
139: {
140: foreach ($this->transitions as $t) {
141: if ($t->hasCondition()) {
142: if ($t->getTransitionFrom() == $current_status->getName() && $t->getName() == $transition_name &&
143: $this->workflow->getStatus($current_status->getName())->getInternalStatus() == $t->getCondition()
144: ) {
145: return $t->process();
146: } else if ($this->workflow->getStatus($current_status->getName())->getInternalStatus() != $t->getCondition()) {
147: throw new StatusException("STATUS: [" . $transition_name . "] cant't run from [" . $current_status->getName()
148: . "] for a different internalState of [" . $current_status->getName() . " => current internal
149: State: "
150: . $this->workflow->getStatus($current_status->getName())->getInternalStatus() . ", Status
151: need: " . $t->getCondition() . " ]",
152: 10,
153: null,
154: $this->getWorkflow()->getOutput());
155: }
156: } else {
157: if ($t->getTransitionFrom() == $current_status->getName() && $t->getName() == $transition_name) {
158: return $t->process();
159: }
160: }
161: }
162: throw new StatusException("STATUS: [" . $transition_name . "] can't run from [" . $current_status->getName() . "]", 30,
163: null,
164: $this->getWorkflow()->getOutput());
165: }
166:
167: 168: 169: 170: 171:
172: public function has($property)
173: {
174: return array_key_exists($property, $this->properties);
175: }
176:
177: 178: 179: 180: 181:
182: public function get($property)
183: {
184: if (!$this->has($property)) {
185: throw new StatusException("Status without a property: " . $property, 90, null,
186: $this->getWorkflow()->getOutput());
187: }
188: return $this->properties[$property];
189: }
190:
191: 192: 193: 194: 195:
196: public function getProperties()
197: {
198: return $this->getProperties();
199: }
200:
201: 202: 203:
204: public function getWorkflow()
205: {
206: return $this->workflow;
207: }
208:
209: 210: 211: 212: 213:
214: public function setInternalStatus($state)
215: {
216: $this->internalState = $state;
217: }
218:
219: 220: 221: 222:
223: public function getInternalStatus()
224: {
225: return $this->internalState;
226: }
227:
228: public function hasInternalState()
229: {
230: if (!isset($this->internalState) || !isnull($this->internalState)) {
231: return true;
232: }
233: return false;
234: }
235: }
236: