Passed
Push — master ( 4da179...4cded1 )
by Yannick
02:33
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
    {
95 30
        Assert::string($transition);
96 30
        Assert::string($state);
97 30
        $from = [];
98 30
        if (isset($this->transitions[$transition]['from'])) {
99 30
            $from = $this->transitions[$transition]['from'];
100
        }
101
102 30
        return in_array($state, $from, true);
103
    }
104
105
    /**
106
     * @param string $state
107
     * @param string $attribute
108
     *
109
     * @return bool
110
     */
111 10
    public function hasAttribute($state, $attribute)
112
    {
113 10
        Assert::string($state);
114 10
        Assert::string($attribute);
115 10
        if (! $this->hasState($state)) {
116
            return false;
117
        }
118
119 10
        return in_array($attribute, $this->states[$state]);
120
    }
121
122
    /**
123
     * @param string $name
124
     *
125
     * @return bool
126
     */
127 54
    public function hasState($name)
128
    {
129 54
        return array_key_exists($name, $this->states);
130
    }
131
132
    /**
133
     * @param TransitionVisitor $visitor
134
     */
135 3
    public function acceptTransitionVisitor(TransitionVisitor $visitor)
136
    {
137 3
        foreach ($this->transitions as $transition => $states) {
138 3
            $visitor->visitTransition($transition);
139
140 3
            foreach ($states['from'] as $from) {
141 3
                $visitor->visitFromState($from, $this->states[$from]);
142
            }
143 3
            $visitor->visitToState($states['to'], $this->states[$states['to']]);
144
        }
145 3
    }
146
147
    /**
148
     * @param StateVisitor $visitor
149
     */
150 2
    public function acceptStateVisitor(StateVisitor $visitor)
151
    {
152 2
        foreach ($this->states as $state => $attributes) {
153 2
            $visitor->visitState($state, $attributes);
154
        }
155 2
    }
156
157
    /**
158
     * @param string $transition
159
     * @param string $stateName
160
     * @param string[] $attributes
161
     */
162 52
    public function registerStartingState($transition, $stateName, array $attributes = [])
163
    {
164 52
        $this->initState($stateName);
165 52
        $this->addAttributes($stateName, $attributes);
166 52
        $this->transitions[$transition]['from'][] = $stateName;
167 52
    }
168
169
    /**
170
     * @param string $transition
171
     * @param string $stateName
172
     * @param string[] $attributes
173
     */
174 48
    public function registerDestinationState($transition, $stateName, array $attributes = [])
175
    {
176 48
        $this->initState($stateName);
177 48
        $this->addAttributes($stateName, $attributes);
178 48
        $this->transitions[$transition]['to'] = $stateName;
179 48
    }
180
181
    /**
182
     * @param string $state
183
     */
184 52
    private function initState($state)
185
    {
186 52
        if (!$this->hasState($state)) {
187 52
            $this->states[$state] = [];
188
        }
189 52
    }
190
}
191