Passed
Push — master ( e1e679...09e224 )
by Quentin
10:29
created

ModuleRepository::traitsMethods()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 14
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 7
CRAP Score 1

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 8
c 1
b 0
f 0
nc 1
nop 1
dl 0
loc 14
ccs 7
cts 7
cp 1
crap 1
rs 10
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 2
    public function delete($id)
347
    {
348
        return DB::transaction(function () use ($id) {
349 2
            if (($object = $this->model->find($id)) === null) {
350
                return false;
351
            }
352
353 2
            if (!method_exists($object, 'canDeleteSafely') || $object->canDeleteSafely()) {
354 2
                $object->delete();
355 2
                $this->afterDelete($object);
356 2
                return true;
357
            }
358
            return false;
359 2
        }, 3);
360
    }
361
362
    /**
363
     * @param array $ids
364
     * @return mixed
365
     */
366 17
    public function bulkDelete($ids)
367
    {
368
        return DB::transaction(function () use ($ids) {
369
            try {
370
                Collection::make($ids)->each(function ($id) {
371
                    $this->delete($id);
372 17
                });
373
            } catch (\Exception $e) {
374
                Log::error($e);
375
                return false;
376
            }
377
378 17
            return true;
379 17
        }, 3);
380
    }
381
382
    /**
383
     * @param mixed $id
384
     * @return mixed
385
     */
386
    public function forceDelete($id)
387
    {
388
        return DB::transaction(function () use ($id) {
389
            if (($object = $this->model->onlyTrashed()->find($id)) === null) {
390
                return false;
391
            } else {
392
                $object->forceDelete();
393
                $this->afterDelete($object);
394
                return true;
395
            }
396
        }, 3);
397
    }
398
399
    /**
400
     * @param mixed $id
401
     * @return mixed
402
     */
403
    public function bulkForceDelete($ids)
404
    {
405
        return DB::transaction(function () use ($ids) {
406
            try {
407
                $query = $this->model->onlyTrashed()->whereIn('id', $ids);
408
                $objects = $query->get();
409
410
                $query->forceDelete();
411
412
                $objects->each(function ($object) {
413
                    $this->afterDelete($object);
414
                });
415
            } catch (\Exception $e) {
416
                Log::error($e);
417
                return false;
418
            }
419
420
            return true;
421
        }, 3);
422
    }
423
424
    /**
425
     * @param mixed $id
426
     * @return mixed
427
     */
428 2
    public function restore($id)
429
    {
430
        return DB::transaction(function () use ($id) {
431 2
            if (($object = $this->model->withTrashed()->find($id)) != null) {
432 1
                $object->restore();
433 1
                $this->afterRestore($object);
434 1
                return true;
435
            }
436
437 1
            return false;
438 2
        }, 3);
439
    }
440
441
    /**
442
     * @param array $ids
443
     * @return mixed
444
     */
445
    public function bulkRestore($ids)
446
    {
447
        return DB::transaction(function () use ($ids) {
448
            try {
449
                $query = $this->model->withTrashed()->whereIn('id', $ids);
450
                $objects = $query->get();
451
452
                $query->restore();
453
454
                $objects->each(function ($object) {
455
                    $this->afterRestore($object);
456
                });
457
            } catch (\Exception $e) {
458
                Log::error($e);
459
                return false;
460
            }
461
462
            return true;
463
        }, 3);
464
    }
465
466
    /**
467
     * @param \A17\Twill\Models\Model $object
468
     * @param array $fields
469
     * @return array
470
     */
471 28
    public function cleanupFields($object, $fields)
472
    {
473 28
        if (property_exists($this->model, 'checkboxes')) {
474 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...
475 21
                if (!$this->shouldIgnoreFieldBeforeSave($field)) {
476 21
                    if (!isset($fields[$field])) {
477 5
                        $fields[$field] = false;
478
                    } else {
479 21
                        $fields[$field] = !empty($fields[$field]);
480
                    }
481
                }
482
            }
483
        }
484
485 28
        if (property_exists($this->model, 'nullable')) {
486
            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...
487
                if (!isset($fields[$field]) && !$this->shouldIgnoreFieldBeforeSave($field)) {
488
                    $fields[$field] = null;
489
                }
490
            }
491
        }
492
493 28
        foreach ($fields as $key => $value) {
494 28
            if (!$this->shouldIgnoreFieldBeforeSave($key)) {
495 28
                if (is_array($value) && empty($value)) {
496 7
                    $fields[$key] = null;
497
                }
498 28
                if ($value === '') {
499
                    $fields[$key] = null;
500
                }
501
            }
502
        }
503
504 28
        return $fields;
505
    }
506
507
    /**
508
     * @param array $fields
509
     * @return array
510
     */
511 22
    public function prepareFieldsBeforeCreate($fields)
512
    {
513 22
        $fields = $this->cleanupFields(null, $fields);
514
515 22
        foreach ($this->traitsMethods(__FUNCTION__) as $method) {
516 22
            $fields = $this->$method($fields);
517
        }
518
519 22
        return $fields;
520
    }
521
522
    /**
523
     * @param \A17\Twill\Models\Model $object
524
     * @param array $fields
525
     * @return string[]
526
     */
527 27
    public function prepareFieldsBeforeSave($object, $fields)
528
    {
529 27
        $fields = $this->cleanupFields($object, $fields);
530
531 27
        foreach ($this->traitsMethods(__FUNCTION__) as $method) {
532 27
            $fields = $this->$method($object, $fields);
533
        }
534
535 27
        return $fields;
536
    }
537
538
    /**
539
     * @param \A17\Twill\Models\Model $object
540
     * @param array $fields
541
     * @return void
542
     */
543 2
    public function afterUpdateBasic($object, $fields)
544
    {
545 2
        foreach ($this->traitsMethods(__FUNCTION__) as $method) {
546
            $this->$method($object, $fields);
547
        }
548 2
    }
549
550
    /**
551
     * @param \A17\Twill\Models\Model $object
552
     * @param array $fields
553
     * @return void
554
     */
555 27
    public function beforeSave($object, $fields)
556
    {
557 27
        foreach ($this->traitsMethods(__FUNCTION__) as $method) {
558 17
            $this->$method($object, $fields);
559
        }
560 27
    }
561
562
    /**
563
     * @param \A17\Twill\Models\Model $object
564
     * @param array $fields
565
     * @return void
566
     */
567 27
    public function afterSave($object, $fields)
568
    {
569 27
        foreach ($this->traitsMethods(__FUNCTION__) as $method) {
570 27
            $this->$method($object, $fields);
571
        }
572 27
    }
573
574
    /**
575
     * @param \A17\Twill\Models\Model $object
576
     * @return void
577
     */
578 2
    public function afterDelete($object)
579
    {
580 2
        foreach ($this->traitsMethods(__FUNCTION__) as $method) {
581 2
            $this->$method($object);
582
        }
583 2
    }
584
585
    /**
586
     * @param \A17\Twill\Models\Model $object
587
     * @return void
588
     */
589 1
    public function afterRestore($object)
590
    {
591 1
        foreach ($this->traitsMethods(__FUNCTION__) as $method) {
592 1
            $this->$method($object);
593
        }
594 1
    }
595
596
    /**
597
     * @param \A17\Twill\Models\Model $object
598
     * @param array $fields
599
     * @return \A17\Twill\Models\Model
600
     */
601 3
    public function hydrate($object, $fields)
602
    {
603 3
        foreach ($this->traitsMethods(__FUNCTION__) as $method) {
604 3
            $object = $this->$method($object, $fields);
605
        }
606
607 3
        return $object;
608
    }
609
610
    /**
611
     * @param \A17\Twill\Models\Model $object
612
     * @return array
613
     */
614 5
    public function getFormFields($object)
615
    {
616 5
        $fields = $object->attributesToArray();
617
618 5
        foreach ($this->traitsMethods(__FUNCTION__) as $method) {
619 5
            $fields = $this->$method($object, $fields);
620
        }
621
622 5
        return $fields;
623
    }
624
625
    /**
626
     * @param \Illuminate\Database\Query\Builder $query
627
     * @param array $scopes
628
     * @return \Illuminate\Database\Query\Builder
629
     */
630 12
    public function filter($query, array $scopes = [])
631
    {
632 12
        $likeOperator = $this->getLikeOperator();
633
634 12
        foreach ($this->traitsMethods(__FUNCTION__) as $method) {
635 11
            $this->$method($query, $scopes);
636
        }
637
638 12
        unset($scopes['search']);
639
640 12
        if (isset($scopes['exceptIds'])) {
641 2
            $query->whereNotIn($this->model->getTable() . '.id', $scopes['exceptIds']);
642 2
            unset($scopes['exceptIds']);
643
        }
644
645 12
        foreach ($scopes as $column => $value) {
646 5
            if (method_exists($this->model, 'scope' . ucfirst($column))) {
647 1
                $query->$column();
648
            } else {
649 4
                if (is_array($value)) {
650 2
                    $query->whereIn($column, $value);
651 2
                } elseif ($column[0] == '%') {
652
                    $value && ($value[0] == '!') ? $query->where(substr($column, 1), "not $likeOperator", '%' . substr($value, 1) . '%') : $query->where(substr($column, 1), $likeOperator, '%' . $value . '%');
653 2
                } elseif (isset($value[0]) && $value[0] == '!') {
654
                    $query->where($column, '<>', substr($value, 1));
655 2
                } elseif ($value !== '') {
656 2
                    $query->where($column, $value);
657
                }
658
            }
659
        }
660
661 12
        return $query;
662
    }
663
664
    /**
665
     * @param \Illuminate\Database\Query\Builder $query
666
     * @param array $orders
667
     * @return \Illuminate\Database\Query\Builder
668
     */
669 12
    public function order($query, array $orders = [])
670
    {
671 12
        foreach ($this->traitsMethods(__FUNCTION__) as $method) {
672 7
            $this->$method($query, $orders);
673
        }
674
675 12
        foreach ($orders as $column => $direction) {
676 5
            $query->orderBy($column, $direction);
677
        }
678
679 12
        return $query;
680
    }
681
682
    /**
683
     * @param \A17\Twill\Models\Model $object
684
     * @param array $fields
685
     * @param string $relationship
686
     * @param string $formField
687
     * @param string $attribute
688
     * @return void
689
     */
690
    public function updateOneToMany($object, $fields, $relationship, $formField, $attribute)
691
    {
692
        if (isset($fields[$formField])) {
693
            foreach ($fields[$formField] as $id) {
694
                $object->$relationship()->updateOrCreate([$attribute => $id]);
695
            }
696
697
            foreach ($object->$relationship as $relationshipObject) {
698
                if (!in_array($relationshipObject->$attribute, $fields[$formField])) {
699
                    $relationshipObject->delete();
700
                }
701
            }
702
        } else {
703
            $object->$relationship()->delete();
704
        }
705
    }
706
707
    /**
708
     * @param \A17\Twill\Models\Model $object
709
     * @param array $fields
710
     * @param string $relationship
711
     * @return void
712
     */
713
    public function updateMultiSelect($object, $fields, $relationship)
714
    {
715
        $object->$relationship()->sync($fields[$relationship] ?? []);
716
    }
717
718
    /**
719
     * @param \Illuminate\Database\Query\Builder $query
720
     * @param array $scopes
721
     * @param string $scopeField
722
     * @param string $scopeRelation
723
     * @return void
724
     */
725 9
    public function addRelationFilterScope($query, &$scopes, $scopeField, $scopeRelation)
726
    {
727 9
        if (isset($scopes[$scopeField])) {
728
            $id = $scopes[$scopeField];
729
            $query->whereHas($scopeRelation, function ($query) use ($id, $scopeField) {
730
                $query->where($scopeField, $id);
731
            });
732
            unset($scopes[$scopeField]);
733
        }
734 9
    }
735
736
    /**
737
     * @param \Illuminate\Database\Query\Builder $query
738
     * @param array $scopes
739
     * @param string $scopeField
740
     * @return void
741
     */
742
    public function addLikeFilterScope($query, &$scopes, $scopeField)
743
    {
744
        if (isset($scopes[$scopeField]) && is_string($scopes[$scopeField])) {
745
            $query->where($scopeField, $this->getLikeOperator(), '%' . $scopes[$scopeField] . '%');
746
            unset($scopes[$scopeField]);
747
        }
748
    }
749
750
    /**
751
     * @param \Illuminate\Database\Query\Builder $query
752
     * @param array $scopes
753
     * @param string $scopeField
754
     * @param string[] $orFields
755
     */
756 5
    public function searchIn($query, &$scopes, $scopeField, $orFields = [])
757
    {
758
759 5
        if (isset($scopes[$scopeField]) && is_string($scopes[$scopeField])) {
760
            $query->where(function ($query) use (&$scopes, $scopeField, $orFields) {
761 2
                foreach ($orFields as $field) {
762 2
                    $query->orWhere($field, $this->getLikeOperator(), '%' . $scopes[$scopeField] . '%');
763 2
                    unset($scopes[$field]);
764
                }
765 2
            });
766
        }
767 5
    }
768
769
    /**
770
     * @return bool
771
     */
772 2
    public function isUniqueFeature()
773
    {
774 2
        return false;
775
    }
776
777
    /**
778
     * @param array $ignore
779
     * @return void
780
     */
781
    public function addIgnoreFieldsBeforeSave($ignore = [])
782
    {
783
        $this->ignoreFieldsBeforeSave = is_array($ignore)
0 ignored issues
show
introduced by
The condition is_array($ignore) is always true.
Loading history...
784
        ? array_merge($this->ignoreFieldsBeforeSave, $ignore)
785
        : array_merge($this->ignoreFieldsBeforeSave, [$ignore]);
786
    }
787
788
    /**
789
     * @param string $ignore
790
     * @return bool
791
     */
792 28
    public function shouldIgnoreFieldBeforeSave($ignore)
793
    {
794 28
        return in_array($ignore, $this->ignoreFieldsBeforeSave);
795
    }
796
797
    /**
798
     * @return string[]
799
     */
800 28
    public function getReservedFields()
801
    {
802
        return [
803 28
            'medias',
804
            'browsers',
805
            'repeaters',
806
            'blocks',
807
        ];
808
    }
809
810
    /**
811
     * @param string $relation
812
     * @param \A17\Twill\Models\Model|null $model
813
     * @return mixed
814
     */
815
    protected function getModelRepository($relation, $model = null)
816
    {
817
        if (!$model) {
818
            $model = ucfirst(Str::singular($relation));
819
        }
820
821
        return App::make(Config::get('twill.namespace') . "\\Repositories\\" . ucfirst($model) . "Repository");
822
    }
823
824
    /**
825
     * @param string|null $method
826
     * @return array
827
     */
828 34
    protected function traitsMethods(string $method = null)
829
    {
830 34
        $method = $method ?? debug_backtrace()[1]['function'];
831
832 34
        $traits = array_values(class_uses_recursive(get_called_class()));
833
834 34
        $uniqueTraits = array_unique(array_map('class_basename', $traits));
835
836
        $methods = array_map(function (string $trait) use ($method) {
837 34
            return $method . $trait;
838 34
        }, $uniqueTraits);
839
840
        return array_filter($methods, function (string $method) {
841 34
            return method_exists(get_called_class(), $method);
842 34
        });
843
    }
844
845
    /**
846
     * @return string
847
     */
848 12
    private function getLikeOperator()
849
    {
850 12
        if (DB::connection()->getPDO()->getAttribute(PDO::ATTR_DRIVER_NAME) === 'pgsql') {
851
            return 'ILIKE';
852
        }
853
854 12
        return 'LIKE';
855
    }
856
857
    /**
858
     * @param string $method
859
     * @param array $parameters
860
     * @return mixed
861
     */
862 27
    public function __call($method, $parameters)
863
    {
864 27
        return $this->model->$method(...$parameters);
865
    }
866
867
    /**
868
     * @param string $behavior
869
     * @return boolean
870
     */
871 29
    public function hasBehavior($behavior)
872
    {
873 29
        $hasBehavior = classHasTrait($this, 'A17\Twill\Repositories\Behaviors\Handle' . ucfirst($behavior));
874
875 29
        if (Str::startsWith($behavior, 'translation')) {
876 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

876
            $hasBehavior = $hasBehavior && $this->/** @scrutinizer ignore-call */ getModel()->isTranslatable();
Loading history...
877
        }
878
879 29
        return $hasBehavior;
880
    }
881
882
    /**
883
     * @return boolean
884
     */
885 6
    public function isTranslatable($column)
886
    {
887 6
        return $this->getModel()->isTranslatable($column);
888
    }
889
}
890