Completed
Push — master ( 3886f0...1f9c9a )
by Nate
02:55
created

ReflectionTypeAdapter::write()   C

Complexity

Conditions 7
Paths 6

Size

Total Lines 39
Code Lines 21

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 21
CRAP Score 7

Importance

Changes 0
Metric Value
dl 0
loc 39
ccs 21
cts 21
cp 1
rs 6.7272
c 0
b 0
f 0
cc 7
eloc 21
nc 6
nop 2
crap 7
1
<?php
2
/*
3
 * Copyright (c) Nate Brunette.
4
 * Distributed under the MIT License (http://opensource.org/licenses/MIT)
5
 */
6
7
namespace Tebru\Gson\Internal\TypeAdapter;
8
9
use Tebru\Gson\Annotation\JsonAdapter;
10
use Tebru\Gson\ClassMetadata;
11
use Tebru\Gson\Internal\Data\AnnotationSet;
12
use Tebru\Gson\Internal\Data\MetadataPropertyCollection;
13
use Tebru\Gson\Internal\Data\Property;
14
use Tebru\Gson\Internal\Excluder;
15
use Tebru\Gson\Internal\TypeAdapterProvider;
16
use Tebru\Gson\JsonWritable;
17
use Tebru\Gson\Internal\Data\PropertyCollection;
18
use Tebru\Gson\JsonReadable;
19
use Tebru\Gson\Internal\ObjectConstructor;
20
use Tebru\Gson\JsonToken;
21
use Tebru\Gson\TypeAdapter;
22
23
/**
24
 * Class ReflectionTypeAdapter
25
 *
26
 * Uses reflected class properties to read/write object
27
 *
28
 * @author Nate Brunette <[email protected]>
29
 */
30
final class ReflectionTypeAdapter extends TypeAdapter
31
{
32
    /**
33
     * @var ObjectConstructor
34
     */
35
    private $objectConstructor;
36
37
    /**
38
     * @var PropertyCollection
39
     */
40
    private $properties;
41
42
    /**
43
     * @var MetadataPropertyCollection
44
     */
45
    private $metadataPropertyCollection;
46
47
    /**
48
     * @var ClassMetadata
49
     */
50
    private $classMetadata;
51
52
    /**
53
     * @var Excluder
54
     */
55
    private $excluder;
56
57
    /**
58
     * @var TypeAdapterProvider
59
     */
60
    private $typeAdapterProvider;
61
62
    /**
63
     * Constructor
64
     *
65
     * @param ObjectConstructor $objectConstructor
66
     * @param PropertyCollection $properties
67
     * @param MetadataPropertyCollection $metadataPropertyCollection
68
     * @param ClassMetadata $classMetadata
69
     * @param Excluder $excluder
70
     * @param TypeAdapterProvider $typeAdapterProvider
71
     */
72 6
    public function __construct(
73
        ObjectConstructor $objectConstructor,
74
        PropertyCollection $properties,
75
        MetadataPropertyCollection $metadataPropertyCollection,
76
        ClassMetadata $classMetadata,
77
        Excluder $excluder,
78
        TypeAdapterProvider $typeAdapterProvider
79
    ) {
80 6
        $this->objectConstructor = $objectConstructor;
81 6
        $this->properties = $properties;
82 6
        $this->metadataPropertyCollection = $metadataPropertyCollection;
83 6
        $this->classMetadata = $classMetadata;
84 6
        $this->excluder = $excluder;
85 6
        $this->typeAdapterProvider = $typeAdapterProvider;
86 6
    }
87
    /**
88
     * Read the next value, convert it to its type and return it
89
     *
90
     * @param JsonReadable $reader
91
     * @return mixed
92
     * @throws \InvalidArgumentException if the type cannot be handled by a type adapter
93
     * @throws \Tebru\Gson\Exception\MalformedTypeException If the type cannot be parsed
94
     */
95 3
    public function read(JsonReadable $reader)
96
    {
97 3
        if ($reader->peek() === JsonToken::NULL) {
98 1
            return $reader->nextNull();
99
        }
100
101 2
        if ($this->excluder->excludeClassByStrategy($this->classMetadata, false)) {
102 1
            $reader->skipValue();
103
104 1
            return null;
105
        }
106
107 1
        $object = $this->objectConstructor->construct();
108
109 1
        $reader->beginObject();
110 1
        while ($reader->hasNext()) {
111 1
            $name = $reader->nextName();
112 1
            $property = $this->properties->getBySerializedName($name);
113
            if (
114 1
                null === $property
115 1
                || $property->skipDeserialize()
116 1
                || $this->excluder->excludePropertyByStrategy($this->metadataPropertyCollection->get($property->getRealName()), false)
117
            ) {
118 1
                $reader->skipValue();
119 1
                continue;
120
            }
121
122
            /** @var JsonAdapter $jsonAdapterAnnotation */
123 1
            $jsonAdapterAnnotation = $property->getAnnotations()->getAnnotation(JsonAdapter::class, AnnotationSet::TYPE_PROPERTY);
124 1
            $adapter = null === $jsonAdapterAnnotation
125 1
                ? $this->typeAdapterProvider->getAdapter($property->getType())
126 1
                : $this->typeAdapterProvider->getAdapterFromAnnotation($property->getType(), $jsonAdapterAnnotation);
127
128 1
            $property->set($object, $adapter->read($reader));
129
        }
130 1
        $reader->endObject();
131
132 1
        return $object;
133
    }
134
135
    /**
136
     * Write the value to the writer for the type
137
     *
138
     * @param JsonWritable $writer
139
     * @param mixed $value
140
     * @return void
141
     * @throws \InvalidArgumentException if the type cannot be handled by a type adapter
142
     * @throws \Tebru\Gson\Exception\MalformedTypeException If the type cannot be parsed
143
     */
144 3
    public function write(JsonWritable $writer, $value): void
145
    {
146 3
        if (null === $value) {
147 1
            $writer->writeNull();
148
149 1
            return;
150
        }
151
152 2
        if ($this->excluder->excludeClassByStrategy($this->classMetadata, true)) {
153 1
            $writer->writeNull();
154
155 1
            return;
156
        }
157
158 1
        $writer->beginObject();
159
160
        /** @var Property $property */
161 1
        foreach ($this->properties as $property) {
162 1
            $writer->name($property->getSerializedName());
163
164
            if (
165 1
                $property->skipSerialize()
166 1
                || $this->excluder->excludePropertyByStrategy($this->metadataPropertyCollection->get($property->getRealName()), true)
167
            ) {
168 1
                $writer->writeNull();
169
170 1
                continue;
171
            }
172
173
            /** @var JsonAdapter $jsonAdapterAnnotation */
174 1
            $jsonAdapterAnnotation = $property->getAnnotations()->getAnnotation(JsonAdapter::class, AnnotationSet::TYPE_PROPERTY);
175 1
            $adapter = null === $jsonAdapterAnnotation
176 1
                ? $this->typeAdapterProvider->getAdapter($property->getType())
177 1
                : $this->typeAdapterProvider->getAdapterFromAnnotation($property->getType(), $jsonAdapterAnnotation);
178 1
            $adapter->write($writer, $property->get($value));
179
        }
180
181 1
        $writer->endObject();
182 1
    }
183
}
184