Completed
Pull Request — master (#22)
by Sergey
14:35
created

Eloquent::save()   B

Complexity

Conditions 5
Paths 9

Size

Total Lines 19
Code Lines 13

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 19
rs 8.8571
c 0
b 0
f 0
nc 9
cc 5
eloc 13
nop 1
1
<?php
2
3
namespace Isswp101\Persimmon\Model;
4
5
use Isswp101\Persimmon\Collection\ICollection;
6
use Isswp101\Persimmon\DI\Container;
7
use Isswp101\Persimmon\Exceptions\IllegalCollectionException;
8
use Isswp101\Persimmon\Exceptions\ModelNotFoundException;
9
use Isswp101\Persimmon\QueryBuilder\IQueryBuilder;
10
use Isswp101\Persimmon\Traits\Containerable;
11
use Isswp101\Persimmon\Traits\Eventable;
12
use Isswp101\Persimmon\Traits\Timestampable;
13
14
/**
15
 * @TODO
16
 * 1. Cache
17
 * 2. Consider columns when searching
18
 * 3. Check __clone()
19
 */
20
abstract class Eloquent implements IEloquent
21
{
22
    use Containerable, Timestampable, Eventable;
23
24
    protected $primaryKey;
25
    protected $exists = false;
26
    protected $timestamps = false;
27
    protected $cache = false;
28
29
    /** @MustBeOverridden */
30
    const COLLECTION = null;
31
32
    const PRIMARY_KEY = 'id';
33
    const CREATED_AT = 'created_at';
34
    const UPDATED_AT = 'updated_at';
35
36
    abstract protected static function di(): Container;
37
38
    protected static function instantiate(string $primaryKey): Eloquent
39
    {
40
        $model = new static();
41
        $model->setPrimaryKey($primaryKey);
42
        return $model;
43
    }
44
45
    public function __construct(array $attributes = [])
46
    {
47
        $this->fill($attributes);
48
    }
49
50
    public function setPrimaryKey(string $key)
51
    {
52
        $this->primaryKey = $key;
53
    }
54
55
    public function getPrimaryKey(): string
56
    {
57
        if ($this->primaryKey == null) {
58
            $this->setPrimaryKey($this->{static::PRIMARY_KEY});
59
        }
60
        return $this->primaryKey;
61
    }
62
63
    final public static function getCollection(): string
64
    {
65
        if (static::COLLECTION == null) {
66
            throw new IllegalCollectionException();
67
        }
68
        return static::COLLECTION;
69
    }
70
71
    public function exists(bool $value = null): bool
72
    {
73
        if ($value != null) {
74
            $this->exists = $value;
75
        }
76
        return $this->exists;
77
    }
78
79
    public static function all(IQueryBuilder $query, callable $callback = null): ICollection
80
    {
81
        $collection = static::di()->getRepository()->all($query, static::class,
82
            function (IEloquent $model) use ($callback) {
83
                $model->exists(true);
84
                if ($callback != null) {
85
                    $callback($model);
86
                }
87
            });
88
        return $collection;
89
    }
90
91
    public static function find(string $id, array $columns = []): ?IEloquent
92
    {
93
        $di = static::di();
94
        $prototype = static::instantiate($id);
95
        if ($prototype->cache) {
96
            $model = $di->getCacheRepository()->find($id, static::class, $columns);
97
            if ($model != null) {
98
                return $model;
99
            }
100
        }
101
        $model = $di->getRepository()->find($id, static::class, $columns);
102
        if ($model != null && $model instanceof IEloquent) {
103
            $model->exists(true);
104
            if ($prototype->cache) {
105
                $di->getCacheRepository()->update($model);
106
            }
107
        }
108
        return $model;
109
    }
110
111
    public static function findOrFail(string $id, array $columns = []): IEloquent
112
    {
113
        $model = static::find($id, $columns);
114
        if ($model == null) {
115
            throw new ModelNotFoundException(get_called_class(), $id);
116
        }
117
        return $model;
118
    }
119
120
    public static function create(array $attributes): IEloquent
121
    {
122
        $model = new static($attributes);
123
        $model->save();
124
        return $model;
125
    }
126
127
    public static function destroy(string $id): void
128
    {
129
        static::findOrFail($id)->delete();
130
    }
131
132
    public function save(array $columns = []): void
133
    {
134
        if ($this->saving() === false) {
135
            return;
136
        }
137
        $repository = $this->di()->getRepository();
138
        if ($this->timestamps) {
139
            $this->updateTimestamps();
140
        }
141
        if (!$this->exists) {
142
            $repository->insert($this);
143
        } else {
144
            $repository->update($this);
145
        }
146
        $this->exists = true;
147
        if ($this->saved() === false) {
148
            return;
149
        }
150
    }
151
152
    public function delete(): void
153
    {
154
        if ($this->deleting() === false) {
155
            return;
156
        }
157
        $this->di()->getRepository()->delete($this);
158
        $this->exists = false;
159
        if ($this->deleted() === false) {
160
            return;
161
        }
162
    }
163
}