StateMachineFactory   A
last analyzed

Complexity

Total Complexity 8

Size/Duplication

Total Lines 127
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 4

Importance

Changes 0
Metric Value
wmc 8
lcom 1
cbo 4
dl 0
loc 127
rs 10
c 0
b 0
f 0

2 Methods

Rating   Name   Duplication   Size   Complexity  
B forDNDeployment() 0 90 2
B addHandlers() 0 28 6
1
<?php
2
3
use Finite\State\StateInterface;
4
5
class StateMachineFactory extends Object {
0 ignored issues
show
Coding Style Compatibility introduced by
PSR1 recommends that each class must be in a namespace of at least one level to avoid collisions.

You can fix this by adding a namespace to your class:

namespace YourVendor;

class YourClass { }

When choosing a vendor namespace, try to pick something that is not too generic to avoid conflicts with other libraries.

Loading history...
6
7
	private static $handlers = [];
0 ignored issues
show
Unused Code introduced by
The property $handlers is not used and could be removed.

This check marks private properties in classes that are never used. Those properties can be removed.

Loading history...
8
9
	private static $initialised = [];
10
11
	public function forDNDeployment(\DNDeployment $obj) {
12
		$loader = new Finite\Loader\ArrayLoader([
13
			'class'   => 'DNDeployment',
14
			'states'  => [
15
				DNDeployment::STATE_NEW => ['type' => StateInterface::TYPE_INITIAL],
16
				DNDeployment::STATE_SUBMITTED => ['type' => StateInterface::TYPE_NORMAL],
17
				DNDeployment::STATE_INVALID => ['type' => StateInterface::TYPE_NORMAL],
18
				DNDeployment::STATE_APPROVED => ['type' => StateInterface::TYPE_NORMAL],
19
				DNDeployment::STATE_REJECTED => ['type' => StateInterface::TYPE_NORMAL],
20
				DNDeployment::STATE_QUEUED => ['type' => StateInterface::TYPE_NORMAL],
21
				DNDeployment::STATE_DEPLOYING => ['type' => StateInterface::TYPE_NORMAL],
22
				DNDeployment::STATE_ABORTING => ['type' => StateInterface::TYPE_NORMAL],
23
				DNDeployment::STATE_COMPLETED => ['type' => StateInterface::TYPE_FINAL],
24
				DNDeployment::STATE_FAILED => ['type' => StateInterface::TYPE_FINAL],
25
				DNDeployment::STATE_DELETED => ['type' => StateInterface::TYPE_FINAL],
26
			],
27
			'transitions' => [
28
				DNDeployment::TR_NEW => ['from' => [DNDeployment::STATE_SUBMITTED], 'to' => DNDeployment::STATE_NEW],
29
				DNDeployment::TR_SUBMIT => ['from' => [DNDeployment::STATE_NEW], 'to' => DNDeployment::STATE_SUBMITTED],
30
				DNDeployment::TR_QUEUE => [
31
					'from' => [
32
						DNDeployment::STATE_NEW, // @deprecated. Remove this when DNRoot::startDeploy() is removed.
33
						DNDeployment::STATE_APPROVED
34
					],
35
					'to' => DNDeployment::STATE_QUEUED
36
				],
37
				DNDeployment::TR_INVALIDATE  => [
38
					'from' => [
39
						DNDeployment::STATE_NEW,
40
						DNDeployment::STATE_SUBMITTED,
41
						DNDeployment::STATE_APPROVED,
42
						DNDeployment::STATE_REJECTED
43
					],
44
					'to' => DNDeployment::STATE_INVALID
45
				],
46
				DNDeployment::TR_APPROVE => ['from' => [
47
						DNDeployment::STATE_NEW,
48
						DNDeployment::STATE_SUBMITTED
49
					],
50
					'to' => DNDeployment::STATE_APPROVED
51
				],
52
				DNDeployment::TR_REJECT => ['from' => [DNDeployment::STATE_SUBMITTED], 'to' => DNDeployment::STATE_REJECTED],
53
				DNDeployment::TR_DEPLOY => ['from' => [DNDeployment::STATE_QUEUED], 'to' => DNDeployment::STATE_DEPLOYING],
54
				DNDeployment::TR_ABORT => [
55
					'from' => [
56
						DNDeployment::STATE_QUEUED,
57
						DNDeployment::STATE_DEPLOYING,
58
						DNDeployment::STATE_ABORTING
59
					],
60
					'to' => DNDeployment::STATE_ABORTING
61
				],
62
				DNDeployment::TR_COMPLETE => ['from' => [DNDeployment::STATE_DEPLOYING], 'to' => DNDeployment::STATE_COMPLETED],
63
				DNDeployment::TR_FAIL  => [
64
					'from' => [
65
						DNDeployment::STATE_NEW,
66
						DNDeployment::STATE_SUBMITTED,
67
						DNDeployment::STATE_INVALID,
68
						DNDeployment::STATE_REJECTED,
69
						DNDeployment::STATE_APPROVED,
70
						DNDeployment::STATE_QUEUED,
71
						DNDeployment::STATE_DEPLOYING,
72
						DNDeployment::STATE_ABORTING
73
					],
74
					'to' => DNDeployment::STATE_FAILED
75
				],
76
				DNDeployment::TR_DELETE  => [
77
					'from' => [
78
						DNDeployment::STATE_NEW,
79
						DNDeployment::STATE_SUBMITTED,
80
						DNDeployment::STATE_INVALID,
81
						DNDeployment::STATE_APPROVED,
82
						DNDeployment::STATE_REJECTED,
83
					],
84
					'to' => DNDeployment::STATE_DELETED
85
				],
86
			]
87
		]);
88
		$stateMachine = Injector::inst()->get('Finite\StateMachine\StateMachine', true, [$obj]);
89
90
		// if we have already initialised a state machine for the given \DNDeployment
91
		// then don't re-initialise it again, as this causes bugs with transition events
92
		// being called multiple times.
93
		if (empty(self::$initialised[$obj->ID])) {
94
			$loader->load($stateMachine);
95
			$stateMachine->initialize();
96
			$this->addHandlers($stateMachine);
97
			self::$initialised[$obj->ID] = true;
98
		}
99
		return $stateMachine;
100
	}
101
102
	protected function addHandlers($machine) {
103
		$class = get_class($machine->getObject());
104
		if (empty($this->config()->handlers[$class])) return;
105
106
		// this is the "internal" state listener that logs all state transitions
107
		$machine->getDispatcher()->addListener(
108
			'finite.post_transition',
109
			[Injector::inst()->get('DNDeploymentHandlers'), 'onAfterTransition']
110
		);
111
112
		$transitions = $this->config()->handlers[$class];
113
		foreach ($transitions as $transName => $handlers) {
114
			if (!is_array($handlers)) {
115
				throw new Exception(sprintf('Transition %s must be configured as an assoc array.', $transName));
116
			}
117
118
			foreach ($handlers as $handlerClass => $handlerMethod) {
119
				$handlerObj = Injector::inst()->get($handlerClass);
120
				if (!is_callable([$handlerObj, $handlerMethod])) {
121
					throw new Exception(sprintf('Handler %s is not callable on %s.', $handlerMethod, $handlerClass));
122
				}
123
				$machine->getDispatcher()->addListener(
124
					sprintf('finite.post_transition.%s', $transName),
125
					[$handlerObj, $handlerMethod]
126
				);
127
			}
128
		}
129
	}
130
131
}
132