Passed
Push — master ( ae720b...07d247 )
by Michael
02:20
created

CustomOrderTrait::joinRelatedTable()   A

Complexity

Conditions 3
Paths 2

Size

Total Lines 10
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 3
eloc 5
nc 2
nop 2
dl 0
loc 10
rs 9.4285
c 0
b 0
f 0
1
<?php
2
3
namespace Blasttech\EloquentRelatedPlus;
4
5
use Illuminate\Database\Eloquent\Builder;
6
use InvalidArgumentException;
7
8
/**
9
 * Trait CustomOrderTrait
10
 *
11
 * @property array attributes
12
 * @property array order_fields
13
 * @property array order_defaults
14
 * @property array order_relations
15
 * @property array order_with
16
 * @property array search_fields
17
 * @property string connection
18
 */
19
trait CustomOrderTrait
20
{
21
    /**
22
     * Check $order_fields and $order_defaults are set
23
     *
24
     * @param string $orderField
25
     * @param string $direction
26
     * @return bool
27
     */
28
    protected function hasOrderFieldsAndDefaults($orderField, $direction)
29
    {
30
        return $this->hasOrderFields() && $this->hasOrderDefaults($orderField, $direction);
31
    }
32
33
    /**
34
     * Check $this->order_fields set correctly
35
     *
36
     * @return bool
37
     */
38
    protected function hasOrderFields()
39
    {
40
        return $this->hasProperty('order_fields');
41
    }
42
43
    /**
44
     * @param string $attributeName
45
     * @param bool $canBeEmpty
46
     * @return bool
47
     */
48
    protected function hasProperty($attributeName, $canBeEmpty = true)
49
    {
50
        if (!isset($this->$attributeName) || !is_array($this->$attributeName) ||
51
            (!$canBeEmpty && empty($this->$attributeName))) {
52
            throw new InvalidArgumentException(
53
                get_class($this) . ' ' . $attributeName . ' property not set correctly.'
54
            );
55
        }
56
57
        return true;
58
    }
59
60
    /**
61
     * Check order defaults set correctly
62
     *
63
     * @param string $orderField
64
     * @param string $direction
65
     * @return bool
66
     */
67
    protected function hasOrderDefaults($orderField, $direction)
68
    {
69
        if ($orderField === '' || $direction === '') {
70
            return $this->hasProperty('order_defaults');
71
        }
72
73
        return true;
74
    }
75
76
    /**
77
     * Check $this->search_fields set correctly
78
     *
79
     * @return bool
80
     */
81
    protected function hasSearchFields()
82
    {
83
        return $this->hasProperty('search_fields', false);
84
    }
85
86
    /**
87
     * Override column if provided column not valid. If $column not in order_fields list, use default.
88
     *
89
     * @param string $column
90
     * @return string
91
     */
92
    protected function setOrderColumn($column)
93
    {
94
        if ($column == '' || !isset($this->order_fields[$column])) {
95
            $column = $this->order_defaults['field'];
96
        }
97
98
        return $column;
99
    }
100
101
    /**
102
     * Override direction if provided direction not valid. If $direction not asc or desc, use default.
103
     *
104
     * @param string $direction
105
     * @return string
106
     */
107
    protected function setOrderDirection($direction)
108
    {
109
        if ($direction == '' || !in_array(strtoupper($direction), ['ASC', 'DESC'])) {
110
            $direction = $this->order_defaults['dir'];
111
        }
112
113
        return $direction;
114
    }
115
116
    /**
117
     * Set order based on order_fields
118
     *
119
     * @param Builder $query
120
     * @param string $column
121
     * @param string $direction
122
     * @return Builder
123
     */
124
    protected function setOrder($query, $column, $direction)
125
    {
126
        if (is_array($this->order_fields[$column])) {
127
            return $this->setOrders($query, $column, $direction);
128
        }
129
130
        return $query->orderByCheckModel($this->order_fields[$column], $direction);
131
    }
132
133
    /**
134
     * Set order based on multiple order_fields
135
     *
136
     * @param Builder $query
137
     * @param string $column
138
     * @param string $direction
139
     * @return Builder
140
     */
141
    protected function setOrders($query, $column, $direction)
142
    {
143
        foreach ($this->order_fields[$column] as $dbField) {
144
            $query->orderByCheckModel($dbField, $direction);
145
        }
146
147
        return $query;
148
    }
149
150
    /**
151
     * Join a related table if not already joined
152
     *
153
     * @param Builder $query
154
     * @param string $table
155
     * @return Builder
156
     */
157
    protected function joinRelatedTable($query, $table)
158
    {
159
        if (isset($this->order_relations[$table]) &&
160
            !$this->hasJoin($query, $table, $this->order_relations[$table])) {
161
            $columnRelations = $this->order_relations[$table];
162
163
            $query->modelJoin($columnRelations, '=', 'left', false, false);
164
        }
165
166
        return $query;
167
    }
168
169
    /**
170
     * Check if this model has already been joined to a table or relation
171
     *
172
     * @param Builder $builder
173
     * @param string $table
174
     * @param \Illuminate\Database\Eloquent\Relations\Relation $relation
175
     * @return bool
176
     */
177
    protected function hasJoin(Builder $builder, $table, $relation)
178
    {
179
        if (!$this->isJoinedToTable($builder, $table)) {
180
            return $this->isEagerLoaded($builder, $relation);
181
        }
182
183
        return true;
184
    }
185
186
    /**
187
     * Check if model is currently joined to $table
188
     *
189
     * @param Builder $builder
190
     * @param string $table
191
     * @return bool
192
     */
193
    protected function isJoinedToTable(Builder $builder, $table)
194
    {
195
        $joins = $builder->getQuery()->joins;
196
        if (!empty($joins)) {
197
            foreach ($joins as $joinClause) {
198
                if ($joinClause->table == $table) {
199
                    return true;
200
                }
201
            }
202
        }
203
204
        return false;
205
    }
206
207
    /**
208
     * Check if relation exists in eager loads
209
     *
210
     * @param Builder $builder
211
     * @param \Illuminate\Database\Eloquent\Relations\Relation $relation
212
     * @return bool
213
     */
214
    protected function isEagerLoaded(Builder $builder, $relation)
215
    {
216
        $eagerLoads = $builder->getEagerLoads();
217
218
        return !is_null($eagerLoads) && in_array($relation, $eagerLoads);
219
    }
220
221
    /**
222
     * Execute a scope in the order_width settings
223
     *
224
     * @param Builder $query
225
     * @param string $order
226
     * @return Builder
227
     */
228
    protected function addOrderWith(Builder $query, $order)
229
    {
230
        $with = 'with' . $this->order_with[$order];
231
232
        return $query->$with();
233
    }
234
235
    /**
236
     * Add join from order_fields
237
     *
238
     * @param Builder $query
239
     * @param string $order
240
     * @return Builder
241
     */
242
    protected function addOrderJoin(Builder $query, $order)
243
    {
244
        $orderOption = (explode('.', $this->order_fields[$order]))[0];
245
246
        if (isset($this->order_relations[$orderOption])) {
247
            $query->modelJoin(
248
                $this->order_relations[$orderOption],
249
                '=',
250
                'left',
251
                false,
252
                false
253
            );
254
        }
255
256
        return $query;
257
    }
258
}
259