Passed
Branch master (af98ab)
by Hamzah
20:42
created

AbstractRepository::builder()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 1
Metric Value
cc 1
eloc 1
c 1
b 0
f 1
nc 1
nop 0
dl 0
loc 3
rs 10
1
<?php
2
/**
3
 * Created by PhpStorm.
4
 * User: Hamza Alayed
5
 * Date: 11/29/18
6
 * Time: 9:38 AM.
7
 */
8
9
namespace Shamaseen\Repository\Generator\Utility;
10
11
use Exception;
12
use Illuminate\Container\Container as App;
13
use Illuminate\Contracts\Container\BindingResolutionException;
14
use Illuminate\Contracts\Pagination\LengthAwarePaginator;
15
use Illuminate\Contracts\Pagination\Paginator;
16
use Illuminate\Database\Eloquent\Builder;
17
use Illuminate\Database\Eloquent\Collection;
18
use Illuminate\Database\Eloquent\Model;
19
use Illuminate\Database\Eloquent\ModelNotFoundException;
20
21
/**
22
 * Class Database.
23
 */
24
abstract class AbstractRepository implements ContractInterface
25
{
26
    protected $with = [];
27
28
    /**
29
     * @var App
30
     */
31
    protected $app;
32
33
    /** @var string */
34
    protected $order = null;
35
36
    protected $direction = 'desc';
37
38
    /**
39
     * @var Entity
40
     */
41
    protected $model;
42
43
    /**
44
     * @var bool
45
     */
46
    private $trash = false;
47
48
    /**
49
     * @var bool
50
     */
51
    private $withTrash = false;
52
53
    /**
54
     * @var bool
55
     */
56
    private $allowCaching = true;
57
58
    /**
59
     * @var array
60
     */
61
    private $cache = [];
62
63
    /**
64
     * @param App $app
65
     * @throws BindingResolutionException
66
     */
67
    public function __construct(App $app)
68
    {
69
        $this->app = $app;
70
        $this->makeModel();
71
    }
72
73
    /**
74
     * @throws BindingResolutionException
75
     */
76
    protected function makeModel()
77
    {
78
        $this->model = $this->app->make($this->getModelClass());
79
    }
80
81
    /**
82
     * @return string
83
     */
84
    abstract protected function getModelClass(): string;
85
86
    /**
87
     * @param int $limit
88
     * @param array $criteria
89
     *
90
     * @return Paginator
91
     */
92
    public function simplePaginate(int $limit = 10, array $criteria = []): Paginator
93
    {
94
        return $this->filter($criteria)->simplePaginate($limit);
95
    }
96
97
    /**
98
     * @return \Illuminate\Database\Query\Builder|Entity
99
     */
100
    public function builder()
101
    {
102
        return $this->model->query();
103
    }
104
105
    /**
106
     * @param array $criteria
107
     *
108
     * @return Builder
109
     */
110
    public function filter(array $criteria = []): Builder
111
    {
112
        $criteria = $this->order($criteria);
113
114
        /** @var Entity $latest */
115
        $latest = $this->model->with($this->with);
116
        if ('' != $this->order) {
117
            $latest->orderBy($this->order, $this->direction);
118
        }
119
120
        if (isset($criteria['search'])) {
121
            foreach ($this->model->searchable as $method => $columns) {
122
                if (method_exists($this->model, $method)) {
123
                    $latest->orWhereHas($method, function ($query) use ($criteria, $columns) {
124
                        /* @var $query Builder */
125
                        $query->where(function ($query2) use ($criteria, $columns) {
126
                            /* @var $query2 Builder */
127
                            foreach ((array)$columns as $column) {
128
                                $query2->orWhere($column, 'like', '%' . $criteria['search'] . '%');
129
                            }
130
                        });
131
                    });
132
                } else {
133
                    $latest->orWhere($columns, 'like', '%' . $criteria['search'] . '%');
134
                }
135
            }
136
        }
137
        unset($criteria['search']);
138
139
        if ($this->trash) {
140
            $latest->onlyTrashed();
141
        }
142
        if ($this->withTrash) {
143
            $latest->withTrashed();
144
        }
145
146
        return $latest->where($criteria);
147
    }
148
149
    /**
150
     * prepare order for query.
151
     *
152
     * @param array $criteria
153
     *
154
     * @return array
155
     */
156
    private function order(array $criteria = []): array
157
    {
158
        if (isset($criteria['order'])) {
159
            $this->order = $criteria['order'];
160
            unset($criteria['order']);
161
        }
162
163
        if (isset($criteria['direction'])) {
164
            $this->direction = $criteria['direction'];
165
            unset($criteria['direction']);
166
        }
167
        unset($criteria['page']);
168
169
        return $criteria;
170
    }
171
172
    /**
173
     * @param int $limit
174
     * @param array $criteria
175
     *
176
     * @return LengthAwarePaginator
177
     */
178
    public function paginate(int $limit = 10, array $criteria = []): LengthAwarePaginator
179
    {
180
        return $this->filter($criteria)->paginate($limit);
181
    }
182
183
    /**
184
     * @param array $criteria
185
     *
186
     * @param array $columns
187
     * @return Builder[]|Collection
188
     */
189
    public function get(array $criteria = [], array $columns = ['*']): LengthAwarePaginator
190
    {
191
        return $this->filter($criteria)->get($columns);
192
    }
193
194
    /**
195
     * @param int $entityId
196
     * @param array $data
197
     *
198
     * @return bool|Collection|Model|Entity
199
     */
200
    public function update(int $entityId = 0, array $data = [])
201
    {
202
        $item = $this->model->findOrFail($entityId);
203
204
        if ($item->update($data)) {
205
            return $item;
206
        }
207
208
        return false;
209
    }
210
211
    /**
212
     * @param int $entityId
213
     *
214
     * @return bool
215
     * @throws Exception
216
     *
217
     */
218
    public function delete(int $entityId = 0): bool
219
    {
220
        $item = $this->model->findOrFail($entityId);
221
222
        return $item->delete();
223
    }
224
225
    /**
226
     * @param array $data
227
     *
228
     * @return bool
229
     */
230
    public function insert(array $data = []): bool
231
    {
232
        return $this->model->insert($data);
233
    }
234
235
    /**
236
     * @param string $name
237
     * @param string $entityId
238
     * @param array $criteria
239
     *
240
     * @return array
241
     */
242
    public function pluck(string $name = 'name', string $entityId = 'id', array $criteria = []): array
243
    {
244
        return $this->filter($criteria)->pluck($name, $entityId)->toArray();
245
    }
246
247
    /**
248
     * @param int $entityId
249
     * @param array $columns
250
     *
251
     * @return Model|null
252
     */
253
    public function find(int $entityId = 0, array $columns = ['*']): ?Model
254
    {
255
        if ($this->allowCaching) {
256
            if (isset($this->cache[$entityId])) {
257
                return $this->cache[$entityId];
258
            }
259
        }
260
261
        $entity = $this->model->with($this->with)->find($entityId, $columns);
262
263
        if ($this->allowCaching) {
264
            $this->cache[$entityId] = $entity;
265
        }
266
267
        return $entity;
268
    }
269
270
    /**
271
     * @param $entityId
272
     * @param array $columns
273
     *
274
     * @return Model|Collection|static|static[]
275
     * @throws ModelNotFoundException
276
     *
277
     */
278
    public function findOrFail($entityId = 0, array $columns = ['*'])
279
    {
280
        if ($this->allowCaching) {
281
            if (isset($this->cache[$entityId])) {
282
                return $this->cache[$entityId];
283
            }
284
        }
285
286
        $entity = $this->model->with($this->with)->findOrFail($entityId, $columns);
287
288
        if ($this->allowCaching) {
289
            $this->cache[$entityId] = $entity;
290
        }
291
292
        return $entity;
293
    }
294
295
    /**
296
     * @param array $filter
297
     * @param array $columns
298
     *
299
     * @return Model|null|object
300
     */
301
    public function first(array $filter = [], array $columns = ['*'])
302
    {
303
        if ($this->allowCaching) {
304
            if (isset($this->cache['first'])) {
305
                return $this->cache['first'];
306
            }
307
        }
308
309
        $entity = $this->filter($filter)->with($this->with)->select($columns)->first();
310
311
        if ($this->allowCaching) {
312
            $this->cache['first'] = $entity;
313
        }
314
315
        return $entity;
316
    }
317
318
    /**
319
     * @param array $filter
320
     * @param array $columns
321
     *
322
     * @return Model|null|object
323
     */
324
    public function last(array $filter = [], array $columns = ['*'])
325
    {
326
        if ($this->allowCaching) {
327
            if (isset($this->cache['last'])) {
328
                return $this->cache['last'];
329
            }
330
        }
331
332
        $entity = $this->filter($filter)->with($this->with)->select($columns)->orderBy('id', 'desc')->first();
333
334
        if ($this->allowCaching) {
335
            $this->cache['last'] = $entity;
336
        }
337
338
        return $entity;
339
    }
340
341
    /**
342
     * @param $haystack
343
     * @param $needle
344
     *
345
     * @return Entity[]|Model[]|Collection
346
     */
347
    public function search($haystack, $needle)
348
    {
349
        return $this->model->where($haystack, 'like', $needle)->get();
350
    }
351
352
    /**
353
     * @param array $criteria
354
     * @param array $columns
355
     *
356
     * @return Model|null|object
357
     */
358
    public function findBy(array $criteria = [], array $columns = ['*'])
359
    {
360
        return $this->model->with($this->with)->select($columns)->where($criteria)->first();
361
    }
362
363
    /**
364
     * @param array $data
365
     *
366
     * @return Entity|Model
367
     */
368
    public function create(array $data = [])
369
    {
370
        return $this->model->create($data);
371
    }
372
373
    /**
374
     * @param array $data
375
     *
376
     * @return Model
377
     */
378
    public function createOrUpdate(array $data = []): Model
379
    {
380
        return $this->model->updateOrCreate($data);
381
    }
382
383
    /**
384
     * @param array $data
385
     *
386
     * @return Model
387
     */
388
    public function createOrFirst(array $data = []): Model
389
    {
390
        return $this->model->firstOrCreate($data);
391
    }
392
393
    /**
394
     * Get entity name.
395
     *
396
     * @return string
397
     */
398
    public function entityName(): string
399
    {
400
        return $this->getModelClass();
401
    }
402
403
    /**
404
     * @param int $entityId
405
     *
406
     * @return bool
407
     */
408
    public function restore(int $entityId = 0): bool
409
    {
410
        /** @var Entity|null $entity */
411
        $entity = $this->model->withTrashed()
412
            ->whereId($entityId)
413
            ->first();
414
        if ($entity) {
0 ignored issues
show
introduced by
$entity is of type Shamaseen\Repository\Generator\Utility\Entity, thus it always evaluated to true.
Loading history...
415
            return $entity->restore() ?? false;
416
        }
417
418
        return false;
419
    }
420
421
    /**
422
     * @param int $entityId
423
     *
424
     * @return bool
425
     */
426
    public function forceDelete(int $entityId = 0): bool
427
    {
428
        /** @var Entity|null $entity */
429
        $entity = $this->model->withTrashed()
430
            ->whereId($entityId)
431
            ->first();
432
        if ($entity) {
0 ignored issues
show
introduced by
$entity is of type Shamaseen\Repository\Generator\Utility\Entity, thus it always evaluated to true.
Loading history...
433
            return $entity->forceDelete() ?? false;
434
        }
435
436
        return false;
437
    }
438
439
    public function trash()
440
    {
441
        $this->trash = true;
442
        $this->withTrash = false;
443
    }
444
445
    public function withTrash()
446
    {
447
        $this->trash = false;
448
        $this->withTrash = true;
449
    }
450
451
    public function disableCaching(): AbstractRepository
452
    {
453
        $this->allowCaching = false;
454
        return $this;
455
    }
456
}
457