GenericEntity   A
last analyzed

Complexity

Total Complexity 32

Size/Duplication

Total Lines 158
Duplicated Lines 0 %

Importance

Changes 2
Bugs 0 Features 0
Metric Value
wmc 32
eloc 61
c 2
b 0
f 0
dl 0
loc 158
rs 9.84

14 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 5 2
A __unset() 0 3 1
A __set() 0 3 1
A __isset() 0 3 1
A castAttribute() 0 17 3
A __get() 0 3 1
A getChanges() 0 12 5
A getPersistenceState() 0 6 2
A set() 0 17 4
A getArrayCopy() 0 9 4
A preventChangesIfDeleted() 0 4 2
A setPersistenceState() 0 6 2
A get() 0 9 2
A maybeLazyLoad() 0 11 2
1
<?php
2
declare(strict_types=1);
3
4
namespace Sirius\Orm\Entity;
5
6
use Sirius\Orm\CastingManager;
7
use Sirius\Orm\Helpers\Str;
8
9
class GenericEntity implements EntityInterface
10
{
11
    protected $state = StateEnum::CHANGED;
12
13
    protected $primaryKey = 'id';
14
15
    protected $attributes = [];
16
17
    protected $lazyLoaders = [];
18
19
    protected $changed = [];
20
21
    protected $casts = [];
22
23
    /**
24
     * @var CastingManager
25
     */
26
    protected $castingManager;
27
28
    public function __construct(array $attributes, CastingManager $castingManager = null)
29
    {
30
        $this->castingManager = $castingManager;
31
        foreach ($attributes as $attr => $value) {
32
            $this->set($attr, $value);
33
        }
34
    }
35
36
    public function __get($name)
37
    {
38
        return $this->get($name);
39
    }
40
41
    public function __set($name, $value)
42
    {
43
        return $this->set($name, $value);
44
    }
45
46
    public function __isset($name)
47
    {
48
        return isset($this->attributes[$name]);
49
    }
50
51
    public function __unset($name)
52
    {
53
        return $this->set($name, null);
54
    }
55
56
    protected function castAttribute($name, $value)
57
    {
58
        $method = Str::methodName($name . ' attribute', 'cast');
59
        if (method_exists($this, $method)) {
60
            return $this->$method($value);
61
        }
62
63
        if (!$this->castingManager) {
64
            return $value;
65
        }
66
67
        /**
68
         * @todo implement additional attributes
69
         */
70
        $type = $this->casts[$name] ?? $name;
71
72
        return $this->castingManager->cast($type, $value);
73
    }
74
75
    protected function set($attribute, $value = null)
76
    {
77
        $this->preventChangesIfDeleted();
78
79
        if ($value instanceof LazyLoader) {
80
            $this->lazyLoaders[$attribute] = $value;
81
            return $this;
82
        }
83
84
        $value = $this->castAttribute($attribute, $value);
85
        if (! isset($this->attributes[$attribute]) || $value != $this->attributes[$attribute]) {
86
            $this->changed[$attribute] = true;
87
            $this->state               = StateEnum::CHANGED;
88
        }
89
        $this->attributes[$attribute] = $value;
90
91
        return $this;
92
    }
93
94
    protected function get($attribute)
95
    {
96
        if (! $attribute) {
97
            return null;
98
        }
99
100
        $this->maybeLazyLoad($attribute);
101
102
        return $this->attributes[$attribute] ?? null;
103
    }
104
105
    public function getPersistenceState()
106
    {
107
        if (! empty($this->changed)) {
108
        }
109
110
        return $this->state;
111
    }
112
113
    public function setPersistenceState($state)
114
    {
115
        if ($state == StateEnum::SYNCHRONIZED) {
116
            $this->changed = [];
117
        }
118
        $this->state = $state;
119
    }
120
121
    public function getArrayCopy()
122
    {
123
        $copy = $this->attributes;
124
        foreach ($copy as $k => $v) {
125
            if (is_object($v) && method_exists($v, 'getArrayCopy')) {
126
                $copy[$k] = $v->getArrayCopy();
127
            }
128
        }
129
        return $copy;
130
    }
131
132
    public function getChanges()
133
    {
134
        $changes = $this->changed;
135
        foreach ($this->attributes as $name => $value) {
136
            if (is_object($value) && method_exists($value, 'getChanges')) {
137
                if (! empty($value->getChanges())) {
138
                    $changes[$name] = true;
139
                }
140
            }
141
        }
142
143
        return $changes;
144
    }
145
146
    protected function preventChangesIfDeleted()
147
    {
148
        if ($this->state == StateEnum::DELETED) {
149
            throw new \BadMethodCallException('Entity was deleted, no further changes are allowed');
150
        }
151
    }
152
153
    /**
154
     * @param $attribute
155
     */
156
    protected function maybeLazyLoad($attribute): void
157
    {
158
        if (isset($this->lazyLoaders[$attribute])) {
159
            // preserve state
160
            $state = $this->state;
161
            /** @var LazyLoader $lazyLoader */
162
            $lazyLoader = $this->lazyLoaders[$attribute];
163
            $lazyLoader->load();
164
            unset($this->changed[$attribute]);
165
            unset($this->lazyLoaders[$attribute]);
166
            $this->state = $state;
167
        }
168
    }
169
}
170