Completed
Push — master ( ac0b2b...25e509 )
by Nate
02:57
created

ReflectionTypeAdapter::read()   C

Complexity

Conditions 7
Paths 5

Size

Total Lines 33
Code Lines 20

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 19
CRAP Score 7

Importance

Changes 0
Metric Value
dl 0
loc 33
ccs 19
cts 19
cp 1
rs 6.7272
c 0
b 0
f 0
cc 7
eloc 20
nc 5
nop 1
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\ClassMetadata;
10
use Tebru\Gson\Internal\Data\MetadataPropertyCollection;
11
use Tebru\Gson\Internal\Data\Property;
12
use Tebru\Gson\Internal\Excluder;
13
use Tebru\Gson\JsonWritable;
14
use Tebru\Gson\Internal\Data\PropertyCollection;
15
use Tebru\Gson\JsonReadable;
16
use Tebru\Gson\Internal\ObjectConstructor;
17
use Tebru\Gson\JsonToken;
18
use Tebru\Gson\TypeAdapter;
19
20
/**
21
 * Class ReflectionTypeAdapter
22
 *
23
 * Uses reflected class properties to read/write object
24
 *
25
 * @author Nate Brunette <[email protected]>
26
 */
27
final class ReflectionTypeAdapter extends TypeAdapter
28
{
29
    /**
30
     * @var ObjectConstructor
31
     */
32
    private $objectConstructor;
33
34
    /**
35
     * @var PropertyCollection
36
     */
37
    private $properties;
38
39
    /**
40
     * @var MetadataPropertyCollection
41
     */
42
    private $metadataPropertyCollection;
43
44
    /**
45
     * @var ClassMetadata
46
     */
47
    private $classMetadata;
48
49
    /**
50
     * Constructor
51
     *
52
     * @param ObjectConstructor $objectConstructor
53
     * @param PropertyCollection $properties
54
     * @param MetadataPropertyCollection $metadataPropertyCollection
55
     * @param ClassMetadata $classMetadata
56
     */
57 6
    public function __construct(
58
        ObjectConstructor $objectConstructor,
59
        PropertyCollection $properties,
60
        MetadataPropertyCollection $metadataPropertyCollection,
61
        ClassMetadata $classMetadata
62
    ) {
63 6
        $this->objectConstructor = $objectConstructor;
64 6
        $this->properties = $properties;
65 6
        $this->metadataPropertyCollection = $metadataPropertyCollection;
66 6
        $this->classMetadata = $classMetadata;
67 6
    }
68
    /**
69
     * Read the next value, convert it to its type and return it
70
     *
71
     * @param JsonReadable $reader
72
     * @return mixed
73
     * @throws \InvalidArgumentException if the type cannot be handled by a type adapter
74
     */
75 3
    public function read(JsonReadable $reader)
76
    {
77 3
        if ($reader->peek() === JsonToken::NULL) {
78 1
            return $reader->nextNull();
79
        }
80
81 2
        if (Excluder::excludeClassByStrategy($this->classMetadata, false)) {
82 1
            $reader->skipValue();
83
84 1
            return null;
85
        }
86
87 1
        $object = $this->objectConstructor->construct();
88
89 1
        $reader->beginObject();
90 1
        while ($reader->hasNext()) {
91 1
            $name = $reader->nextName();
92 1
            $property = $this->properties->getBySerializedName($name);
93
            if (
94 1
                null === $property
95 1
                || $property->skipDeserialize()
96 1
                || Excluder::excludePropertyByStrategy($this->metadataPropertyCollection->get($property->getRealName()), false)
0 ignored issues
show
Bug introduced by
It seems like $this->metadataPropertyC...roperty->getRealName()) can be null; however, excludePropertyByStrategy() does not accept null, maybe add an additional type check?

Unless you are absolutely sure that the expression can never be null because of other conditions, we strongly recommend to add an additional type check to your code:

/** @return stdClass|null */
function mayReturnNull() { }

function doesNotAcceptNull(stdClass $x) { }

// With potential error.
function withoutCheck() {
    $x = mayReturnNull();
    doesNotAcceptNull($x); // Potential error here.
}

// Safe - Alternative 1
function withCheck1() {
    $x = mayReturnNull();
    if ( ! $x instanceof stdClass) {
        throw new \LogicException('$x must be defined.');
    }
    doesNotAcceptNull($x);
}

// Safe - Alternative 2
function withCheck2() {
    $x = mayReturnNull();
    if ($x instanceof stdClass) {
        doesNotAcceptNull($x);
    }
}
Loading history...
97
            ) {
98 1
                $reader->skipValue();
99 1
                continue;
100
            }
101
102 1
            $property->read($reader, $object);
103
        }
104 1
        $reader->endObject();
105
106 1
        return $object;
107
    }
108
109
    /**
110
     * Write the value to the writer for the type
111
     *
112
     * @param JsonWritable $writer
113
     * @param mixed $value
114
     * @return void
115
     */
116 3
    public function write(JsonWritable $writer, $value): void
117
    {
118 3
        if (null === $value) {
119 1
            $writer->writeNull();
120
121 1
            return;
122
        }
123
124 2
        if (Excluder::excludeClassByStrategy($this->classMetadata, true)) {
125 1
            $writer->writeNull();
126
127 1
            return;
128
        }
129
130 1
        $writer->beginObject();
131
132
        /** @var Property $property */
133 1
        foreach ($this->properties as $property) {
134 1
            $writer->name($property->getSerializedName());
135
136
            if (
137 1
                $property->skipSerialize()
138 1
                || Excluder::excludePropertyByStrategy($this->metadataPropertyCollection->get($property->getRealName()), true)
0 ignored issues
show
Bug introduced by
It seems like $this->metadataPropertyC...roperty->getRealName()) can be null; however, excludePropertyByStrategy() does not accept null, maybe add an additional type check?

Unless you are absolutely sure that the expression can never be null because of other conditions, we strongly recommend to add an additional type check to your code:

/** @return stdClass|null */
function mayReturnNull() { }

function doesNotAcceptNull(stdClass $x) { }

// With potential error.
function withoutCheck() {
    $x = mayReturnNull();
    doesNotAcceptNull($x); // Potential error here.
}

// Safe - Alternative 1
function withCheck1() {
    $x = mayReturnNull();
    if ( ! $x instanceof stdClass) {
        throw new \LogicException('$x must be defined.');
    }
    doesNotAcceptNull($x);
}

// Safe - Alternative 2
function withCheck2() {
    $x = mayReturnNull();
    if ($x instanceof stdClass) {
        doesNotAcceptNull($x);
    }
}
Loading history...
139
            ) {
140
                $writer->writeNull();
141
142
                continue;
143
            }
144
145 1
            $property->write($writer, $value);
146
        }
147
148 1
        $writer->endObject();
149 1
    }
150
}
151