Passed
Pull Request — master (#965)
by Asmir
02:38
created

Context::setGroups()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 9
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 4
CRAP Score 2.032

Importance

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