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

Eloquent::find()   C

Complexity

Conditions 7
Paths 13

Size

Total Lines 27
Code Lines 16

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 27
rs 6.7272
c 0
b 0
f 0
cc 7
eloc 16
nc 13
nop 2
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\IllegalModelHashException;
9
use Isswp101\Persimmon\Exceptions\ModelNotFoundException;
10
use Isswp101\Persimmon\QueryBuilder\IQueryBuilder;
11
use Isswp101\Persimmon\Traits\Containerable;
12
use Isswp101\Persimmon\Traits\Eventable;
13
use Isswp101\Persimmon\Traits\Timestampable;
14
15
/**
16
 * @TODO
17
 * 1. Cache
18
 * 2. Consider columns when searching
19
 * 3. Check __clone()
20
 */
21
abstract class Eloquent implements IEloquent
22
{
23
    use Containerable, Timestampable, Eventable;
24
25
    protected $primaryKey;
26
    protected $exists = false;
27
    protected $timestamps = false;
28
    protected $cache = false;
29
30
    /** @MustBeOverridden */
31
    const COLLECTION = null;
32
33
    const PRIMARY_KEY = 'id';
34
    const CREATED_AT = 'created_at';
35
    const UPDATED_AT = 'updated_at';
36
37
    abstract protected static function di(): Container;
38
39
    protected static function instantiate(string $primaryKey): IEloquent
40
    {
41
        $model = new static();
42
        $model->setPrimaryKey($primaryKey);
43
        return $model;
44
    }
45
46
    public function __construct(array $attributes = [])
47
    {
48
        $this->fill($attributes);
49
    }
50
51
    public function setPrimaryKey(string $key)
52
    {
53
        $this->primaryKey = $key;
54
    }
55
56
    public function getPrimaryKey(): string
57
    {
58
        if ($this->primaryKey == null) {
59
            $this->setPrimaryKey($this->{static::PRIMARY_KEY});
60
        }
61
        return $this->primaryKey;
62
    }
63
64
    final public static function getCollection(): string
65
    {
66
        if (static::COLLECTION == null) {
67
            throw new IllegalCollectionException();
68
        }
69
        return static::COLLECTION;
70
    }
71
72
    public function exists(bool $value = null): bool
73
    {
74
        if ($value != null) {
75
            $this->exists = $value;
76
        }
77
        return $this->exists;
78
    }
79
80
    public static function all(IQueryBuilder $query, callable $callback = null): ICollection
81
    {
82
        $collection = static::di()->getRepository()->all($query, static::class,
83
            function (IEloquent $model) use ($callback) {
84
                $model->exists(true);
85
                if ($callback != null) {
86
                    $callback($model);
87
                }
88
            });
89
        return $collection;
90
    }
91
92
    public static function find($id, array $columns = []): IEloquent
93
    {
94
        $di = static::di();
95
        $model = Eloquent::instantiate($id);
96
        if ($model->shouldUseCache()) {
97
            $cache = $di->getCache()->get($model->getHash());
98
            $columns = array_diff($columns, $cache->getCachedAttributes());
99
            if (!$columns && $cache->get() != null) {
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...
100
                return $cache->get();
101
            }
102
        }
103
104
        $cache = $di->getCacheRepository()->find($id, static::class, $columns);
0 ignored issues
show
Bug introduced by
The method getCacheRepository() does not exist on Isswp101\Persimmon\DI\Container. Did you maybe mean getCache()?

This check marks calls to methods that do not seem to exist on an object.

This is most likely the result of a method being renamed without all references to it being renamed likewise.

Loading history...
105
        if ($cache->isReturnable()) {
0 ignored issues
show
Unused Code introduced by
This if statement is empty and can be removed.

This check looks for the bodies of if statements that have no statements or where all statements have been commented out. This may be the result of changes for debugging or the code may simply be obsolete.

These if bodies can be removed. If you have an empty if but statements in the else branch, consider inverting the condition.

if (rand(1, 6) > 3) {
//print "Check failed";
} else {
    print "Check succeeded";
}

could be turned into

if (rand(1, 6) <= 3) {
    print "Check succeeded";
}

This is much more concise to read.

Loading history...
106
107
        }
108
109
110
        $model = $di->getRepository()->find($id, static::class, $columns);
111
        if ($model != null) {
112
            $model->exists = true;
0 ignored issues
show
Bug introduced by
Accessing exists on the interface Isswp101\Persimmon\Contracts\Storable suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
113
            if ($model->shouldUseCache()) {
114
                $cache->put($model, $columns);
115
            }
116
        }
117
        return $model;
118
    }
119
120
    public static function findOrFail($id, array $columns = []): IEloquent
121
    {
122
        $model = static::find($id, $columns);
123
        if ($model == null) {
124
            throw new ModelNotFoundException(get_called_class(), $id);
125
        }
126
        return $model;
127
    }
128
129
    public static function create(array $attributes): IEloquent
130
    {
131
        $model = new static($attributes);
132
        $model->save();
133
        return $model;
134
    }
135
136
    public static function destroy($id)
137
    {
138
        static::findOrFail($id)->delete();
139
    }
140
141
    public function save(array $columns = [])
142
    {
143
        if ($this->saving() === false) {
144
            return;
145
        }
146
        $repository = $this->di()->getRepository();
147
        if ($this->timestamps) {
148
            $this->updateTimestamps();
149
        }
150
        if (!$this->exists) {
151
            $repository->insert($this);
152
        } else {
153
            $repository->update($this);
154
        }
155
        $this->exists = true;
156
        if ($this->saved() === false) {
157
            return;
158
        }
159
    }
160
161
    public function delete()
162
    {
163
        if ($this->deleting() === false) {
164
            return;
165
        }
166
        $this->di()->getRepository()->delete($this);
167
        $this->exists = false;
168
        if ($this->deleted() === false) {
169
            return;
170
        }
171
    }
172
173
    public function getHash(): string
174
    {
175
        if ($this->getPrimaryKey() == null) {
176
            throw new IllegalModelHashException($this);
177
        }
178
        return get_class($this) . '@' . $this->getPrimaryKey();
179
    }
180
181
    public function shouldUseCache(): bool
182
    {
183
        return $this->cache;
184
    }
185
}