Passed
Pull Request — master (#21)
by Yannick
01:58
created

TransitionRegistry::initState()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 2

Importance

Changes 0
Metric Value
cc 2
eloc 2
nc 2
nop 1
dl 0
loc 4
ccs 3
cts 3
cp 1
crap 2
rs 10
c 0
b 0
f 0
1
<?php
2
/**
3
 * This file is part of the php-state project.
4
 *
5
 * (c) Yannick Voyer <[email protected]> (http://github.com/yvoyer)
6
 */
7
8
namespace Star\Component\State;
9
10
use Star\Component\State\Transitions\ReadOnlyTransition;
11
use Webmozart\Assert\Assert;
12
13
final class TransitionRegistry implements StateRegistry
14
{
15
    /**
16
     * @var array[] Collection of states indexed by transition name
17
     */
18
    private $transitions = [];
19
20
    /**
21
     * @var array[] Collection of attributes indexed by state name
22
     */
23
    private $states = [];
24
25
    /**
26
     * @param StateTransition $transition
27
     */
28 47
    public function addTransition(StateTransition $transition)
29
    {
30 47
        $name = $transition->getName();
31 47
        if (isset($this->transitions[$name])) {
32 1
            throw DuplicateEntryException::duplicateTransition($name);
33
        }
34
35 47
        $transition->onRegister($this);
36 47
    }
37
38
    /**
39
     * @param string $name The transition name
40
     *
41
     * @return StateTransition
42
     * @throws NotFoundException
43
     */
44 32
    public function getTransition($name)
45
    {
46 32
        Assert::string($name);
47 32
        $transition = null;
48 32
        if (isset($this->transitions[$name]['to'])) {
49 30
            $transition = new ReadOnlyTransition($this->transitions[$name]['to']);
50
        }
51
52 32
        if (! $transition) {
53 2
            throw NotFoundException::transitionNotFound($name);
54
        }
55
56 30
        return $transition;
57
    }
58
59
    /**
60
     * @param string $state
61
     * @param string $attribute
62
     */
63 35
    public function addAttribute($state, $attribute)
64
    {
65 35
        $attributes = [$attribute];
66 35
        if ($this->hasState($state)) {
67 35
            $attributes = array_merge($this->states[$state], $attributes);
68
        }
69
70 35
        $this->states[$state] = array_unique($attributes);
71 35
    }
72
73
    /**
74
     * @param string $state
75
     * @param string[] $attributes
76
     */
77 52
    private function addAttributes($state, array $attributes)
78
    {
79 52
        array_map(
80 52
            function ($attribute) use ($state) {
81 3
                $this->addAttribute($state, $attribute);
82 52
            },
83 52
            $attributes
84
        );
85 52
    }
86
87
    /**
88
     * @param string $transition
89
     * @param string $state
90
     *
91
     * @return bool
92
     */
93 30
    public function transitionStartsFrom($transition, $state) {
94 30
        Assert::string($transition);
95 30
        Assert::string($state);
96 30
        $from = [];
97 30
        if (isset($this->transitions[$transition]['from'])) {
98 30
            $from = $this->transitions[$transition]['from'];
99
        }
100
101 30
        return in_array($state, $from, true);
102
    }
103
104
    /**
105
     * @param string $state
106
     * @param string $attribute
107
     *
108
     * @return bool
109
     */
110 10
    public function hasAttribute($state, $attribute)
111
    {
112 10
        Assert::string($state);
113 10
        Assert::string($attribute);
114 10
        if (! $this->hasState($state)) {
115
            return false;
116
        }
117
118 10
        return in_array($attribute, $this->states[$state]);
119
    }
120
121
    /**
122
     * @param string $name
123
     *
124
     * @return bool
125
     */
126 54
    public function hasState($name)
127
    {
128 54
        return array_key_exists($name, $this->states);
129
    }
130
131
    /**
132
     * @param TransitionVisitor $visitor
133
     */
134 3
    public function acceptTransitionVisitor(TransitionVisitor $visitor)
135
    {
136 3
        foreach ($this->transitions as $transition => $states) {
137 3
            $visitor->visitTransition($transition);
138
139 3
            foreach ($states['from'] as $from) {
140 3
                $visitor->visitFromState($from, $this->states[$from]);
141
            }
142 3
            $visitor->visitToState($states['to'], $this->states[$states['to']]);
143
        }
144 3
    }
145
146
    /**
147
     * @param StateVisitor $visitor
148
     */
149 2
    public function acceptStateVisitor(StateVisitor $visitor)
150
    {
151 2
        foreach ($this->states as $state => $attributes) {
152 2
            $visitor->visitState($state, $attributes);
153
        }
154 2
    }
155
156
    /**
157
     * @param string $transition
158
     * @param string $stateName
159
     * @param string[] $attributes
160
     */
161 52
    public function registerStartingState($transition, $stateName, array $attributes = [])
162
    {
163 52
        $this->initState($stateName);
164 52
        $this->addAttributes($stateName, $attributes);
165 52
        $this->transitions[$transition]['from'][] = $stateName;
166 52
    }
167
168
    /**
169
     * @param string $transition
170
     * @param string $stateName
171
     * @param string[] $attributes
172
     */
173 48
    public function registerDestinationState($transition, $stateName, array $attributes = [])
174
    {
175 48
        $this->initState($stateName);
176 48
        $this->addAttributes($stateName, $attributes);
177 48
        $this->transitions[$transition]['to'] = $stateName;
178 48
    }
179
180
    /**
181
     * @param string $state
182
     */
183 52
    private function initState($state)
184
    {
185 52
        if (!$this->hasState($state)) {
186 52
            $this->states[$state] = [];
187
        }
188 52
    }
189
}
190