Passed
Push — master ( 77eb7f...a4e2d8 )
by Quentin
07:54
created

ModuleRepository::duplicate()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 18
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 12

Importance

Changes 2
Bugs 0 Features 0
Metric Value
cc 3
eloc 9
nc 3
nop 1
dl 0
loc 18
ccs 0
cts 10
cp 0
crap 12
rs 9.9666
c 2
b 0
f 0
1
<?php
2
3
namespace A17\Twill\Repositories;
4
5
use A17\Twill\Models\Behaviors\Sortable;
6
use A17\Twill\Repositories\Behaviors\HandleBrowsers;
7
use A17\Twill\Repositories\Behaviors\HandleDates;
8
use A17\Twill\Repositories\Behaviors\HandleFieldsGroups;
9
use A17\Twill\Repositories\Behaviors\HandleRepeaters;
10
use Illuminate\Support\Arr;
11
use Illuminate\Support\Collection;
12
use Illuminate\Support\Facades\App;
13
use Illuminate\Support\Facades\Config;
14
use Illuminate\Support\Facades\DB;
15
use Illuminate\Support\Facades\Log;
16
use Illuminate\Support\Str;
17
use PDO;
18
19
abstract class ModuleRepository
20
{
21
    use HandleDates, HandleBrowsers, HandleRepeaters, HandleFieldsGroups;
0 ignored issues
show
introduced by
The trait A17\Twill\Repositories\Behaviors\HandleBrowsers requires some properties which are not provided by A17\Twill\Repositories\ModuleRepository: $titleInBrowser, $id, $adminEditUrl, $title
Loading history...
Bug introduced by
The trait A17\Twill\Repositories\Behaviors\HandleRepeaters requires the property $id which is not provided by A17\Twill\Repositories\ModuleRepository.
Loading history...
22
23
    /**
24
     * @var \A17\Twill\Models\Model
25
     */
26
    protected $model;
27
28
    /**
29
     * @var string[]
30
     */
31
    protected $ignoreFieldsBeforeSave = [];
32
33
    /**
34
     * @var array
35
     */
36
    protected $countScope = [];
37
38
    /**
39
     * @var array
40
     */
41
    protected $fieldsGroups = [];
42
43
    /**
44
     * @param array $with
45
     * @param array $scopes
46
     * @param array $orders
47
     * @param int $perPage
48
     * @param bool $forcePagination
49
     * @return \Illuminate\Database\Eloquent\Collection
50
     */
51 12
    public function get($with = [], $scopes = [], $orders = [], $perPage = 20, $forcePagination = false)
52
    {
53 12
        $query = $this->model->with($with);
54
55 12
        $query = $this->filter($query, $scopes);
0 ignored issues
show
Bug introduced by
$query of type Illuminate\Database\Eloquent\Builder is incompatible with the type Illuminate\Database\Query\Builder expected by parameter $query of A17\Twill\Repositories\ModuleRepository::filter(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

55
        $query = $this->filter(/** @scrutinizer ignore-type */ $query, $scopes);
Loading history...
56 12
        $query = $this->order($query, $orders);
57
58 12
        if (!$forcePagination && $this->model instanceof Sortable) {
59 3
            return $query->ordered()->get();
60
        }
61
62 10
        if ($perPage == -1) {
63
            return $query->get();
64
        }
65
66 10
        return $query->paginate($perPage);
67
    }
68
69
    /**
70
     * @param string $slug
71
     * @param array $scope
72
     * @return int
73
     */
74 6
    public function getCountByStatusSlug($slug, $scope = [])
75
    {
76 6
        $this->countScope = $scope;
77
78 6
        switch ($slug) {
79 6
            case 'all':
80 5
                return $this->getCountForAll();
81 6
            case 'published':
82 6
                return $this->getCountForPublished();
83 6
            case 'draft':
84 6
                return $this->getCountForDraft();
85 6
            case 'trash':
86 6
                return $this->getCountForTrash();
87
        }
88
89 5
        foreach ($this->traitsMethods(__FUNCTION__) as $method) {
90 5
            if (($count = $this->$method($slug)) !== false) {
91 5
                return $count;
92
            }
93
        }
94
95
        return 0;
96
    }
97
98
    /**
99
     * @return int
100
     */
101 5
    public function getCountForAll()
102
    {
103 5
        $query = $this->model->newQuery();
104 5
        return $this->filter($query, $this->countScope)->count();
0 ignored issues
show
Bug introduced by
$query of type Illuminate\Database\Eloquent\Builder is incompatible with the type Illuminate\Database\Query\Builder expected by parameter $query of A17\Twill\Repositories\ModuleRepository::filter(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

104
        return $this->filter(/** @scrutinizer ignore-type */ $query, $this->countScope)->count();
Loading history...
105
    }
106
107
    /**
108
     * @return int
109
     */
110 5
    public function getCountForPublished()
111
    {
112 5
        $query = $this->model->newQuery();
113 5
        return $this->filter($query, $this->countScope)->published()->count();
0 ignored issues
show
Bug introduced by
$query of type Illuminate\Database\Eloquent\Builder is incompatible with the type Illuminate\Database\Query\Builder expected by parameter $query of A17\Twill\Repositories\ModuleRepository::filter(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

113
        return $this->filter(/** @scrutinizer ignore-type */ $query, $this->countScope)->published()->count();
Loading history...
114
    }
115
116
    /**
117
     * @return int
118
     */
119 5
    public function getCountForDraft()
120
    {
121 5
        $query = $this->model->newQuery();
122 5
        return $this->filter($query, $this->countScope)->draft()->count();
0 ignored issues
show
Bug introduced by
$query of type Illuminate\Database\Eloquent\Builder is incompatible with the type Illuminate\Database\Query\Builder expected by parameter $query of A17\Twill\Repositories\ModuleRepository::filter(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

122
        return $this->filter(/** @scrutinizer ignore-type */ $query, $this->countScope)->draft()->count();
Loading history...
123
    }
124
125
    /**
126
     * @return int
127
     */
128 5
    public function getCountForTrash()
129
    {
130 5
        $query = $this->model->newQuery();
131 5
        return $this->filter($query, $this->countScope)->onlyTrashed()->count();
0 ignored issues
show
Bug introduced by
$query of type Illuminate\Database\Eloquent\Builder is incompatible with the type Illuminate\Database\Query\Builder expected by parameter $query of A17\Twill\Repositories\ModuleRepository::filter(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

131
        return $this->filter(/** @scrutinizer ignore-type */ $query, $this->countScope)->onlyTrashed()->count();
Loading history...
132
    }
133
134
    /**
135
     * @param $id
136
     * @param array $with
137
     * @param array $withCount
138
     * @return \A17\Twill\Models\Model
139
     * @throws \Illuminate\Database\Eloquent\ModelNotFoundException
140
     */
141 17
    public function getById($id, $with = [], $withCount = [])
142
    {
143 17
        return $this->model->with($with)->withCount($withCount)->findOrFail($id);
144
    }
145
146
    /**
147
     * @param string $column
148
     * @param array $orders
149
     * @param null $exceptId
0 ignored issues
show
Documentation Bug introduced by
Are you sure the doc-type for parameter $exceptId is correct as it would always require null to be passed?
Loading history...
150
     * @return \Illuminate\Support\Collection
151
     */
152
    public function listAll($column = 'title', $orders = [], $exceptId = null)
153
    {
154
        $query = $this->model->newQuery();
155
156
        if ($exceptId) {
0 ignored issues
show
introduced by
$exceptId is of type null, thus it always evaluated to false.
Loading history...
157
            $query = $query->where($this->model->getTable() . '.id', '<>', $exceptId);
158
        }
159
160
        if ($this->model instanceof Sortable) {
161
            $query = $query->ordered();
162
        } elseif (!empty($orders)) {
163
            $query = $this->order($query, $orders);
0 ignored issues
show
Bug introduced by
$query of type Illuminate\Database\Eloquent\Builder is incompatible with the type Illuminate\Database\Query\Builder expected by parameter $query of A17\Twill\Repositories\ModuleRepository::order(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

163
            $query = $this->order(/** @scrutinizer ignore-type */ $query, $orders);
Loading history...
164
        }
165
166
        if ($this->model->isTranslatable()) {
167
            $query = $query->withTranslation();
168
        }
169
170
        return $query->get()->pluck($column, 'id');
171
    }
172
173
    /**
174
     * @param $search
175
     * @param array $fields
176
     * @return \Illuminate\Database\Eloquent\Collection
177
     */
178
    public function cmsSearch($search, $fields = [])
179
    {
180
        $query = $this->model->latest();
181
182
        $translatedAttributes = $this->model->translatedAttributes ?? [];
0 ignored issues
show
Bug introduced by
The property translatedAttributes does not seem to exist on A17\Twill\Models\Model. Are you sure there is no database migration missing?

Checks if undeclared accessed properties appear in database migrations and if the creating migration is correct.

Loading history...
183
184
        foreach ($fields as $field) {
185
            if (in_array($field, $translatedAttributes)) {
186
                $query->orWhereHas('translations', function ($q) use ($field, $search) {
187
                    $q->where($field, $this->getLikeOperator(), "%{$search}%");
188
                });
189
            } else {
190
                $query->orWhere($field, $this->getLikeOperator(), "%{$search}%");
191
            }
192
        }
193
194
        return $query->get();
195
    }
196
197
    /**
198
     * @param $attributes
199
     * @param $fields
200
     * @return \A17\Twill\Models\Model
201
     */
202
    public function firstOrCreate($attributes, $fields = [])
203
    {
204
        return $this->model->where($attributes)->first() ?? $this->create($attributes + $fields);
205
    }
206
207
    /**
208
     * @param string[] $fields
209
     * @return \A17\Twill\Models\Model
210
     */
211 27
    public function create($fields)
212
    {
213
        return DB::transaction(function () use ($fields) {
214 27
            $original_fields = $fields;
215
216 27
            $fields = $this->prepareFieldsBeforeCreate($fields);
217
218 27
            $object = $this->model->create(Arr::except($fields, $this->getReservedFields()));
219
220 27
            $this->beforeSave($object, $original_fields);
221
222 27
            $fields = $this->prepareFieldsBeforeSave($object, $fields);
223
224 27
            $object->save();
225
226 27
            $this->afterSave($object, $fields);
227
228 27
            return $object;
229 27
        }, 3);
230
    }
231
232
    /**
233
     * @param array $fields
234
     * @return \A17\Twill\Models\Model
235
     */
236 2
    public function createForPreview($fields)
237
    {
238 2
        $fields = $this->prepareFieldsBeforeCreate($fields);
239
240 2
        $object = $this->model->newInstance(Arr::except($fields, $this->getReservedFields()));
241
242 2
        return $this->hydrate($object, $fields);
243
    }
244
245
    /**
246
     * @param array $attributes
247
     * @param array $fields
248
     * @return \A17\Twill\Models\Model
249
     */
250
    public function updateOrCreate($attributes, $fields)
251
    {
252
        $object = $this->model->where($attributes)->first();
253
254
        if (!$object) {
255
            return $this->create($fields);
256
        }
257
258
        $this->update($object->id, $fields);
259
    }
260
261
    /**
262
     * @param mixed $id
263
     * @param array $fields
264
     * @return void
265
     */
266 11
    public function update($id, $fields)
267
    {
268
        DB::transaction(function () use ($id, $fields) {
269 11
            $object = $this->model->findOrFail($id);
270
271 11
            $this->beforeSave($object, $fields);
272
273 11
            $fields = $this->prepareFieldsBeforeSave($object, $fields);
274
275 11
            $object->fill(Arr::except($fields, $this->getReservedFields()));
276
277 11
            $object->save();
278
279 11
            $this->afterSave($object, $fields);
280 11
        }, 3);
281 11
    }
282
283
    /**
284
     * @param mixed $id
285
     * @param array $values
286
     * @param array $scopes
287
     * @return mixed
288
     */
289 4
    public function updateBasic($id, $values, $scopes = [])
290
    {
291
        return DB::transaction(function () use ($id, $values, $scopes) {
292
            // apply scopes if no id provided
293 4
            if (is_null($id)) {
294 1
                $query = $this->model->query();
295
296 1
                foreach ($scopes as $column => $value) {
297
                    $query->where($column, $value);
298
                }
299
300 1
                $query->update($values);
301
302
                $query->get()->each(function ($object) use ($values) {
303
                    $this->afterUpdateBasic($object, $values);
304 1
                });
305
306 1
                return true;
307
            }
308
309
            // apply to all ids if array of ids provided
310 3
            if (is_array($id)) {
311
                $query = $this->model->whereIn('id', $id);
312
                $query->update($values);
313
314
                $query->get()->each(function ($object) use ($values) {
315
                    $this->afterUpdateBasic($object, $values);
316
                });
317
318
                return true;
319
            }
320
321 3
            if (($object = $this->model->find($id)) != null) {
322 2
                $object->update($values);
323 2
                $this->afterUpdateBasic($object, $values);
324 2
                return true;
325
            }
326
327 1
            return false;
328 4
        }, 3);
329
    }
330
331
    /**
332
     * @param array $ids
333
     * @return void
334
     */
335 2
    public function setNewOrder($ids)
336
    {
337
        DB::transaction(function () use ($ids) {
338 2
            $this->model->setNewOrder($ids);
339 2
        }, 3);
340 1
    }
341
342
    /**
343
     * @param mixed $id
344
     * @return mixed
345
     */
346
    public function duplicate($id)
347
    {
348
349
        if (($object = $this->model->find($id)) === null) {
350
            return false;
351
        }
352
353
        if (($revision = $object->revisions()->orderBy('created_at', 'desc')->first()) === null) {
354
            return false;
355
        }
356
357
        $revisionInput = json_decode($revision->payload, true);
0 ignored issues
show
Bug introduced by
The property payload does not seem to exist on A17\Twill\Models\Model. Are you sure there is no database migration missing?

Checks if undeclared accessed properties appear in database migrations and if the creating migration is correct.

Loading history...
358
        $baseInput = collect($revisionInput)->only(['slug', 'languages'])->filter()->toArray();
359
        $newObject = $this->create($baseInput);
360
361
        $this->update($newObject->id, $revisionInput);
362
363
        return $newObject;
364
    }
365
366
    /**
367
     * @param mixed $id
368
     * @return mixed
369
     */
370 2
    public function delete($id)
371
    {
372
        return DB::transaction(function () use ($id) {
373 2
            if (($object = $this->model->find($id)) === null) {
374
                return false;
375
            }
376
377 2
            if (!method_exists($object, 'canDeleteSafely') || $object->canDeleteSafely()) {
378 2
                $object->delete();
379 2
                $this->afterDelete($object);
380 2
                return true;
381
            }
382
            return false;
383 2
        }, 3);
384
    }
385
386
    /**
387
     * @param array $ids
388
     * @return mixed
389
     */
390 17
    public function bulkDelete($ids)
391
    {
392
        return DB::transaction(function () use ($ids) {
393
            try {
394
                Collection::make($ids)->each(function ($id) {
395
                    $this->delete($id);
396 17
                });
397
            } catch (\Exception $e) {
398
                Log::error($e);
399
                return false;
400
            }
401
402 17
            return true;
403 17
        }, 3);
404
    }
405
406
    /**
407
     * @param mixed $id
408
     * @return mixed
409
     */
410
    public function forceDelete($id)
411
    {
412
        return DB::transaction(function () use ($id) {
413
            if (($object = $this->model->onlyTrashed()->find($id)) === null) {
414
                return false;
415
            } else {
416
                $object->forceDelete();
417
                $this->afterDelete($object);
418
                return true;
419
            }
420
        }, 3);
421
    }
422
423
    /**
424
     * @param mixed $id
425
     * @return mixed
426
     */
427
    public function bulkForceDelete($ids)
428
    {
429
        return DB::transaction(function () use ($ids) {
430
            try {
431
                $query = $this->model->onlyTrashed()->whereIn('id', $ids);
432
                $objects = $query->get();
433
434
                $query->forceDelete();
435
436
                $objects->each(function ($object) {
437
                    $this->afterDelete($object);
438
                });
439
            } catch (\Exception $e) {
440
                Log::error($e);
441
                return false;
442
            }
443
444
            return true;
445
        }, 3);
446
    }
447
448
    /**
449
     * @param mixed $id
450
     * @return mixed
451
     */
452 2
    public function restore($id)
453
    {
454
        return DB::transaction(function () use ($id) {
455 2
            if (($object = $this->model->withTrashed()->find($id)) != null) {
456 1
                $object->restore();
457 1
                $this->afterRestore($object);
458 1
                return true;
459
            }
460
461 1
            return false;
462 2
        }, 3);
463
    }
464
465
    /**
466
     * @param array $ids
467
     * @return mixed
468
     */
469
    public function bulkRestore($ids)
470
    {
471
        return DB::transaction(function () use ($ids) {
472
            try {
473
                $query = $this->model->withTrashed()->whereIn('id', $ids);
474
                $objects = $query->get();
475
476
                $query->restore();
477
478
                $objects->each(function ($object) {
479
                    $this->afterRestore($object);
480
                });
481
            } catch (\Exception $e) {
482
                Log::error($e);
483
                return false;
484
            }
485
486
            return true;
487
        }, 3);
488
    }
489
490
    /**
491
     * @param \A17\Twill\Models\Model $object
492
     * @param array $fields
493
     * @return array
494
     */
495 28
    public function cleanupFields($object, $fields)
496
    {
497 28
        if (property_exists($this->model, 'checkboxes')) {
498 21
            foreach ($this->model->checkboxes as $field) {
0 ignored issues
show
Bug introduced by
The property checkboxes does not seem to exist on A17\Twill\Models\Model. Are you sure there is no database migration missing?

Checks if undeclared accessed properties appear in database migrations and if the creating migration is correct.

Loading history...
499 21
                if (!$this->shouldIgnoreFieldBeforeSave($field)) {
500 21
                    if (!isset($fields[$field])) {
501 5
                        $fields[$field] = false;
502
                    } else {
503 21
                        $fields[$field] = !empty($fields[$field]);
504
                    }
505
                }
506
            }
507
        }
508
509 28
        if (property_exists($this->model, 'nullable')) {
510
            foreach ($this->model->nullable as $field) {
0 ignored issues
show
Bug introduced by
The property nullable does not seem to exist on A17\Twill\Models\Model. Are you sure there is no database migration missing?

Checks if undeclared accessed properties appear in database migrations and if the creating migration is correct.

Loading history...
511
                if (!isset($fields[$field]) && !$this->shouldIgnoreFieldBeforeSave($field)) {
512
                    $fields[$field] = null;
513
                }
514
            }
515
        }
516
517 28
        foreach ($fields as $key => $value) {
518 28
            if (!$this->shouldIgnoreFieldBeforeSave($key)) {
519 28
                if (is_array($value) && empty($value)) {
520 7
                    $fields[$key] = null;
521
                }
522 28
                if ($value === '') {
523
                    $fields[$key] = null;
524
                }
525
            }
526
        }
527
528 28
        return $fields;
529
    }
530
531
    /**
532
     * @param array $fields
533
     * @return array
534
     */
535 22
    public function prepareFieldsBeforeCreate($fields)
536
    {
537 22
        $fields = $this->cleanupFields(null, $fields);
538
539 22
        foreach ($this->traitsMethods(__FUNCTION__) as $method) {
540 22
            $fields = $this->$method($fields);
541
        }
542
543 22
        return $fields;
544
    }
545
546
    /**
547
     * @param \A17\Twill\Models\Model $object
548
     * @param array $fields
549
     * @return string[]
550
     */
551 27
    public function prepareFieldsBeforeSave($object, $fields)
552
    {
553 27
        $fields = $this->cleanupFields($object, $fields);
554
555 27
        foreach ($this->traitsMethods(__FUNCTION__) as $method) {
556 27
            $fields = $this->$method($object, $fields);
557
        }
558
559 27
        return $fields;
560
    }
561
562
    /**
563
     * @param \A17\Twill\Models\Model $object
564
     * @param array $fields
565
     * @return void
566
     */
567 2
    public function afterUpdateBasic($object, $fields)
568
    {
569 2
        foreach ($this->traitsMethods(__FUNCTION__) as $method) {
570
            $this->$method($object, $fields);
571
        }
572 2
    }
573
574
    /**
575
     * @param \A17\Twill\Models\Model $object
576
     * @param array $fields
577
     * @return void
578
     */
579 27
    public function beforeSave($object, $fields)
580
    {
581 27
        foreach ($this->traitsMethods(__FUNCTION__) as $method) {
582 17
            $this->$method($object, $fields);
583
        }
584 27
    }
585
586
    /**
587
     * @param \A17\Twill\Models\Model $object
588
     * @param array $fields
589
     * @return void
590
     */
591 27
    public function afterSave($object, $fields)
592
    {
593 27
        foreach ($this->traitsMethods(__FUNCTION__) as $method) {
594 27
            $this->$method($object, $fields);
595
        }
596 27
    }
597
598
    /**
599
     * @param \A17\Twill\Models\Model $object
600
     * @return void
601
     */
602 2
    public function afterDelete($object)
603
    {
604 2
        foreach ($this->traitsMethods(__FUNCTION__) as $method) {
605 2
            $this->$method($object);
606
        }
607 2
    }
608
609
    /**
610
     * @param \A17\Twill\Models\Model $object
611
     * @return void
612
     */
613 1
    public function afterRestore($object)
614
    {
615 1
        foreach ($this->traitsMethods(__FUNCTION__) as $method) {
616 1
            $this->$method($object);
617
        }
618 1
    }
619
620
    /**
621
     * @param \A17\Twill\Models\Model $object
622
     * @param array $fields
623
     * @return \A17\Twill\Models\Model
624
     */
625 3
    public function hydrate($object, $fields)
626
    {
627 3
        foreach ($this->traitsMethods(__FUNCTION__) as $method) {
628 3
            $object = $this->$method($object, $fields);
629
        }
630
631 3
        return $object;
632
    }
633
634
    /**
635
     * @param \A17\Twill\Models\Model $object
636
     * @return array
637
     */
638 5
    public function getFormFields($object)
639
    {
640 5
        $fields = $object->attributesToArray();
641
642 5
        foreach ($this->traitsMethods(__FUNCTION__) as $method) {
643 5
            $fields = $this->$method($object, $fields);
644
        }
645
646 5
        return $fields;
647
    }
648
649
    /**
650
     * @param \Illuminate\Database\Query\Builder $query
651
     * @param array $scopes
652
     * @return \Illuminate\Database\Query\Builder
653
     */
654 12
    public function filter($query, array $scopes = [])
655
    {
656 12
        $likeOperator = $this->getLikeOperator();
657
658 12
        foreach ($this->traitsMethods(__FUNCTION__) as $method) {
659 11
            $this->$method($query, $scopes);
660
        }
661
662 12
        unset($scopes['search']);
663
664 12
        if (isset($scopes['exceptIds'])) {
665 2
            $query->whereNotIn($this->model->getTable() . '.id', $scopes['exceptIds']);
666 2
            unset($scopes['exceptIds']);
667
        }
668
669 12
        foreach ($scopes as $column => $value) {
670 5
            if (method_exists($this->model, 'scope' . ucfirst($column))) {
671 1
                $query->$column();
672
            } else {
673 4
                if (is_array($value)) {
674 2
                    $query->whereIn($column, $value);
675 2
                } elseif ($column[0] == '%') {
676
                    $value && ($value[0] == '!') ? $query->where(substr($column, 1), "not $likeOperator", '%' . substr($value, 1) . '%') : $query->where(substr($column, 1), $likeOperator, '%' . $value . '%');
677 2
                } elseif (isset($value[0]) && $value[0] == '!') {
678
                    $query->where($column, '<>', substr($value, 1));
679 2
                } elseif ($value !== '') {
680 2
                    $query->where($column, $value);
681
                }
682
            }
683
        }
684
685 12
        return $query;
686
    }
687
688
    /**
689
     * @param \Illuminate\Database\Query\Builder $query
690
     * @param array $orders
691
     * @return \Illuminate\Database\Query\Builder
692
     */
693 12
    public function order($query, array $orders = [])
694
    {
695 12
        foreach ($this->traitsMethods(__FUNCTION__) as $method) {
696 7
            $this->$method($query, $orders);
697
        }
698
699 12
        foreach ($orders as $column => $direction) {
700 5
            $query->orderBy($column, $direction);
701
        }
702
703 12
        return $query;
704
    }
705
706
    /**
707
     * @param \A17\Twill\Models\Model $object
708
     * @param array $fields
709
     * @param string $relationship
710
     * @param string $formField
711
     * @param string $attribute
712
     * @return void
713
     */
714
    public function updateOneToMany($object, $fields, $relationship, $formField, $attribute)
715
    {
716
        if (isset($fields[$formField])) {
717
            foreach ($fields[$formField] as $id) {
718
                $object->$relationship()->updateOrCreate([$attribute => $id]);
719
            }
720
721
            foreach ($object->$relationship as $relationshipObject) {
722
                if (!in_array($relationshipObject->$attribute, $fields[$formField])) {
723
                    $relationshipObject->delete();
724
                }
725
            }
726
        } else {
727
            $object->$relationship()->delete();
728
        }
729
    }
730
731
    /**
732
     * @param \A17\Twill\Models\Model $object
733
     * @param array $fields
734
     * @param string $relationship
735
     * @return void
736
     */
737
    public function updateMultiSelect($object, $fields, $relationship)
738
    {
739
        $object->$relationship()->sync($fields[$relationship] ?? []);
740
    }
741
742
    /**
743
     * @param \Illuminate\Database\Query\Builder $query
744
     * @param array $scopes
745
     * @param string $scopeField
746
     * @param string $scopeRelation
747
     * @return void
748
     */
749 9
    public function addRelationFilterScope($query, &$scopes, $scopeField, $scopeRelation)
750
    {
751 9
        if (isset($scopes[$scopeField])) {
752
            $id = $scopes[$scopeField];
753
            $query->whereHas($scopeRelation, function ($query) use ($id, $scopeField) {
754
                $query->where($scopeField, $id);
755
            });
756
            unset($scopes[$scopeField]);
757
        }
758 9
    }
759
760
    /**
761
     * @param \Illuminate\Database\Query\Builder $query
762
     * @param array $scopes
763
     * @param string $scopeField
764
     * @return void
765
     */
766
    public function addLikeFilterScope($query, &$scopes, $scopeField)
767
    {
768
        if (isset($scopes[$scopeField]) && is_string($scopes[$scopeField])) {
769
            $query->where($scopeField, $this->getLikeOperator(), '%' . $scopes[$scopeField] . '%');
770
            unset($scopes[$scopeField]);
771
        }
772
    }
773
774
    /**
775
     * @param \Illuminate\Database\Query\Builder $query
776
     * @param array $scopes
777
     * @param string $scopeField
778
     * @param string[] $orFields
779
     */
780 5
    public function searchIn($query, &$scopes, $scopeField, $orFields = [])
781
    {
782
783 5
        if (isset($scopes[$scopeField]) && is_string($scopes[$scopeField])) {
784
            $query->where(function ($query) use (&$scopes, $scopeField, $orFields) {
785 2
                foreach ($orFields as $field) {
786 2
                    $query->orWhere($field, $this->getLikeOperator(), '%' . $scopes[$scopeField] . '%');
787 2
                    unset($scopes[$field]);
788
                }
789 2
            });
790
        }
791 5
    }
792
793
    /**
794
     * @return bool
795
     */
796 2
    public function isUniqueFeature()
797
    {
798 2
        return false;
799
    }
800
801
    /**
802
     * @param array $ignore
803
     * @return void
804
     */
805
    public function addIgnoreFieldsBeforeSave($ignore = [])
806
    {
807
        $this->ignoreFieldsBeforeSave = is_array($ignore)
0 ignored issues
show
introduced by
The condition is_array($ignore) is always true.
Loading history...
808
        ? array_merge($this->ignoreFieldsBeforeSave, $ignore)
809
        : array_merge($this->ignoreFieldsBeforeSave, [$ignore]);
810
    }
811
812
    /**
813
     * @param string $ignore
814
     * @return bool
815
     */
816 28
    public function shouldIgnoreFieldBeforeSave($ignore)
817
    {
818 28
        return in_array($ignore, $this->ignoreFieldsBeforeSave);
819
    }
820
821
    /**
822
     * @return string[]
823
     */
824 28
    public function getReservedFields()
825
    {
826
        return [
827 28
            'medias',
828
            'browsers',
829
            'repeaters',
830
            'blocks',
831
        ];
832
    }
833
834
    /**
835
     * @param string $relation
836
     * @param \A17\Twill\Models\Model|null $model
837
     * @return mixed
838
     */
839
    protected function getModelRepository($relation, $model = null)
840
    {
841
        if (!$model) {
842
            $model = ucfirst(Str::singular($relation));
843
        }
844
845
        return App::make(Config::get('twill.namespace') . "\\Repositories\\" . ucfirst($model) . "Repository");
846
    }
847
848
    /**
849
     * @param string|null $method
850
     * @return array
851
     */
852 34
    protected function traitsMethods(string $method = null)
853
    {
854 34
        $method = $method ?? debug_backtrace()[1]['function'];
855
856 34
        $traits = array_values(class_uses_recursive(get_called_class()));
857
858 34
        $uniqueTraits = array_unique(array_map('class_basename', $traits));
859
860
        $methods = array_map(function (string $trait) use ($method) {
861 34
            return $method . $trait;
862 34
        }, $uniqueTraits);
863
864
        return array_filter($methods, function (string $method) {
865 34
            return method_exists(get_called_class(), $method);
866 34
        });
867
    }
868
869
    /**
870
     * @return string
871
     */
872 12
    private function getLikeOperator()
873
    {
874 12
        if (DB::connection()->getPDO()->getAttribute(PDO::ATTR_DRIVER_NAME) === 'pgsql') {
875
            return 'ILIKE';
876
        }
877
878 12
        return 'LIKE';
879
    }
880
881
    /**
882
     * @param string $method
883
     * @param array $parameters
884
     * @return mixed
885
     */
886 27
    public function __call($method, $parameters)
887
    {
888 27
        return $this->model->$method(...$parameters);
889
    }
890
891
    /**
892
     * @param string $behavior
893
     * @return boolean
894
     */
895 29
    public function hasBehavior($behavior)
896
    {
897 29
        $hasBehavior = classHasTrait($this, 'A17\Twill\Repositories\Behaviors\Handle' . ucfirst($behavior));
898
899 29
        if (Str::startsWith($behavior, 'translation')) {
900 28
            $hasBehavior = $hasBehavior && $this->getModel()->isTranslatable();
0 ignored issues
show
Bug introduced by
The method getModel() does not exist on A17\Twill\Repositories\ModuleRepository. Since you implemented __call, consider adding a @method annotation. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

900
            $hasBehavior = $hasBehavior && $this->/** @scrutinizer ignore-call */ getModel()->isTranslatable();
Loading history...
901
        }
902
903 29
        return $hasBehavior;
904
    }
905
906
    /**
907
     * @return boolean
908
     */
909 6
    public function isTranslatable($column)
910
    {
911 6
        return $this->getModel()->isTranslatable($column);
912
    }
913
}
914