AbstractWriteModel   A
last analyzed

Complexity

Total Complexity 23

Size/Duplication

Total Lines 113
Duplicated Lines 0 %

Test Coverage

Coverage 97.96%

Importance

Changes 1
Bugs 0 Features 0
Metric Value
wmc 23
eloc 53
dl 0
loc 113
ccs 48
cts 49
cp 0.9796
rs 10
c 1
b 0
f 0

7 Methods

Rating   Name   Duplication   Size   Complexity  
A mapValueAsArray() 0 5 1
A jsonSerialize() 0 3 1
A fromArray() 0 25 6
A toArray() 0 12 3
B hasMandatoryFields() 0 28 10
A mapValueAsObject() 0 3 1
A isScalar() 0 3 1
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Chemaclass\StockTicker\Domain\WriteModel;
6
7
use JsonSerializable;
8
9
use function array_key_exists;
10
use function in_array;
11
12
abstract class AbstractWriteModel implements JsonSerializable
13
{
14
    protected const TYPE_INT = 'int';
15
    protected const TYPE_FLOAT = 'float';
16
    protected const TYPE_STRING = 'string';
17
    protected const TYPE_ARRAY = 'array';
18
19
    protected const SCALAR_TYPES = [
20
        self::TYPE_INT,
21
        self::TYPE_FLOAT,
22
        self::TYPE_STRING,
23
        self::TYPE_ARRAY,
24
    ];
25
26
    protected const PROPERTY_NAME_MAP = [];
27
28 23
    /**
29
     * @return static
30 23
     */
31
    public function fromArray(array $data)
32 23
    {
33 23
        $props = get_object_vars($this);
34
35 23
        foreach ($data as $property => $value) {
36 5
            $propertyName = static::PROPERTY_NAME_MAP[$property] ?? $property;
37
38
            if (!array_key_exists($propertyName, $props)) {
39 23
                continue;
40 23
            }
41
42 23
            $concreteMeta = $this->metadata()[$propertyName] ?? [];
43 15
            $type = $concreteMeta['type'] ?? '';
44 15
45 14
            if (class_exists($type)) {
46 15
                $isArray = $concreteMeta['is_array'] ?? false;
47 23
                $this->$propertyName = ($isArray)
48 23
                    ? $this->mapValueAsArray($type, $value)
49
                    : $this->mapValueAsObject($type, $value);
50
            } elseif ($this->isScalar($type)) {
51
                $this->$propertyName = $value;
52 23
            }
53
        }
54
55 5
        return $this;
56
    }
57 5
58
    public function hasMandatoryFields(): bool
59 5
    {
60 5
        $props = get_object_vars($this);
61 5
62
        foreach ($props as $propertyName => $value) {
63 5
            $concreteMeta = $this->metadata()[$propertyName] ?? [];
64 5
            $type = $concreteMeta['type'] ?? '';
65 3
66 2
            if (class_exists($type)) {
67
                if (($concreteMeta['is_array'] ?? false)) {
68
                    foreach ($value as $item) {
69
                        if (!$item->hasMandatoryFields()) {
70 5
                            return false;
71 2
                        }
72
                    }
73
                } elseif ($value && !$value->hasMandatoryFields()) {
74
                    return false;
75 5
                }
76
            }
77 5
78 2
            $isMandatoryField = $concreteMeta['mandatory'] ?? false;
79
80
            if ($isMandatoryField && empty($value)) {
81
                return false;
82 3
            }
83
        }
84
85 1
        return true;
86
    }
87 1
88
    public function jsonSerialize(): array
89
    {
90 9
        return $this->toArray();
91
    }
92 9
93 9
    public function toArray(): array
94
    {
95 9
        $result = [];
96 9
        $props = get_object_vars($this);
97 1
98 9
        foreach ($props as $name => $value) {
99
            $result[$name] = ($value instanceof self)
100
                ? $value->toArray()
101 9
                : $value;
102
        }
103
104
        return $result;
105
    }
106 14
107
    abstract protected function metadata(): array;
108 14
109 14
    private function mapValueAsArray(string $type, array $value): array
110
    {
111
        return array_map(
112
            static fn (array $i): self => (new $type())->fromArray($i),
113
            $value,
114 15
        );
115
    }
116 15
117
    private function mapValueAsObject(string $type, array $value): self
118
    {
119 23
        return (new $type())->fromArray($value);
120
    }
121 23
122
    private function isScalar(string $type): bool
123
    {
124
        return in_array($type, self::SCALAR_TYPES);
125
    }
126
}
127