TdbmHydrator::hydrateObjectFromUnderscoredData()   A
last analyzed

Complexity

Conditions 3
Paths 3

Size

Total Lines 19
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 19
rs 9.4285
cc 3
eloc 9
nc 3
nop 2
1
<?php
2
3
4
namespace Mouf\Hydrator;
5
6
7
use Stringy\StaticStringy;
8
use function Stringy\create as s;
9
10
class TdbmHydrator implements Hydrator
11
{
12
13
    /**
14
     * Creates a new $className object, filling it with $data.
15
     *
16
     * @param array $data
17
     * @param string $className
18
     * @return object
19
     */
20
    public function hydrateNewObject(array $data, string $className)
21
    {
22
        $reflectionClass = new \ReflectionClass($className);
23
        $underscoredData = $this->underscoreData($data);
24
        $parameters = [];
25
26
        $constructor = $reflectionClass->getConstructor();
27
28
        if ($constructor !== null) {
29
            $constructorParameters = $constructor->getParameters();
30
31
            foreach ($constructorParameters as $constructorParameter) {
32
                $underscoredVariableName = (string) StaticStringy::underscored($constructorParameter->getName());
33
34
                if (array_key_exists($underscoredVariableName, $underscoredData)) {
35
                    $value = $underscoredData[$underscoredVariableName];
36
                    unset($underscoredData[$underscoredVariableName]);
37
                } else {
38
                    if (!$constructorParameter->isDefaultValueAvailable()) {
39
                        throw MissingParameterException::create($constructorParameter->getName());
40
                    }
41
                    $value = $constructorParameter->getDefaultValue();
42
                }
43
44
                // TODO: check if sub object!
45
                $parameters[] = $value;
46
            }
47
        }
48
49
        $object = $reflectionClass->newInstanceArgs($parameters);
50
51
        $this->hydrateObjectFromUnderscoredData($underscoredData, $object);
52
53
        return $object;
54
    }
55
56
    /**
57
     * Underscores the keys of the array.
58
     *
59
     * @param array $data
60
     */
61
    private function underscoreData(array $data)
62
    {
63
        $underscoredData = [];
64
        foreach ($data as $key => $value) {
65
            $underscoredData[(string) StaticStringy::underscored($key)] = $value;
66
        }
67
        return $underscoredData;
68
    }
69
70
    /**
71
     * Fills $object with $data.
72
     *
73
     * @param array $data
74
     * @param $object
75
     */
76
    public function hydrateObject(array $data, $object)
77
    {
78
        $underscoredData = $this->underscoreData($data);
79
        $this->hydrateObjectFromUnderscoredData($underscoredData, $object);
80
    }
81
82
    private function hydrateObjectFromUnderscoredData(array $underscoredData, $object)
83
    {
84
        $reflectionClass = new \ReflectionClass($object);
85
86
        $setters = $this->getSetters($reflectionClass);
87
88
        foreach ($setters as $underscoredName => $setter) {
89
90
            if (array_key_exists($underscoredName, $underscoredData)) {
91
                $value = $underscoredData[$underscoredName];
92
                unset($underscoredData[$underscoredName]);
93
                $setterName = $setter->getName();
0 ignored issues
show
Bug introduced by
Consider using $setter->name. There is an issue with getName() and APC-enabled PHP versions.
Loading history...
94
95
                $object->$setterName($value);
96
            }
97
98
            // TODO: check if sub object!
99
        }
100
    }
101
102
    /**
103
     * Returns an array of setters reflection methods, indexed by "underscored" name.
104
     *
105
     * @param \ReflectionClass $reflectionClass
106
     * @return \ReflectionMethod[]
107
     */
108
    private function getSetters(\ReflectionClass $reflectionClass) {
109
        $reflectionMethods = $reflectionClass->getMethods(\ReflectionMethod::IS_PUBLIC);
110
111
        $setters = [];
112
113
        foreach ($reflectionMethods as $reflectionMethod) {
114
            $methodName = s($reflectionMethod->getName());
0 ignored issues
show
Bug introduced by
Consider using $reflectionMethod->name. There is an issue with getName() and APC-enabled PHP versions.
Loading history...
115
            $parameters = $reflectionMethod->getParameters();
116
            if ($methodName->startsWith('set') && count($parameters) >= 1) {
117
                // Let's check that the setter has no more than 1 compulsory parameter.
118
                array_shift($parameters);
119
                foreach ($parameters as $optionalParameters) {
120
                    if (!$optionalParameters->isDefaultValueAvailable()) {
121
                        continue 2;
122
                    }
123
                }
124
                $underscored = (string) $methodName->substr(3)->underscored();
125
                $setters[$underscored] = $reflectionMethod;
126
            }
127
        }
128
129
        return $setters;
130
    }
131
}
132