Completed
Pull Request — master (#22)
by Sergey
13:25
created

Eloquent   A

Complexity

Total Complexity 30

Size/Duplication

Total Lines 156
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 9

Importance

Changes 0
Metric Value
wmc 30
lcom 1
cbo 9
dl 0
loc 156
rs 10
c 0
b 0
f 0

14 Methods

Rating   Name   Duplication   Size   Complexity  
di() 0 1 ?
A instantiate() 0 6 1
A __construct() 0 4 1
A setPrimaryKey() 0 4 1
A getPrimaryKey() 0 7 2
A getCollection() 0 7 2
A exists() 0 7 2
A all() 0 11 2
C find() 0 31 7
A findOrFail() 0 8 2
A create() 0 6 1
A destroy() 0 4 1
B save() 0 19 5
A delete() 0 11 3
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
        $allColumnsRequested = !$columns;
95
        $prototype = static::instantiate($id);
96
        if ($prototype->cache) {
97
            $cachedModel = $di->getCacheRepository()->find($id, static::class, $columns);
98
            if ($cachedModel != null) {
99
                $columns = array_diff($columns, array_keys($cachedModel->toArray()));
100
                if (!$columns) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $columns of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
101
                    $cachedModel->exists = true;
102
                    return $cachedModel;
103
                }
104
            }
105
        }
106
        $model = $di->getRepository()->find($id, static::class, $columns);
107
        if ($model != null) {
108
            if ($prototype->cache) {
109
                $di->getCacheRepository()->update($model);
110
                if ($allColumnsRequested) {
111
                    $di->getCacheRepository()->setAllColumns($id, static::class);
112
                }
113
                dd($di->getCacheRepository()->find($id, static::class));
114
                dd($id, static::class);
115
                dd($di->getCacheRepository());
116
                $model = $di->getCacheRepository()->find($id, static::class);
117
            }
118
            $model->exists = true;
119
        }
120
        return $model;
121
    }
122
123
    public static function findOrFail(string $id, array $columns = []): IEloquent
124
    {
125
        $model = static::find($id, $columns);
126
        if ($model == null) {
127
            throw new ModelNotFoundException(get_called_class(), $id);
128
        }
129
        return $model;
130
    }
131
132
    public static function create(array $attributes): IEloquent
133
    {
134
        $model = new static($attributes);
135
        $model->save();
136
        return $model;
137
    }
138
139
    public static function destroy(string $id): void
140
    {
141
        static::findOrFail($id)->delete();
142
    }
143
144
    public function save(array $columns = []): void
145
    {
146
        if ($this->saving() === false) {
147
            return;
148
        }
149
        $repository = $this->di()->getRepository();
150
        if ($this->timestamps) {
151
            $this->updateTimestamps();
152
        }
153
        if (!$this->exists) {
154
            $repository->insert($this);
155
        } else {
156
            $repository->update($this);
157
        }
158
        $this->exists = true;
159
        if ($this->saved() === false) {
160
            return;
161
        }
162
    }
163
164
    public function delete(): void
165
    {
166
        if ($this->deleting() === false) {
167
            return;
168
        }
169
        $this->di()->getRepository()->delete($this);
170
        $this->exists = false;
171
        if ($this->deleted() === false) {
172
            return;
173
        }
174
    }
175
}