Passed
Pull Request — 1.2 (#556)
by
unknown
07:51
created

ModuleRepository::duplicate()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 18
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Importance

Changes 2
Bugs 0 Features 0
Metric Value
cc 3
eloc 9
c 2
b 0
f 0
nc 3
nop 1
dl 0
loc 18
rs 9.9666
1
<?php
2
3
namespace A17\Twill\Repositories;
4
5
use A17\Twill\Models\Behaviors\HasMedias;
6
use A17\Twill\Models\Behaviors\Sortable;
7
use A17\Twill\Repositories\Behaviors\HandleDates;
8
use A17\Twill\Repositories\Behaviors\HandleBrowsers;
9
use A17\Twill\Repositories\Behaviors\HandleFieldsGroups;
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, 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, $browsers, $title
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
    public function get($with = [], $scopes = [], $orders = [], $perPage = 20, $forcePagination = false)
52
    {
53
        $query = $this->model->with($with);
54
55
        $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
        $query = $this->order($query, $orders);
57
58
        if (!$forcePagination && $this->model instanceof Sortable) {
59
            return $query->ordered()->get();
60
        }
61
62
        if ($perPage == -1) {
63
            return $query->get();
64
        }
65
66
        return $query->paginate($perPage);
0 ignored issues
show
Bug Best Practice introduced by
The expression return $query->paginate($perPage) returns the type Illuminate\Pagination\LengthAwarePaginator which is incompatible with the documented return type Illuminate\Database\Eloquent\Collection.
Loading history...
67
    }
68
69
    /**
70
     * @param string $slug
71
     * @param array $scope
72
     * @return int
73
     */
74
    public function getCountByStatusSlug($slug, $scope = [])
75
    {
76
        $this->countScope = $scope;
77
78
        switch ($slug) {
79
            case 'all':
80
                return $this->getCountForAll();
81
            case 'published':
82
                return $this->getCountForPublished();
83
            case 'draft':
84
                return $this->getCountForDraft();
85
            case 'trash':
86
                return $this->getCountForTrash();
87
        }
88
89
        foreach ($this->traitsMethods(__FUNCTION__) as $method) {
90
            if (($count = $this->$method($slug)) !== false) {
91
                return $count;
92
            }
93
        }
94
95
        return 0;
96
    }
97
98
    /**
99
     * @return int
100
     */
101
    public function getCountForAll()
102
    {
103
        $query = $this->model->newQuery();
104
        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
    public function getCountForPublished()
111
    {
112
        $query = $this->model->newQuery();
113
        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
    public function getCountForDraft()
120
    {
121
        $query = $this->model->newQuery();
122
        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
    public function getCountForTrash()
129
    {
130
        $query = $this->model->newQuery();
131
        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
    public function getById($id, $with = [], $withCount = [])
142
    {
143
        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 (property_exists($this->model, 'translatedAttributes')) {
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($fields);
205
    }
206
207
    /**
208
     * @param string[] $fields
209
     * @return \A17\Twill\Models\Model
210
     */
211
    public function create($fields)
212
    {
213
        return DB::transaction(function () use ($fields) {
214
            $original_fields = $fields;
215
216
            $fields = $this->prepareFieldsBeforeCreate($fields);
217
218
            $object = $this->model->create(Arr::except($fields, $this->getReservedFields()));
219
220
            $this->beforeSave($object, $original_fields);
221
222
            $fields = $this->prepareFieldsBeforeSave($object, $fields);
223
224
            $object->save();
225
226
            $this->afterSave($object, $fields);
227
228
            return $object;
229
        }, 3);
230
    }
231
232
    /**
233
     * @param array $fields
234
     * @return \A17\Twill\Models\Model
235
     */
236
    public function createForPreview($fields)
237
    {
238
        $fields = $this->prepareFieldsBeforeCreate($fields);
239
240
        $object = $this->model->newInstance(Arr::except($fields, $this->getReservedFields()));
241
242
        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
    public function update($id, $fields)
267
    {
268
        DB::transaction(function () use ($id, $fields) {
269
            $object = $this->model->findOrFail($id);
270
271
            $this->beforeSave($object, $fields);
272
273
            $fields = $this->prepareFieldsBeforeSave($object, $fields);
274
275
            $object->fill(Arr::except($fields, $this->getReservedFields()));
276
277
            $object->save();
278
279
            $this->afterSave($object, $fields);
280
        }, 3);
281
    }
282
283
    /**
284
     * @param mixed $id
285
     * @param array $values
286
     * @param array $scopes
287
     * @return mixed
288
     */
289
    public function updateBasic($id, $values, $scopes = [])
290
    {
291
        return DB::transaction(function () use ($id, $values, $scopes) {
292
            // apply scopes if no id provided
293
            if (is_null($id)) {
294
                $query = $this->model->query();
295
296
                foreach ($scopes as $column => $value) {
297
                    $query->where($column, $value);
298
                }
299
300
                $query->update($values);
301
302
                $query->get()->each(function ($object) use ($values) {
303
                    $this->afterUpdateBasic($object, $values);
304
                });
305
306
                return true;
307
            }
308
309
            // apply to all ids if array of ids provided
310
            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
            if (($object = $this->model->find($id)) != null) {
322
                $object->update($values);
323
                $this->afterUpdateBasic($object, $values);
324
                return true;
325
            }
326
327
            return false;
328
        }, 3);
329
    }
330
331
    /**
332
     * @param array $ids
333
     * @return void
334
     */
335
    public function setNewOrder($ids)
336
    {
337
        DB::transaction(function () use ($ids) {
338
            $this->model->setNewOrder($ids);
339
        }, 3);
340
    }
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
    public function delete($id)
371
    {
372
        return DB::transaction(function () use ($id) {
373
            if (($object = $this->model->find($id)) === null) {
374
                return false;
375
            }
376
377
            if (!method_exists($object, 'canDeleteSafely') || $object->canDeleteSafely()) {
378
                $object->delete();
379
                $this->afterDelete($object);
380
                return true;
381
            }
382
            return false;
383
        }, 3);
384
    }
385
386
    /**
387
     * @param array $ids
388
     * @return mixed
389
     */
390
    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
                });
397
            } catch (\Exception $e) {
398
                Log::error($e);
399
                return false;
400
            }
401
402
            return true;
403
        }, 3);
404
    }
405
406
    /**
407
     * @param mixed $id
408
     * @return mixed
409
     */
410
    public function restore($id)
411
    {
412
        return DB::transaction(function () use ($id) {
413
            if (($object = $this->model->withTrashed()->find($id)) != null) {
414
                $object->restore();
415
                $this->afterRestore($object);
416
                return true;
417
            }
418
419
            return false;
420
        }, 3);
421
    }
422
423
    /**
424
     * @param array $ids
425
     * @return mixed
426
     */
427
    public function bulkRestore($ids)
428
    {
429
        return DB::transaction(function () use ($ids) {
430
            try {
431
                $query = $this->model->withTrashed()->whereIn('id', $ids);
432
                $objects = $query->get();
433
434
                $query->restore();
435
436
                $objects->each(function ($object) {
437
                    $this->afterRestore($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 \A17\Twill\Models\Model $object
450
     * @param array $fields
451
     * @return array
452
     */
453
    public function cleanupFields($object, $fields)
454
    {
455
        if (property_exists($this->model, 'checkboxes')) {
456
            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...
457
                if (!$this->shouldIgnoreFieldBeforeSave($field)) {
458
                    if (!isset($fields[$field])) {
459
                        $fields[$field] = false;
460
                    } else {
461
                        $fields[$field] = !empty($fields[$field]);
462
                    }
463
                }
464
            }
465
        }
466
467
        if (property_exists($this->model, 'nullable')) {
468
            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...
469
                if (!isset($fields[$field]) && !$this->shouldIgnoreFieldBeforeSave($field)) {
470
                    $fields[$field] = null;
471
                }
472
            }
473
        }
474
475
        foreach ($fields as $key => $value) {
476
            if (!$this->shouldIgnoreFieldBeforeSave($key)) {
477
                if (is_array($value) && empty($value)) {
478
                    $fields[$key] = null;
479
                }
480
                if ($value === '') {
481
                    $fields[$key] = null;
482
                }
483
            }
484
        }
485
486
        return $fields;
487
    }
488
489
    /**
490
     * @param array $fields
491
     * @return array
492
     */
493
    public function prepareFieldsBeforeCreate($fields)
494
    {
495
        $fields = $this->cleanupFields(null, $fields);
496
497
        foreach ($this->traitsMethods(__FUNCTION__) as $method) {
498
            $fields = $this->$method($fields);
499
        }
500
501
        return $fields;
502
    }
503
504
    /**
505
     * @param \A17\Twill\Models\Model $object
506
     * @param array $fields
507
     * @return string[]
508
     */
509
    public function prepareFieldsBeforeSave($object, $fields)
510
    {
511
        $fields = $this->cleanupFields($object, $fields);
512
513
        foreach ($this->traitsMethods(__FUNCTION__) as $method) {
514
            $fields = $this->$method($object, $fields);
515
        }
516
517
        return $fields;
518
    }
519
520
    /**
521
     * @param \A17\Twill\Models\Model $object
522
     * @param array $fields
523
     * @return void
524
     */
525
    public function afterUpdateBasic($object, $fields)
526
    {
527
        foreach ($this->traitsMethods(__FUNCTION__) as $method) {
528
            $this->$method($object, $fields);
529
        }
530
    }
531
532
    /**
533
     * @param \A17\Twill\Models\Model $object
534
     * @param array $fields
535
     * @return void
536
     */
537
    public function beforeSave($object, $fields)
538
    {
539
        foreach ($this->traitsMethods(__FUNCTION__) as $method) {
540
            $this->$method($object, $fields);
541
        }
542
    }
543
544
    /**
545
     * @param \A17\Twill\Models\Model $object
546
     * @param array $fields
547
     * @return void
548
     */
549
    public function afterSave($object, $fields)
550
    {
551
        foreach ($this->traitsMethods(__FUNCTION__) as $method) {
552
            $this->$method($object, $fields);
553
        }
554
    }
555
556
    /**
557
     * @param \A17\Twill\Models\Model $object
558
     * @return void
559
     */
560
    public function afterDelete($object)
561
    {
562
        foreach ($this->traitsMethods(__FUNCTION__) as $method) {
563
            $this->$method($object);
564
        }
565
    }
566
567
    /**
568
     * @param \A17\Twill\Models\Model $object
569
     * @return void
570
     */
571
    public function afterRestore($object)
572
    {
573
        foreach ($this->traitsMethods(__FUNCTION__) as $method) {
574
            $this->$method($object);
575
        }
576
    }
577
578
    /**
579
     * @param \A17\Twill\Models\Model $object
580
     * @param array $fields
581
     * @return \A17\Twill\Models\Model
582
     */
583
    public function hydrate($object, $fields)
584
    {
585
        foreach ($this->traitsMethods(__FUNCTION__) as $method) {
586
            $object = $this->$method($object, $fields);
587
        }
588
589
        return $object;
590
    }
591
592
    /**
593
     * @param \A17\Twill\Models\Model $object
594
     * @return array
595
     */
596
    public function getFormFields($object)
597
    {
598
        $fields = $object->attributesToArray();
599
600
        foreach ($this->traitsMethods(__FUNCTION__) as $method) {
601
            $fields = $this->$method($object, $fields);
602
        }
603
604
        return $fields;
605
    }
606
607
    /**
608
     * @param \Illuminate\Database\Query\Builder $query
609
     * @param array $scopes
610
     * @return \Illuminate\Database\Query\Builder
611
     */
612
    public function filter($query, array $scopes = [])
613
    {
614
        $likeOperator = $this->getLikeOperator();
615
616
        foreach ($this->traitsMethods(__FUNCTION__) as $method) {
617
            $this->$method($query, $scopes);
618
        }
619
620
        unset($scopes['search']);
621
622
        if (isset($scopes['exceptIds'])) {
623
            $query->whereNotIn($this->model->getTable() . '.id', $scopes['exceptIds']);
624
            unset($scopes['exceptIds']);
625
        }
626
627
        foreach ($scopes as $column => $value) {
628
            if (method_exists($this->model, 'scope' . ucfirst($column))) {
629
                $query->$column();
630
            } else {
631
                if (is_array($value)) {
632
                    $query->whereIn($column, $value);
633
                } elseif ($column[0] == '%') {
634
                    $value && ($value[0] == '!') ? $query->where(substr($column, 1), "not $likeOperator", '%' . substr($value, 1) . '%') : $query->where(substr($column, 1), $likeOperator, '%' . $value . '%');
635
                } elseif (isset($value[0]) && $value[0] == '!') {
636
                    $query->where($column, '<>', substr($value, 1));
637
                } elseif ($value !== '') {
638
                    $query->where($column, $value);
639
                }
640
            }
641
        }
642
643
        return $query;
644
    }
645
646
    /**
647
     * @param \Illuminate\Database\Query\Builder $query
648
     * @param array $orders
649
     * @return \Illuminate\Database\Query\Builder
650
     */
651
    public function order($query, array $orders = [])
652
    {
653
        foreach ($this->traitsMethods(__FUNCTION__) as $method) {
654
            $this->$method($query, $orders);
655
        }
656
657
        foreach ($orders as $column => $direction) {
658
            $query->orderBy($column, $direction);
659
        }
660
661
        return $query;
662
    }
663
664
    /**
665
     * @param \A17\Twill\Models\Model $object
666
     * @param array $fields
667
     * @param string $relationship
668
     * @param string $formField
669
     * @param string $attribute
670
     * @return void
671
     */
672
    public function updateOneToMany($object, $fields, $relationship, $formField, $attribute)
673
    {
674
        if (isset($fields[$formField])) {
675
            foreach ($fields[$formField] as $id) {
676
                $object->$relationship()->updateOrCreate([$attribute => $id]);
677
            }
678
679
            foreach ($object->$relationship as $relationshipObject) {
680
                if (!in_array($relationshipObject->$attribute, $fields[$formField])) {
681
                    $relationshipObject->delete();
682
                }
683
            }
684
        } else {
685
            $object->$relationship()->delete();
686
        }
687
    }
688
689
    /**
690
     * @param \A17\Twill\Models\Model $object
691
     * @param array $fields
692
     * @param string $relationship
693
     * @return void
694
     */
695
    public function updateMultiSelect($object, $fields, $relationship)
696
    {
697
        $object->$relationship()->sync($fields[$relationship] ?? []);
698
    }
699
700
    /**
701
     * @param \Illuminate\Database\Query\Builder $query
702
     * @param array $scopes
703
     * @param string $scopeField
704
     * @param string $scopeRelation
705
     * @return void
706
     */
707
    public function addRelationFilterScope($query, &$scopes, $scopeField, $scopeRelation)
708
    {
709
        if (isset($scopes[$scopeField])) {
710
            $id = $scopes[$scopeField];
711
            $query->whereHas($scopeRelation, function ($query) use ($id, $scopeField) {
712
                $query->where($scopeField, $id);
713
            });
714
            unset($scopes[$scopeField]);
715
        }
716
    }
717
718
    /**
719
     * @param \Illuminate\Database\Query\Builder $query
720
     * @param array $scopes
721
     * @param string $scopeField
722
     * @return void
723
     */
724
    public function addLikeFilterScope($query, &$scopes, $scopeField)
725
    {
726
        if (isset($scopes[$scopeField]) && is_string($scopes[$scopeField])) {
727
            $query->where($scopeField, $this->getLikeOperator(), '%' . $scopes[$scopeField] . '%');
728
            unset($scopes[$scopeField]);
729
        }
730
    }
731
732
    /**
733
     * @param \Illuminate\Database\Query\Builder $query
734
     * @param array $scopes
735
     * @param string $scopeField
736
     * @param string[] $orFields
737
     */
738
    public function searchIn($query, &$scopes, $scopeField, $orFields = [])
739
    {
740
741
        if (isset($scopes[$scopeField]) && is_string($scopes[$scopeField])) {
742
            $query->where(function ($query) use (&$scopes, $scopeField, $orFields) {
743
                foreach ($orFields as $field) {
744
                    $query->orWhere($field, $this->getLikeOperator(), '%' . $scopes[$scopeField] . '%');
745
                    unset($scopes[$field]);
746
                }
747
            });
748
        }
749
    }
750
751
    /**
752
     * @return bool
753
     */
754
    public function isUniqueFeature()
755
    {
756
        return false;
757
    }
758
759
    /**
760
     * @param array $ignore
761
     * @return void
762
     */
763
    public function addIgnoreFieldsBeforeSave($ignore = [])
764
    {
765
        $this->ignoreFieldsBeforeSave = is_array($ignore)
0 ignored issues
show
introduced by
The condition is_array($ignore) is always true.
Loading history...
766
        ? array_merge($this->ignoreFieldsBeforeSave, $ignore)
767
        : array_merge($this->ignoreFieldsBeforeSave, [$ignore]);
768
    }
769
770
    /**
771
     * @param string $ignore
772
     * @return bool
773
     */
774
    public function shouldIgnoreFieldBeforeSave($ignore)
775
    {
776
        return in_array($ignore, $this->ignoreFieldsBeforeSave);
777
    }
778
779
    /**
780
     * @return string[]
781
     */
782
    public function getReservedFields()
783
    {
784
        return [
785
            'medias',
786
            'browsers',
787
            'repeaters',
788
            'blocks',
789
        ];
790
    }
791
792
    /**
793
     * @param string $relation
794
     * @param \A17\Twill\Models\Model|null $model
795
     * @return mixed
796
     */
797
    protected function getModelRepository($relation, $model = null)
798
    {
799
        if (!$model) {
800
            $model = ucfirst(Str::singular($relation));
801
        }
802
803
        return App::make(Config::get('twill.namespace') . "\\Repositories\\" . ucfirst($model) . "Repository");
804
    }
805
806
    /**
807
     * @param string|null $method
808
     * @return array
809
     */
810
    protected function traitsMethods(string $method = null)
811
    {
812
        $method = $method ?? debug_backtrace()[1]['function'];
813
814
        $traits = array_values(class_uses_recursive(get_called_class()));
815
816
        $uniqueTraits = array_unique(array_map('class_basename', $traits));
817
818
        $methods = array_map(function (string $trait) use ($method) {
819
            return $method . $trait;
820
        }, $uniqueTraits);
821
822
        return array_filter($methods, function (string $method) {
823
            return method_exists(get_called_class(), $method);
824
        });
825
    }
826
827
    /**
828
     * @return string
829
     */
830
    private function getLikeOperator()
831
    {
832
        if (DB::connection()->getPDO()->getAttribute(PDO::ATTR_DRIVER_NAME) === 'pgsql') {
833
            return 'ILIKE';
834
        }
835
836
        return 'LIKE';
837
    }
838
839
    /**
840
     * @param string $method
841
     * @param array $parameters
842
     * @return mixed
843
     */
844
    public function __call($method, $parameters)
845
    {
846
        return $this->model->$method(...$parameters);
847
    }
848
}
849