AbstractBinding::getParameterValue()   A
last analyzed

Complexity

Conditions 3
Paths 4

Size

Total Lines 10
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 5
CRAP Score 3

Importance

Changes 2
Bugs 0 Features 0
Metric Value
c 2
b 0
f 0
dl 0
loc 10
ccs 5
cts 5
cp 1
rs 9.4285
cc 3
eloc 5
nc 4
nop 2
crap 3
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 113
    public function __construct($typeName, array $parameterValues = array())
70
    {
71 113
        Assert::stringNotEmpty($typeName, 'The type name must be a non-empty string. Got: %s');
72
73 112
        ksort($parameterValues);
74
75 112
        $this->typeName = $typeName;
76 112
        $this->userParameterValues = $parameterValues;
77 112
        $this->parameterValues = $parameterValues;
78 112
    }
79
80
    /**
81
     * {@inheritdoc}
82
     */
83 97
    public function initialize(BindingType $type)
84
    {
85 97
        if ($this->typeName !== $type->getName()) {
86 1
            throw new InvalidArgumentException(sprintf(
87 1
                'The passed type "%s" does not match the configured type "%s".',
88 1
                $type->getName(),
89 1
                $this->typeName
90
            ));
91
        }
92
93 96
        if (!$type->acceptsBinding($this)) {
94 6
            throw BindingNotAcceptedException::forBindingClass($type->getName(), get_class($this));
95
        }
96
97
        // Merge default parameter values of the type
98 90
        $this->assertParameterValuesValid($this->userParameterValues, $type);
99
100 88
        $this->type = $type;
101 88
        $this->parameterValues = array_replace($type->getParameterValues(), $this->userParameterValues);
102
103 88
        ksort($this->parameterValues);
104 88
    }
105
106
    /**
107
     * {@inheritdoc}
108
     */
109 1
    public function isInitialized()
110
    {
111 1
        return null !== $this->type;
112
    }
113
114
    /**
115
     * {@inheritdoc}
116
     */
117 95
    public function getTypeName()
118
    {
119 95
        return $this->typeName;
120
    }
121
122
    /**
123
     * {@inheritdoc}
124
     */
125 2
    public function getType()
126
    {
127 2
        if (null === $this->type) {
128 1
            throw new NotInitializedException('The binding must be initialized before accessing the type.');
129
        }
130
131 1
        return $this->type;
132
    }
133
134
    /**
135
     * {@inheritdoc}
136
     */
137 5
    public function getParameterValues($includeDefault = true)
138
    {
139 5
        if ($includeDefault) {
140 5
            return $this->parameterValues;
141
        }
142
143 3
        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 27
    public function getParameterValue($parameterName, $includeDefault = true)
162
    {
163 27
        $parameterValues = $includeDefault ? $this->parameterValues : $this->userParameterValues;
164
165 27
        if (!array_key_exists($parameterName, $parameterValues)) {
166 1
            throw NoSuchParameterException::forParameterName($parameterName, $this->typeName);
167
        }
168
169 26
        return $parameterValues[$parameterName];
170
    }
171
172
    /**
173
     * {@inheritdoc}
174
     */
175 5
    public function hasParameterValue($parameterName, $includeDefault = true)
176
    {
177 5
        if ($includeDefault) {
178 5
            return array_key_exists($parameterName, $this->parameterValues);
179
        }
180
181 3
        return array_key_exists($parameterName, $this->userParameterValues);
182
    }
183
184
    /**
185
     * {@inheritdoc}
186
     */
187 71
    public function serialize()
188
    {
189 71
        $data = array();
190
191 71
        $this->preSerialize($data);
192
193 71
        return serialize($data);
194
    }
195
196
    /**
197
     * {@inheritdoc}
198
     */
199 28
    public function unserialize($serialized)
200
    {
201 28
        $data = unserialize($serialized);
202
203 28
        $this->postUnserialize($data);
204 28
    }
205
206
    /**
207
     * {@inheritdoc}
208
     */
209
    public function equals(Binding $other)
210
    {
211
        if (get_class($this) !== get_class($other)) {
212
            return false;
213
        }
214
215
        /** @var AbstractBinding $other */
216
        if ($this->typeName !== $other->typeName) {
217
            return false;
218
        }
219
220
        return $this->userParameterValues === $other->userParameterValues;
221
    }
222
223 71
    protected function preSerialize(array &$data)
224
    {
225 71
        $data[] = $this->typeName;
226 71
        $data[] = $this->userParameterValues;
227 71
    }
228
229 28
    protected function postUnserialize(array &$data)
230
    {
231 28
        $this->userParameterValues = array_pop($data);
232 28
        $this->parameterValues = $this->userParameterValues;
233 28
        $this->typeName = array_pop($data);
234 28
    }
235
236 90
    private function assertParameterValuesValid(array $parameterValues, BindingType $type)
237
    {
238 90
        foreach ($parameterValues as $name => $value) {
239 27
            if (!$type->hasParameter($name)) {
240 27
                throw NoSuchParameterException::forParameterName($name, $type->getName());
241
            }
242
        }
243
244 89
        foreach ($type->getParameters() as $parameter) {
245 27
            if (!isset($parameterValues[$parameter->getName()])) {
246 22
                if ($parameter->isRequired()) {
247 27
                    throw MissingParameterException::forParameterName($parameter->getName(), $type->getName());
248
                }
249
            }
250
        }
251 88
    }
252
}
253