Completed
Push — master ( eacc73...69d932 )
by Adrian
01:58
created

GenericEntity::getPersistenceState()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 6
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 2
c 0
b 0
f 0
nc 2
nop 0
dl 0
loc 6
rs 10
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
    public function getPk()
76
    {
77
        /**
78
         * @todo implement a way to retrieve the proper PK columns
79
         */
80
        return $this->get($this->primaryKey);
81
    }
82
83
    public function setPk($val)
84
    {
85
        /**
86
         * @todo implement a way to retrieve the proper PK columns
87
         */
88
        $this->set($this->primaryKey, $val);
89
    }
90
91
    public function set($attribute, $value = null)
92
    {
93
        $this->preventChangesIfDeleted();
94
95
        if ($value instanceof LazyValueLoader) {
96
            $this->lazyLoaders[$attribute] = $value;
97
            return $this;
98
        }
99
100
        $value = $this->castAttribute($attribute, $value);
101
        if (! isset($this->attributes[$attribute]) || $value != $this->attributes[$attribute]) {
102
            $this->changed[$attribute] = true;
103
            $this->state               = StateEnum::CHANGED;
104
        }
105
        $this->attributes[$attribute] = $value;
106
107
        return $this;
108
    }
109
110
    public function get($attribute)
111
    {
112
        if (! $attribute) {
113
            return null;
114
        }
115
116
        $this->maybeLazyLoad($attribute);
117
118
        return $this->attributes[$attribute] ?? null;
119
    }
120
121
    public function getPersistenceState()
122
    {
123
        if (! empty($this->changed)) {
124
        }
125
126
        return $this->state;
127
    }
128
129
    public function setPersistenceState($state)
130
    {
131
        if ($state == StateEnum::SYNCHRONIZED) {
132
            $this->changed = [];
133
        }
134
        $this->state = $state;
135
    }
136
137
    public function getArrayCopy()
138
    {
139
        $copy = $this->attributes;
140
        foreach ($copy as $k => $v) {
141
            if (is_object($v) && method_exists($v, 'getArrayCopy')) {
142
                $copy[$k] = $v->getArrayCopy();
143
            }
144
        }
145
        return $copy;
146
    }
147
148
    public function getChanges()
149
    {
150
        $changes = $this->changed;
151
        foreach ($this->attributes as $name => $value) {
152
            if (is_object($value) && method_exists($value, 'getChanges')) {
153
                if (! empty($value->getChanges())) {
154
                    $changes[$name] = true;
155
                }
156
            }
157
        }
158
159
        return $changes;
160
    }
161
162
    protected function preventChangesIfDeleted()
163
    {
164
        if ($this->state == StateEnum::DELETED) {
165
            throw new \BadMethodCallException('Entity was deleted, no further changes are allowed');
166
        }
167
    }
168
169
    /**
170
     * @param $attribute
171
     */
172
    protected function maybeLazyLoad($attribute): void
173
    {
174
        if (isset($this->lazyLoaders[$attribute])) {
175
            /** @var LazyValueLoader $lazyLoader */
176
            $lazyLoader = $this->lazyLoaders[$attribute];
177
            $lazyLoader->load();
178
            unset($this->changed[$attribute]);
179
            unset($this->lazyLoaders[$attribute]);
180
        }
181
    }
182
}
183