Completed
Push — master ( 9912c8...76f230 )
by Asmir
13s
created

Context   A

Complexity

Total Complexity 33

Size/Duplication

Total Lines 248
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 8

Test Coverage

Coverage 77.66%

Importance

Changes 0
Metric Value
wmc 33
lcom 1
cbo 8
dl 0
loc 248
ccs 73
cts 94
cp 0.7766
rs 9.3999
c 0
b 0
f 0

24 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 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 getMetadataFactory() 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 359
    public function __construct()
63
    {
64 359
        $this->attributes = new Map();
65 359
    }
66
67
    /**
68
     * @param string $format
69
     */
70 305
    public function initialize($format, VisitorInterface $visitor, GraphNavigator $navigator, MetadataFactoryInterface $factory)
71
    {
72 305
        if ($this->initialized) {
73
            throw new \LogicException('This context was already initialized, and cannot be re-used.');
74
        }
75
76 305
        $this->initialized = true;
77 305
        $this->format = $format;
78 305
        $this->visitor = $visitor;
79 305
        $this->navigator = $navigator;
80 305
        $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 305
        $this->metadataStack = new \SplStack();
82 305
    }
83
84
    public function accept($data, array $type = null)
85
    {
86
        return $this->navigator->accept($data, $type, $this);
87
    }
88
89 1
    public function getMetadataFactory()
90
    {
91 1
        return $this->metadataFactory;
92
    }
93
94 305
    public function getVisitor()
95
    {
96 305
        return $this->visitor;
97
    }
98
99
    public function getNavigator()
100
    {
101
        return $this->navigator;
102
    }
103
104 202
    public function getExclusionStrategy()
105
    {
106 202
        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 24
    private function assertMutable()
118
    {
119 24
        if ( ! $this->initialized) {
120 24
            return;
121
        }
122
123
        throw new \LogicException('This context was already initialized and is immutable; you cannot modify it anymore.');
124
    }
125
126 21
    public function addExclusionStrategy(ExclusionStrategyInterface $strategy)
127
    {
128 21
        $this->assertMutable();
129
130 21
        if (null === $this->exclusionStrategy) {
131 21
            $this->exclusionStrategy = $strategy;
132
133 21
            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 13
    public function setGroups($groups)
169
    {
170 13
        if (empty($groups)) {
171
            throw new \LogicException('The groups must not be empty.');
172
        }
173
174 13
        $this->attributes->set('groups', (array) $groups);
175 13
        $this->addExclusionStrategy(new GroupsExclusionStrategy((array) $groups));
176
177 13
        return $this;
178
    }
179
180
    public function enableMaxDepthChecks()
181
    {
182
        $this->addExclusionStrategy(new DepthExclusionStrategy());
183
184
        return $this;
185
    }
186
187
    /**
188
     * Set if NULLs should be serialized (TRUE) ot not (FALSE)
189
     *
190
     * @param bool $bool
191
     * @return $this
192
     */
193 20
    public function setSerializeNull($bool)
194
    {
195 20
        $this->serializeNull = (boolean) $bool;
196
197 20
        return $this;
198
    }
199
200
    /**
201
     * Returns TRUE when NULLs should be serialized
202
     * Returns FALSE when NULLs should not be serialized
203
     * Returns NULL when NULLs should not be serialized,
204
     * but the user has not explicitly decided to use this policy
205
     *
206
     * @return bool|null
207
     */
208 41
    public function shouldSerializeNull()
209
    {
210 41
        return $this->serializeNull;
211
    }
212
213
    /**
214
     * @return string
215
     */
216 226
    public function getFormat()
217
    {
218 226
        return $this->format;
219
    }
220
221 194
    public function pushClassMetadata(ClassMetadata $metadata)
222
    {
223 194
        $this->metadataStack->push($metadata);
224 194
    }
225
226 188
    public function pushPropertyMetadata(PropertyMetadata $metadata)
227
    {
228 188
        $this->metadataStack->push($metadata);
229 188
    }
230
231 187
    public function popPropertyMetadata()
232
    {
233 187
        $metadata = $this->metadataStack->pop();
234
235 187
        if ( ! $metadata instanceof PropertyMetadata) {
236
            throw new RuntimeException('Context metadataStack not working well');
237
        }
238 187
    }
239
240 191
    public function popClassMetadata()
241
    {
242 191
        $metadata = $this->metadataStack->pop();
243
244 191
        if ( ! $metadata instanceof ClassMetadata) {
245
            throw new RuntimeException('Context metadataStack not working well');
246
        }
247 191
    }
248
249 4
    public function getMetadataStack()
250
    {
251 4
        return $this->metadataStack;
252
    }
253
254
    /**
255
     * @return array
256
     */
257 31
    public function getCurrentPath()
258
    {
259 31
        if (!$this->metadataStack) {
260 18
            return array();
261
        }
262
263 13
        $paths = array();
264 13
        foreach ($this->metadataStack as $metadata) {
265 13
            if ($metadata instanceof PropertyMetadata) {
266 3
                array_unshift($paths, $metadata->name);
267 3
            }
268 13
        }
269
270 13
        return $paths;
271
    }
272
273
274
    abstract public function getDepth();
275
276
    /**
277
     * @return integer
278
     */
279
    abstract public function getDirection();
280
}
281