Completed
Push — master ( d2652c...770afa )
by Abdelrahman
01:18
created

EloquentRepository::update()   B

Complexity

Conditions 8
Paths 36

Size

Total Lines 39

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 39
rs 8.0515
cc 8
nc 36
nop 3
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Rinvex\Repository\Repositories;
6
7
use Illuminate\Pagination\Paginator;
8
use Illuminate\Database\Eloquent\Model;
9
use Rinvex\Repository\Exceptions\RepositoryException;
10
use Rinvex\Repository\Exceptions\EntityNotFoundException;
11
12
class EloquentRepository extends BaseRepository
13
{
14
    /**
15
     * {@inheritdoc}
16
     */
17
    public function createModel()
18
    {
19
        if (is_string($model = $this->getModel())) {
20
            if (! class_exists($class = '\\'.ltrim($model, '\\'))) {
21
                throw new RepositoryException("Class {$model} does NOT exist!");
22
            }
23
24
            $model = $this->getContainer()->make($class);
25
        }
26
27
        // Set the connection used by the model
28
        if (! empty($this->connection)) {
29
            $model = $model->setConnection($this->connection);
30
        }
31
32
        if (! $model instanceof Model) {
33
            throw new RepositoryException("Class {$model} must be an instance of \\Illuminate\\Database\\Eloquent\\Model");
34
        }
35
36
        return $model;
37
    }
38
39
    /**
40
     * {@inheritdoc}
41
     */
42
    public function find($id, $attributes = ['*'])
43
    {
44
        return $this->executeCallback(get_called_class(), __FUNCTION__, func_get_args(), function () use ($id, $attributes) {
45
            return $this->prepareQuery($this->createModel())->find($id, $attributes);
46
        });
47
    }
48
49
    /**
50
     * {@inheritdoc}
51
     */
52
    public function findOrFail($id, $attributes = ['*'])
53
    {
54
        $result = $this->find($id, $attributes);
55
56
        if (is_array($id)) {
57
            if (count($result) === count(array_unique($id))) {
58
                return $result;
59
            }
60
        } elseif (! is_null($result)) {
61
            return $result;
62
        }
63
64
        throw new EntityNotFoundException($this->getModel(), $id);
65
    }
66
67
    /**
68
     * {@inheritdoc}
69
     */
70
    public function findOrNew($id, $attributes = ['*'])
71
    {
72
        if (! is_null($entity = $this->find($id, $attributes))) {
73
            return $entity;
74
        }
75
76
        return $this->createModel();
77
    }
78
79
    /**
80
     * {@inheritdoc}
81
     */
82
    public function findBy($attribute, $value, $attributes = ['*'])
83
    {
84
        return $this->executeCallback(get_called_class(), __FUNCTION__, func_get_args(), function () use ($attribute, $value, $attributes) {
85
            return $this->prepareQuery($this->createModel())->where($attribute, '=', $value)->first($attributes);
86
        });
87
    }
88
89
    /**
90
     * {@inheritdoc}
91
     */
92
    public function findFirst($attributes = ['*'])
93
    {
94
        return $this->executeCallback(get_called_class(), __FUNCTION__, func_get_args(), function () use ($attributes) {
95
            return $this->prepareQuery($this->createModel())->first($attributes);
96
        });
97
    }
98
99
    /**
100
     * {@inheritdoc}
101
     */
102
    public function findAll($attributes = ['*'])
103
    {
104
        return $this->executeCallback(get_called_class(), __FUNCTION__, func_get_args(), function () use ($attributes) {
105
            return $this->prepareQuery($this->createModel())->get($attributes);
106
        });
107
    }
108
109
    /**
110
     * {@inheritdoc}
111
     */
112
    public function paginate($perPage = null, $attributes = ['*'], $pageName = 'page', $page = null)
113
    {
114
        $page = $page ?: Paginator::resolveCurrentPage($pageName);
115
116
        return $this->executeCallback(get_called_class(), __FUNCTION__, array_merge(func_get_args(), compact('page')), function () use ($perPage, $attributes, $pageName, $page) {
117
            return $this->prepareQuery($this->createModel())->paginate($perPage, $attributes, $pageName, $page);
118
        });
119
    }
120
121
    /**
122
     * {@inheritdoc}
123
     */
124
    public function simplePaginate($perPage = null, $attributes = ['*'], $pageName = 'page', $page = null)
125
    {
126
        $page = $page ?: Paginator::resolveCurrentPage($pageName);
127
128
        return $this->executeCallback(get_called_class(), __FUNCTION__, array_merge(func_get_args(), compact('page')), function () use ($perPage, $attributes, $pageName, $page) {
0 ignored issues
show
Coding Style introduced by
This line exceeds maximum limit of 120 characters; contains 178 characters

Overly long lines are hard to read on any screen. Most code styles therefor impose a maximum limit on the number of characters in a line.

Loading history...
129
            return $this->prepareQuery($this->createModel())->simplePaginate($perPage, $attributes, $pageName, $page);
130
        });
131
    }
132
133
    /**
134
     * {@inheritdoc}
135
     */
136
    public function findWhere(array $where, $attributes = ['*'])
137
    {
138
        return $this->executeCallback(get_called_class(), __FUNCTION__, func_get_args(), function () use ($where, $attributes) {
0 ignored issues
show
Coding Style introduced by
This line exceeds maximum limit of 120 characters; contains 128 characters

Overly long lines are hard to read on any screen. Most code styles therefor impose a maximum limit on the number of characters in a line.

Loading history...
139
            [$attribute, $operator, $value, $boolean] = array_pad($where, 4, null);
0 ignored issues
show
Bug introduced by
The variable $attribute does not exist. Did you mean $attributes?

This check looks for variables that are accessed but have not been defined. It raises an issue if it finds another variable that has a similar name.

The variable may have been renamed without also renaming all references.

Loading history...
Bug introduced by
The variable $operator does not exist. Did you forget to declare it?

This check marks access to variables or properties that have not been declared yet. While PHP has no explicit notion of declaring a variable, accessing it before a value is assigned to it is most likely a bug.

Loading history...
Bug introduced by
The variable $value does not exist. Did you forget to declare it?

This check marks access to variables or properties that have not been declared yet. While PHP has no explicit notion of declaring a variable, accessing it before a value is assigned to it is most likely a bug.

Loading history...
Bug introduced by
The variable $boolean does not exist. Did you forget to declare it?

This check marks access to variables or properties that have not been declared yet. While PHP has no explicit notion of declaring a variable, accessing it before a value is assigned to it is most likely a bug.

Loading history...
140
141
            $this->where($attribute, $operator, $value, $boolean);
0 ignored issues
show
Bug introduced by
The variable $attribute does not exist. Did you mean $attributes?

This check looks for variables that are accessed but have not been defined. It raises an issue if it finds another variable that has a similar name.

The variable may have been renamed without also renaming all references.

Loading history...
142
143
            return $this->prepareQuery($this->createModel())->get($attributes);
144
        });
145
    }
146
147
    /**
148
     * {@inheritdoc}
149
     */
150
    public function findWhereIn(array $where, $attributes = ['*'])
151
    {
152
        return $this->executeCallback(get_called_class(), __FUNCTION__, func_get_args(), function () use ($where, $attributes) {
0 ignored issues
show
Coding Style introduced by
This line exceeds maximum limit of 120 characters; contains 128 characters

Overly long lines are hard to read on any screen. Most code styles therefor impose a maximum limit on the number of characters in a line.

Loading history...
153
            [$attribute, $values, $boolean, $not] = array_pad($where, 4, null);
0 ignored issues
show
Bug introduced by
The variable $attribute does not exist. Did you mean $attributes?

This check looks for variables that are accessed but have not been defined. It raises an issue if it finds another variable that has a similar name.

The variable may have been renamed without also renaming all references.

Loading history...
Bug introduced by
The variable $values does not exist. Did you forget to declare it?

This check marks access to variables or properties that have not been declared yet. While PHP has no explicit notion of declaring a variable, accessing it before a value is assigned to it is most likely a bug.

Loading history...
Bug introduced by
The variable $boolean does not exist. Did you forget to declare it?

This check marks access to variables or properties that have not been declared yet. While PHP has no explicit notion of declaring a variable, accessing it before a value is assigned to it is most likely a bug.

Loading history...
Bug introduced by
The variable $not does not exist. Did you forget to declare it?

This check marks access to variables or properties that have not been declared yet. While PHP has no explicit notion of declaring a variable, accessing it before a value is assigned to it is most likely a bug.

Loading history...
154
155
            $this->whereIn($attribute, $values, $boolean, $not);
0 ignored issues
show
Bug introduced by
The variable $attribute does not exist. Did you mean $attributes?

This check looks for variables that are accessed but have not been defined. It raises an issue if it finds another variable that has a similar name.

The variable may have been renamed without also renaming all references.

Loading history...
156
157
            return $this->prepareQuery($this->createModel())->get($attributes);
158
        });
159
    }
160
161
    /**
162
     * {@inheritdoc}
163
     */
164
    public function findWhereNotIn(array $where, $attributes = ['*'])
165
    {
166
        return $this->executeCallback(get_called_class(), __FUNCTION__, func_get_args(), function () use ($where, $attributes) {
167
            [$attribute, $values, $boolean] = array_pad($where, 3, null);
0 ignored issues
show
Bug introduced by
The variable $attribute does not exist. Did you mean $attributes?

This check looks for variables that are accessed but have not been defined. It raises an issue if it finds another variable that has a similar name.

The variable may have been renamed without also renaming all references.

Loading history...
Bug introduced by
The variable $values does not exist. Did you forget to declare it?

This check marks access to variables or properties that have not been declared yet. While PHP has no explicit notion of declaring a variable, accessing it before a value is assigned to it is most likely a bug.

Loading history...
Bug introduced by
The variable $boolean does not exist. Did you forget to declare it?

This check marks access to variables or properties that have not been declared yet. While PHP has no explicit notion of declaring a variable, accessing it before a value is assigned to it is most likely a bug.

Loading history...
168
169
            $this->whereNotIn($attribute, $values, $boolean);
0 ignored issues
show
Bug introduced by
The variable $attribute does not exist. Did you mean $attributes?

This check looks for variables that are accessed but have not been defined. It raises an issue if it finds another variable that has a similar name.

The variable may have been renamed without also renaming all references.

Loading history...
170
171
            return $this->prepareQuery($this->createModel())->get($attributes);
172
        });
173
    }
174
175
    /**
176
     * {@inheritdoc}
177
     */
178
    public function findWhereHas(array $where, $attributes = ['*'])
179
    {
180
        return $this->executeCallback(get_called_class(), __FUNCTION__, func_get_args(), function () use ($where, $attributes) {
0 ignored issues
show
Coding Style introduced by
This line exceeds maximum limit of 120 characters; contains 128 characters

Overly long lines are hard to read on any screen. Most code styles therefor impose a maximum limit on the number of characters in a line.

Loading history...
181
            [$relation, $callback, $operator, $count] = array_pad($where, 4, null);
0 ignored issues
show
Bug introduced by
The variable $relation does not exist. Did you forget to declare it?

This check marks access to variables or properties that have not been declared yet. While PHP has no explicit notion of declaring a variable, accessing it before a value is assigned to it is most likely a bug.

Loading history...
Bug introduced by
The variable $callback does not exist. Did you forget to declare it?

This check marks access to variables or properties that have not been declared yet. While PHP has no explicit notion of declaring a variable, accessing it before a value is assigned to it is most likely a bug.

Loading history...
Bug introduced by
The variable $operator does not exist. Did you forget to declare it?

This check marks access to variables or properties that have not been declared yet. While PHP has no explicit notion of declaring a variable, accessing it before a value is assigned to it is most likely a bug.

Loading history...
Bug introduced by
The variable $count does not exist. Did you forget to declare it?

This check marks access to variables or properties that have not been declared yet. While PHP has no explicit notion of declaring a variable, accessing it before a value is assigned to it is most likely a bug.

Loading history...
182
183
            $this->whereHas($relation, $callback, $operator, $count);
184
185
            return $this->prepareQuery($this->createModel())->get($attributes);
186
        });
187
    }
188
189
    /**
190
     * {@inheritdoc}
191
     */
192
    public function create(array $attributes = [], bool $syncRelations = false)
193
    {
194
        // Create a new instance
195
        $entity = $this->createModel();
196
197
        // Fire the created event
198
        $this->getContainer('events')->dispatch($this->getRepositoryId().'.entity.creating', [$this, $entity]);
199
200
        // Extract relationships
201
        if ($syncRelations) {
202
            $relations = $this->extractRelations($entity, $attributes);
203
            array_forget($attributes, array_keys($relations));
204
        }
205
206
        // Fill instance with data
207
        $entity->fill($attributes);
208
209
        // Save the instance
210
        $created = $entity->save();
211
212
        // Sync relationships
213
        if ($syncRelations && isset($relations)) {
214
            $this->syncRelations($entity, $relations);
215
        }
216
217
        // Fire the created event
218
        $this->getContainer('events')->dispatch($this->getRepositoryId().'.entity.created', [$this, $entity]);
219
220
        // Return instance
221
        return $created ? $entity : $created;
222
    }
223
224
    /**
225
     * {@inheritdoc}
226
     */
227
    public function update($id, array $attributes = [], bool $syncRelations = false)
228
    {
229
        $updated = false;
230
231
        // Find the given instance
232
        $entity = $id instanceof Model ? $id : $this->find($id);
233
234
        if ($entity) {
235
            // Fire the updated event
236
            $this->getContainer('events')->dispatch($this->getRepositoryId().'.entity.updating', [$this, $entity]);
237
238
            // Extract relationships
239
            if ($syncRelations) {
240
                $relations = $this->extractRelations($entity, $attributes);
241
                array_forget($attributes, array_keys($relations));
242
            }
243
244
            // Fill instance with data
245
            $entity->fill($attributes);
246
247
            //Check if we are updating attributes values
248
            $dirty = $entity->getDirty();
249
250
            // Update the instance
251
            $updated = $entity->save();
252
253
            // Sync relationships
254
            if ($syncRelations && isset($relations)) {
255
                $this->syncRelations($entity, $relations);
256
            }
257
258
            if (count($dirty) > 0) {
259
                // Fire the updated event
260
                $this->getContainer('events')->dispatch($this->getRepositoryId().'.entity.updated', [$this, $entity]);
261
            }
262
        }
263
264
        return $updated ? $entity : $updated;
265
    }
266
267
    /**
268
     * {@inheritdoc}
269
     */
270
    public function delete($id)
271
    {
272
        $deleted = false;
273
274
        // Find the given instance
275
        $entity = $id instanceof Model ? $id : $this->find($id);
276
277
        if ($entity) {
278
            // Fire the deleted event
279
            $this->getContainer('events')->dispatch($this->getRepositoryId().'.entity.deleting', [$this, $entity]);
280
281
            // Delete the instance
282
            $deleted = $entity->delete();
283
284
            // Fire the deleted event
285
            $this->getContainer('events')->dispatch($this->getRepositoryId().'.entity.deleted', [$this, $entity]);
286
        }
287
288
        return $deleted ? $entity : $deleted;
289
    }
290
291
    /**
292
     * {@inheritdoc}
293
     */
294
    public function restore($id)
295
    {
296
        $restored = false;
297
298
        // Find the given instance
299
        $entity = $id instanceof Model ? $id : $this->find($id);
300
301
        if ($entity) {
302
            // Fire the restoring event
303
            $this->getContainer('events')->dispatch($this->getRepositoryId().'.entity.restoring', [$this, $entity]);
304
305
            // Restore the instance
306
            $restored = $entity->restore();
307
308
            // Fire the restored event
309
            $this->getContainer('events')->dispatch($this->getRepositoryId().'.entity.restored', [$this, $entity]);
310
        }
311
312
        return $restored ? $entity : $restored;
313
    }
314
315
    /**
316
     * {@inheritdoc}
317
     */
318
    public function beginTransaction(): void
319
    {
320
        $this->getContainer('db')->beginTransaction();
321
    }
322
323
    /**
324
     * {@inheritdoc}
325
     */
326
    public function commit(): void
327
    {
328
        $this->getContainer('db')->commit();
329
    }
330
331
    /**
332
     * {@inheritdoc}
333
     */
334
    public function rollBack(): void
335
    {
336
        $this->getContainer('db')->rollBack();
337
    }
338
339
    /**
340
     * {@inheritdoc}
341
     */
342
    public function count($columns = '*'): int
343
    {
344
        return $this->executeCallback(get_called_class(), __FUNCTION__, func_get_args(), function () use ($columns) {
345
            return $this->prepareQuery($this->createModel())->count($columns);
346
        });
347
    }
348
349
    /**
350
     * {@inheritdoc}
351
     */
352
    public function min($column)
353
    {
354
        return $this->executeCallback(get_called_class(), __FUNCTION__, func_get_args(), function () use ($column) {
355
            return $this->prepareQuery($this->createModel())->min($column);
356
        });
357
    }
358
359
    /**
360
     * {@inheritdoc}
361
     */
362
    public function max($column)
363
    {
364
        return $this->executeCallback(get_called_class(), __FUNCTION__, func_get_args(), function () use ($column) {
365
            return $this->prepareQuery($this->createModel())->max($column);
366
        });
367
    }
368
369
    /**
370
     * {@inheritdoc}
371
     */
372
    public function avg($column)
373
    {
374
        return $this->executeCallback(get_called_class(), __FUNCTION__, func_get_args(), function () use ($column) {
375
            return $this->prepareQuery($this->createModel())->avg($column);
376
        });
377
    }
378
379
    /**
380
     * {@inheritdoc}
381
     */
382
    public function sum($column)
383
    {
384
        return $this->executeCallback(get_called_class(), __FUNCTION__, func_get_args(), function () use ($column) {
385
            return $this->prepareQuery($this->createModel())->sum($column);
386
        });
387
    }
388
389
    /**
390
     * Extract relationships.
391
     *
392
     * @param mixed $entity
393
     * @param array $attributes
394
     *
395
     * @return array
396
     */
397
    protected function extractRelations($entity, array $attributes): array
398
    {
399
        $relations = [];
400
        $potential = array_diff(array_keys($attributes), $entity->getFillable());
401
402
        array_walk($potential, function ($relation) use ($entity, $attributes, &$relations) {
403
            if (method_exists($entity, $relation)) {
404
                $relations[$relation] = [
405
                    'values' => $attributes[$relation],
406
                    'class' => get_class($entity->{$relation}()),
407
                ];
408
            }
409
        });
410
411
        return $relations;
412
    }
413
414
    /**
415
     * Sync relationships.
416
     *
417
     * @param mixed $entity
418
     * @param array $relations
419
     * @param bool  $detaching
420
     *
421
     * @return void
422
     */
423
    protected function syncRelations($entity, array $relations, $detaching = true): void
424
    {
425
        foreach ($relations as $method => $relation) {
426
            switch ($relation['class']) {
427
                case 'Illuminate\Database\Eloquent\Relations\BelongsToMany':
428
                default:
429
                    $entity->{$method}()->sync((array) $relation['values'], $detaching);
430
                    break;
431
            }
432
        }
433
    }
434
}
435