Completed
Pull Request — master (#447)
by Ivan
07:22
created

Context::popIndexMetadata()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 8
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 8
rs 9.4285
cc 2
eloc 4
nc 2
nop 0
1
<?php
2
3
/*
4
 * Copyright 2013 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\RuntimeException;
22
use JMS\Serializer\Exclusion\DepthExclusionStrategy;
23
use JMS\Serializer\Exclusion\DisjunctExclusionStrategy;
24
use JMS\Serializer\Exclusion\ExclusionStrategyInterface;
25
use JMS\Serializer\Exclusion\GroupsExclusionStrategy;
26
use JMS\Serializer\Exclusion\VersionExclusionStrategy;
27
use JMS\Serializer\Metadata\ClassMetadata;
28
use JMS\Serializer\Metadata\IndexMetadata;
29
use JMS\Serializer\Metadata\PropertyMetadata;
30
use Metadata\MetadataFactory;
31
use Metadata\MetadataFactoryInterface;
32
use PhpCollection\Map;
33
34
abstract class Context
35
{
36
    /**
37
     * @var \PhpCollection\Map
38
     */
39
    public $attributes;
40
41
    private $format;
42
43
    /** @var VisitorInterface */
44
    private $visitor;
45
46
    /** @var GraphNavigator */
47
    private $navigator;
48
49
    /** @var MetadataFactory */
50
    private $metadataFactory;
51
52
    /** @var ExclusionStrategyInterface */
53
    private $exclusionStrategy;
54
55
    /** @var boolean */
56
    private $serializeNull;
57
58
    private $initialized = false;
59
60
    /** @var \SplStack */
61
    private $metadataStack;
62
63
    public function __construct()
64
    {
65
        $this->attributes = new Map();
66
    }
67
68
    /**
69
     * @param string $format
70
     */
71
    public function initialize($format, VisitorInterface $visitor, GraphNavigator $navigator, MetadataFactoryInterface $factory)
72
    {
73
        if ($this->initialized) {
74
            throw new \LogicException('This context was already initialized, and cannot be re-used.');
75
        }
76
77
        $this->initialized = true;
78
        $this->format = $format;
79
        $this->visitor = $visitor;
80
        $this->navigator = $navigator;
81
        $this->metadataFactory = $factory;
0 ignored issues
show
Documentation Bug introduced by
$factory is of type object<Metadata\MetadataFactoryInterface>, but the property $metadataFactory was declared to be of type object<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
        $this->metadataStack = new \SplStack();
83
    }
84
85
    public function accept($data, array $type = null)
86
    {
87
        return $this->navigator->accept($data, $type, $this);
88
    }
89
90
    public function getMetadataFactory()
91
    {
92
        return $this->metadataFactory;
93
    }
94
95
    public function getVisitor()
96
    {
97
        return $this->visitor;
98
    }
99
100
    public function getNavigator()
101
    {
102
        return $this->navigator;
103
    }
104
105
    public function getExclusionStrategy()
106
    {
107
        return $this->exclusionStrategy;
108
    }
109
110
    public function setAttribute($key, $value)
111
    {
112
        $this->assertMutable();
113
        $this->attributes->set($key, $value);
114
115
        return $this;
116
    }
117
118
    private function assertMutable()
119
    {
120
        if ( ! $this->initialized) {
121
            return;
122
        }
123
124
        throw new \LogicException('This context was already initialized and is immutable; you cannot modify it anymore.');
125
    }
126
127
    public function addExclusionStrategy(ExclusionStrategyInterface $strategy)
128
    {
129
        $this->assertMutable();
130
131
        if (null === $this->exclusionStrategy) {
132
            $this->exclusionStrategy = $strategy;
133
134
            return $this;
135
        }
136
137
        if ($this->exclusionStrategy instanceof DisjunctExclusionStrategy) {
138
            $this->exclusionStrategy->addStrategy($strategy);
139
140
            return $this;
141
        }
142
143
        $this->exclusionStrategy = new DisjunctExclusionStrategy(array(
144
            $this->exclusionStrategy,
145
            $strategy,
146
        ));
147
148
        return $this;
149
    }
150
151
    /**
152
     * @param integer $version
153
     */
154
    public function setVersion($version)
155
    {
156
        if (null === $version) {
157
            throw new \LogicException('The version must not be null.');
158
        }
159
160
        $this->attributes->set('version', $version);
0 ignored issues
show
Documentation introduced by
$version is of type integer, but the function expects a object<PhpCollection\V>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
161
        $this->addExclusionStrategy(new VersionExclusionStrategy($version));
162
163
        return $this;
164
    }
165
166
    /**
167
     * @param array|string $groups
168
     */
169
    public function setGroups($groups)
170
    {
171
        if (empty($groups)) {
172
            throw new \LogicException('The groups must not be empty.');
173
        }
174
175
        $this->attributes->set('groups', (array) $groups);
0 ignored issues
show
Documentation introduced by
(array) $groups is of type array, but the function expects a object<PhpCollection\V>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
176
        $this->addExclusionStrategy(new GroupsExclusionStrategy((array) $groups));
177
178
        return $this;
179
    }
180
181
    public function enableMaxDepthChecks()
182
    {
183
        $this->addExclusionStrategy(new DepthExclusionStrategy());
184
185
        return $this;
186
    }
187
188
    public function setSerializeNull($bool)
189
    {
190
        $this->serializeNull = (boolean) $bool;
191
192
        return $this;
193
    }
194
195
    public function shouldSerializeNull()
196
    {
197
        return $this->serializeNull;
198
    }
199
200
    /**
201
     * @return string
202
     */
203
    public function getFormat()
204
    {
205
        return $this->format;
206
    }
207
208
    public function pushClassMetadata(ClassMetadata $metadata)
209
    {
210
        $this->metadataStack->push($metadata);
211
    }
212
213
    public function pushPropertyMetadata(PropertyMetadata $metadata)
214
    {
215
        $this->metadataStack->push($metadata);
216
    }
217
218
    public function pushIndexMetadata(IndexMetadata $metadata)
219
    {
220
        $this->metadataStack->push($metadata);
221
    }
222
223
    public function popIndexMetadata()
224
    {
225
        $metadata = $this->metadataStack->pop();
226
227
        if ( ! $metadata instanceof IndexMetadata) {
228
            throw new RuntimeException('Context metadataStack not working well');
229
        }
230
    }
231
232
    public function popPropertyMetadata()
233
    {
234
        $metadata = $this->metadataStack->pop();
235
236
        if ( ! $metadata instanceof PropertyMetadata) {
237
            throw new RuntimeException('Context metadataStack not working well');
238
        }
239
    }
240
241
    public function popClassMetadata()
242
    {
243
        $metadata = $this->metadataStack->pop();
244
245
        if ( ! $metadata instanceof ClassMetadata) {
246
            throw new RuntimeException('Context metadataStack not working well');
247
        }
248
    }
249
250
    public function getMetadataStack()
251
    {
252
        return $this->metadataStack;
253
    }
254
255
    abstract public function getDepth();
256
257
    /**
258
     * @return integer
259
     */
260
    abstract public function getDirection();
261
}
262