Completed
Pull Request — master (#22)
by Sergey
24:02 queued 09:01
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 $exists = false;
25
    protected $timestamps = false;
26
27
    /** @MustBeOverridden */
28
    const COLLECTION = null;
29
30
    const PRIMARY_KEY = 'id';
31
    const CREATED_AT = 'created_at';
32
    const UPDATED_AT = 'updated_at';
33
34
    abstract protected static function di(): Container;
35
36
    public function __construct(array $attributes = [])
37
    {
38
        $this->fill($attributes);
39
    }
40
41
    public function getPrimaryKey(): string
42
    {
43
        return $this->{static::PRIMARY_KEY};
44
    }
45
46
    public function setPrimaryKey(string $key)
47
    {
48
        $this->{static::PRIMARY_KEY} = $key;
49
    }
50
51
    final public static function getCollectionName(): string
52
    {
53
        if (static::COLLECTION == null) {
54
            throw new IllegalCollectionException();
55
        }
56
        return static::COLLECTION;
57
    }
58
59
    public function exists(bool $value = null): bool
60
    {
61
        if ($value != null) {
62
            $this->exists = $value;
63
        }
64
        return $this->exists;
65
    }
66
67
    public static function all(IQueryBuilder $query, callable $callback = null): ICollection
68
    {
69
        $collection = static::di()->getRepository()->all(
70
            $query,
71
            static::class,
72
            function (IEloquent $model) use ($callback) {
73
                $model->exists(true);
74
                if ($callback != null) {
75
                    $callback($model);
76
                }
77
            });
78
        return $collection;
79
    }
80
81
    public static function find($id, array $columns = []): IEloquent
82
    {
83
        $model = static::di()->getRepository()->find($id, static::class, $columns);
84
        if ($model != null) {
85
            $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...
86
        }
87
        return $model;
88
    }
89
90
    public static function findOrFail($id, array $columns = []): IEloquent
91
    {
92
        $model = static::find($id, $columns);
93
        if ($model == null) {
94
            throw new ModelNotFoundException(get_called_class(), $id);
95
        }
96
        return $model;
97
    }
98
99
    public static function create(array $attributes): IEloquent
100
    {
101
        $model = new static($attributes);
102
        $model->save();
103
        return $model;
104
    }
105
106
    public static function destroy($id)
107
    {
108
        static::findOrFail($id)->delete();
109
    }
110
111
    public function save(array $columns = [])
112
    {
113
        if ($this->saving() === false) {
114
            return;
115
        }
116
        $repository = $this->di()->getRepository();
117
        if ($this->timestamps) {
118
            $this->updateTimestamps();
119
        }
120
        if (!$this->exists) {
121
            $repository->insert($this);
122
        } else {
123
            $repository->update($this);
124
        }
125
        $this->exists = true;
126
        if ($this->saved() === false) {
127
            return;
128
        }
129
    }
130
131
    public function delete()
132
    {
133
        if ($this->deleting() === false) {
134
            return;
135
        }
136
        $this->di()->getRepository()->delete($this->getPrimaryKey());
0 ignored issues
show
Documentation introduced by
$this->getPrimaryKey() is of type string, but the function expects a object<Isswp101\Persimmon\Contracts\Storable>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
137
        $this->exists = false;
138
        if ($this->deleted() === false) {
139
            return;
140
        }
141
    }
142
}