Passed
Push — master ( 73ce07...16e866 )
by Michael
04:10
created

Sorts::setDefaultSort()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 3
c 1
b 0
f 0
nc 1
nop 2
dl 0
loc 6
rs 10
1
<?php
2
3
namespace Mblarsen\LaravelRepository\Traits;
4
5
use Exception;
6
use Illuminate\Database\Eloquent\Relations\BelongsTo;
7
use Illuminate\Database\Eloquent\Relations\HasOneOrMany;
8
use Illuminate\Database\Eloquent\Relations\MorphOneOrMany;
9
use Illuminate\Database\Eloquent\Relations\Relation;
10
11
trait Sorts
12
{
13
    public function setDefaultSort(string $by, string $order = 'asc')
14
    {
15
        $this->default_sort_by = $by;
0 ignored issues
show
Bug Best Practice introduced by
The property default_sort_by does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
16
        $this->default_sort_order = $order;
0 ignored issues
show
Bug Best Practice introduced by
The property default_sort_order does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
17
18
        return $this;
19
    }
20
21
    private function applySort($query)
22
    {
23
        [$by, $order] = $this->resource_context->sortBy();
24
25
        $by = $by ?: $this->default_sort_by;
26
        $order = $order ?: $this->default_sort_order;
27
28
        if (!$by) {
29
            return $this;
30
        }
31
32
        if (strpos($by, '.') === false) {
33
            $query->orderBy($by, $order);
34
        } else {
35
            $this->applyRelationSort($query, $by, $order);
36
        }
37
38
        return $this;
39
    }
40
41
    private function applyRelationSort($query, $by, $order)
42
    {
43
        /** @var Model */
44
        $model = new $this->model();
45
46
        [$relation_name, $by] = explode('.', $by);
47
48
        $relation = $model->$relation_name();
49
50
        [$model_key, $relation_key, $morph_class] = $this->getJoinKeys(
51
            $relation,
52
        );
53
54
        $related = $relation->getRelated();
55
        $query->orderBy(
56
            $related
57
                ::select($by)
58
                ->whereColumn($relation_key, $model_key)
59
                ->when($morph_class, function ($query) use ($morph_class) {
60
                    $query->where($morph_class, $this->model);
61
                })
62
                ->limit(1),
63
            $order,
64
        );
65
    }
66
67
    private function getJoinKeys(Relation $relation): array
68
    {
69
        if ($relation instanceof BelongsTo) {
70
            return [
71
                $relation->getQualifiedForeignKeyName(),
72
                $relation->getQualifiedOwnerKeyName(),
73
                null,
74
            ];
75
        }
76
        if ($relation instanceof MorphOneOrMany) {
77
            return [
78
                $relation->getQualifiedParentKeyName(),
79
                $relation->getQualifiedForeignKeyName(),
80
                $relation->getMorphType(),
81
            ];
82
        }
83
        if ($relation instanceof HasOneOrMany) {
84
            return [
85
                $relation->getQualifiedParentKeyName(),
86
                $relation->getQualifiedForeignKeyName(),
87
                null,
88
            ];
89
        }
90
        throw new Exception(
91
            'Relation type ' . class_basename($relation) . ' is not supported',
92
        );
93
    }
94
}
95