Completed
Push — master ( d7fafd...7052bb )
by Arjay
01:48
created

EloquentDataTable::getEagerLoads()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 2
nc 1
nop 0
dl 0
loc 4
rs 10
c 0
b 0
f 0
1
<?php
2
3
namespace Yajra\DataTables;
4
5
use Illuminate\Database\Eloquent\Builder;
6
use Illuminate\Database\Eloquent\Relations\BelongsTo;
7
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
8
use Illuminate\Database\Eloquent\Relations\HasOneOrMany;
9
use Yajra\DataTables\Exceptions\Exception;
10
11
class EloquentDataTable extends QueryDataTable
12
{
13
    /**
14
     * @var \Illuminate\Database\Eloquent\Builder
15
     */
16
    protected $query;
17
18
    /**
19
     * EloquentEngine constructor.
20
     *
21
     * @param mixed $model
22
     */
23
    public function __construct($model)
24
    {
25
        $builder = $model instanceof Builder ? $model : $model->getQuery();
26
        parent::__construct($builder->getQuery());
27
28
        $this->query = $builder;
29
    }
30
31
    /**
32
     * If column name could not be resolved then use primary key.
33
     *
34
     * @return string
35
     */
36
    protected function getPrimaryKeyName()
37
    {
38
        return $this->query->getModel()->getKeyName();
39
    }
40
41
    /**
42
     * Compile query builder where clause depending on configurations.
43
     *
44
     * @param mixed  $query
45
     * @param string $columnName
46
     * @param string $keyword
47
     * @param string $boolean
48
     */
49
    protected function compileQuerySearch($query, $columnName, $keyword, $boolean = 'or')
50
    {
51
        $parts    = explode('.', $columnName);
52
        $column   = array_pop($parts);
53
        $relation = implode('.', $parts);
54
55
        if (!$relation || $relation === $this->query->getModel()->getTable()) {
56
            return parent::compileQuerySearch($query, $columnName, $keyword, $boolean);
57
        }
58
59
        $query->{$boolean . 'WhereHas'}($relation, function (Builder $query) use ($column, $keyword) {
60
            parent::compileQuerySearch($query, $column, $keyword, '');
61
        });
62
    }
63
64
    /**
65
     * Resolve the proper column name be used.
66
     *
67
     * @param string $column
68
     * @return string
69
     */
70
    protected function resolveRelationColumn($column)
71
    {
72
        $parts      = explode('.', $column);
73
        $columnName = array_pop($parts);
74
        $relation   = implode('.', $parts);
75
76
        if (!$relation || $relation === $this->query->getModel()->getTable()) {
77
            return $columnName;
78
        }
79
80
        return $this->joinEagerLoadedColumn($relation, $columnName);
81
    }
82
83
    /**
84
     * Join eager loaded relation and get the related column name.
85
     *
86
     * @param string $relation
87
     * @param string $relationColumn
88
     * @return string
89
     * @throws \Yajra\DataTables\Exceptions\Exception
90
     */
91
    protected function joinEagerLoadedColumn($relation, $relationColumn)
92
    {
93
        $table     = '';
94
        $lastQuery = $this->query;
95
        foreach (explode('.', $relation) as $eachRelation) {
96
            $model = $lastQuery->getRelation($eachRelation);
97
            switch (true) {
98
                case $model instanceof BelongsToMany:
99
                    $pivot   = $model->getTable();
100
                    $pivotPK = $model->getExistenceCompareKey();
101
                    $pivotFK = $model->getQualifiedParentKeyName();
102
                    $this->performJoin($pivot, $pivotPK, $pivotFK);
103
104
                    $related = $model->getRelated();
105
                    $table   = $related->getTable();
106
                    $tablePK = $related->getForeignKey();
107
                    $foreign = $pivot . '.' . $tablePK;
108
                    $other   = $related->getQualifiedKeyName();
109
110
                    $lastQuery->addSelect($table . '.' . $relationColumn);
111
                    $this->performJoin($table, $foreign, $other);
112
113
                    break;
114
115
                case $model instanceof HasOneOrMany:
116
                    $table   = $model->getRelated()->getTable();
117
                    $foreign = $model->getQualifiedForeignKeyName();
118
                    $other   = $model->getQualifiedParentKeyName();
119
                    break;
120
121
                case $model instanceof BelongsTo:
122
                    $table   = $model->getRelated()->getTable();
123
                    $foreign = $model->getQualifiedForeignKey();
124
                    $other   = $model->getQualifiedOwnerKeyName();
125
                    break;
126
127
                default:
128
                    throw new Exception('Relation ' . get_class($model) . ' is not yet supported.');
129
            }
130
            $this->performJoin($table, $foreign, $other);
131
            $lastQuery = $model->getQuery();
132
        }
133
134
        return $table . '.' . $relationColumn;
135
    }
136
137
    /**
138
     * Perform join query.
139
     *
140
     * @param string $table
141
     * @param string $foreign
142
     * @param string $other
143
     * @param string $type
144
     */
145
    protected function performJoin($table, $foreign, $other, $type = 'left')
146
    {
147
        $joins = [];
148
        foreach ((array) $this->getBaseQueryBuilder()->joins as $key => $join) {
149
            $joins[] = $join->table;
150
        }
151
152
        if (!in_array($table, $joins)) {
153
            $this->getBaseQueryBuilder()->join($table, $foreign, '=', $other, $type);
154
        }
155
    }
156
}
157