Passed
Push — main ( 843490...c1da4d )
by Mohammad
07:53
created

AbstractRepository::findBy()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 1
c 1
b 0
f 0
nc 1
nop 2
dl 0
loc 3
rs 10
1
<?php
2
/** @noinspection DuplicatedCode */
3
/** @noinspection PhpMultipleClassDeclarationsInspection */
4
5
namespace Shamaseen\Repository\Utility;
6
7
use Exception;
8
use Illuminate\Container\Container as App;
9
use Illuminate\Contracts\Pagination\LengthAwarePaginator;
10
use Illuminate\Contracts\Pagination\Paginator;
11
use Illuminate\Database\Eloquent\Builder;
12
use Illuminate\Database\Eloquent\Collection;
13
use Illuminate\Database\Eloquent\Model as EloquentModel;
14
15
/**
16
 * Class Database.
17
 */
18
abstract class AbstractRepository implements RepositoryInterface
19
{
20
    protected App $app;
21
22
    protected Model $model;
23
24
    protected ?string $order = null;
25
26
    protected string $direction = 'desc';
27
28
    protected array $with = [];
29
30
    private array $scopes = [];
31
32
    public function __construct()
33
    {
34
        $this->model = \App::make($this->getModelClass());
35
    }
36
37
    /**
38
     * @return string
39
     */
40
    abstract protected function getModelClass(): string;
41
42
    /**
43
     * @param int $limit
44
     * @param array $criteria
45
     *
46
     * @return LengthAwarePaginator
47
     */
48
    public function paginate(int $limit = 10, array $criteria = []): LengthAwarePaginator
49
    {
50
        $this->injectDefaultCriteria($criteria);
51
52
        return $this->getNewBuilderWithScope()
53
            ->with($this->with)
54
            ->orderByCriteria($criteria)
55
            ->searchByCriteria($criteria)
56
            ->filterByCriteria($criteria)
57
            ->paginate($limit);
58
    }
59
60
    /**
61
     * @param int $limit
62
     * @param array $criteria
63
     *
64
     * @return Paginator
65
     */
66
    public function simplePaginate(int $limit = 10, array $criteria = []): Paginator
67
    {
68
        return $this->getNewBuilderWithScope()
69
            ->with($this->with)
70
            ->orderByCriteria($criteria)
71
            ->searchByCriteria($criteria)
72
            ->filterByCriteria($criteria)
73
            ->simplePaginate($limit);
74
    }
75
76
    /**
77
     * @param int $id
78
     * @param array $columns
79
     *
80
     * @return Model|null
81
     */
82
    public function findOrFail(int $id, array $columns = ['*']): ?EloquentModel
83
    {
84
        return $this->getNewBuilderWithScope()
85
            ->with($this->with)
86
            ->findOrFail($id, $columns);
87
    }
88
89
    /**
90
     * @param array $data
91
     *
92
     * @return EloquentModel|null
93
     */
94
    public function create(array $data = []): ?EloquentModel
95
    {
96
        return $this->getNewBuilderWithScope()->create($data);
97
    }
98
99
    /**
100
     *
101
     * @param int $id
102
     * @param array $data
103
     *
104
     * @return bool
105
     */
106
    public function update(int $id, array $data = []): bool
107
    {
108
        return $this->getNewBuilderWithScope()->where('id', $id)->update($data);
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->getNewBuil...d', $id)->update($data) returns the type integer which is incompatible with the type-hinted return boolean.
Loading history...
109
    }
110
111
    /**
112
     * @param int $id
113
     *
114
     * @return bool
115
     * @throws Exception
116
     *
117
     */
118
    public function delete(int $id = 0): bool
119
    {
120
        return $this->getNewBuilderWithScope()->where('id', $id)->delete();
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->getNewBuil...re('id', $id)->delete() could return the type integer which is incompatible with the type-hinted return boolean. Consider adding an additional type-check to rule them out.
Loading history...
121
    }
122
123
    /**
124
     * @param array $criteria
125
     *
126
     * @param array $columns
127
     * @return Builder[]|Collection
128
     */
129
    public function get(array $criteria = [], array $columns = ['*']): Collection|array
130
    {
131
        return $this->getNewBuilderWithScope()
132
            ->with($this->with)
133
            ->orderByCriteria($criteria)
134
            ->searchByCriteria($criteria)
135
            ->filterByCriteria($criteria)
136
            ->get($columns);
137
    }
138
139
    public function find(int $id, array $columns = ['*']): ?EloquentModel
140
    {
141
        return $this->getNewBuilderWithScope()
142
            ->with($this->with)
143
            ->find($id, $columns);
144
    }
145
146
    /**
147
     * @param array $criteria
148
     * @param array $columns
149
     *
150
     * @return Model|null
151
     */
152
    public function first(array $criteria = [], array $columns = ['*']): ?Model
153
    {
154
        return $this->getNewBuilderWithScope()
155
            ->with($this->with)
156
            ->orderByCriteria($criteria)
157
            ->searchByCriteria($criteria)
158
            ->filterByCriteria($criteria)
159
            ->first($columns);
160
    }
161
162
    /**
163
     * @param string $key
164
     * @param array $criteria
165
     * @param array $columns
166
     *
167
     * @return Model|null
168
     */
169
    public function last(string $key = 'id', array $criteria = [], array $columns = ['*']): ?Model
170
    {
171
        return $this->getNewBuilderWithScope()
172
            ->with($this->with)
173
            ->searchByCriteria($criteria)
174
            ->filterByCriteria($criteria)
175
            ->orderBy($key, 'desc')
176
            ->first($columns);
177
    }
178
179
180
    public function injectDefaultCriteria(&$criteria)
181
    {
182
        $criteria['order'] = $criteria['order'] ?? $this->order;
183
        $criteria['direction'] = $criteria['direction'] ?? $this->direction;
184
    }
185
186
    public function scope(callable $callable): static
187
    {
188
        $this->scopes[] = $callable;
189
        return $this;
190
    }
191
192
    private function getNewBuilderWithScope(): Builder
193
    {
194
        $newQuery = $this->model->newQuery();
195
196
        foreach ($this->scopes as $scope) {
197
            $scope($newQuery);
198
        }
199
200
        return $newQuery;
201
    }
202
}
203