Passed
Pull Request — 2.x (#729)
by Antonio Carlos
06:30
created

ModuleRepository::duplicate()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 23
Code Lines 13

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 12

Importance

Changes 3
Bugs 0 Features 0
Metric Value
cc 3
eloc 13
nc 3
nop 2
dl 0
loc 23
ccs 0
cts 14
cp 0
crap 12
rs 9.8333
c 3
b 0
f 0
1
<?php
2
3
namespace A17\Twill\Repositories;
4
5
use A17\Twill\Models\Model;
6
use A17\Twill\Models\Behaviors\Sortable;
7
use A17\Twill\Models\Model;
0 ignored issues
show
Bug introduced by
A parse error occurred: Cannot use A17\Twill\Models\Model as Model because the name is already in use
Loading history...
8
use A17\Twill\Repositories\Behaviors\HandleBrowsers;
9
use A17\Twill\Repositories\Behaviors\HandleDates;
10
use A17\Twill\Repositories\Behaviors\HandleFieldsGroups;
11
use A17\Twill\Repositories\Behaviors\HandleRepeaters;
12
use A17\Twill\Services\Capsules\HasCapsules;
13
use Illuminate\Database\Eloquent\Relations\Relation;
14
use Illuminate\Support\Arr;
15
use Illuminate\Support\Collection;
16
use Illuminate\Support\Facades\App;
17
use Illuminate\Support\Facades\Config;
18
use Illuminate\Support\Facades\DB;
19
use Illuminate\Support\Facades\Log;
20
use Illuminate\Support\Str;
21
use PDO;
22
23
abstract class ModuleRepository
24
{
25
    use HandleDates, HandleBrowsers, HandleRepeaters, HandleFieldsGroups, HasCapsules;
26
27
    /**
28
     * @var \A17\Twill\Models\Model
29
     */
30
    protected $model;
31
32
    /**
33
     * @var string[]
34
     */
35
    protected $ignoreFieldsBeforeSave = [];
36
37
    /**
38
     * @var array
39
     */
40
    protected $countScope = [];
41
42
    /**
43
     * @var array
44
     */
45
    protected $fieldsGroups = [];
46
47
    /**
48
     * @param array $with
49
     * @param array $scopes
50
     * @param array $orders
51
     * @param int $perPage
52
     * @param bool $forcePagination
53
     * @return \Illuminate\Database\Eloquent\Collection
54 12
     */
55
    public function get($with = [], $scopes = [], $orders = [], $perPage = 20, $forcePagination = false)
56 12
    {
57
        $query = $this->model->with($with);
58 12
59 12
        $query = $this->filter($query, $scopes);
60
        $query = $this->order($query, $orders);
61 12
62 3
        if (!$forcePagination && $this->model instanceof Sortable) {
63
            return $query->ordered()->get();
64
        }
65 10
66
        if ($perPage == -1) {
67
            return $query->get();
68
        }
69 10
70
        return $query->paginate($perPage);
71
    }
72
73
    /**
74
     * @param string $slug
75
     * @param array $scope
76
     * @return int
77 33
     */
78
    public function getCountByStatusSlug($slug, $scope = [])
79 33
    {
80
        $this->countScope = $scope;
81 33
82 33
        switch ($slug) {
83 32
            case 'all':
84 6
                return $this->getCountForAll();
85 6
            case 'published':
86 6
                return $this->getCountForPublished();
87 6
            case 'draft':
88 6
                return $this->getCountForDraft();
89 6
            case 'trash':
90
                return $this->getCountForTrash();
91
        }
92 5
93 5
        foreach ($this->traitsMethods(__FUNCTION__) as $method) {
94 5
            if (($count = $this->$method($slug)) !== false) {
95
                return $count;
96
            }
97
        }
98
99
        return 0;
100
    }
101
102
    /**
103
     * @return int
104 32
     */
105
    public function getCountForAll()
106 32
    {
107 32
        $query = $this->model->newQuery();
108
        return $this->filter($query, $this->countScope)->count();
109
    }
110
111
    /**
112
     * @return int
113 5
     */
114
    public function getCountForPublished()
115 5
    {
116 5
        $query = $this->model->newQuery();
117
        return $this->filter($query, $this->countScope)->published()->count();
118
    }
119
120
    /**
121
     * @return int
122 5
     */
123
    public function getCountForDraft()
124 5
    {
125 5
        $query = $this->model->newQuery();
126
        return $this->filter($query, $this->countScope)->draft()->count();
127
    }
128
129
    /**
130
     * @return int
131 5
     */
132
    public function getCountForTrash()
133 5
    {
134 5
        $query = $this->model->newQuery();
135
        return $this->filter($query, $this->countScope)->onlyTrashed()->count();
136
    }
137
138
    /**
139
     * @param $id
140
     * @param array $with
141
     * @param array $withCount
142
     * @return \A17\Twill\Models\Model
143
     * @throws \Illuminate\Database\Eloquent\ModelNotFoundException
144 18
     */
145
    public function getById($id, $with = [], $withCount = [])
146 18
    {
147
        return $this->model->with($with)->withCount($withCount)->findOrFail($id);
148
    }
149
150
    /**
151
     * @param string $column
152
     * @param array $orders
153
     * @param null $exceptId
154
     * @return \Illuminate\Support\Collection
155
     */
156
    public function listAll($column = 'title', $orders = [], $exceptId = null)
157
    {
158
        $query = $this->model->newQuery();
159
160
        if ($exceptId) {
161
            $query = $query->where($this->model->getTable() . '.id', '<>', $exceptId);
162
        }
163
164
        if ($this->model instanceof Sortable) {
165
            $query = $query->ordered();
166
        } elseif (!empty($orders)) {
167
            $query = $this->order($query, $orders);
168
        }
169
170
        if ($this->model->isTranslatable()) {
171
            $query = $query->withTranslation();
172
        }
173
174
        return $query->get()->pluck($column, 'id');
175
    }
176
177
    /**
178
     * @param $search
179
     * @param array $fields
180
     * @return \Illuminate\Database\Eloquent\Collection
181 1
     */
182
    public function cmsSearch($search, $fields = [])
183 1
    {
184
        $query = $this->model->latest();
185 1
186
        $translatedAttributes = $this->model->translatedAttributes ?? [];
187 1
188 1
        foreach ($fields as $field) {
189 1
            if (in_array($field, $translatedAttributes)) {
190 1
                $query->orWhereHas('translations', function ($q) use ($field, $search) {
191 1
                    $q->where($field, $this->getLikeOperator(), "%{$search}%");
192
                });
193
            } else {
194
                $query->orWhere($field, $this->getLikeOperator(), "%{$search}%");
195
            }
196
        }
197 1
198
        return $query->get();
199
    }
200
201
    /**
202
     * @param $attributes
203
     * @param $fields
204
     * @return \A17\Twill\Models\Model
205
     */
206
    public function firstOrCreate($attributes, $fields = [])
207
    {
208
        return $this->model->where($attributes)->first() ?? $this->create($attributes + $fields);
209
    }
210
211
    /**
212
     * @param string[] $fields
213
     * @return \A17\Twill\Models\Model
214 31
     */
215
    public function create($fields)
216 31
    {
217 31
        return DB::transaction(function () use ($fields) {
218
            $original_fields = $fields;
219 31
220
            $fields = $this->prepareFieldsBeforeCreate($fields);
221 31
222
            $object = $this->model->create(Arr::except($fields, $this->getReservedFields()));
223 31
224
            $this->beforeSave($object, $original_fields);
225 31
226
            $fields = $this->prepareFieldsBeforeSave($object, $fields);
227 31
228
            $object->save();
229 31
230
            $this->afterSave($object, $fields);
231 31
232 31
            return $object;
233
        }, 3);
234
    }
235
236
    /**
237
     * @param array $fields
238
     * @return \A17\Twill\Models\Model
239 2
     */
240
    public function createForPreview($fields)
241 2
    {
242
        $fields = $this->prepareFieldsBeforeCreate($fields);
243 2
244
        $object = $this->model->newInstance(Arr::except($fields, $this->getReservedFields()));
245 2
246
        return $this->hydrate($object, $fields);
247
    }
248
249
    /**
250
     * @param array $attributes
251
     * @param array $fields
252
     * @return \A17\Twill\Models\Model
253
     */
254
    public function updateOrCreate($attributes, $fields)
255
    {
256
        $object = $this->model->where($attributes)->first();
257
258
        if (!$object) {
259
            return $this->create($fields);
260
        }
261
262
        $this->update($object->id, $fields);
263
    }
264
265
    /**
266
     * @param mixed $id
267
     * @param array $fields
268
     * @return void
269 12
     */
270
    public function update($id, $fields)
271 12
    {
272 12
        DB::transaction(function () use ($id, $fields) {
273
            $object = $this->model->findOrFail($id);
274 12
275
            $this->beforeSave($object, $fields);
276 12
277
            $fields = $this->prepareFieldsBeforeSave($object, $fields);
278 12
279
            $object->fill(Arr::except($fields, $this->getReservedFields()));
280 12
281
            $object->save();
282 12
283 12
            $this->afterSave($object, $fields);
284 12
        }, 3);
285
    }
286
287
    /**
288
     * @param mixed $id
289
     * @param array $values
290
     * @param array $scopes
291
     * @return mixed
292 4
     */
293
    public function updateBasic($id, $values, $scopes = [])
294 4
    {
295
        return DB::transaction(function () use ($id, $values, $scopes) {
296 4
            // apply scopes if no id provided
297 1
            if (is_null($id)) {
298
                $query = $this->model->query();
299 1
300
                foreach ($scopes as $column => $value) {
301
                    $query->where($column, $value);
302
                }
303 1
304
                $query->update($values);
305 1
306
                $query->get()->each(function ($object) use ($values) {
307 1
                    $this->afterUpdateBasic($object, $values);
308
                });
309 1
310
                return true;
311
            }
312
313 3
            // apply to all ids if array of ids provided
314
            if (is_array($id)) {
315
                $query = $this->model->whereIn('id', $id);
316
                $query->update($values);
317
318
                $query->get()->each(function ($object) use ($values) {
319
                    $this->afterUpdateBasic($object, $values);
320
                });
321
322
                return true;
323
            }
324 3
325 2
            if (($object = $this->model->find($id)) != null) {
326 2
                $object->update($values);
327 2
                $this->afterUpdateBasic($object, $values);
328
                return true;
329
            }
330 1
331 4
            return false;
332
        }, 3);
333
    }
334
335
    /**
336
     * @param array $ids
337
     * @return void
338 2
     */
339
    public function setNewOrder($ids)
340 2
    {
341 2
        DB::transaction(function () use ($ids) {
342 2
            $this->model->setNewOrder($ids);
343 1
        }, 3);
344
    }
345
346
    /**
347
     * @param mixed $id
348
     * @return mixed
349
     */
350
    public function duplicate($id, $titleColumnKey = 'title')
351
    {
352
353
        if (($object = $this->model->find($id)) === null) {
354
            return false;
355
        }
356
357
        if (($revision = $object->revisions()->orderBy('created_at', 'desc')->first()) === null) {
358
            return false;
359
        }
360
361
        $revisionInput = json_decode($revision->payload, true);
362
        $baseInput = collect($revisionInput)->only([
363
            $titleColumnKey,
364
            'slug',
365
            'languages',
366
        ])->filter()->toArray();
367
368
        $newObject = $this->create($baseInput);
369
370
        $this->update($newObject->id, $revisionInput);
371
372
        return $newObject;
373
    }
374
375
    /**
376
     * @param mixed $id
377
     * @return mixed
378 2
     */
379
    public function delete($id)
380 2
    {
381 2
        return DB::transaction(function () use ($id) {
382
            if (($object = $this->model->find($id)) === null) {
383
                return false;
384
            }
385 2
386 2
            if (!method_exists($object, 'canDeleteSafely') || $object->canDeleteSafely()) {
387 2
                $object->delete();
388 2
                $this->afterDelete($object);
389
                return true;
390
            }
391 2
            return false;
392
        }, 3);
393
    }
394
395
    /**
396
     * @param array $ids
397
     * @return mixed
398 21
     */
399
    public function bulkDelete($ids)
400 21
    {
401
        return DB::transaction(function () use ($ids) {
402 21
            try {
403
                Collection::make($ids)->each(function ($id) {
404 21
                    $this->delete($id);
405
                });
406
            } catch (\Exception $e) {
407
                Log::error($e);
408
                return false;
409
            }
410 21
411 21
            return true;
412
        }, 3);
413
    }
414
415
    /**
416
     * @param mixed $id
417
     * @return mixed
418
     */
419
    public function forceDelete($id)
420
    {
421
        return DB::transaction(function () use ($id) {
422
            if (($object = $this->model->onlyTrashed()->find($id)) === null) {
423
                return false;
424
            } else {
425
                $object->forceDelete();
426
                $this->afterDelete($object);
427
                return true;
428
            }
429
        }, 3);
430
    }
431
432
    /**
433
     * @param mixed $id
434
     * @return mixed
435
     */
436
    public function bulkForceDelete($ids)
437
    {
438
        return DB::transaction(function () use ($ids) {
439
            try {
440
                $query = $this->model->onlyTrashed()->whereIn('id', $ids);
441
                $objects = $query->get();
442
443
                $query->forceDelete();
444
445
                $objects->each(function ($object) {
446
                    $this->afterDelete($object);
447
                });
448
            } catch (\Exception $e) {
449
                Log::error($e);
450
                return false;
451
            }
452
453
            return true;
454
        }, 3);
455
    }
456
457
    /**
458
     * @param mixed $id
459
     * @return mixed
460 2
     */
461
    public function restore($id)
462 2
    {
463 2
        return DB::transaction(function () use ($id) {
464 1
            if (($object = $this->model->withTrashed()->find($id)) != null) {
465 1
                $object->restore();
466 1
                $this->afterRestore($object);
467
                return true;
468
            }
469 1
470 2
            return false;
471
        }, 3);
472
    }
473
474
    /**
475
     * @param array $ids
476
     * @return mixed
477
     */
478
    public function bulkRestore($ids)
479
    {
480
        return DB::transaction(function () use ($ids) {
481
            try {
482
                $query = $this->model->withTrashed()->whereIn('id', $ids);
483
                $objects = $query->get();
484
485
                $query->restore();
486
487
                $objects->each(function ($object) {
488
                    $this->afterRestore($object);
489
                });
490
            } catch (\Exception $e) {
491
                Log::error($e);
492
                return false;
493
            }
494
495
            return true;
496
        }, 3);
497
    }
498
499
    /**
500
     * @param \A17\Twill\Models\Model $object
501
     * @param array $fields
502
     * @return array
503 32
     */
504
    public function cleanupFields($object, $fields)
505 32
    {
506 25
        if (property_exists($this->model, 'checkboxes')) {
507 25
            foreach ($this->model->checkboxes as $field) {
508 25
                if (!$this->shouldIgnoreFieldBeforeSave($field)) {
509 5
                    if (!isset($fields[$field])) {
510
                        $fields[$field] = false;
511 25
                    } else {
512
                        $fields[$field] = !empty($fields[$field]);
513
                    }
514
                }
515
            }
516
        }
517 32
518
        if (property_exists($this->model, 'nullable')) {
519
            foreach ($this->model->nullable as $field) {
520
                if (!isset($fields[$field]) && !$this->shouldIgnoreFieldBeforeSave($field)) {
521
                    $fields[$field] = null;
522
                }
523
            }
524
        }
525 32
526 32
        foreach ($fields as $key => $value) {
527 32
            if (!$this->shouldIgnoreFieldBeforeSave($key)) {
528 8
                if (is_array($value) && empty($value)) {
529
                    $fields[$key] = null;
530 32
                }
531
                if ($value === '') {
532
                    $fields[$key] = null;
533
                }
534
            }
535
        }
536 32
537
        return $fields;
538
    }
539
540
    /**
541
     * @param array $fields
542
     * @return array
543 26
     */
544
    public function prepareFieldsBeforeCreate($fields)
545 26
    {
546
        $fields = $this->cleanupFields(null, $fields);
547 26
548 26
        foreach ($this->traitsMethods(__FUNCTION__) as $method) {
549
            $fields = $this->$method($fields);
550
        }
551 26
552
        return $fields;
553
    }
554
555
    /**
556
     * @param \A17\Twill\Models\Model $object
557
     * @param array $fields
558
     * @return string[]
559 31
     */
560
    public function prepareFieldsBeforeSave($object, $fields)
561 31
    {
562
        $fields = $this->cleanupFields($object, $fields);
563 31
564 31
        foreach ($this->traitsMethods(__FUNCTION__) as $method) {
565
            $fields = $this->$method($object, $fields);
566
        }
567 31
568
        return $fields;
569
    }
570
571
    /**
572
     * @param \A17\Twill\Models\Model $object
573
     * @param array $fields
574
     * @return void
575 2
     */
576
    public function afterUpdateBasic($object, $fields)
577 2
    {
578
        foreach ($this->traitsMethods(__FUNCTION__) as $method) {
579
            $this->$method($object, $fields);
580 2
        }
581
    }
582
583
    /**
584
     * @param \A17\Twill\Models\Model $object
585
     * @param array $fields
586
     * @return void
587 31
     */
588
    public function beforeSave($object, $fields)
589 31
    {
590 21
        foreach ($this->traitsMethods(__FUNCTION__) as $method) {
591
            $this->$method($object, $fields);
592 31
        }
593
    }
594
595
    /**
596
     * @param \A17\Twill\Models\Model $object
597
     * @param array $fields
598
     * @return void
599 31
     */
600
    public function afterSave($object, $fields)
601 31
    {
602 31
        foreach ($this->traitsMethods(__FUNCTION__) as $method) {
603
            $this->$method($object, $fields);
604 31
        }
605
    }
606
607
    /**
608
     * @param \A17\Twill\Models\Model $object
609
     * @return void
610 2
     */
611
    public function afterDelete($object)
612 2
    {
613 2
        foreach ($this->traitsMethods(__FUNCTION__) as $method) {
614
            $this->$method($object);
615 2
        }
616
    }
617
618
    /**
619
     * @param \A17\Twill\Models\Model $object
620
     * @return void
621 1
     */
622
    public function afterRestore($object)
623 1
    {
624 1
        foreach ($this->traitsMethods(__FUNCTION__) as $method) {
625
            $this->$method($object);
626 1
        }
627
    }
628
629
    /**
630
     * @param \A17\Twill\Models\Model $object
631
     * @param array $fields
632
     * @return \A17\Twill\Models\Model
633 3
     */
634
    public function hydrate($object, $fields)
635 3
    {
636 3
        foreach ($this->traitsMethods(__FUNCTION__) as $method) {
637
            $object = $this->$method($object, $fields);
638
        }
639 3
640
        return $object;
641
    }
642
643
    /**
644
     * @param \A17\Twill\Models\Model $object
645
     * @return array
646 6
     */
647
    public function getFormFields($object)
648 6
    {
649
        $fields = $object->attributesToArray();
650 6
651 6
        foreach ($this->traitsMethods(__FUNCTION__) as $method) {
652
            $fields = $this->$method($object, $fields);
653
        }
654 6
655
        return $fields;
656
    }
657
658
    /**
659
     * @param \Illuminate\Database\Query\Builder $query
660
     * @param array $scopes
661
     * @return \Illuminate\Database\Query\Builder
662 37
     */
663
    public function filter($query, array $scopes = [])
664 37
    {
665
        $likeOperator = $this->getLikeOperator();
666 37
667 36
        foreach ($this->traitsMethods(__FUNCTION__) as $method) {
668
            $this->$method($query, $scopes);
669
        }
670 37
671
        unset($scopes['search']);
672 37
673 2
        if (isset($scopes['exceptIds'])) {
674 2
            $query->whereNotIn($this->model->getTable() . '.id', $scopes['exceptIds']);
675
            unset($scopes['exceptIds']);
676
        }
677 37
678 5
        foreach ($scopes as $column => $value) {
679 1
            if (method_exists($this->model, 'scope' . ucfirst($column))) {
680
                $query->$column();
681 4
            } else {
682 2
                if (is_array($value)) {
683 2
                    $query->whereIn($column, $value);
684
                } elseif ($column[0] == '%') {
685 2
                    $value && ($value[0] == '!') ? $query->where(substr($column, 1), "not $likeOperator", '%' . substr($value, 1) . '%') : $query->where(substr($column, 1), $likeOperator, '%' . $value . '%');
686
                } elseif (isset($value[0]) && $value[0] == '!') {
687 2
                    $query->where($column, '<>', substr($value, 1));
688 2
                } elseif ($value !== '') {
689
                    $query->where($column, $value);
690
                }
691
            }
692
        }
693 37
694
        return $query;
695
    }
696
697
    /**
698
     * @param \Illuminate\Database\Query\Builder $query
699
     * @param array $orders
700
     * @return \Illuminate\Database\Query\Builder
701 12
     */
702
    public function order($query, array $orders = [])
703 12
    {
704 7
        foreach ($this->traitsMethods(__FUNCTION__) as $method) {
705
            $this->$method($query, $orders);
706
        }
707 12
708 5
        foreach ($orders as $column => $direction) {
709
            $query->orderBy($column, $direction);
710
        }
711 12
712
        return $query;
713
    }
714
715
    /**
716
     * @param \A17\Twill\Models\Model $object
717
     * @param array $fields
718
     * @param string $relationship
719
     * @param string $formField
720
     * @param string $attribute
721
     * @return void
722
     */
723
    public function updateOneToMany($object, $fields, $relationship, $formField, $attribute)
724
    {
725
        if (isset($fields[$formField])) {
726
            foreach ($fields[$formField] as $id) {
727
                $object->$relationship()->updateOrCreate([$attribute => $id]);
728
            }
729
730
            foreach ($object->$relationship as $relationshipObject) {
731
                if (!in_array($relationshipObject->$attribute, $fields[$formField])) {
732
                    $relationshipObject->delete();
733
                }
734
            }
735
        } else {
736
            $object->$relationship()->delete();
737
        }
738
    }
739
740
    /**
741
     * @param \A17\Twill\Models\Model $object
742
     * @param array $fields
743
     * @param string $relationship
744
     * @return void
745
     */
746
    public function updateMultiSelect($object, $fields, $relationship)
747
    {
748
        $object->$relationship()->sync($fields[$relationship] ?? []);
749
    }
750
751
    /**
752
     * @param \Illuminate\Database\Query\Builder $query
753
     * @param array $scopes
754
     * @param string $scopeField
755
     * @param string $scopeRelation
756
     * @return void
757 36
     */
758
    public function addRelationFilterScope($query, &$scopes, $scopeField, $scopeRelation)
759 36
    {
760
        if (isset($scopes[$scopeField])) {
761
            $id = $scopes[$scopeField];
762
            $query->whereHas($scopeRelation, function ($query) use ($id, $scopeField) {
763
                $query->where($scopeField, $id);
764
            });
765
            unset($scopes[$scopeField]);
766 36
        }
767
    }
768
769
    /**
770
     * @param \Illuminate\Database\Query\Builder $query
771
     * @param array $scopes
772
     * @param string $scopeField
773
     * @return void
774
     */
775
    public function addLikeFilterScope($query, &$scopes, $scopeField)
776
    {
777
        if (isset($scopes[$scopeField]) && is_string($scopes[$scopeField])) {
778
            $query->where($scopeField, $this->getLikeOperator(), '%' . $scopes[$scopeField] . '%');
779
            unset($scopes[$scopeField]);
780
        }
781
    }
782
783
    /**
784
     * @param \Illuminate\Database\Query\Builder $query
785
     * @param array $scopes
786
     * @param string $scopeField
787
     * @param string[] $orFields
788 5
     */
789
    public function searchIn($query, &$scopes, $scopeField, $orFields = [])
790
    {
791 5
792 2
        if (isset($scopes[$scopeField]) && is_string($scopes[$scopeField])) {
793 2
            $query->where(function ($query) use (&$scopes, $scopeField, $orFields) {
794 2
                foreach ($orFields as $field) {
795 2
                    $query->orWhere($field, $this->getLikeOperator(), '%' . $scopes[$scopeField] . '%');
796
                    unset($scopes[$field]);
797 2
                }
798
            });
799 5
        }
800
    }
801
802
    /**
803
     * @return bool
804 2
     */
805
    public function isUniqueFeature()
806 2
    {
807
        return false;
808
    }
809
810
    /**
811
     * @param array $ignore
812
     * @return void
813
     */
814
    public function addIgnoreFieldsBeforeSave($ignore = [])
815
    {
816
        $this->ignoreFieldsBeforeSave = is_array($ignore)
817
        ? array_merge($this->ignoreFieldsBeforeSave, $ignore)
818
        : array_merge($this->ignoreFieldsBeforeSave, [$ignore]);
819
    }
820
821
    /**
822
     * @param string $ignore
823
     * @return bool
824 32
     */
825
    public function shouldIgnoreFieldBeforeSave($ignore)
826 32
    {
827
        return in_array($ignore, $this->ignoreFieldsBeforeSave);
828
    }
829
830
    /**
831
     * @return string[]
832 32
     */
833
    public function getReservedFields()
834
    {
835 32
        return [
836
            'medias',
837
            'browsers',
838
            'repeaters',
839
            'blocks',
840
        ];
841
    }
842
843
    /**
844
     * @param string $relation
845
     * @param \A17\Twill\Models\Model|\A17\Twill\Repositories\ModuleRepository|null $modelOrRepository
846
     * @return mixed
847
     */
848
    protected function getModelRepository($relation, $modelOrRepository = null)
849
    {
850
        if (!$modelOrRepository) {
851
            if (class_exists($relation) && (new $relation) instanceof Model) {
852
                $modelOrRepository = Str::afterLast($relation, '\\');
853
            } else {
854
                $morphedModel = Relation::getMorphedModel($relation);
855
                if (class_exists($morphedModel) && (new $morphedModel) instanceof Model) {
856
                    $modelOrRepository = (new \ReflectionClass($morphedModel))->getShortName();
857
                    $model = (new \ReflectionClass($morphedModel))->getShortName();
858
                } else {
859
                    $modelOrRepository = ucfirst(Str::singular($relation));
860
                }
861
            }
862
        }
863
864
        $repository = class_exists($modelOrRepository)
865
        ? App::make($modelOrRepository)
866
        : $modelOrRepository;
867
868
        if ($repository instanceof ModuleRepository) {
869 46
            return $repository;
870
        } else {
871 46
            $class = Config::get('twill.namespace') . "\\Repositories\\" . ucfirst($modelOrRepository) . "Repository";
872
        }
873 46
874
        if (class_exists($class)) {
875 46
            return App::make($class);
876
        }
877 46
878 46
        $capsule = $this->getCapsuleByModel($modelOrRepository);
879 46
880
        if (blank($capsule)) {
881 46
            throw new \Exception("Repository class not found for model '{$modelOrRepository}'");
882 46
        }
883 46
884
        return App::make($capsule['repository']);
885
    }
886
    
887
    /**
888
     * @param string|null $method
889 37
     * @return array
890
     */
891 37
    protected function traitsMethods(string $method = null)
892
    {
893
        $method = $method ?? debug_backtrace()[1]['function'];
894
895 37
        $traits = array_values(class_uses_recursive(get_called_class()));
896
897
        $uniqueTraits = array_unique(array_map('class_basename', $traits));
898
899
        $methods = array_map(function (string $trait) use ($method) {
900
            return $method . $trait;
901
        }, $uniqueTraits);
902
903 31
        return array_filter($methods, function (string $method) {
904
            return method_exists(get_called_class(), $method);
905 31
        });
906
    }
907
908
    /**
909
     * @return string
910
     */
911
    private function getLikeOperator()
912 35
    {
913
        if (DB::connection()->getPDO()->getAttribute(PDO::ATTR_DRIVER_NAME) === 'pgsql') {
914 35
            return 'ILIKE';
915
        }
916 35
917 32
        return 'LIKE';
918
    }
919
920 35
    /**
921
     * @param string $method
922
     * @param array $parameters
923
     * @return mixed
924
     */
925
    public function __call($method, $parameters)
926 11
    {
927
        return $this->model->$method(...$parameters);
928 11
    }
929
930
    /**
931
     * @param string $behavior
932
     * @return boolean
933
     */
934
    public function hasBehavior($behavior)
935
    {
936
        $hasBehavior = classHasTrait($this, 'A17\Twill\Repositories\Behaviors\Handle' . ucfirst($behavior));
937
938
        if (Str::startsWith($behavior, 'translation')) {
939
            $hasBehavior = $hasBehavior && $this->model->isTranslatable();
940
        }
941
942
        return $hasBehavior;
943
    }
944
945
    /**
946
     * @return boolean
947
     */
948
    public function isTranslatable($column)
949
    {
950
        return $this->model->isTranslatable($column);
951
    }
952
}
953