Model   A
last analyzed

Complexity

Total Complexity 36

Size/Duplication

Total Lines 178
Duplicated Lines 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 69
c 1
b 0
f 0
dl 0
loc 178
rs 9.52
wmc 36

17 Methods

Rating   Name   Duplication   Size   Complexity  
A setRawAttributes() 0 7 2
A parse() 0 4 1
A set() 0 16 5
A __construct() 0 14 2
A setIdentifier() 0 4 1
A fill() 0 7 2
A get() 0 12 5
A setRawAttribute() 0 4 1
A jsonSerialize() 0 14 3
A getRawAttribute() 0 3 1
A schemaLoadDefaults() 0 6 3
A setRelation() 0 4 1
A getIdentifier() 0 3 1
A setSchemaName() 0 4 1
A tryParse() 0 6 2
A loadMutator() 0 15 4
A getRelation() 0 3 1
1
<?php
2
3
namespace Ipag\Sdk\Model;
4
5
use Ipag\Sdk\Model\Schema\Exception\MutatorAttributeException;
6
use Ipag\Sdk\Model\Schema\Exception\SchemaAttributeParseException;
7
use Ipag\Sdk\Model\Schema\Mutator;
8
use Ipag\Sdk\Model\Schema\MutatorContext;
9
use Ipag\Sdk\Model\Schema\Schema;
10
use Ipag\Sdk\Model\Schema\SchemaAttribute;
11
use Ipag\Sdk\Model\Schema\SchemaBuilder;
12
use Ipag\Sdk\Model\Schema\SchemaRelationAttribute;
13
use Ipag\Sdk\Model\SerializableModelInterface;
14
use Ipag\Sdk\Util\ClassUtil;
15
use UnexpectedValueException;
16
17
/**
18
 * @codeCoverageIgnore
19
 */
20
abstract class Model implements SerializableModelInterface
21
{
22
    private Schema $schema;
23
    private array $data;
24
    private array $relations;
25
    private string $identifier;
26
    private array $mutators;
27
28
    public function __construct(array $data = [], array $relations = [], ?string $name = null)
29
    {
30
        if (is_numeric(key($data)))
31
            throw new \Exception('Dados mal formatados passado para o construtor da classe ' . ClassUtil::basename(static::class));
32
33
        $this->data = $data;
34
        $this->relations = $relations;
35
        $this->identifier = $name ?? ClassUtil::basename(static::class);
36
        $this->schema = new Schema($this->identifier);
37
38
        $this->schema($this->schema->builder());
39
        $this->schemaLoadDefaults();
40
41
        $this->fill($data);
42
    }
43
44
    //
45
46
    protected abstract function schema(SchemaBuilder $schema): Schema;
47
48
    //
49
50
    public function getIdentifier(): string
51
    {
52
        return $this->identifier;
53
    }
54
55
    public function setIdentifier(string $name): self
56
    {
57
        $this->identifier = $name;
58
        return $this;
59
    }
60
61
    public function setSchemaName(string $name): self
62
    {
63
        $this->schema->setName($name);
64
        return $this;
65
    }
66
67
    public function fill(array $data): self
68
    {
69
        foreach ($data as $key => $value) {
70
            $this->set($key, $value);
71
        }
72
73
        return $this;
74
    }
75
76
    protected function set(string $attribute, $value): self
77
    {
78
        $attributeSchema = $this->schema->query($attribute);
79
        $mutator = $this->loadMutator($attribute);
80
81
        $value = $mutator && $mutator->setter ? $mutator->setter->__invoke($value, new MutatorContext($this, $attribute, $attributeSchema)) : $value;
82
83
        if ($attributeSchema) {
84
            if ($attributeSchema instanceof SchemaRelationAttribute) {
85
                return $this->setRelation($attribute, $attributeSchema->parse($value));
86
            }
87
88
            return $this->setRawAttribute($attribute, $attributeSchema->parse($value));
89
        }
90
91
        return $this->setRawAttribute($attribute, $value);
92
    }
93
94
    protected function get(string $attribute)
95
    {
96
        $attributeSchema = $this->schema->query($attribute);
97
98
        if ($attributeSchema && $attributeSchema instanceof SchemaRelationAttribute) {
99
            return $this->getRelation($attribute);
100
        }
101
102
        $value = $this->getRawAttribute($attribute);
103
        $mutator = $this->loadMutator($attribute);
104
105
        return $mutator && $mutator->getter ? $mutator->getter->__invoke($value, new MutatorContext($this, $attribute, $attributeSchema)) : $value;
106
    }
107
108
    public function jsonSerialize(): array
109
    {
110
        $serialized = [];
111
112
        foreach ($this->schema->getAttributes() as $schema) {
113
            /** @var SchemaAttribute $schema */
114
            if ($schema->isHidden()) {
115
                continue;
116
            }
117
118
            $serialized[$schema->getName()] = $schema->serialize($this->get($schema->getName()));
119
        }
120
121
        return $serialized;
122
    }
123
124
    //
125
126
    protected function getRawAttribute(string $name)
127
    {
128
        return $this->data[$name] ?? null;
129
    }
130
131
    protected function setRawAttribute(string $name, $value): self
132
    {
133
        $this->data[$name] = $value;
134
        return $this;
135
    }
136
137
    protected function setRawAttributes(array $values): self
138
    {
139
        foreach ($values as $name => $value) {
140
            $this->setRawAttribute($name, $value);
141
        }
142
143
        return $this;
144
    }
145
146
    protected function setRelation(string $name, $value): self
147
    {
148
        $this->relations[$name] = $value;
149
        return $this;
150
    }
151
152
    protected function getRelation(string $name)
153
    {
154
        return $this->relations[$name] ?? null;
155
    }
156
157
    protected function schemaLoadDefaults(): void
158
    {
159
        foreach ($this->schema->getAttributes() as $schema) {
160
            /** @var SchemaAttribute $schema */
161
            if ($schema->hasDefault()) {
162
                $this->set($schema->getName(), $schema->getDefault());
163
            }
164
        }
165
    }
166
167
    protected function loadMutator(string $name): ?Mutator
168
    {
169
        $mutator = $this->mutators[$name] ?? null;
170
171
        if (!$mutator && is_callable([$this, $name])) {
172
            $mutator = call_user_func([$this, $name]);
173
174
            if (!$mutator instanceof Mutator) {
175
                throw new UnexpectedValueException("Expected value from mutator '$name' to be instance of Mutator");
176
            } else {
177
                $this->mutators[$name] = $mutator;
178
            }
179
        }
180
181
        return $mutator;
182
    }
183
184
    //
185
186
    public static function parse(array $data): self
187
    {
188
        $model = new static();
189
        return $model->fill($data);
190
    }
191
192
    public static function tryParse(array $data): ?self
193
    {
194
        try {
195
            return self::parse($data);
196
        } catch (SchemaAttributeParseException | MutatorAttributeException $e) {
197
            return null;
198
        }
199
    }
200
}