Passed
Pull Request — master (#1394)
by
unknown
11:16
created

Context::getPropertyNamingStrategy()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 1
CRAP Score 1.125

Importance

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