Passed
Push — master ( e3c67b...98eade )
by Fran
08:10
created

Dto::castValue()   B

Complexity

Conditions 8
Paths 8

Size

Total Lines 19
Code Lines 17

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 5
CRAP Score 30.5117

Importance

Changes 0
Metric Value
cc 8
eloc 17
c 0
b 0
f 0
nc 8
nop 3
dl 0
loc 19
ccs 5
cts 17
cp 0.294
crap 30.5117
rs 8.4444
1
<?php
2
namespace PSFS\base\dto;
3
4
use PSFS\base\Logger;
5
use PSFS\base\Request;
6
use PSFS\base\Singleton;
7
use PSFS\base\types\helpers\InjectorHelper;
8
9
/**
10
 * Class Dto
11
 * @package PSFS\base\dto
12
 */
13
class Dto extends Singleton implements \JsonSerializable
14
{
15
    /**
16
     * @var array
17
     */
18
    protected $__cache = [];
19 3
    public function __construct($hydrate = true)
20
    {
21 3
        parent::__construct();
22 3
        if($hydrate) {
23 1
            $this->fromArray(Request::getInstance()->getData());
24
        }
25 3
    }
26
27
    /**
28
     * ToArray wrapper
29
     * @return array
30
     */
31 3
    public function toArray()
32
    {
33 3
        return $this->__toArray();
34
    }
35
36
    /**
37
     * Convert dto to array representation
38
     * @return array
39
     */
40 3
    public function __toArray()
41
    {
42 3
        $dto = array();
43
        try {
44 3
            $reflectionClass = new \ReflectionClass($this);
45 3
            $properties = $reflectionClass->getProperties(\ReflectionProperty::IS_PUBLIC);
46 3
            if (count($properties) > 0) {
47
                /** @var \ReflectionProperty $property */
48 3
                foreach ($properties as $property) {
49 3
                    $value = $property->getValue($this);
50 3
                    if(is_object($value) && method_exists($value, 'toArray')) {
51 1
                        $dto[$property->getName()] = $value->toArray();
52 3
                    } elseif(is_array($value)) {
53 3
                        foreach($value as &$arrValue) {
54 2
                            if($arrValue instanceof Dto) {
55 2
                                $arrValue = $arrValue->toArray();
56
                            }
57
                        }
58 3
                        $dto[$property->getName()] = $value;
59
                    } else {
60 3
                        $dto[$property->getName()] = $property->getValue($this);
61
                    }
62
                }
63
            }
64
        } catch (\Exception $e) {
65
            Logger::log(get_class($this) . ': ' . $e->getMessage(), LOG_ERR);
66
        }
67 3
        return $dto;
68
    }
69
70
    /**
71
     * Convert to string representation
72
     * @return string
73
     */
74
    public function __toString()
75
    {
76
        return get_class($this);
77
    }
78
79
    /**
80
     * @param array $properties
81
     * @param $key
82
     * @param null $value
0 ignored issues
show
Documentation Bug introduced by
Are you sure the doc-type for parameter $value is correct as it would always require null to be passed?
Loading history...
83
     * @throws \ReflectionException
84
     */
85 1
    protected function parseDtoField(array $properties, $key, $value = null) {
86 1
        list($type, $isArray) = $this->extractTypes($properties, $key);
87 1
        $reflector = (class_exists($type)) ? new \ReflectionClass($type) : null;
88 1
        if(null !== $reflector && $reflector->isSubclassOf(Dto::class)) {
89 1
            if(null !== $value && is_array($value)) {
0 ignored issues
show
introduced by
The condition null !== $value is always false.
Loading history...
90 1
                if(!array_key_exists($type, $this->__cache)) {
91 1
                    $this->__cache[$type] = new $type(false);
92
                }
93 1
                if($isArray) {
94 1
                    $this->$key = [];
95 1
                    foreach($value as $data) {
96 1
                        if(null !== $data && is_array($data)) {
97 1
                            $dto = clone $this->__cache[$type];
98 1
                            $dto->fromArray($data);
99 1
                            array_push($this->$key, $dto);
100
                        }
101
                    }
102
                } else {
103 1
                    $this->$key = clone $this->__cache[$type];
104 1
                    $this->$key->fromArray($value);
105
                }
106
            }
107
        } else {
108 1
            $this->castValue($key, $value, $type);
109
        }
110 1
    }
111
112
    /**
113
     * Hydrate object from array
114
     * @param array $object
115
     * @throws \ReflectionException
116
     */
117 2
    public function fromArray(array $object = array())
118
    {
119 2
        if (count($object) > 0) {
120 1
            $reflector = new \ReflectionClass($this);
121 1
            $properties = InjectorHelper::extractProperties($reflector, \ReflectionProperty::IS_PUBLIC, InjectorHelper::VAR_PATTERN);
122 1
            unset($reflector);
123 1
            foreach ($object as $key => $value) {
124 1
                if (property_exists($this, $key) && null !== $value) {
125 1
                    $this->parseDtoField($properties, $key, $value);
126
                }
127
            }
128
        }
129 2
    }
130
131
    /**
132
     * @return array|mixed
133
     */
134
    public function jsonSerialize()
135
    {
136
        return $this->toArray();
137
    }
138
139
    /**
140
     * @param array $properties
141
     * @param $key
142
     * @return array
143
     */
144 1
    protected function extractTypes(array $properties, $key)
145
    {
146 1
        $type = 'string';
147 1
        $isArray = false;
148 1
        if (array_key_exists($key, $properties)) {
149 1
            $type = $properties[$key];
150 1
            if (preg_match('/(\[\]|Array)/i', $type)) {
151 1
                $type = preg_replace('/(\[\]|Array)/i', '', $type);
152 1
                $isArray = true;
153
            }
154
        }
155 1
        return array($type, $isArray);
156
    }
157
158
    /**
159
     * @param $key
160
     * @param $value
161
     * @param $type
162
     */
163 1
    protected function castValue($key, $value, $type)
164
    {
165 1
        switch ($type) {
166
            default:
167 1
            case 'string':
168 1
                $this->$key = (string)$value;
169 1
                break;
170
            case 'integer':
171
            case 'int':
172
                $this->$key = (integer)$value;
173
                break;
174
            case 'float':
175
            case 'double':
176
                $this->$key = (float)$value;
177
                break;
178
            case 'boolean':
179
            case 'bool':
180
                $this->$key = (bool)$value;
181
                break;
182
        }
183
    }
184
}