Completed
Push — master ( 2cb393...81b69d )
by Eric
02:29
created

AbstractVisitor::navigate()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 4
c 0
b 0
f 0
rs 10
cc 1
eloc 2
nc 1
nop 3
1
<?php
2
3
/*
4
 * This file is part of the Ivory Serializer package.
5
 *
6
 * (c) Eric GELOEN <[email protected]>
7
 *
8
 * For the full copyright and license information, please read the LICENSE
9
 * file that was distributed with this source code.
10
 */
11
12
namespace Ivory\Serializer\Visitor;
13
14
use Ivory\Serializer\Context\ContextInterface;
15
use Ivory\Serializer\Mapping\ClassMetadataInterface;
16
use Ivory\Serializer\Mapping\MetadataInterface;
17
use Ivory\Serializer\Mapping\PropertyMetadataInterface;
18
use Ivory\Serializer\Mapping\TypeMetadataInterface;
19
use Ivory\Serializer\Navigator\NavigatorInterface;
20
21
/**
22
 * @author GeLo <[email protected]>
23
 */
24
abstract class AbstractVisitor implements VisitorInterface
25
{
26
    /**
27
     * @var \SplStack
28
     */
29
    private $dataStack;
30
31
    /**
32
     * @var \SplStack
33
     */
34
    private $metadataStack;
35
36
    /**
37
     * @var NavigatorInterface
38
     */
39
    protected $navigator;
40
41
    /**
42
     * {@inheritdoc}
43
     */
44
    public function prepare($data, ContextInterface $context)
45
    {
46
        $this->navigator = $context->getNavigator();
47
        $this->dataStack = $context->getDataStack();
48
        $this->metadataStack = $context->getMetadataStack();
49
50
        return $data;
51
    }
52
53
    /**
54
     * {@inheritdoc}
55
     */
56
    public function visitArray($data, TypeMetadataInterface $type, ContextInterface $context)
57
    {
58
        $this->enterScope($data, $type);
59
60
        if ($context->getExclusionStrategy()->skipType($type, $context)) {
61
            $data = [];
62
        }
63
64
        $result = $this->doVisitArray($data, $type, $context);
65
        $this->leaveScope();
66
67
        return $result;
68
    }
69
70
    /**
71
     * {@inheritdoc}
72
     */
73
    public function visitBoolean($data, TypeMetadataInterface $type, ContextInterface $context)
74
    {
75
        return $this->visitData((bool) $data, $type, $context);
76
    }
77
78
    /**
79
     * {@inheritdoc}
80
     */
81
    public function visitFloat($data, TypeMetadataInterface $type, ContextInterface $context)
82
    {
83
        return $this->visitData((float) $data, $type, $context);
84
    }
85
86
    /**
87
     * {@inheritdoc}
88
     */
89
    public function visitInteger($data, TypeMetadataInterface $type, ContextInterface $context)
90
    {
91
        return $this->visitData((int) $data, $type, $context);
92
    }
93
94
    /**
95
     * {@inheritdoc}
96
     */
97
    public function visitNull($data, TypeMetadataInterface $type, ContextInterface $context)
98
    {
99
        return $this->visitData(null, $type, $context);
100
    }
101
102
    /**
103
     * {@inheritdoc}
104
     */
105
    public function visitResource($data, TypeMetadataInterface $type, ContextInterface $context)
106
    {
107
        throw new \RuntimeException('(De)-Serializing a resource is not supported.');
108
    }
109
110
    /**
111
     * {@inheritdoc}
112
     */
113
    public function visitString($data, TypeMetadataInterface $type, ContextInterface $context)
114
    {
115
        return $this->visitData((string) $data, $type, $context);
116
    }
117
118
    /**
119
     * {@inheritdoc}
120
     */
121
    public function startVisitingObject($data, ClassMetadataInterface $class, ContextInterface $context)
122
    {
123
        if ($context->getExclusionStrategy()->skipClass($class, $context)) {
124
            return false;
125
        }
126
127
        $this->enterScope($data, $class);
128
129
        return true;
130
    }
131
132
    /**
133
     * {@inheritdoc}
134
     */
135
    public function visitObjectProperty($data, PropertyMetadataInterface $property, ContextInterface $context)
136
    {
137
        $visited = false;
138
139
        if (!$context->getExclusionStrategy()->skipProperty($property, $context)) {
140
            $this->enterScope($data, $property);
141
142
            $name = $property->hasAlias()
143
                ? $property->getAlias()
144
                : $context->getNamingStrategy()->convert($property->getName());
145
146
            $visited = $this->doVisitObjectProperty($data, $name, $property, $context);
147
            $this->leaveScope();
148
        }
149
150
        return $visited;
151
    }
152
153
    /**
154
     * {@inheritdoc}
155
     */
156
    public function finishVisitingObject($data, ClassMetadataInterface $class, ContextInterface $context)
157
    {
158
        $this->leaveScope();
159
    }
160
161
    /**
162
     * @param mixed                 $data
163
     * @param TypeMetadataInterface $type
164
     * @param ContextInterface      $context
165
     *
166
     * @return mixed
167
     */
168
    abstract protected function doVisitArray($data, TypeMetadataInterface $type, ContextInterface $context);
169
170
    /**
171
     * @param mixed                     $data
172
     * @param string                    $name
173
     * @param PropertyMetadataInterface $property
174
     * @param ContextInterface          $context
175
     *
176
     * @return bool
177
     */
178
    abstract protected function doVisitObjectProperty(
179
        $data,
180
        $name,
181
        PropertyMetadataInterface $property,
182
        ContextInterface $context
183
    );
184
185
    /**
186
     * @param mixed             $data
187
     * @param MetadataInterface $metadata
188
     */
189
    private function enterScope($data, MetadataInterface $metadata)
190
    {
191
        $this->dataStack->push($data);
192
        $this->metadataStack->push($metadata);
193
    }
194
195
    private function leaveScope()
196
    {
197
        $this->dataStack->pop();
198
        $this->metadataStack->pop();
199
    }
200
}
201