Completed
Pull Request — master (#812)
by
unknown
03:54
created

Context   A

Complexity

Total Complexity 34

Size/Duplication

Total Lines 256
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 8

Test Coverage

Coverage 79.17%

Importance

Changes 0
Metric Value
wmc 34
lcom 1
cbo 8
dl 0
loc 256
ccs 76
cts 96
cp 0.7917
rs 9.2
c 0
b 0
f 0

25 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 4 1
A initialize() 0 13 2
A accept() 0 4 1
A getVisitor() 0 4 1
A getNavigator() 0 4 1
A getExclusionStrategy() 0 4 1
A setAttribute() 0 7 1
A assertMutable() 0 8 2
A addExclusionStrategy() 0 23 3
A setVersion() 0 11 2
A setGroups() 0 11 2
A getMetadataFactory() 0 4 1
A getGroups() 0 4 1
A enableMaxDepthChecks() 0 6 1
A setSerializeNull() 0 6 1
A shouldSerializeNull() 0 4 1
A getFormat() 0 4 1
A pushClassMetadata() 0 4 1
A pushPropertyMetadata() 0 4 1
A popPropertyMetadata() 0 8 2
A popClassMetadata() 0 8 2
A getMetadataStack() 0 4 1
A getCurrentPath() 0 15 4
getDepth() 0 1 ?
getDirection() 0 1 ?
1
<?php
2
3
/*
4
 * Copyright 2016 Johannes M. Schmitt <[email protected]>
5
 *
6
 * Licensed under the Apache License, Version 2.0 (the "License");
7
 * you may not use this file except in compliance with the License.
8
 * You may obtain a copy of the License at
9
 *
10
 *     http://www.apache.org/licenses/LICENSE-2.0
11
 *
12
 * Unless required by applicable law or agreed to in writing, software
13
 * distributed under the License is distributed on an "AS IS" BASIS,
14
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
 * See the License for the specific language governing permissions and
16
 * limitations under the License.
17
 */
18
19
namespace JMS\Serializer;
20
21
use JMS\Serializer\Exception\RuntimeException;
22
use JMS\Serializer\Exclusion\DepthExclusionStrategy;
23
use JMS\Serializer\Exclusion\DisjunctExclusionStrategy;
24
use JMS\Serializer\Exclusion\ExclusionStrategyInterface;
25
use JMS\Serializer\Exclusion\GroupsExclusionStrategy;
26
use JMS\Serializer\Exclusion\VersionExclusionStrategy;
27
use JMS\Serializer\Metadata\ClassMetadata;
28
use JMS\Serializer\Metadata\PropertyMetadata;
29
use Metadata\MetadataFactory;
30
use Metadata\MetadataFactoryInterface;
31
use PhpCollection\Map;
32
33
abstract class Context
34
{
35
    /**
36
     * @var \PhpCollection\Map
37
     */
38
    public $attributes;
39
40
    private $format;
41
42
    /** @var VisitorInterface */
43
    private $visitor;
44
45
    /** @var GraphNavigator */
46
    private $navigator;
47
48
    /** @var MetadataFactory */
49
    private $metadataFactory;
50
51
    /** @var ExclusionStrategyInterface */
52
    private $exclusionStrategy;
53
54
    /** @var boolean|null */
55
    private $serializeNull;
56
57
    private $initialized = false;
58
59
    /** @var \SplStack */
60
    private $metadataStack;
61
62 413
    public function __construct()
63
    {
64 413
        $this->attributes = new Map();
65 413
    }
66
67
    /**
68
     * @param string $format
69
     */
70 369
    public function initialize($format, VisitorInterface $visitor, GraphNavigator $navigator, MetadataFactoryInterface $factory)
71
    {
72 369
        if ($this->initialized) {
73
            throw new \LogicException('This context was already initialized, and cannot be re-used.');
74
        }
75
76 369
        $this->initialized = true;
77 369
        $this->format = $format;
78 369
        $this->visitor = $visitor;
79 369
        $this->navigator = $navigator;
80 369
        $this->metadataFactory = $factory;
0 ignored issues
show
Documentation Bug introduced by
$factory is of type object<Metadata\MetadataFactoryInterface>, but the property $metadataFactory was declared to be of type object<Metadata\MetadataFactory>. Are you sure that you always receive this specific sub-class here, or does it make sense to add an instanceof check?

Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a given class or a super-class is assigned to a property that is type hinted more strictly.

Either this assignment is in error or an instanceof check should be added for that assignment.

class Alien {}

class Dalek extends Alien {}

class Plot
{
    /** @var  Dalek */
    public $villain;
}

$alien = new Alien();
$plot = new Plot();
if ($alien instanceof Dalek) {
    $plot->villain = $alien;
}
Loading history...
81 369
        $this->metadataStack = new \SplStack();
82 369
    }
83
84
    public function accept($data, array $type = null)
85
    {
86
        return $this->navigator->accept($data, $type, $this);
87
    }
88
89 8
    public function getMetadataFactory()
90
    {
91 8
        return $this->metadataFactory;
92
    }
93
94 369
    public function getVisitor()
95
    {
96 369
        return $this->visitor;
97
    }
98
99
    public function getNavigator()
100
    {
101
        return $this->navigator;
102
    }
103
104 225
    public function getExclusionStrategy()
105
    {
106 225
        return $this->exclusionStrategy;
107
    }
108
109 3
    public function setAttribute($key, $value)
110
    {
111 3
        $this->assertMutable();
112 3
        $this->attributes->set($key, $value);
113
114 3
        return $this;
115
    }
116
117 31
    private function assertMutable()
118
    {
119 31
        if (!$this->initialized) {
120 31
            return;
121
        }
122
123
        throw new \LogicException('This context was already initialized and is immutable; you cannot modify it anymore.');
124
    }
125
126 28
    public function addExclusionStrategy(ExclusionStrategyInterface $strategy)
127
    {
128 28
        $this->assertMutable();
129
130 28
        if (null === $this->exclusionStrategy) {
131 28
            $this->exclusionStrategy = $strategy;
132
133 28
            return $this;
134
        }
135
136
        if ($this->exclusionStrategy instanceof DisjunctExclusionStrategy) {
137
            $this->exclusionStrategy->addStrategy($strategy);
138
139
            return $this;
140
        }
141
142
        $this->exclusionStrategy = new DisjunctExclusionStrategy(array(
143
            $this->exclusionStrategy,
144
            $strategy,
145
        ));
146
147
        return $this;
148
    }
149
150
    /**
151
     * @param integer $version
152
     */
153 3
    public function setVersion($version)
154
    {
155 3
        if (null === $version) {
156
            throw new \LogicException('The version must not be null.');
157
        }
158
159 3
        $this->attributes->set('version', $version);
160 3
        $this->addExclusionStrategy(new VersionExclusionStrategy($version));
161
162 3
        return $this;
163
    }
164
165
    /**
166
     * @param array|string $groups
167
     */
168 17
    public function setGroups($groups)
169
    {
170 17
        if (empty($groups)) {
171
            throw new \LogicException('The groups must not be empty.');
172
        }
173
174 17
        $this->attributes->set('groups', (array)$groups);
175 17
        $this->addExclusionStrategy(new GroupsExclusionStrategy((array)$groups));
176
177 17
        return $this;
178
    }
179
180
    /**
181
     * @return \PhpOption\None|\PhpOption\Option|\PhpOption\Some
182
     */
183
    public function getGroups()
184
    {
185
        return $this->attributes->get('groups');
186
    }
187
188 3
    public function enableMaxDepthChecks()
189
    {
190 3
        $this->addExclusionStrategy(new DepthExclusionStrategy());
191
192 3
        return $this;
193
    }
194
195
    /**
196
     * Set if NULLs should be serialized (TRUE) ot not (FALSE)
197
     *
198
     * @param bool $bool
199
     * @return $this
200
     */
201 20
    public function setSerializeNull($bool)
202
    {
203 20
        $this->serializeNull = (boolean)$bool;
204
205 20
        return $this;
206
    }
207
208
    /**
209
     * Returns TRUE when NULLs should be serialized
210
     * Returns FALSE when NULLs should not be serialized
211
     * Returns NULL when NULLs should not be serialized,
212
     * but the user has not explicitly decided to use this policy
213
     *
214
     * @return bool|null
215
     */
216 46
    public function shouldSerializeNull()
217
    {
218 46
        return $this->serializeNull;
219
    }
220
221
    /**
222
     * @return string
223
     */
224 253
    public function getFormat()
225
    {
226 253
        return $this->format;
227
    }
228
229 217
    public function pushClassMetadata(ClassMetadata $metadata)
230
    {
231 217
        $this->metadataStack->push($metadata);
232 217
    }
233
234 212
    public function pushPropertyMetadata(PropertyMetadata $metadata)
235
    {
236 212
        $this->metadataStack->push($metadata);
237 212
    }
238
239 208
    public function popPropertyMetadata()
240
    {
241 208
        $metadata = $this->metadataStack->pop();
242
243 208
        if (!$metadata instanceof PropertyMetadata) {
244
            throw new RuntimeException('Context metadataStack not working well');
245
        }
246 208
    }
247
248 211
    public function popClassMetadata()
249
    {
250 211
        $metadata = $this->metadataStack->pop();
251
252 211
        if (!$metadata instanceof ClassMetadata) {
253
            throw new RuntimeException('Context metadataStack not working well');
254
        }
255 211
    }
256
257 7
    public function getMetadataStack()
258
    {
259 7
        return $this->metadataStack;
260
    }
261
262
    /**
263
     * @return array
264
     */
265 35
    public function getCurrentPath()
266
    {
267 35
        if (!$this->metadataStack) {
268 18
            return array();
269
        }
270
271 17
        $paths = array();
272 17
        foreach ($this->metadataStack as $metadata) {
273 17
            if ($metadata instanceof PropertyMetadata) {
274 7
                array_unshift($paths, $metadata->name);
275 7
            }
276 17
        }
277
278 17
        return $paths;
279
    }
280
281
282
    abstract public function getDepth();
283
284
    /**
285
     * @return integer
286
     */
287
    abstract public function getDirection();
288
}
289