Completed
Push — master ( 0d4fd4...557d64 )
by Denis
02:02
created

TypeAdapter::createMap()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 14
Code Lines 9

Duplication

Lines 5
Ratio 35.71 %

Importance

Changes 0
Metric Value
dl 5
loc 14
rs 9.4285
c 0
b 0
f 0
cc 2
eloc 9
nc 2
nop 2
1
<?php
2
3
namespace PhpJsonRpc\Common\TypeAdapter;
4
5
class TypeAdapter
6
{
7
    /**
8
     * @var Rule[]
9
     */
10
    private $rules = [];
11
12
    /**
13
     * @param Rule
14
     *
15
     * @return $this
16
     */
17
    public function register(Rule $rule)
18
    {
19
        $this->rules[$rule->getClass()] = $rule;
20
        return $this;
21
    }
22
23
    /**
24
     * @param string $class
25
     *
26
     * @return bool
27
     */
28
    public function isClassRegistered(string $class): bool
29
    {
30
        return array_key_exists($class, $this->rules);
31
    }
32
33
    /**
34
     * @param mixed $value Array
35
     *
36
     * @return mixed Instance of registered class
37
     */
38
    public function toObject($value)
39
    {
40
        if (!is_array($value)) {
41
            throw new TypeCastException('Is not array');
42
        }
43
44
        foreach ($this->rules as $class => $rule) {
45
            if ($this->isMatch($rule, $value)) {
46
                return $this->createInstance($class, $value);
47
            }
48
        }
49
50
        throw new TypeCastException('Rule not found');
51
    }
52
53
    /**
54
     * @param mixed $value Instance of registered class
55
     *
56
     * @return array
57
     */
58
    public function toArray($value)
59
    {
60
        if (!is_object($value)) {
61
            throw new TypeCastException('Is not object');
62
        }
63
64
        foreach ($this->rules as $class => $rule)
65
        {
66
            if (get_class($value) === $class) {
0 ignored issues
show
Unused Code Bug introduced by
The strict comparison === seems to always evaluate to false as the types of get_class($value) (string) and $class (integer) can never be identical. Maybe you want to use a loose comparison == instead?
Loading history...
67
                return $this->createMap($class, $value);
68
            }
69
        }
70
71
        throw new TypeCastException('Rule not found');
72
    }
73
74
    /**
75
     * @return bool
76
     */
77
    public function isEmpty(): bool
78
    {
79
        return count($this->rules) === 0;
80
    }
81
82
    /**
83
     * @param Rule $expected Transform rule
84
     * @param array $value   Raw unknown value
85
     *
86
     * @return bool
87
     */
88
    private function isMatch(Rule $expected, array $value): bool
89
    {
90
        return 0 === count(array_diff(array_keys($expected->getReflectedMap()), array_keys($value)));
91
    }
92
93
    /**
94
     * @param string $class
95
     * @param array  $data
96
     *
97
     * @return object
98
     */
99
    private function createInstance(string $class, array $data)
100
    {
101
        $rule = $this->rules[$class];
102
103
        $reflectionClass = new \ReflectionClass($class);
104
        $object = $reflectionClass->newInstanceWithoutConstructor();
105
        $reflectionObject = new \ReflectionObject($object);
106
107 View Code Duplication
        foreach ($rule->getMap() as $property => $key) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
108
            $reflectionProperty = $reflectionObject->getProperty($property);
109
            $reflectionProperty->setAccessible(true);
110
            $reflectionProperty->setValue($object, $data[$key]);
111
        }
112
113
        return $object;
114
    }
115
116
    /**
117
     * @param string $class
118
     * @param object $object
119
     *
120
     * @return array
121
     */
122
    private function createMap(string $class, $object)
123
    {
124
        $rule = $this->rules[$class];
125
        $reflectionObject = new \ReflectionObject($object);
126
        $result = [];
127
128 View Code Duplication
        foreach ($rule->getMap() as $property => $key) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
129
            $reflectionProperty = $reflectionObject->getProperty($property);
130
            $reflectionProperty->setAccessible(true);
131
            $result[$key] = $reflectionProperty->getValue($object);
132
        }
133
134
        return $result;
135
    }
136
}
137