BindingType::__construct()   B
last analyzed

Complexity

Conditions 4
Paths 3

Size

Total Lines 23
Code Lines 13

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 12
CRAP Score 4

Importance

Changes 2
Bugs 0 Features 0
Metric Value
c 2
b 0
f 0
dl 0
loc 23
ccs 12
cts 12
cp 1
rs 8.7972
cc 4
eloc 13
nc 3
nop 3
crap 4
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\Api\Type;
13
14
use InvalidArgumentException;
15
use Puli\Discovery\Api\Binding\Binding;
16
use Serializable;
17
use Webmozart\Assert\Assert;
18
19
/**
20
 * A type that a binding can be bound to.
21
 *
22
 * @since  1.0
23
 *
24
 * @author Bernhard Schussek <[email protected]>
25
 */
26
final class BindingType implements Serializable
27
{
28
    /**
29
     * @var string
30
     */
31
    private $name;
32
33
    /**
34
     * @var string
35
     */
36
    private $acceptedBindingClass;
37
38
    /**
39
     * @var BindingParameter[]
40
     */
41
    private $parameters = array();
42
43
    /**
44
     * Creates a new type.
45
     *
46
     * @param string             $name         The name of the type.
47
     * @param string             $bindingClass The class name of the accepted
48
     *                                         bindings.
49
     * @param BindingParameter[] $parameters   The parameters that can be set
50
     *                                         for a binding.
51
     */
52 182
    public function __construct($name, $bindingClass, array $parameters = array())
53
    {
54 182
        Assert::stringNotEmpty($name, 'The type name must be a non-empty string. Got: %s');
55 181
        Assert::allIsInstanceOf($parameters, 'Puli\Discovery\Api\Type\BindingParameter');
56
57 180
        if (!class_exists($bindingClass) && !interface_exists($bindingClass)) {
58 1
            throw new InvalidArgumentException(sprintf(
59
                'The binding class "%s" is neither a class nor an '.
60 1
                'interface name. Is there a typo?',
61
                $bindingClass
62
            ));
63
        }
64
65 179
        $this->name = $name;
66 179
        $this->acceptedBindingClass = $bindingClass;
67
68 179
        foreach ($parameters as $parameter) {
69 40
            $this->parameters[$parameter->getName()] = $parameter;
70
        }
71
72
        // Sort to facilitate comparison
73 179
        ksort($this->parameters);
74 179
    }
75
76
    /**
77
     * Returns the type's name.
78
     *
79
     * @return string The name of the type.
80
     */
81 157
    public function getName()
82
    {
83 157
        return $this->name;
84
    }
85
86
    /**
87
     * Returns the parameters.
88
     *
89
     * @return BindingParameter[] The type parameters.
90
     */
91 90
    public function getParameters()
92
    {
93 90
        return $this->parameters;
94
    }
95
96
    /**
97
     * Returns whether the type has parameters.
98
     *
99
     * @return bool Returns `true` if the type has parameters and `false`
100
     *              otherwise.
101
     */
102 2
    public function hasParameters()
103
    {
104 2
        return count($this->parameters) > 0;
105
    }
106
107
    /**
108
     * Returns whether the type has any required parameters.
109
     *
110
     * @return bool Returns `true` if the type has at least one required
111
     *              parameter.
112
     */
113 2
    public function hasRequiredParameters()
114
    {
115 2
        foreach ($this->parameters as $parameter) {
116 2
            if ($parameter->isRequired()) {
117 2
                return true;
118
            }
119
        }
120
121 1
        return false;
122
    }
123
124
    /**
125
     * Returns whether the type has any optional parameters.
126
     *
127
     * @return bool Returns `true` if the type has at least one optional
128
     *              parameter.
129
     */
130 2
    public function hasOptionalParameters()
131
    {
132 2
        foreach ($this->parameters as $parameter) {
133 2
            if (!$parameter->isRequired()) {
134 2
                return true;
135
            }
136
        }
137
138 1
        return false;
139
    }
140
141
    /**
142
     * Returns a parameter by name.
143
     *
144
     * @param string $name The parameter name.
145
     *
146
     * @return BindingParameter The parameter.
147
     *
148
     * @throws NoSuchParameterException If the parameter was not found.
149
     */
150 7
    public function getParameter($name)
151
    {
152 7
        if (!isset($this->parameters[$name])) {
153 3
            throw new NoSuchParameterException(sprintf(
154 3
                'The parameter "%s" does not exist on type "%s".',
155
                $name,
156 3
                $this->name
157
            ));
158
        }
159
160 4
        return $this->parameters[$name];
161
    }
162
163
    /**
164
     * Returns whether a parameter exists.
165
     *
166
     * @param string $name The parameter name.
167
     *
168
     * @return bool Returns `true` if a parameter with that name exists.
169
     */
170 28
    public function hasParameter($name)
171
    {
172 28
        return isset($this->parameters[$name]);
173
    }
174
175
    /**
176
     * Returns the default values of the parameters.
177
     *
178
     * @return array The default values of the parameters.
179
     */
180 90
    public function getParameterValues()
181
    {
182 90
        $values = array();
183
184 90
        foreach ($this->parameters as $name => $parameter) {
185 28
            if (!$parameter->isRequired()) {
186 28
                $values[$name] = $parameter->getDefaultValue();
187
            }
188
        }
189
190 90
        return $values;
191
    }
192
193
    /**
194
     * Returns whether the type has parameters with default values.
195
     *
196
     * @return bool Returns `true` if at least one parameter has a default value
197
     *              and `false` otherwise.
198
     */
199 2
    public function hasParameterValues()
200
    {
201 2
        foreach ($this->parameters as $name => $parameter) {
202 2
            if (!$parameter->isRequired()) {
203 2
                return true;
204
            }
205
        }
206
207 1
        return false;
208
    }
209
210
    /**
211
     * Returns the default value of a parameter.
212
     *
213
     * @param string $name The parameter name.
214
     *
215
     * @return mixed The default value.
216
     *
217
     * @throws NoSuchParameterException If the parameter was not found.
218
     */
219 3
    public function getParameterValue($name)
220
    {
221 3
        return $this->getParameter($name)->getDefaultValue();
222
    }
223
224
    /**
225
     * Returns whether a parameter has a default value set.
226
     *
227
     * @param string $name The parameter name.
228
     *
229
     * @return bool Returns `true` if the parameter has a default value set and
230
     *              `false` otherwise.
231
     *
232
     * @throws NoSuchParameterException If the parameter was not found.
233
     */
234 2
    public function hasParameterValue($name)
235
    {
236 2
        return !$this->getParameter($name)->isRequired();
237
    }
238
239
    /**
240
     * Returns whether the type accepts a binding class.
241
     *
242
     * @param Binding|string $binding The binding or the fully-qualified name of
243
     *                                the binding class.
244
     *
245
     * @return bool Returns `true` if the binding can be bound to this type and
246
     *              `false` otherwise.
247
     */
248 97
    public function acceptsBinding($binding)
249
    {
250 97
        return $binding instanceof $this->acceptedBindingClass
251 7
            || $binding === $this->acceptedBindingClass
252 97
            || is_subclass_of($binding, $this->acceptedBindingClass);
253
    }
254
255
    /**
256
     * Returns the binding class name that can be bound to this type.
257
     *
258
     * @return string The accepted binding class name.
259
     */
260 1
    public function getAcceptedBindingClass()
261
    {
262 1
        return $this->acceptedBindingClass;
263
    }
264
265
    /**
266
     * {@inheritdoc}
267
     */
268 122
    public function serialize()
269
    {
270 122
        $data = array();
271
272 122
        $this->preSerialize($data);
273
274 122
        return serialize($data);
275
    }
276
277
    /**
278
     * {@inheritdoc}
279
     */
280 36
    public function unserialize($serialized)
281
    {
282 36
        $data = unserialize($serialized);
283
284 36
        $this->postUnserialize($data);
285 36
    }
286
287 122
    protected function preSerialize(array &$data)
288
    {
289 122
        $data[] = $this->name;
290 122
        $data[] = $this->acceptedBindingClass;
291
292 122
        foreach ($this->parameters as $parameter) {
293 19
            $data[] = $parameter->getName();
294 19
            $data[] = $parameter->getFlags();
295 19
            $data[] = $parameter->getDefaultValue();
296
        }
297 122
    }
298
299 36
    protected function postUnserialize(array &$data)
300
    {
301 36
        while (count($data) > 2) {
302 10
            $defaultValue = array_pop($data);
303 10
            $flags = array_pop($data);
304 10
            $name = array_pop($data);
305
306 10
            $this->parameters[$name] = new BindingParameter($name, $flags, $defaultValue);
307
        }
308
309 36
        $this->acceptedBindingClass = array_pop($data);
310 36
        $this->name = array_pop($data);
311 36
    }
312
}
313