Passed
Push — develop ( 5da5fd...cba003 )
by nguereza
06:12
created

BaseParam::fromEntity()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 3
Bugs 0 Features 1
Metric Value
cc 1
eloc 1
c 3
b 0
f 1
nc 1
nop 1
dl 0
loc 3
rs 10
1
<?php
2
3
/**
4
 * Platine Framework
5
 *
6
 * Platine Framework is a lightweight, high-performance, simple and elegant
7
 * PHP Web framework
8
 *
9
 * This content is released under the MIT License (MIT)
10
 *
11
 * Copyright (c) 2020 Platine Framework
12
 *
13
 * Permission is hereby granted, free of charge, to any person obtaining a copy
14
 * of this software and associated documentation files (the "Software"), to deal
15
 * in the Software without restriction, including without limitation the rights
16
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
17
 * copies of the Software, and to permit persons to whom the Software is
18
 * furnished to do so, subject to the following conditions:
19
 *
20
 * The above copyright notice and this permission notice shall be included in all
21
 * copies or substantial portions of the Software.
22
 *
23
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
24
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
25
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
26
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
27
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
28
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
29
 * SOFTWARE.
30
 */
31
32
/**
33
 *  @file BaseParam.php
34
 *
35
 *  The Form base parameter class
36
 *
37
 *  @package    Platine\Framework\Form\Param
38
 *  @author Platine Developers team
39
 *  @copyright  Copyright (c) 2020
40
 *  @license    http://opensource.org/licenses/MIT  MIT License
41
 *  @link   https://www.platine-php.com
42
 *  @version 1.0.0
43
 *  @filesource
44
 */
45
46
declare(strict_types=1);
47
48
namespace Platine\Framework\Form\Param;
49
50
use JsonSerializable;
51
use Platine\Orm\Entity;
52
use Platine\Stdlib\Helper\Str;
53
use ReflectionClass;
54
use ReflectionNamedType;
55
use ReflectionProperty;
56
57
/**
58
 * @class BaseParam
59
 * @package Platine\Framework\Form\Param
60
 * @template TEntity as Entity
61
 */
62
class BaseParam implements JsonSerializable
63
{
64
    /**
65
     * Create new instance
66
     * @param array<string, mixed> $data
67
     */
68
    public function __construct(array $data = [])
69
    {
70
        // Load default values
71
        $this->loadDefaultValues();
72
73
        $params = array_merge($this->getDefault(), $data);
74
        $this->load($params);
75
    }
76
77
    /**
78
     * Load the field data
79
     * @param array<string, mixed> $data
80
     * @return void
81
     */
82
    public function load(array $data): void
83
    {
84
        foreach ($data as $name => $value) {
85
            $key = Str::camel($name, true);
86
            $typedValue = $this->getPropertyValue($key, $value);
87
88
            $setterMethod = 'set' . ucfirst($key);
89
            if (method_exists($this, $setterMethod)) {
90
                $this->{$setterMethod}($typedValue);
91
            } elseif (property_exists($this, $key)) {
92
                $this->{$key} = $typedValue;
93
            }
94
        }
95
    }
96
97
    /**
98
     *
99
     * @param TEntity $entity
0 ignored issues
show
Bug introduced by
The type Platine\Framework\Form\Param\TEntity was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
100
     * @return $this
101
     */
102
    public function fromEntity(Entity $entity): self
103
    {
104
        return $this;
105
    }
106
107
    /**
108
     * Return the fields default values
109
     * @return array<string, mixed>
110
     */
111
    public function getDefault(): array
112
    {
113
        return [];
114
    }
115
116
    /**
117
     * Return the parameters values
118
     * @return array<string, mixed>
119
     */
120
    public function data(): array
121
    {
122
        return get_object_vars($this);
123
    }
124
125
    /**
126
     * Convert parameter to JSON array
127
     * @return array<string, mixed>
128
     */
129
    public function jsonSerialize()
130
    {
131
        return $this->data();
132
    }
133
134
    /**
135
     * Return the value for the given property
136
     * @param string $name
137
     * @return mixed|null
138
     */
139
    public function __get($name)
140
    {
141
        if (property_exists($this, $name)) {
142
            return $this->{$name};
143
        }
144
145
        //convert to camel
146
        $key = Str::camel($name, true);
147
        if (property_exists($this, $key)) {
148
            return $this->{$key};
149
        }
150
151
        return null;
152
    }
153
154
    /**
155
     * Return the value after cast
156
     * @param string $attribute
157
     * @param mixed $value
158
     * @return mixed
159
     */
160
    protected function getPropertyValue(string $attribute, $value)
161
    {
162
        $types = $this->getPropertyTypes();
163
        $property = $types[$attribute] ?? null;
164
        if ($property === null) {
165
            return $value;
166
        }
167
168
        $type = $property[0];
169
        $allowNull = $property[1];
170
171
        if (
172
            in_array($type, ['array', 'object']) === false &&
173
            strlen((string) $value) === 0 && $allowNull
174
        ) {
175
            return null;
176
        }
177
        
178
        if($type === 'string' && $value !== null){
179
            $value = trim($value);
180
        }
181
182
        $maps = $this->getPropertiesCastMaps();
183
        $map = $maps[$type] ?? [];
184
        if (count($map) === 0) {
185
            return $value;
186
        }
187
188
        $closure = $map[0] ?? fn($value) => $value;
189
190
        return $closure($value);
191
    }
192
193
    /**
194
     * Return the properties of this class
195
     * @return array<string, array<int, bool|ReflectionProperty|string>>
196
     */
197
    protected function getPropertyTypes(): array
198
    {
199
        $props = [];
200
201
        $reflectionClass = new ReflectionClass($this);
202
        /** @var ReflectionProperty[] $properties */
203
        $properties = $reflectionClass->getProperties(ReflectionProperty::IS_PROTECTED);
204
        foreach ($properties as $property) {
205
            /** @var ReflectionNamedType|null $type */
206
            $type = $property->getType();
207
            if ($type !== null && $type->isBuiltin()) {
208
                $props[$property->getName()] = [$type->getName(), $type->allowsNull(), $property];
209
            }
210
        }
211
212
        return $props;
213
    }
214
215
    /**
216
     * Return the properties cast maps
217
     * @return array<string, array<int, Closure|mixed>>
218
     */
219
    protected function getPropertiesCastMaps(): array
220
    {
221
        return [
222
            'int' => [fn($value) => intval($value), 0],
223
            'float' => [fn($value) => floatval($value), 0.0],
224
            'double' => [fn($value) => doubleval($value), 0.0],
225
            'bool' => [fn($value) => boolval($value), false],
226
            'string' => [fn($value) => strval($value), ''],
227
            'array' => [fn($value) => (array) $value, []],
228
        ];
229
    }
230
231
    /**
232
     * Load the default value based on data type
233
     * @return void
234
     */
235
    protected function loadDefaultValues(): void
236
    {
237
        $data = [];
238
        $types = $this->getPropertyTypes();
239
        $maps = $this->getPropertiesCastMaps();
240
241
        foreach ($types as $attr => $val) {
242
            /** @var ReflectionProperty $property */
243
            $property = $val[2];
244
            $property->setAccessible(true);
245
            if (isset($maps[$val[0]]) && $property->isInitialized($this) === false) {
246
                $data[$attr] = $maps[$val[0]][1];
247
            }
248
        }
249
250
        $this->load($data);
251
    }
252
}
253