Passed
Push — master ( bac3b4...e5a3b7 )
by Asmir
06:04 queued 03:03
created

Context::pushClassMetadata()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
eloc 1
nc 1
nop 1
dl 0
loc 3
ccs 2
cts 2
cp 1
crap 1
rs 10
c 0
b 0
f 0
1
<?php
2
3
declare(strict_types=1);
4
5
/*
6
 * Copyright 2016 Johannes M. Schmitt <[email protected]>
7
 *
8
 * Licensed under the Apache License, Version 2.0 (the "License");
9
 * you may not use this file except in compliance with the License.
10
 * You may obtain a copy of the License at
11
 *
12
 *     http://www.apache.org/licenses/LICENSE-2.0
13
 *
14
 * Unless required by applicable law or agreed to in writing, software
15
 * distributed under the License is distributed on an "AS IS" BASIS,
16
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17
 * See the License for the specific language governing permissions and
18
 * limitations under the License.
19
 */
20
21
namespace JMS\Serializer;
22
23
use JMS\Serializer\Exception\LogicException;
24
use JMS\Serializer\Exception\RuntimeException;
25
use JMS\Serializer\Exclusion\DepthExclusionStrategy;
26
use JMS\Serializer\Exclusion\DisjunctExclusionStrategy;
27
use JMS\Serializer\Exclusion\ExclusionStrategyInterface;
28
use JMS\Serializer\Exclusion\GroupsExclusionStrategy;
29
use JMS\Serializer\Exclusion\VersionExclusionStrategy;
30
use JMS\Serializer\Metadata\ClassMetadata;
31
use JMS\Serializer\Metadata\PropertyMetadata;
32
use Metadata\MetadataFactory;
33
use Metadata\MetadataFactoryInterface;
34
35
abstract class Context
36
{
37
    /**
38
     * @var array
39
     */
40
    private $attributes = array();
41
42
    private $format;
43
44
    /** @var SerializationVisitorInterface|DeserializationVisitorInterface */
45
    private $visitor;
46
47
    /** @var GraphNavigatorInterface */
48
    private $navigator;
49
50
    /** @var MetadataFactory */
51
    private $metadataFactory;
52
53
    /** @var DisjunctExclusionStrategy */
54
    private $exclusionStrategy;
55
56
    /** @var boolean */
57
    private $serializeNull = false;
58
59
    private $initialized = false;
60
61
    /** @var \SplStack */
62
    private $metadataStack;
63
64 353
    public function __construct()
65
    {
66 353
        $this->exclusionStrategy = new DisjunctExclusionStrategy();
67 353
    }
68
69
    /**
70
     * @param string $format
71
     */
72 282
    public function initialize(string $format, $visitor, GraphNavigatorInterface $navigator, MetadataFactoryInterface $factory): void
73
    {
74 282
        if ($this->initialized) {
75
            throw new LogicException('This context was already initialized, and cannot be re-used.');
76
        }
77
78 282
        $this->format = $format;
79 282
        $this->visitor = $visitor;
80 282
        $this->navigator = $navigator;
81 282
        $this->metadataFactory = $factory;
0 ignored issues
show
Documentation Bug introduced by
$factory is of type Metadata\MetadataFactoryInterface, but the property $metadataFactory was declared to be of type 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...
82 282
        $this->metadataStack = new \SplStack();
83
84 282
        if (isset($this->attributes['groups'])) {
85 15
            $this->addExclusionStrategy(new GroupsExclusionStrategy($this->attributes['groups']));
86
        }
87
88 282
        if (isset($this->attributes['version'])) {
89 3
            $this->addExclusionStrategy(new VersionExclusionStrategy($this->attributes['version']));
90
        }
91
92 282
        if (!empty($this->attributes['max_depth_checks'])) {
93 2
            $this->addExclusionStrategy(new DepthExclusionStrategy());
94
        }
95
96 282
        $this->initialized = true;
97 282
    }
98
99 13
    public function getMetadataFactory(): MetadataFactoryInterface
100
    {
101 13
        return $this->metadataFactory;
102
    }
103
104 282
    public function getVisitor()
105
    {
106 282
        return $this->visitor;
107
    }
108
109 2
    public function getNavigator(): GraphNavigatorInterface
110
    {
111 2
        return $this->navigator;
112
    }
113
114 181
    public function getExclusionStrategy(): ExclusionStrategyInterface
115
    {
116 181
        return $this->exclusionStrategy;
117
    }
118
119 33
    public function getAttribute(string $key)
120
    {
121 33
        return $this->attributes[$key];
122
    }
123
124 267
    public function hasAttribute(string $key)
125
    {
126 267
        return isset($this->attributes[$key]);
127
    }
128
129 11
    public function setAttribute(string $key, $value)
130
    {
131 11
        $this->assertMutable();
132 11
        $this->attributes[$key] = $value;
133
134 11
        return $this;
135
    }
136
137 37
    private function assertMutable(): void
138
    {
139 37
        if (!$this->initialized) {
140 37
            return;
141
        }
142
143
        throw new LogicException('This context was already initialized and is immutable; you cannot modify it anymore.');
144
    }
145
146 30
    public function addExclusionStrategy(ExclusionStrategyInterface $strategy): self
147
    {
148 30
        $this->assertMutable();
149
150 30
        $this->exclusionStrategy->addStrategy($strategy);
151
152 30
        return $this;
153
    }
154
155 3
    public function setVersion(string $version): self
156
    {
157 3
        $this->attributes['version'] = $version;
158
159 3
        return $this;
160
    }
161
162
    /**
163
     * @param array|string $groups
164
     */
165 15
    public function setGroups($groups): self
166
    {
167 15
        if (empty($groups)) {
168
            throw new LogicException('The groups must not be empty.');
169
        }
170
171 15
        $this->attributes['groups'] = (array)$groups;
172
173 15
        return $this;
174
    }
175
176 2
    public function enableMaxDepthChecks(): self
177
    {
178 2
        $this->attributes['max_depth_checks'] = true;
179
180 2
        return $this;
181
    }
182
183
    /**
184
     * Set if NULLs should be serialized (TRUE) ot not (FALSE)
185
     */
186 19
    public function setSerializeNull(bool $bool): self
187
    {
188 19
        $this->serializeNull = $bool;
189
190 19
        return $this;
191
    }
192
193
    /**
194
     * Returns TRUE when NULLs should be serialized
195
     * Returns FALSE when NULLs should not be serialized
196
     * Returns NULL when NULLs should not be serialized,
197
     * but the user has not explicitly decided to use this policy
198
     *
199
     * @return bool
200
     */
201 274
    public function shouldSerializeNull(): bool
202
    {
203 274
        return $this->serializeNull;
204
    }
205
206
    /**
207
     * @return string
208
     */
209 205
    public function getFormat(): string
210
    {
211 205
        return $this->format;
212
    }
213
214 171
    public function pushClassMetadata(ClassMetadata $metadata): void
215
    {
216 171
        $this->metadataStack->push($metadata);
217 171
    }
218
219 170
    public function pushPropertyMetadata(PropertyMetadata $metadata): void
220
    {
221 170
        $this->metadataStack->push($metadata);
222 170
    }
223
224 167
    public function popPropertyMetadata(): void
225
    {
226 167
        $metadata = $this->metadataStack->pop();
227
228 167
        if (!$metadata instanceof PropertyMetadata) {
229
            throw new RuntimeException('Context metadataStack not working well');
230
        }
231 167
    }
232
233 166
    public function popClassMetadata(): void
234
    {
235 166
        $metadata = $this->metadataStack->pop();
236
237 166
        if (!$metadata instanceof ClassMetadata) {
238
            throw new RuntimeException('Context metadataStack not working well');
239
        }
240 166
    }
241
242 7
    public function getMetadataStack(): \SplStack
243
    {
244 7
        return $this->metadataStack;
245
    }
246
247
    /**
248
     * @return array
249
     */
250 33
    public function getCurrentPath()
251
    {
252 33
        if (!$this->metadataStack) {
253 18
            return array();
254
        }
255
256 15
        $paths = array();
257 15
        foreach ($this->metadataStack as $metadata) {
258 15
            if ($metadata instanceof PropertyMetadata) {
259 15
                array_unshift($paths, $metadata->name);
260
            }
261
        }
262
263 15
        return $paths;
264
    }
265
266
267
    abstract public function getDepth(): int;
268
269
    /**
270
     * @return integer
271
     */
272
    abstract public function getDirection(): int;
273
}
274