Sorts::setDefaultSort()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 6
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 4
CRAP Score 1

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
ccs 4
cts 4
cp 1
crap 1
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
    /** @var string $default_sort_by */
14
    protected $default_sort_by;
15
16
    /** @var string $default_sort_order */
17
    protected $default_sort_order = 'asc';
18
19 2
    public function setDefaultSort(string $by, string $order = 'asc')
20
    {
21 2
        $this->default_sort_by = $by;
22 2
        $this->default_sort_order = $order;
23
24 2
        return $this;
25
    }
26
27 36
    private function applySort($query)
28
    {
29 36
        [$by, $order] = $this->resource_context->sortBy();
30
31 36
        $by = $by ?: $this->default_sort_by;
32 36
        $order = $order ?: $this->default_sort_order;
33
34 36
        if (!$by) {
35 22
            return $this;
36
        }
37
38 14
        if (strpos($by, '.') === false) {
39 10
            $query->orderBy($by, $order);
40
        } else {
41 4
            $this->applyRelationSort($query, $by, $order);
42
        }
43
44 13
        return $this;
45
    }
46
47 4
    private function applyRelationSort($query, $by, $order)
48
    {
49
        /** @var Model */
50 4
        $model = new $this->model();
51
52 4
        [$relation_name, $by] = explode('.', $by);
53
54 4
        $relation = $model->$relation_name();
55
56 4
        [$model_key, $relation_key, $morph_class] = $this->getJoinKeys(
57 4
            $relation,
58
        );
59
60 3
        $related = $relation->getRelated();
61 3
        $query->orderBy(
62 3
            $related
63 3
                ::select($by)
64 3
                ->whereColumn($relation_key, $model_key)
65
                ->when($morph_class, function ($query) use ($morph_class) {
66 1
                    $query->where($morph_class, $this->model);
67 3
                })
68 3
                ->limit(1),
69
            $order,
70
        );
71 3
    }
72
73 4
    private function getJoinKeys(Relation $relation): array
74
    {
75 4
        if ($relation instanceof BelongsTo) {
76
            return [
77 1
                $relation->getQualifiedForeignKeyName(),
78 1
                $relation->getQualifiedOwnerKeyName(),
79
                null,
80
            ];
81
        }
82 3
        if ($relation instanceof MorphOneOrMany) {
83
            return [
84 1
                $relation->getQualifiedParentKeyName(),
85 1
                $relation->getQualifiedForeignKeyName(),
86 1
                $relation->getMorphType(),
87
            ];
88
        }
89 2
        if ($relation instanceof HasOneOrMany) {
90
            return [
91 1
                $relation->getQualifiedParentKeyName(),
92 1
                $relation->getQualifiedForeignKeyName(),
93
                null,
94
            ];
95
        }
96 1
        throw new Exception(
97 1
            'Relation type ' . class_basename($relation) . ' is not supported',
98
        );
99
    }
100
}
101