Completed
Push — master ( e1d713...d0f693 )
by Arjay
02:05
created

EloquentDataTable::compileQuerySearch()   A

Complexity

Conditions 4
Paths 3

Size

Total Lines 19
Code Lines 11

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 4
eloc 11
nc 3
nop 4
dl 0
loc 19
rs 9.2
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
        $sql = "{$column} LIKE ?";
60
        if ($this->config->isCaseInsensitive()) {
61
            $sql = 'LOWER(' . $column . ') LIKE ?';
62
        }
63
64
        $query->orWhereHas($relation, function (Builder $query) use ($sql, $keyword) {
65
            $query->whereRaw($sql, [$this->prepareKeyword($keyword)]);
66
        });
67
    }
68
69
    /**
70
     * Resolve the proper column name be used.
71
     *
72
     * @param string $column
73
     * @return string
74
     */
75
    protected function resolveRelationColumn($column)
76
    {
77
        $parts      = explode('.', $column);
78
        $columnName = array_pop($parts);
79
        $relation   = implode('.', $parts);
80
81
        if (!$relation || $relation === $this->query->getModel()->getTable()) {
82
            return $columnName;
83
        }
84
85
        $parts          = explode('.', $column);
86
        $relationColumn = array_pop($parts);
87
        $relation       = implode('.', $parts);
88
89
        return $this->joinEagerLoadedColumn($relation, $relationColumn);
90
    }
91
92
    /**
93
     * Get eager loads keys if eloquent.
94
     *
95
     * @return array
96
     */
97
    protected function getEagerLoads()
98
    {
99
        return array_keys($this->query->getEagerLoads());
100
    }
101
102
    /**
103
     * Join eager loaded relation and get the related column name.
104
     *
105
     * @param string $relation
106
     * @param string $relationColumn
107
     * @return string
108
     * @throws \Yajra\DataTables\Exceptions\Exception
109
     */
110
    protected function joinEagerLoadedColumn($relation, $relationColumn)
111
    {
112
        $table     = '';
113
        $lastQuery = $this->query;
114
        foreach (explode('.', $relation) as $eachRelation) {
115
            $model = $lastQuery->getRelation($eachRelation);
116
            switch (true) {
117
                case $model instanceof BelongsToMany:
118
                    $pivot   = $model->getTable();
119
                    $pivotPK = $model->getExistenceCompareKey();
120
                    $pivotFK = $model->getQualifiedParentKeyName();
121
                    $this->performJoin($pivot, $pivotPK, $pivotFK);
122
123
                    $related = $model->getRelated();
124
                    $table   = $related->getTable();
125
                    $tablePK = $related->getForeignKey();
126
                    $foreign = $pivot . '.' . $tablePK;
127
                    $other   = $related->getQualifiedKeyName();
128
129
                    $lastQuery->addSelect($table . '.' . $relationColumn);
130
                    $this->performJoin($table, $foreign, $other);
131
132
                    break;
133
134
                case $model instanceof HasOneOrMany:
135
                    $table   = $model->getRelated()->getTable();
136
                    $foreign = $model->getQualifiedForeignKeyName();
137
                    $other   = $model->getQualifiedParentKeyName();
138
                    break;
139
140
                case $model instanceof BelongsTo:
141
                    $table   = $model->getRelated()->getTable();
142
                    $foreign = $model->getQualifiedForeignKey();
143
                    $other   = $model->getQualifiedOwnerKeyName();
144
                    break;
145
146
                default:
147
                    throw new Exception('Relation ' . get_class($model) . ' is not yet supported.');
148
            }
149
            $this->performJoin($table, $foreign, $other);
150
            $lastQuery = $model->getQuery();
151
        }
152
153
        return $table . '.' . $relationColumn;
154
    }
155
156
    /**
157
     * Perform join query.
158
     *
159
     * @param string $table
160
     * @param string $foreign
161
     * @param string $other
162
     * @param string $type
163
     */
164
    protected function performJoin($table, $foreign, $other, $type = 'left')
165
    {
166
        $joins = [];
167
        foreach ((array) $this->getBaseQueryBuilder()->joins as $key => $join) {
168
            $joins[] = $join->table;
169
        }
170
171
        if (!in_array($table, $joins)) {
172
            $this->getBaseQueryBuilder()->join($table, $foreign, '=', $other, $type);
173
        }
174
    }
175
}
176