Completed
Pull Request — master (#5)
by
unknown
02:22 queued 32s
created

EloquentRepository::makeModel()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 10
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 6

Importance

Changes 0
Metric Value
cc 2
eloc 5
nc 2
nop 0
dl 0
loc 10
ccs 0
cts 5
cp 0
crap 6
rs 9.4285
c 0
b 0
f 0
1
<?php
2
3
namespace Recca0120\Repository;
4
5
use RuntimeException;
6
use Illuminate\Container\Container;
7
use Illuminate\Database\Eloquent\Model;
8
use Recca0120\Repository\Contracts\EloquentRepository as EloquentRepositoryContract;
9
10
abstract class EloquentRepository implements EloquentRepositoryContract
11
{
12
    /**
13
     * $model.
14
     *
15
     * @var \Illuminate\Database\Eloquent\Model
16
     */
17
    protected $model;
18
19
    /**
20
     * @var
21
     */
22
    private $app;
23
24
    /**
25
     * EloquentRepository constructor.
26
     * @param Container $app
27
     */
28
    public function __construct(Container $app)
29
    {
30
        $this->app = $app;
31
32
        $this->makeModel();
33
    }
34
35
    /**
36
     * @return Model|mixed
37
     */
38
    protected function makeModel()
39
    {
40
        $model = $this->app->make($this->model);
41
42
        if (! $model instanceof Model) {
43
            throw new RuntimeException("Class {$this->model} must be an instance of Illuminate\\Database\\Eloquent\\Model");
44
        }
45
46
        return $this->model = $model;
47
    }
48
49
    /**
50
     * Find a model by its primary key.
51
     *
52
     * @param  mixed $id
53
     * @param  array $columns
54
     * @return \Illuminate\Database\Eloquent\Model|\Illuminate\Database\Eloquent\Collection|static[]|static|null
55
     */
56
    public function find($id, $columns = ['*'])
57
    {
58
        return $this->newQuery()->find($id, $columns);
59
    }
60
61
    /**
62
     * Find multiple models by their primary keys.
63
     *
64
     * @param  \Illuminate\Contracts\Support\Arrayable|array $ids
65
     * @param  array $columns
66
     * @return \Illuminate\Database\Eloquent\Collection
67
     */
68
    public function findMany($ids, $columns = ['*'])
69
    {
70
        return $this->newQuery()->findMany($ids, $columns);
71
    }
72
73
    /**
74
     * Find a model by its primary key or throw an exception.
75
     *
76
     * @param  mixed $id
77
     * @param  array $columns
78
     * @return \Illuminate\Database\Eloquent\Model|\Illuminate\Database\Eloquent\Collection
79
     *
80
     * @throws \Illuminate\Database\Eloquent\ModelNotFoundException
81
     */
82
    public function findOrFail($id, $columns = ['*'])
83
    {
84
        return $this->newQuery()->findOrFail($id, $columns);
85
    }
86
87
    /**
88
     * Find a model by its primary key or return fresh model instance.
89
     *
90
     * @param  mixed $id
91
     * @param  array $columns
92
     * @return \Illuminate\Database\Eloquent\Model
93
     */
94
    public function findOrNew($id, $columns = ['*'])
95
    {
96
        return $this->newQuery()->findOrNew($id, $columns);
97
    }
98
99
    /**
100
     * Get the first record matching the attributes or instantiate it.
101
     *
102
     * @param  array $attributes
103
     * @param  array $values
104
     * @return \Illuminate\Database\Eloquent\Model
105
     */
106
    public function firstOrNew(array $attributes, array $values = [])
107
    {
108
        return $this->newQuery()->firstOrNew($attributes, $values);
109
    }
110
111
    /**
112
     * Get the first record matching the attributes or create it.
113
     *
114
     * @param  array $attributes
115
     * @param  array $values
116
     * @return \Illuminate\Database\Eloquent\Model
117
     */
118
    public function firstOrCreate(array $attributes, array $values = [])
119
    {
120
        return $this->newQuery()->firstOrCreate($attributes, $values);
121
    }
122
123
    /**
124
     * Create or update a record matching the attributes, and fill it with values.
125
     *
126
     * @param  array $attributes
127
     * @param  array $values
128
     * @return \Illuminate\Database\Eloquent\Model
129
     */
130
    public function updateOrCreate(array $attributes, array $values = [])
131
    {
132
        return $this->newQuery()->updateOrCreate($attributes, $values);
133
    }
134
135
    /**
136
     * Execute the query and get the first result or throw an exception.
137
     *
138
     * @param  array $columns
139
     * @param  \Recca0120\Repository\Criteria[] $criteria
140
     * @return \Illuminate\Database\Eloquent\Model|static
141
     *
142
     * @throws \Illuminate\Database\Eloquent\ModelNotFoundException
143
     */
144
    public function firstOrFail($criteria = [], $columns = ['*'])
145
    {
146
        return $this->matching($criteria)->firstOrFail($columns);
147
    }
148
149
    /**
150
     * create.
151
     *
152
     * @param  array $attributes
153
     * @return \Illuminate\Database\Eloquent\Model
154
     *
155
     * @throws \Throwable
156
     */
157
    public function create($attributes)
158
    {
159
        return tap($this->newInstance(), function ($instance) use ($attributes) {
160
            $instance->fill($attributes)->saveOrFail();
161
        });
162
    }
163
164
    /**
165
     * Save a new model and return the instance.
166
     *
167
     * @param  array $attributes
168
     * @return \Illuminate\Database\Eloquent\Model
169
     *
170
     * @throws \Throwable
171
     */
172
    public function forceCreate($attributes)
173
    {
174
        return tap($this->newInstance(), function ($instance) use ($attributes) {
175
            $instance->forceFill($attributes)->saveOrFail();
176
        });
177
    }
178
179
    /**
180
     * update.
181
     *
182
     * @param  array $attributes
183
     * @param  mixed $id
184
     * @return \Illuminate\Database\Eloquent\Model
185
     *
186
     * @throws \Throwable
187
     */
188
    public function update($id, $attributes)
189
    {
190
        return tap($this->findOrFail($id), function ($instance) use ($attributes) {
191
            $instance->fill($attributes)->saveOrFail();
192
        });
193
    }
194
195
    /**
196
     * forceCreate.
197
     *
198
     * @param  array $attributes
199
     * @param  mixed $id
200
     * @return \Illuminate\Database\Eloquent\Model
201
     *
202
     * @throws \Throwable
203
     */
204
    public function forceUpdate($id, $attributes)
205
    {
206
        return tap($this->findOrFail($id), function ($instance) use ($attributes) {
207
            $instance->forceFill($attributes)->saveOrFail();
208
        });
209
    }
210
211
    /**
212
     * delete.
213
     *
214
     * @param  mixed $id
215
     */
216
    public function delete($id)
217
    {
218
        return $this->find($id)->delete();
219
    }
220
221
    /**
222
     * Restore a soft-deleted model instance.
223
     *
224
     * @param  mixed $id
225
     * @return bool|null
226
     */
227
    public function restore($id)
228
    {
229
        return $this->newQuery()->restore($id);
230
    }
231
232
    /**
233
     * Force a hard delete on a soft deleted model.
234
     *
235
     * This method protects developers from running forceDelete when trait is missing.
236
     *
237
     * @param  mixed $id
238
     * @return bool|null
239
     */
240
    public function forceDelete($id)
241
    {
242
        return $this->findOrFail($id)->forceDelete();
243
    }
244
245
    /**
246
     * Create a new model instance that is existing.
247
     *
248
     * @param  array $attributes
249
     * @return \Illuminate\Database\Eloquent\Model
250
     */
251
    public function newInstance($attributes = [], $exists = false)
252
    {
253
        return $this->getModel()->newInstance($attributes, $exists);
254
    }
255
256
    /**
257
     * Execute the query as a "select" statement.
258
     *
259
     * @param  \Recca0120\Repository\Criteria[] $criteria
260
     * @param  array $columns
261
     * @return \Illuminate\Support\Collection
262
     */
263
    public function get($criteria = [], $columns = ['*'])
264
    {
265
        return $this->matching($criteria)->get($columns);
266
    }
267
268
    /**
269
     * Chunk the results of the query.
270
     *
271
     * @param  \Recca0120\Repository\Criteria[] $criteria
272
     * @param  int $count
273
     * @param  callable $callback
274
     * @return bool
275
     */
276
    public function chunk($criteria, $count, callable $callback)
277
    {
278
        return $this->matching($criteria)->chunk($count, $callback);
279
    }
280
281
    /**
282
     * Execute a callback over each item while chunking.
283
     *
284
     * @param  \Recca0120\Repository\Criteria[] $criteria
285
     * @param  callable $callback
286
     * @param  int $count
287
     * @return bool
288
     */
289
    public function each($criteria, callable $callback, $count = 1000)
290
    {
291
        return $this->matching($criteria)->each($callback, $count);
292
    }
293
294
    /**
295
     * Execute the query and get the first result.
296
     *
297
     * @param  \Recca0120\Repository\Criteria[] $criteria
298
     * @param  array $columns
299
     * @return \Illuminate\Database\Eloquent\Model|static|null
300
     */
301
    public function first($criteria = [], $columns = ['*'])
302
    {
303
        return $this->matching($criteria)->first($columns);
304
    }
305
306
    /**
307
     * Paginate the given query.
308
     *
309
     * @param  \Recca0120\Repository\Criteria[] $criteria
310
     * @param  int $perPage
311
     * @param  array $columns
312
     * @param  string $pageName
313
     * @param  int|null $page
314
     * @return \Illuminate\Contracts\Pagination\LengthAwarePaginator
315
     *
316
     * @throws \InvalidArgumentException
317
     */
318
    public function paginate($criteria = [], $perPage = null, $columns = ['*'], $pageName = 'page', $page = null)
319
    {
320
        return $this->matching($criteria)->paginate($perPage, $columns, $pageName, $page);
321
    }
322
323
    /**
324
     * Paginate the given query into a simple paginator.
325
     *
326
     * @param  \Recca0120\Repository\Criteria[] $criteria
327
     * @param  int $perPage
328
     * @param  array $columns
329
     * @param  string $pageName
330
     * @param  int|null $page
331
     * @return \Illuminate\Contracts\Pagination\Paginator
332
     */
333
    public function simplePaginate($criteria = [], $perPage = null, $columns = ['*'], $pageName = 'page', $page = null)
334
    {
335
        return $this->matching($criteria)->simplePaginate($perPage, $columns, $pageName, $page);
336
    }
337
338
    /**
339
     * Retrieve the "count" result of the query.
340
     *
341
     * @param  \Recca0120\Repository\Criteria[] $criteria
342
     * @param  string $columns
343
     * @return int
344
     */
345
    public function count($criteria = [], $columns = '*')
346
    {
347
        return (int) $this->matching($criteria)->count($columns);
348
    }
349
350
    /**
351
     * Retrieve the minimum value of a given column.
352
     *
353
     * @param  \Recca0120\Repository\Criteria[] $criteria
354
     * @param  string $column
355
     * @return mixed
356
     */
357
    public function min($criteria, $column)
358
    {
359
        return $this->matching($criteria)->min($column);
360
    }
361
362
    /**
363
     * Retrieve the maximum value of a given column.
364
     *
365
     * @param  \Recca0120\Repository\Criteria[] $criteria
366
     * @param  string $column
367
     * @return mixed
368
     */
369
    public function max($criteria, $column)
370
    {
371
        return $this->matching($criteria)->max($column);
372
    }
373
374
    /**
375
     * Retrieve the sum of the values of a given column.
376
     *
377
     * @param  \Recca0120\Repository\Criteria[] $criteria
378
     * @param  string $column
379
     * @return mixed
380
     */
381
    public function sum($criteria, $column)
382
    {
383
        $result = $this->matching($criteria)->sum($column);
384
385
        return $result ?: 0;
386
    }
387
388
    /**
389
     * Retrieve the average of the values of a given column.
390
     *
391
     * @param  \Recca0120\Repository\Criteria[] $criteria
392
     * @param  string $column
393
     * @return mixed
394
     */
395 1
    public function avg($criteria, $column)
396
    {
397 1
        return $this->matching($criteria)->avg($column);
398
    }
399
400
    /**
401
     * Alias for the "avg" method.
402
     *
403
     * @param  string $column
404
     * @return mixed
405
     */
406 1
    public function average($criteria, $column)
407
    {
408 1
        return $this->avg($criteria, $column);
409
    }
410
411
    /**
412
     * matching.
413
     *
414
     * @param  \Recca0120\Repository\Criteria[] $criteria
415
     * @return \Illuminate\Database\Eloquent\Builder
416
     */
417 1
    public function matching($criteria)
418
    {
419 1
        $criteria = is_array($criteria) === false ? [$criteria] : $criteria;
420
421
        return array_reduce($criteria, function ($query, $criteria) {
422
            $criteria->each(function ($method) use ($query) {
423
                call_user_func_array([$query, $method->name], $method->parameters);
424
            });
425
426
            return $query;
427 1
        }, $this->newQuery());
428
    }
429
430
    /**
431
     * getQuery.
432
     *
433
     * @param \Recca0120\Repository\Criteria[] $criteria
434
     * @return \Illuminate\Database\Eloquent\Builder
435
     */
436
    public function getQuery($criteria = [])
437
    {
438
        return $this->matching($criteria)->getQuery();
439
    }
440
441
    /**
442
     * getModel.
443
     *
444
     * @return \Illuminate\Database\Eloquent\Model
445
     */
446
    public function getModel()
447
    {
448
        return $this->model instanceof Model
449
            ? clone $this->model
450
            : $this->model->getModel();
451
    }
452
453
    /**
454
     * Get a new query builder for the model's table.
455
     *
456
     * @return \Illuminate\Database\Eloquent\Builder
457
     */
458 1
    public function newQuery()
459
    {
460 1
        return $this->model instanceof Model
461
            ? $this->model->newQuery()
462 1
            : clone $this->model;
463
    }
464
}
465