Completed
Push — master ( 360824...c62b77 )
by Bernhard
02:24
created

AbstractBinding::equals()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 13
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 4
CRAP Score 3.3332

Importance

Changes 6
Bugs 0 Features 3
Metric Value
c 6
b 0
f 3
dl 0
loc 13
ccs 4
cts 6
cp 0.6667
rs 9.4285
cc 3
eloc 6
nc 3
nop 1
crap 3.3332
1
<?php
2
3
/*
4
 * This file is part of the puli/discovery package.
5
 *
6
 * (c) Bernhard Schussek <[email protected]>
7
 *
8
 * For the full copyright and license information, please view the LICENSE
9
 * file that was distributed with this source code.
10
 */
11
12
namespace Puli\Discovery\Binding;
13
14
use InvalidArgumentException;
15
use Puli\Discovery\Api\Binding\Binding;
16
use Puli\Discovery\Api\Binding\Initializer\NotInitializedException;
17
use Puli\Discovery\Api\Type\BindingNotAcceptedException;
18
use Puli\Discovery\Api\Type\BindingType;
19
use Puli\Discovery\Api\Type\MissingParameterException;
20
use Puli\Discovery\Api\Type\NoSuchParameterException;
21
use Webmozart\Assert\Assert;
22
23
/**
24
 * Base class for bindings.
25
 *
26
 * @since  1.0
27
 *
28
 * @author Bernhard Schussek <[email protected]>
29
 */
30
abstract class AbstractBinding implements Binding
31
{
32
    /**
33
     * @var string
34
     */
35
    private $typeName;
36
37
    /**
38
     * @var BindingType|null
39
     */
40
    private $type;
41
42
    /**
43
     * @var array
44
     */
45
    private $userParameterValues = array();
46
47
    /**
48
     * @var array
49
     */
50
    private $parameterValues = array();
51
52
    /**
53
     * Creates a new binding.
54
     *
55
     * You can pass parameters that have been defined for the type. If you pass
56
     * unknown parameters, or if a required parameter is missing, an exception
57
     * is thrown.
58
     *
59
     * All parameters that you do not set here will receive the default values
60
     * set for the parameter.
61
     *
62
     * @param string $typeName        The name of the type to bind against.
63
     * @param array  $parameterValues The values of the parameters defined
64
     *                                for the type.
65
     *
66
     * @throws NoSuchParameterException  If an invalid parameter was passed.
67
     * @throws MissingParameterException If a required parameter was not passed.
68
     */
69 132
    public function __construct($typeName, array $parameterValues = array())
70
    {
71 132
        Assert::stringNotEmpty($typeName, 'The type name must be a non-empty string. Got: %s');
72
73 130
        ksort($parameterValues);
74
75 130
        $this->typeName = $typeName;
76 130
        $this->userParameterValues = $parameterValues;
77 130
        $this->parameterValues = $parameterValues;
78 130
    }
79
80
    /**
81
     * {@inheritdoc}
82
     */
83 106
    public function initialize(BindingType $type)
84
    {
85 106
        if ($this->typeName !== $type->getName()) {
86 2
            throw new InvalidArgumentException(sprintf(
87 2
                'The passed type "%s" does not match the configured type "%s".',
88 2
                $type->getName(),
89 2
                $this->typeName
90
            ));
91
        }
92
93 104
        if (!$type->acceptsBinding($this)) {
94 7
            throw BindingNotAcceptedException::forBindingClass($type->getName(), get_class($this));
95
        }
96
97
        // Merge default parameter values of the type
98 97
        $this->assertParameterValuesValid($this->userParameterValues, $type);
99
100 93
        $this->type = $type;
101 93
        $this->parameterValues = array_replace($type->getParameterValues(), $this->userParameterValues);
102
103 93
        ksort($this->parameterValues);
104 93
    }
105
106
    /**
107
     * {@inheritdoc}
108
     */
109 2
    public function isInitialized()
110
    {
111 2
        return null !== $this->type;
112
    }
113
114
    /**
115
     * {@inheritdoc}
116
     */
117 98
    public function getTypeName()
118
    {
119 98
        return $this->typeName;
120
    }
121
122
    /**
123
     * {@inheritdoc}
124
     */
125 4
    public function getType()
126
    {
127 4
        if (null === $this->type) {
128 2
            throw new NotInitializedException('The binding must be initialized before accessing the type.');
129
        }
130
131 2
        return $this->type;
132
    }
133
134
    /**
135
     * {@inheritdoc}
136
     */
137 10
    public function getParameterValues($includeDefault = true)
138
    {
139 10
        if ($includeDefault) {
140 10
            return $this->parameterValues;
141
        }
142
143 6
        return $this->userParameterValues;
144
    }
145
146
    /**
147
     * {@inheritdoc}
148
     */
149
    public function hasParameterValues($includeDefault = true)
150
    {
151
        if ($includeDefault) {
152
            return count($this->parameterValues) > 0;
153
        }
154
155
        return count($this->userParameterValues) > 0;
156
    }
157
158
    /**
159
     * {@inheritdoc}
160
     */
161 32
    public function getParameterValue($parameterName, $includeDefault = true)
162
    {
163 32
        $parameterValues = $includeDefault ? $this->parameterValues : $this->userParameterValues;
164
165 32
        if (!array_key_exists($parameterName, $parameterValues)) {
166 2
            throw NoSuchParameterException::forParameterName($parameterName, $this->typeName);
167
        }
168
169 30
        return $parameterValues[$parameterName];
170
    }
171
172
    /**
173
     * {@inheritdoc}
174
     */
175 10
    public function hasParameterValue($parameterName, $includeDefault = true)
176
    {
177 10
        if ($includeDefault) {
178 10
            return array_key_exists($parameterName, $this->parameterValues);
179
        }
180
181 6
        return array_key_exists($parameterName, $this->userParameterValues);
182
    }
183
184
    /**
185
     * {@inheritdoc}
186
     */
187 73
    public function serialize()
188
    {
189 73
        $data = array();
190
191 73
        $this->preSerialize($data);
192
193 73
        return serialize($data);
194
    }
195
196
    /**
197
     * {@inheritdoc}
198
     */
199 30
    public function unserialize($serialized)
200
    {
201 30
        $data = unserialize($serialized);
202
203 30
        $this->postUnserialize($data);
204 30
    }
205
206
    /**
207
     * {@inheritdoc}
208
     */
209 58
    public function equals(Binding $other)
210
    {
211 58
        if (get_class($this) !== get_class($other)) {
212
            return false;
213
        }
214
215
        /** @var AbstractBinding $other */
216 58
        if ($this->typeName !== $other->typeName) {
217
            return false;
218
        }
219
220 58
        return $this->userParameterValues === $other->userParameterValues;
221
    }
222
223 73
    protected function preSerialize(array &$data)
224
    {
225 73
        $data[] = $this->typeName;
226 73
        $data[] = $this->userParameterValues;
227 73
    }
228
229 30
    protected function postUnserialize(array &$data)
230
    {
231 30
        $this->userParameterValues = array_pop($data);
232 30
        $this->parameterValues = $this->userParameterValues;
233 30
        $this->typeName = array_pop($data);
234 30
    }
235
236 97
    private function assertParameterValuesValid(array $parameterValues, BindingType $type)
237
    {
238 97
        foreach ($parameterValues as $name => $value) {
239 32
            if (!$type->hasParameter($name)) {
240 32
                throw NoSuchParameterException::forParameterName($name, $type->getName());
241
            }
242
        }
243
244 95
        foreach ($type->getParameters() as $parameter) {
245 32
            if (!isset($parameterValues[$parameter->getName()])) {
246 27
                if ($parameter->isRequired()) {
247 32
                    throw MissingParameterException::forParameterName($parameter->getName(), $type->getName());
248
                }
249
            }
250
        }
251 93
    }
252
}
253