1 | <?php |
||||
2 | |||||
3 | namespace SleepingOwl\Admin\Display\Column; |
||||
4 | |||||
5 | use Illuminate\Database\Eloquent\Builder; |
||||
6 | use Illuminate\Database\Eloquent\Model; |
||||
7 | use Illuminate\Database\Eloquent\Relations\BelongsTo; |
||||
8 | use Illuminate\Database\Eloquent\Relations\HasOneOrMany; |
||||
9 | use Illuminate\Database\Eloquent\Relations\Relation; |
||||
10 | use Illuminate\Support\Collection; |
||||
11 | use Illuminate\Support\Facades\DB; |
||||
12 | use Illuminate\Support\Str; |
||||
13 | use Mockery\Matcher\Closure; |
||||
14 | use SleepingOwl\Admin\Contracts\Display\OrderByClauseInterface; |
||||
15 | |||||
16 | class OrderByClause implements OrderByClauseInterface |
||||
17 | { |
||||
18 | /** |
||||
19 | * @var string|\Closure |
||||
20 | */ |
||||
21 | protected $name; |
||||
22 | |||||
23 | /** |
||||
24 | * @var string|null |
||||
25 | */ |
||||
26 | protected $sortedColumnAlias = null; |
||||
27 | 17 | ||||
28 | /** |
||||
29 | 17 | * OrderByClause constructor. |
|||
30 | 17 | * |
|||
31 | * @param string|Closure $name |
||||
32 | */ |
||||
33 | public function __construct($name) |
||||
34 | { |
||||
35 | $this->setName($name); |
||||
36 | } |
||||
37 | |||||
38 | /** |
||||
39 | * @param Builder $query |
||||
40 | * @param string $direction |
||||
41 | */ |
||||
42 | public function modifyQuery(Builder $query, $direction = 'asc') |
||||
43 | { |
||||
44 | $this->name instanceof \Closure |
||||
45 | ? $this->callCallable($query, $direction) |
||||
46 | : $this->callDefaultClause($query, $direction); |
||||
47 | } |
||||
48 | 17 | ||||
49 | /** |
||||
50 | 17 | * @param string|\Closure $name |
|||
51 | * |
||||
52 | 17 | * @return $this |
|||
53 | */ |
||||
54 | public function setName($name) |
||||
55 | { |
||||
56 | $this->name = $name; |
||||
57 | |||||
58 | return $this; |
||||
59 | } |
||||
60 | |||||
61 | /** |
||||
62 | * @param Builder $query |
||||
63 | * @param string $direction |
||||
64 | */ |
||||
65 | protected function callCallable(Builder $query, $direction) |
||||
66 | { |
||||
67 | call_user_func_array($this->name, [$query, $direction]); |
||||
68 | } |
||||
69 | |||||
70 | /** |
||||
71 | * @param Builder $query |
||||
72 | * @param string $direction |
||||
73 | */ |
||||
74 | protected function callDefaultClause(Builder $query, $direction) |
||||
75 | { |
||||
76 | if ($this->isRelationName($this->name)) { |
||||
77 | $this->loadRelationOrder($query, $direction); |
||||
78 | } else { |
||||
79 | $query->orderBy($this->name, $direction); |
||||
80 | } |
||||
81 | } |
||||
82 | |||||
83 | /** |
||||
84 | * @param $name |
||||
85 | * @return bool |
||||
86 | */ |
||||
87 | protected function isRelationName($name) |
||||
88 | { |
||||
89 | return Str::contains($name, '.'); |
||||
90 | } |
||||
91 | |||||
92 | /** |
||||
93 | * Make EagerLoad. |
||||
94 | */ |
||||
95 | protected function eagerLoad() |
||||
96 | { |
||||
97 | } |
||||
98 | |||||
99 | /** |
||||
100 | * Load Relations by this->name. |
||||
101 | * @param Builder $query |
||||
102 | * @param $direction |
||||
103 | */ |
||||
104 | protected function loadRelationOrder(Builder $query, $direction) |
||||
105 | { |
||||
106 | /** @var Relation $relationClass */ |
||||
107 | $relations = collect(explode('.', $this->name)); |
||||
0 ignored issues
–
show
Bug
introduced
by
![]() |
|||||
108 | $loop = 0; |
||||
109 | if ($relations->count() >= 2) { |
||||
110 | $query->select($query->getModel()->getTable().'.*'); |
||||
111 | |||||
112 | do { |
||||
113 | $model = ! $loop++ ? $query->getModel() : $relationClass->getModel(); |
||||
0 ignored issues
–
show
Comprehensibility
Best Practice
introduced
by
|
|||||
114 | $relation = $relations->shift(); |
||||
115 | |||||
116 | if (method_exists($model, $relation)) { |
||||
117 | $relationClass = $model->{$relation}(); |
||||
118 | $relationModel = $relationClass->getRelated(); |
||||
119 | |||||
120 | $loadRelationMethod = implode('', ['load', class_basename(get_class($relationClass))]); |
||||
121 | call_user_func([$this, $loadRelationMethod], |
||||
122 | $relations, $relationClass, $relationModel, $model, $query, $direction); |
||||
123 | } else { |
||||
124 | break; |
||||
125 | } |
||||
126 | } while (true); |
||||
127 | |||||
128 | if ($this->sortedColumnAlias) { |
||||
129 | $query->orderBy(DB::raw($this->sortedColumnAlias), $direction); |
||||
130 | } |
||||
131 | } |
||||
132 | } |
||||
133 | |||||
134 | /** |
||||
135 | * Load HasOneOrMany keys. |
||||
136 | * @param Collection $relations |
||||
137 | * @param HasOneOrMany $relationClass |
||||
138 | * @param Model $relationModel |
||||
139 | * @param Model $model |
||||
140 | * @param Builder $query |
||||
141 | * @param $direction |
||||
142 | */ |
||||
143 | protected function loadHasOne( |
||||
144 | Collection $relations, |
||||
145 | HasOneOrMany $relationClass, |
||||
146 | Model $relationModel, |
||||
147 | Model $model, |
||||
148 | Builder $query, |
||||
149 | $direction |
||||
150 | ) { |
||||
151 | $this->loadHasOneOrMany($relations, $relationClass, $relationModel, $model, $query, $direction); |
||||
152 | } |
||||
153 | |||||
154 | /** |
||||
155 | * Load HasMany keys. |
||||
156 | * @param Collection $relations |
||||
157 | * @param HasOneOrMany $relationClass |
||||
158 | * @param Model $relationModel |
||||
159 | * @param Model $model |
||||
160 | * @param Builder $query |
||||
161 | * @param $direction |
||||
162 | */ |
||||
163 | protected function loadHasMany( |
||||
164 | Collection $relations, |
||||
165 | HasOneOrMany $relationClass, |
||||
166 | Model $relationModel, |
||||
167 | Model $model, |
||||
168 | Builder $query, |
||||
169 | $direction |
||||
170 | ) { |
||||
171 | $this->loadHasOneOrMany($relations, $relationClass, $relationModel, $model, $query, $direction); |
||||
172 | } |
||||
173 | |||||
174 | /** |
||||
175 | * Load HasOneOrMany keys. |
||||
176 | * @param Collection $relations |
||||
177 | * @param HasOneOrMany $relationClass |
||||
178 | * @param Model $relationModel |
||||
179 | * @param Model $model |
||||
180 | * @param Builder $query |
||||
181 | * @param $direction |
||||
182 | */ |
||||
183 | protected function loadHasOneOrMany( |
||||
184 | Collection $relations, |
||||
185 | HasOneOrMany $relationClass, |
||||
186 | Model $relationModel, |
||||
187 | Model $model, |
||||
188 | Builder $query, |
||||
189 | $direction |
||||
190 | ) { |
||||
191 | $ownerTable = $model->getTable(); |
||||
0 ignored issues
–
show
|
|||||
192 | $foreignTable = $relationModel->getTable(); |
||||
193 | |||||
194 | $ownerColumn = $relationClass->getQualifiedForeignKeyName(); |
||||
195 | $foreignColumn = $relationClass->getQualifiedParentKeyName(); |
||||
196 | $sortedColumnRaw = '`'.$foreignTable.'`.`'.$relations->last().'`'; |
||||
197 | $sortedColumnAlias = implode('__', [$foreignTable, $relations->last()]); |
||||
198 | |||||
199 | $this->sortedColumnAlias = $sortedColumnAlias; |
||||
200 | |||||
201 | $query |
||||
202 | ->addSelect([DB::raw($sortedColumnRaw.' AS '.$sortedColumnAlias)]) |
||||
203 | ->join($foreignTable, $foreignColumn, '=', $ownerColumn, 'left'); |
||||
204 | } |
||||
205 | |||||
206 | /** |
||||
207 | * Load keys for BelongsTo. |
||||
208 | * @param Collection $relations |
||||
209 | * @param BelongsTo $relationClass |
||||
210 | * @param Model $relationModel |
||||
211 | * @param Model $model |
||||
212 | * @param Builder $query |
||||
213 | */ |
||||
214 | protected function loadBelongsTo( |
||||
215 | Collection $relations, |
||||
216 | BelongsTo $relationClass, |
||||
217 | Model $relationModel, |
||||
218 | Model $model, |
||||
219 | Builder $query |
||||
220 | ) { |
||||
221 | if (version_compare(app()->version(), '5.8.0', 'gt')) { |
||||
0 ignored issues
–
show
The method
version() does not exist on Illuminate\Container\Container . Are you sure you never get this type here, but always one of the subclasses?
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||
222 | $foreignKey = $relationClass->getOwnerKeyName(); |
||||
223 | $ownerKey = $relationClass->getForeignKeyName(); |
||||
224 | } else { |
||||
225 | $foreignKey = $relationClass->getOwnerKey(); |
||||
226 | $ownerKey = $relationClass->getForeignKey(); |
||||
227 | } |
||||
228 | |||||
229 | $ownerTable = $model->getTable(); |
||||
230 | $foreignTable = $relationModel->getTable(); |
||||
231 | |||||
232 | $ownerColumn = implode('.', [$ownerTable, $ownerKey]); |
||||
233 | $foreignColumn = implode('.', [$foreignTable, $foreignKey]); |
||||
234 | $sortedColumnRaw = '`'.$foreignTable.'`.`'.$relations->last().'`'; |
||||
235 | $sortedColumnAlias = implode('__', [$foreignTable, $relations->last()]); |
||||
236 | |||||
237 | $this->sortedColumnAlias = $sortedColumnAlias; |
||||
238 | |||||
239 | $query |
||||
240 | ->addSelect([DB::raw($sortedColumnRaw.' AS '.$sortedColumnAlias)]) |
||||
241 | ->join($foreignTable, $foreignColumn, '=', $ownerColumn, 'left'); |
||||
242 | } |
||||
243 | } |
||||
244 |