Test Failed
Push — master ( 1b7368...050678 )
by Fran
25:16 queued 22:49
created

Dto::toArray()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 1
c 1
b 0
f 0
nc 1
nop 0
dl 0
loc 3
ccs 0
cts 2
cp 0
crap 2
rs 10
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
    public function __construct($hydrate = true)
20
    {
21
        parent::__construct();
22
        if($hydrate) {
23
            $this->fromArray(Request::getInstance()->getData());
24
        }
25
    }
26
27
    /**
28
     * ToArray wrapper
29
     * @return array
30
     */
31
    public function toArray()
32
    {
33
        return $this->__toArray();
34
    }
35
36
    /**
37
     * Convert dto to array representation
38
     * @return array
39
     */
40
    public function __toArray()
41
    {
42
        $dto = [];
43
        try {
44
            $reflectionClass = new \ReflectionClass($this);
45
            $properties = $reflectionClass->getProperties(\ReflectionProperty::IS_PUBLIC);
46
            if (count($properties) > 0) {
47
                /** @var \ReflectionProperty $property */
48
                foreach ($properties as $property) {
49
                    $value = $property->getValue($this);
50
                    if(is_object($value) && method_exists($value, 'toArray')) {
51
                        $dto[$property->getName()] = $value->toArray();
52
                    } elseif(is_array($value)) {
53
                        foreach($value as &$arrValue) {
54
                            if($arrValue instanceof Dto) {
55
                                $arrValue = $arrValue->toArray();
56
                            }
57
                        }
58
                        $dto[$property->getName()] = $value;
59
                    } else {
60
                        $type = InjectorHelper::extractVarType($property->getDocComment());
0 ignored issues
show
Bug introduced by
Are you sure the assignment to $type is correct as PSFS\base\types\helpers\...perty->getDocComment()) targeting PSFS\base\types\helpers\...elper::extractVarType() seems to always return null.

This check looks for function or method calls that always return null and whose return value is assigned to a variable.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
$object = $a->getObject();

The method getObject() can return nothing but null, so it makes no sense to assign that value to a variable.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

Loading history...
61
                        $dto[$property->getName()] = $this->checkCastedValue($property->getValue($this), $type);
62
                    }
63
                }
64
            }
65
        } catch (\Exception $e) {
66
            Logger::log(get_class($this) . ': ' . $e->getMessage(), LOG_ERR);
67
        }
68
        return $dto;
69
    }
70
71
    /**
72
     * Convert to string representation
73
     * @return string
74
     */
75
    public function __toString()
76
    {
77
        return get_class($this);
78
    }
79
80
    /**
81
     * @param array $properties
82
     * @param $key
83
     * @param mixed $value
84
     * @throws \ReflectionException
85
     */
86
    protected function parseDtoField(array $properties, $key, $value = null) {
87
        list($type, $isArray) = $this->extractTypes($properties, $key);
88
        $reflector = (class_exists($type)) ? new \ReflectionClass($type) : null;
89
        if(null !== $reflector && $reflector->isSubclassOf(Dto::class)) {
90
            if(null !== $value && is_array($value)) {
91
                if(!array_key_exists($type, $this->__cache)) {
92
                    $this->__cache[$type] = new $type(false);
93
                }
94
                if($isArray) {
95
                    $this->$key = [];
96
                    foreach($value as $data) {
97
                        if(null !== $data && is_array($data)) {
98
                            $dto = clone $this->__cache[$type];
99
                            $dto->fromArray($data);
100
                            array_push($this->$key, $dto);
101
                        }
102
                    }
103
                } else {
104
                    $this->$key = clone $this->__cache[$type];
105
                    $this->$key->fromArray($value);
106
                }
107
            }
108
        } else {
109
            $this->castValue($key, $value, $type);
110
        }
111
    }
112
113
    /**
114
     * Hydrate object from array
115
     * @param array $object
116
     * @throws \ReflectionException
117
     */
118
    public function fromArray(array $object = array())
119
    {
120
        if (count($object) > 0) {
121
            $reflector = new \ReflectionClass($this);
122
            $properties = InjectorHelper::extractProperties($reflector, \ReflectionProperty::IS_PUBLIC, InjectorHelper::VAR_PATTERN);
123
            unset($reflector);
124
            foreach ($object as $key => $value) {
125
                if (property_exists($this, $key) && null !== $value) {
126
                    $this->parseDtoField($properties, $key, $value);
127
                }
128
            }
129
        }
130
    }
131
132
    /**
133
     * @return array|mixed
134
     */
135
    public function jsonSerialize(): mixed
136
    {
137
        return $this->toArray();
138
    }
139
140
    /**
141
     * @param array $properties
142
     * @param $key
143
     * @return array
144
     */
145
    protected function extractTypes(array $properties, $key)
146
    {
147
        $type = 'string';
148
        $isArray = false;
149
        if (array_key_exists($key, $properties)) {
150
            $type = $properties[$key];
151
            if (preg_match('/(\[\]|Array)/i', $type)) {
152
                $type = preg_replace('/(\[\]|Array)/i', '', $type);
153
                $isArray = true;
154
            }
155
        }
156
        return array($type, $isArray);
157
    }
158
159
    /**
160
     * @param string $key
161
     * @param mixed $value
162
     * @param string $type
163
     */
164
    protected function castValue($key, $value, $type)
165
    {
166
        $this->$key = $this->checkCastedValue($value, $type);
167
    }
168
169
    /**
170
     * @param mixed $rawValue
171
     * @param string $type
172
     * @return mixed
173
     */
174
    protected function checkCastedValue($rawValue, $type) {
175
        if(null !== $rawValue) {
176
            switch ($type) {
177
                default:
178
                case 'string':
179
                    $value = $rawValue;
180
                    break;
181
                case 'integer':
182
                case 'int':
183
                    $value = (integer)$rawValue;
184
                    break;
185
                case 'float':
186
                case 'double':
187
                    $value = (float)$rawValue;
188
                    break;
189
                case 'boolean':
190
                case 'bool':
191
                    $value = (bool)$rawValue;
192
                    break;
193
            }
194
        } else {
195
            $value = $rawValue;
196
        }
197
        return $value;
198
    }
199
}
200