Passed
Push — master ( 674c51...574e3e )
by Michael
02:41
created

CustomOrderTrait::isValidProperty()   A

Complexity

Conditions 4
Paths 5

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

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