Passed
Push — master ( 512e38...6090ed )
by Runner
01:34
created

Blueprint::getDispatcher()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 1
nc 1
nop 0
dl 0
loc 3
rs 10
c 0
b 0
f 0
1
<?php
2
/**
3
 * @author: RunnerLee
4
 * @email: [email protected]
5
 * @time: 2018-02
6
 */
7
8
namespace Runner\Heshen;
9
10
use Closure;
11
use Runner\Heshen\Event\Event;
12
use Runner\Heshen\Exceptions\LogicException;
13
use Runner\Heshen\Exceptions\StateNotFoundException;
14
use Runner\Heshen\Exceptions\TransitionNotFoundException;
15
use Runner\Heshen\Support\StateEvents;
16
use Runner\Heshen\Support\Str;
17
use Symfony\Component\EventDispatcher\EventDispatcher;
18
19
class Blueprint
20
{
21
    /**
22
     * @var State[]
23
     */
24
    protected $states = [];
25
26
    /**
27
     * @var Transition[]
28
     */
29
    protected $transitions = [];
30
31
    /**
32
     * @var EventDispatcher
33
     */
34
    protected $dispatcher;
35
36
    /**
37
     * Blueprint constructor.
38
     */
39
    public function __construct()
40
    {
41
        $this->dispatcher = new EventDispatcher();
42
43
        $this->configure();
44
    }
45
46
    /**
47
     * @param $name
48
     *
49
     * @return Transition
50
     */
51
    public function getTransition(string $name): Transition
52
    {
53
        if (array_key_exists($name, $this->transitions)) {
54
            return $this->transitions[$name];
55
        }
56
57
        throw new TransitionNotFoundException($name);
58
    }
59
60
    /**
61
     * @param $name
62
     *
63
     * @return State
64
     */
65
    public function getState(string $name): State
66
    {
67
        if (array_key_exists($name, $this->states)) {
68
            return $this->states[$name];
69
        }
70
71
        throw new StateNotFoundException($name);
72
    }
73
74
    /**
75
     * @return EventDispatcher
76
     */
77
    public function getDispatcher(): EventDispatcher
78
    {
79
        return $this->dispatcher;
80
    }
81
82
    /**
83
     * @param string $name
84
     * @param string $type
85
     *
86
     * @return Blueprint
87
     */
88
    protected function addState(string $name, string $type): self
89
    {
90
        $this->states[$name] = new State($name, $type);
91
92
        return $this;
93
    }
94
95
    /**
96
     * @param string       $name
97
     * @param string|array $from
98
     * @param string       $to
99
     * @param null         $checker
0 ignored issues
show
Documentation Bug introduced by
Are you sure the doc-type for parameter $checker is correct as it would always require null to be passed?
Loading history...
100
     *
101
     * @return $this
102
     */
103
    protected function addTransition(string $name, $from, string $to, $checker = null): self
104
    {
105
        $from = (array) $from;
106
        $fromStates = array_map(function ($state) {
107
            return $this->getState($state);
108
        }, $from);
109
        $this->transitions[$name] = new Transition(
110
            $name,
111
            $fromStates,
112
            $this->getState($to),
113
            $checker
114
        );
115
116
        $preMethod = Str::studly("pre{$name}");
117
        $postMethod = Str::studly("post{$name}");
118
119
        if (method_exists($this, $preMethod)) {
120
            $this->dispatcher->addListener(
121
                StateEvents::PRE_TRANSITION.$name,
122
                $this->eventListener($preMethod)
123
            );
124
        }
125
126
        if (method_exists($this, $postMethod)) {
127
            $this->dispatcher->addListener(
128
                StateEvents::POST_TRANSITION.$name,
129
                $this->eventListener($postMethod)
130
            );
131
        }
132
133
        return $this;
134
    }
135
136
    /**
137
     * @param $method
138
     *
139
     * @return Closure
140
     */
141
    protected function eventListener($method): Closure
142
    {
143
        return function (Event $event) use ($method) {
144
            return call_user_func([$this, $method], $event->getStateful(), $event->getParameters());
145
        };
146
    }
147
148
    protected function configure(): void
149
    {
150
        throw new LogicException('you must overwrite the configure method in the concrete blueprint class');
151
    }
152
}
153