Passed
Pull Request — master (#1394)
by
unknown
02:56
created

Context::setPropertyNamingStrategy()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 7
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

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