Completed
Push — master ( 5c03a8...602bd8 )
by Johannes
8s
created

GenericDeserializationVisitor::visitProperty()   B

Complexity

Conditions 5
Paths 4

Size

Total Lines 16
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 8
CRAP Score 5.0342

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 16
ccs 8
cts 9
cp 0.8889
rs 8.8571
cc 5
eloc 8
nc 4
nop 3
crap 5.0342
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\Metadata\PropertyMetadata;
23
use JMS\Serializer\Metadata\ClassMetadata;
24
25
/**
26
 * Generic Deserialization Visitor.
27
 *
28
 * @author Johannes M. Schmitt <[email protected]>
29
 */
30
abstract class GenericDeserializationVisitor extends AbstractVisitor
31
{
32
    private $navigator;
33
    private $result;
34
    private $objectStack;
35
    private $currentObject;
36
37 47
    public function setNavigator(GraphNavigator $navigator)
38
    {
39 47
        $this->navigator = $navigator;
40 47
        $this->result = null;
41 47
        $this->objectStack = new \SplStack;
42 47
    }
43
44 1
    public function getNavigator()
45
    {
46 1
        return $this->navigator;
47
    }
48
49 46
    public function prepare($data)
50
    {
51 46
        return $this->decode($data);
52
    }
53
54 1
    public function visitNull($data, array $type, Context $context)
55
    {
56 1
        return null;
57
    }
58
59 18
    public function visitString($data, array $type, Context $context)
60
    {
61 18
        $data = (string) $data;
62
63 18
        if (null === $this->result) {
64 3
            $this->result = $data;
65 3
        }
66
67 18
        return $data;
68
    }
69
70 5
    public function visitBoolean($data, array $type, Context $context)
71
    {
72 5
        $data = (Boolean) $data;
73
74 5
        if (null === $this->result) {
75 2
            $this->result = $data;
76 2
        }
77
78 5
        return $data;
79
    }
80
81 8
    public function visitInteger($data, array $type, Context $context)
82
    {
83 8
        $data = (integer) $data;
84
85 8
        if (null === $this->result) {
86 2
            $this->result = $data;
87 2
        }
88
89 8
        return $data;
90
    }
91
92 13
    public function visitDouble($data, array $type, Context $context)
93
    {
94 13
        $data = (double) $data;
95
96 13
        if (null === $this->result) {
97 6
            $this->result = $data;
98 6
        }
99
100 13
        return $data;
101
    }
102
103 15
    public function visitArray($data, array $type, Context $context)
104
    {
105 15
        if ( ! is_array($data)) {
106
            throw new RuntimeException(sprintf('Expected array, but got %s: %s', gettype($data), json_encode($data)));
107
        }
108
109
        // If no further parameters were given, keys/values are just passed as is.
110 15
        if ( ! $type['params']) {
111 1
            if (null === $this->result) {
112 1
                $this->result = $data;
113 1
            }
114
115 1
            return $data;
116
        }
117
118 14
        switch (count($type['params'])) {
119 14
            case 1: // Array is a list.
120 13
                $listType = $type['params'][0];
121
122 13
                $result = array();
123 13
                if (null === $this->result) {
124 5
                    $this->result = &$result;
125 5
                }
126
127 13
                foreach ($data as $v) {
128 12
                    $result[] = $this->navigator->accept($v, $listType, $context);
129 13
                }
130
131 13
                return $result;
132
133 4
            case 2: // Array is a map.
134 4
                list($keyType, $entryType) = $type['params'];
135
136 4
                $result = array();
137 4
                if (null === $this->result) {
138
                    $this->result = &$result;
139
                }
140
141 4
                foreach ($data as $k => $v) {
142 4
                    $result[$this->navigator->accept($k, $keyType, $context)] = $this->navigator->accept($v, $entryType, $context);
143 4
                }
144
145 4
                return $result;
146
147
            default:
148
                throw new RuntimeException(sprintf('Array type cannot have more than 2 parameters, but got %s.', json_encode($type['params'])));
149
        }
150
    }
151
152 23
    public function startVisitingObject(ClassMetadata $metadata, $object, array $type, Context $context)
153
    {
154 23
        $this->setCurrentObject($object);
155
156 23
        if (null === $this->result) {
157 22
            $this->result = $this->currentObject;
158 22
        }
159 23
    }
160
161 23
    public function visitProperty(PropertyMetadata $metadata, $data, Context $context)
162
    {
163 23
        $name = $this->namingStrategy->translateName($metadata);
164
165 23
        if (null === $data || ! array_key_exists($name, $data)) {
166 1
            return;
167
        }
168
169 23
        if ( ! $metadata->type) {
170
            throw new RuntimeException(sprintf('You must define a type for %s::$%s.', $metadata->reflection->class, $metadata->name));
171
        }
172
173 23
        $v = $data[$name] !== null ? $this->navigator->accept($data[$name], $metadata->type, $context) : null;
174
175 23
        $metadata->setValue($this->currentObject, $v);
176 23
    }
177
178 23
    public function endVisitingObject(ClassMetadata $metadata, $data, array $type, Context $context)
179
    {
180 23
        $obj = $this->currentObject;
181 23
        $this->revertCurrentObject();
182
183 23
        return $obj;
184
    }
185
186 46
    public function getResult()
187
    {
188 46
        return $this->result;
189
    }
190
191 23
    public function setCurrentObject($object)
192
    {
193 23
        $this->objectStack->push($this->currentObject);
194 23
        $this->currentObject = $object;
195 23
    }
196
197
    public function getCurrentObject()
198
    {
199
        return $this->currentObject;
200
    }
201
202 23
    public function revertCurrentObject()
203
    {
204 23
        return $this->currentObject = $this->objectStack->pop();
205
    }
206
207
    abstract protected function decode($str);
208
}
209