Passed
Branch master (bf85d9)
by Johannes
05:40
created

Context::initialize()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 12
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 8
CRAP Score 2.0054

Importance

Changes 0
Metric Value
cc 2
eloc 8
nc 2
nop 4
dl 0
loc 12
ccs 8
cts 9
cp 0.8889
crap 2.0054
rs 9.4285
c 0
b 0
f 0
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\LogicException;
22
use JMS\Serializer\Exception\RuntimeException;
23
use JMS\Serializer\Exclusion\DepthExclusionStrategy;
24
use JMS\Serializer\Exclusion\DisjunctExclusionStrategy;
25
use JMS\Serializer\Exclusion\ExclusionStrategyInterface;
26
use JMS\Serializer\Exclusion\GroupsExclusionStrategy;
27
use JMS\Serializer\Exclusion\VersionExclusionStrategy;
28
use JMS\Serializer\Metadata\ClassMetadata;
29
use JMS\Serializer\Metadata\PropertyMetadata;
30
use Metadata\MetadataFactory;
31
use Metadata\MetadataFactoryInterface;
32
33
abstract class Context
34
{
35
    /**
36
     * @var array
37
     */
38
    private $attributes = array();
39
40
    private $format;
41
42
    /** @var SerializationVisitorInterface|DeserializationVisitorInterface */
43
    private $visitor;
44
45
    /** @var GraphNavigatorInterface */
46
    private $navigator;
47
48
    /** @var MetadataFactory */
49
    private $metadataFactory;
50
51
    /** @var DisjunctExclusionStrategy */
52
    private $exclusionStrategy;
53
54
    /** @var boolean */
55
    private $serializeNull = false;
56
57
    private $initialized = false;
58
59
    /** @var \SplStack */
60
    private $metadataStack;
61
62 352
    public function __construct()
63
    {
64 352
        $this->exclusionStrategy = new DisjunctExclusionStrategy();
65 352
    }
66
67
    /**
68
     * @param string $format
69
     */
70 277
    public function initialize(string $format, $visitor, GraphNavigatorInterface $navigator, MetadataFactoryInterface $factory): void
71
    {
72 277
        if ($this->initialized) {
73
            throw new LogicException('This context was already initialized, and cannot be re-used.');
74
        }
75
76 277
        $this->initialized = true;
77 277
        $this->format = $format;
78 277
        $this->visitor = $visitor;
79 277
        $this->navigator = $navigator;
80 277
        $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...
81 277
        $this->metadataStack = new \SplStack();
82 277
    }
83
84
    /**
85
     * @deprecated  Will be removed in 2.0, Use getNavigator()->accept() instead
86
     * @param $data
87
     * @param array|null $type
88
     * @return mixed
89
     */
90
    public function accept($data, array $type = null)
91
    {
92
        return $this->navigator->accept($data, $type, $this);
93
    }
94
95 13
    public function getMetadataFactory(): MetadataFactoryInterface
96
    {
97 13
        return $this->metadataFactory;
98
    }
99
100 277
    public function getVisitor()
101
    {
102 277
        return $this->visitor;
103
    }
104
105 2
    public function getNavigator(): GraphNavigatorInterface
106
    {
107 2
        return $this->navigator;
108
    }
109
110 176
    public function getExclusionStrategy(): ExclusionStrategyInterface
111
    {
112 176
        return $this->exclusionStrategy;
113
    }
114
115 33
    public function getAttribute(string $key)
116
    {
117 33
        return $this->attributes[$key];
118
    }
119
120 261
    public function hasAttribute(string $key)
121
    {
122 261
        return isset($this->attributes[$key]);
123
    }
124
125 11
    public function setAttribute(string $key, $value)
126
    {
127 11
        $this->assertMutable();
128 11
        $this->attributes[$key] = $value;
129
130 11
        return $this;
131
    }
132
133 33
    private function assertMutable(): void
134
    {
135 33
        if (!$this->initialized) {
136 33
            return;
137
        }
138
139
        throw new LogicException('This context was already initialized and is immutable; you cannot modify it anymore.');
140
    }
141
142 26
    public function addExclusionStrategy(ExclusionStrategyInterface $strategy): self
143
    {
144 26
        $this->assertMutable();
145
146 26
        $this->exclusionStrategy->addStrategy($strategy);
147
148 26
        return $this;
149
    }
150
151 2
    public function setVersion(string $version): self
152
    {
153 2
        if (null === $version) {
0 ignored issues
show
introduced by
The condition null === $version is always false.
Loading history...
154
            throw new LogicException('The version must not be null.');
155
        }
156
157 2
        $this->attributes['version'] = $version;
158 2
        $this->addExclusionStrategy(new VersionExclusionStrategy($version));
159
160 2
        return $this;
161
    }
162
163
    /**
164
     * @param array|string $groups
165
     */
166 12
    public function setGroups($groups): self
167
    {
168 12
        if (empty($groups)) {
169
            throw new LogicException('The groups must not be empty.');
170
        }
171
172 12
        $this->attributes['groups'] = (array)$groups;
173 12
        $this->addExclusionStrategy(new GroupsExclusionStrategy((array)$groups));
174
175 12
        return $this;
176
    }
177
178 2
    public function enableMaxDepthChecks(): self
179
    {
180 2
        $this->addExclusionStrategy(new DepthExclusionStrategy());
181
182 2
        return $this;
183
    }
184
185
    /**
186
     * Set if NULLs should be serialized (TRUE) ot not (FALSE)
187
     */
188 19
    public function setSerializeNull(bool $bool): self
189
    {
190 19
        $this->serializeNull = $bool;
191
192 19
        return $this;
193
    }
194
195
    /**
196
     * Returns TRUE when NULLs should be serialized
197
     * Returns FALSE when NULLs should not be serialized
198
     * Returns NULL when NULLs should not be serialized,
199
     * but the user has not explicitly decided to use this policy
200
     *
201
     * @return bool
202
     */
203 272
    public function shouldSerializeNull(): bool
204
    {
205 272
        return $this->serializeNull;
206
    }
207
208
    /**
209
     * @return string
210
     */
211 200
    public function getFormat(): string
212
    {
213 200
        return $this->format;
214
    }
215
216 166
    public function pushClassMetadata(ClassMetadata $metadata): void
217
    {
218 166
        $this->metadataStack->push($metadata);
219 166
    }
220
221 165
    public function pushPropertyMetadata(PropertyMetadata $metadata): void
222
    {
223 165
        $this->metadataStack->push($metadata);
224 165
    }
225
226 162
    public function popPropertyMetadata(): void
227
    {
228 162
        $metadata = $this->metadataStack->pop();
229
230 162
        if (!$metadata instanceof PropertyMetadata) {
231
            throw new RuntimeException('Context metadataStack not working well');
232
        }
233 162
    }
234
235 161
    public function popClassMetadata(): void
236
    {
237 161
        $metadata = $this->metadataStack->pop();
238
239 161
        if (!$metadata instanceof ClassMetadata) {
240
            throw new RuntimeException('Context metadataStack not working well');
241
        }
242 161
    }
243
244 7
    public function getMetadataStack(): \SplStack
245
    {
246 7
        return $this->metadataStack;
247
    }
248
249
250
    abstract public function getDepth(): int;
251
252
    /**
253
     * @return integer
254
     */
255
    abstract public function getDirection(): int;
256
}
257