1 | <?php |
||||
2 | |||||
3 | namespace SleepingOwl\Admin\Display; |
||||
4 | |||||
5 | use Illuminate\Database\Eloquent\Builder; |
||||
6 | use Illuminate\Routing\Router; |
||||
7 | use Illuminate\Support\Collection; |
||||
8 | use Illuminate\Support\Facades\Request; |
||||
9 | use SleepingOwl\Admin\Contracts\Display\ColumnInterface; |
||||
10 | use SleepingOwl\Admin\Contracts\Display\ColumnMetaInterface; |
||||
11 | use SleepingOwl\Admin\Contracts\WithRoutesInterface; |
||||
12 | use SleepingOwl\Admin\Display\Column\Control; |
||||
13 | |||||
14 | class DisplayDatatablesAsync extends DisplayDatatables implements WithRoutesInterface |
||||
15 | { |
||||
16 | protected $rowClassCallback; |
||||
17 | |||||
18 | /** |
||||
19 | * Register display routes. |
||||
20 | * |
||||
21 | * @param Router $router |
||||
22 | * |
||||
23 | * @throws \Symfony\Component\HttpKernel\Exception\NotFoundHttpException |
||||
24 | */ |
||||
25 | public static function registerRoutes(Router $router) |
||||
26 | 285 | { |
|||
27 | $routeName = 'admin.display.async'; |
||||
28 | 285 | if (! $router->has($routeName)) { |
|||
29 | 285 | $router->get('{adminModel}/async/{adminDisplayName?}', [ |
|||
30 | 285 | 'as' => $routeName, |
|||
31 | 285 | 'uses' => 'SleepingOwl\Admin\Http\Controllers\DisplayController@async', |
|||
0 ignored issues
–
show
|
|||||
32 | 285 | ]); |
|||
33 | 285 | } |
|||
34 | 285 | ||||
35 | $routeName = 'admin.display.async.inlineEdit'; |
||||
36 | 285 | if (! $router->has($routeName)) { |
|||
37 | 285 | $router->post('{adminModel}/async/{adminDisplayName?}', [ |
|||
38 | 285 | 'as' => $routeName, |
|||
39 | 285 | 'uses' => 'SleepingOwl\Admin\Http\Controllers\AdminController@inlineEdit', |
|||
0 ignored issues
–
show
The controller
App\Http\Controllers\Sle...rollers\AdminController does not seem to exist.
If there is a route defined but the controller class cannot be found there are two options: 1. the controller class needs to be implemented or 2. the route is outdated and can be removed. If ?FooController? was found and ?BarController? is missing for the following example, either the controller should be implemented or the route should be removed: $app->group(['as' => 'foo', 'prefix' => 'foo', 'namespace' => 'Foo'], function($app) {
$app->group(['as' => 'foo', 'prefix' => 'foo'], function($app) {
$app->get('/all/{from}/{to}', ['as' => 'all', 'uses' => 'FooController@getFoo']);
$app->get('/all/{from}/{to}', ['as' => 'all', 'uses' => 'BarController@getBar']);
});
});
![]() |
|||||
40 | 285 | ]); |
|||
41 | 285 | } |
|||
42 | 285 | } |
|||
43 | 285 | ||||
44 | protected $payload; |
||||
45 | /** |
||||
46 | * @var string |
||||
47 | */ |
||||
48 | protected $name; |
||||
49 | |||||
50 | /** |
||||
51 | * @param string|null $name |
||||
52 | */ |
||||
53 | protected $distinct; |
||||
54 | |||||
55 | /** |
||||
56 | * @var |
||||
57 | */ |
||||
58 | protected $displaySearch = false; |
||||
59 | |||||
60 | /** |
||||
61 | * @var |
||||
62 | */ |
||||
63 | protected $displayLength = false; |
||||
64 | |||||
65 | /** |
||||
66 | * DisplayDatatablesAsync constructor. |
||||
67 | * |
||||
68 | * @param string|null $name |
||||
69 | * @param string|null $distinct |
||||
70 | */ |
||||
71 | public function __construct($name = null, $distinct = null) |
||||
72 | { |
||||
73 | parent::__construct(); |
||||
74 | |||||
75 | $this->setName($name); |
||||
76 | $this->setDistinct($distinct); |
||||
77 | |||||
78 | $this->getColumns()->setView('display.extensions.columns_async'); |
||||
79 | } |
||||
80 | |||||
81 | /** |
||||
82 | * Initialize display. |
||||
83 | */ |
||||
84 | public function initialize() |
||||
85 | { |
||||
86 | parent::initialize(); |
||||
87 | |||||
88 | $attributes = Request::all(); |
||||
89 | array_unshift($attributes, $this->getName()); |
||||
90 | array_unshift($attributes, $this->getModelConfiguration()->getAlias()); |
||||
91 | |||||
92 | $this->setHtmlAttribute('style', 'width:100%'); |
||||
93 | $this->setHtmlAttribute('data-url', route('admin.display.async', $attributes)); |
||||
94 | $this->setHtmlAttribute('data-payload', json_encode($this->payload)); |
||||
95 | |||||
96 | if ($this->getDisplaySearch()) { |
||||
97 | $this->setHtmlAttribute('data-display-search', 1); |
||||
98 | } |
||||
99 | |||||
100 | if ($this->getDisplayLength()) { |
||||
101 | $this->setHtmlAttribute('data-display-dtlength', 1); |
||||
102 | } |
||||
103 | } |
||||
104 | |||||
105 | /** |
||||
106 | * @param bool $length |
||||
107 | * @return $this |
||||
108 | */ |
||||
109 | public function setDisplayLength($length) |
||||
110 | { |
||||
111 | $this->displayLength = $length; |
||||
112 | |||||
113 | return $this; |
||||
114 | } |
||||
115 | |||||
116 | /** |
||||
117 | * @return bool |
||||
118 | */ |
||||
119 | public function getDisplayLength() |
||||
120 | { |
||||
121 | return $this->displayLength; |
||||
122 | } |
||||
123 | |||||
124 | /** |
||||
125 | * @param $search |
||||
126 | * @return $this |
||||
127 | */ |
||||
128 | public function setDisplaySearch($search) |
||||
129 | { |
||||
130 | $this->displaySearch = $search; |
||||
131 | |||||
132 | return $this; |
||||
133 | } |
||||
134 | |||||
135 | /** |
||||
136 | * @return bool |
||||
137 | */ |
||||
138 | public function getDisplaySearch() |
||||
139 | { |
||||
140 | return $this->displaySearch; |
||||
141 | } |
||||
142 | |||||
143 | /** |
||||
144 | * @return string |
||||
145 | */ |
||||
146 | public function getName() |
||||
147 | { |
||||
148 | return $this->name; |
||||
149 | } |
||||
150 | |||||
151 | /** |
||||
152 | * @param string $name |
||||
153 | * |
||||
154 | * @return $this |
||||
155 | */ |
||||
156 | public function setName($name) |
||||
157 | { |
||||
158 | $this->name = $name; |
||||
159 | |||||
160 | return $this; |
||||
161 | } |
||||
162 | |||||
163 | /** |
||||
164 | * @return mixed |
||||
165 | */ |
||||
166 | public function getDistinct() |
||||
167 | { |
||||
168 | return $this->distinct; |
||||
169 | } |
||||
170 | |||||
171 | /** |
||||
172 | * @param mixed $distinct |
||||
173 | * |
||||
174 | * @return $this |
||||
175 | */ |
||||
176 | public function setDistinct($distinct) |
||||
177 | { |
||||
178 | $this->distinct = $distinct; |
||||
179 | |||||
180 | return $this; |
||||
181 | } |
||||
182 | |||||
183 | /** |
||||
184 | * Render async request. |
||||
185 | * |
||||
186 | * @param \Illuminate\Http\Request $request |
||||
187 | * |
||||
188 | * @return array |
||||
189 | */ |
||||
190 | public function renderAsync(\Illuminate\Http\Request $request) |
||||
191 | { |
||||
192 | $query = $this->getRepository()->getQuery(); |
||||
193 | $totalCount = $query->count(); |
||||
194 | $filteredCount = 0; |
||||
195 | |||||
196 | if (! is_null($this->distinct)) { |
||||
197 | $filteredCount = $query->distinct()->count($this->getDistinct()); |
||||
198 | } |
||||
199 | |||||
200 | $this->modifyQuery($query); |
||||
201 | $this->applySearch($query, $request); |
||||
202 | |||||
203 | if (is_null($this->distinct)) { |
||||
204 | $countQuery = clone $query; |
||||
205 | $countQuery->getQuery()->orders = null; |
||||
206 | $filteredCount = $countQuery->count(); |
||||
207 | } |
||||
208 | |||||
209 | $this->applyOffset($query, $request); |
||||
0 ignored issues
–
show
$query of type Illuminate\Database\Eloquent\Builder is incompatible with the type Illuminate\Database\Query\Builder expected by parameter $query of SleepingOwl\Admin\Displa...lesAsync::applyOffset() .
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||
210 | $collection = $query->get(); |
||||
211 | |||||
212 | return $this->prepareDatatablesStructure($request, $collection, $totalCount, $filteredCount); |
||||
0 ignored issues
–
show
It seems like
$totalCount can also be of type Illuminate\Database\Eloquent\Builder ; however, parameter $totalCount of SleepingOwl\Admin\Displa...reDatatablesStructure() does only seem to accept integer , maybe add an additional type check?
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||
213 | } |
||||
214 | |||||
215 | /** |
||||
216 | * Apply offset and limit to the query. |
||||
217 | * |
||||
218 | * @param \Illuminate\Database\Query\Builder $query |
||||
219 | * @param \Illuminate\Http\Request $request |
||||
220 | */ |
||||
221 | public function applyOffset($query, \Illuminate\Http\Request $request) |
||||
222 | { |
||||
223 | $offset = $request->input('start', 0); |
||||
224 | $limit = $request->input('length', 10); |
||||
225 | |||||
226 | if ($limit == -1) { |
||||
227 | return; |
||||
228 | } |
||||
229 | |||||
230 | $query->offset((int) $offset)->limit((int) $limit); |
||||
231 | } |
||||
232 | |||||
233 | /** |
||||
234 | * Apply search to the query. |
||||
235 | * |
||||
236 | * @param Builder $query |
||||
237 | * @param \Illuminate\Http\Request $request |
||||
238 | */ |
||||
239 | public function applySearch(Builder $query, \Illuminate\Http\Request $request) |
||||
240 | { |
||||
241 | $search = $request->input('search.value'); |
||||
242 | if (empty($search)) { |
||||
243 | return; |
||||
244 | } |
||||
245 | |||||
246 | $query->where(function (Builder $query) use ($search) { |
||||
247 | $columns = $this->getColumns()->all(); |
||||
248 | |||||
249 | $_model = $query->getModel(); |
||||
250 | |||||
251 | foreach ($columns as $column) { |
||||
252 | if ($column->isSearchable()) { |
||||
253 | if ($column instanceof ColumnInterface) { |
||||
254 | if (($metaInstance = $column->getMetaData()) instanceof ColumnMetaInterface) { |
||||
0 ignored issues
–
show
The method
getMetaData() does not exist on SleepingOwl\Admin\Contra...Display\ColumnInterface . It seems like you code against a sub-type of said class. However, the method does not exist in SleepingOwl\Admin\Contra...ColumnEditableInterface . Are you sure you never get one of those?
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||
255 | if (method_exists($metaInstance, 'onSearch')) { |
||||
256 | $metaInstance->onSearch($column, $query, $search); |
||||
257 | continue; |
||||
258 | } |
||||
259 | } |
||||
260 | |||||
261 | if (is_callable($callback = $column->getSearchCallback())) { |
||||
0 ignored issues
–
show
The method
getSearchCallback() does not exist on SleepingOwl\Admin\Contra...Display\ColumnInterface . It seems like you code against a sub-type of said class. However, the method does not exist in SleepingOwl\Admin\Contra...ColumnEditableInterface . Are you sure you never get one of those?
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||
262 | $callback($column, $query, $search); |
||||
263 | continue; |
||||
264 | } |
||||
265 | } |
||||
266 | |||||
267 | if ($_model->getAttribute($column->getName())) { |
||||
0 ignored issues
–
show
The method
getName() does not exist on SleepingOwl\Admin\Contra...Display\ColumnInterface . It seems like you code against a sub-type of SleepingOwl\Admin\Contra...Display\ColumnInterface such as SleepingOwl\Admin\Display\Column\NamedColumn or SleepingOwl\Admin\Display\Column\Editable\DateTime or SleepingOwl\Admin\Display\Column\Editable\Select or SleepingOwl\Admin\Display\Column\Editable\Textarea or SleepingOwl\Admin\Display\Column\Editable\Checkbox or SleepingOwl\Admin\Display\Column\Editable\Text .
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||
268 | continue; |
||||
269 | } |
||||
270 | |||||
271 | $query->orWhere($column->getName(), 'like', '%'.$search.'%'); |
||||
272 | } |
||||
273 | } |
||||
274 | }); |
||||
275 | } |
||||
276 | |||||
277 | /** |
||||
278 | * Convert collection to the datatables structure. |
||||
279 | * |
||||
280 | * @param \Illuminate\Http\Request $request |
||||
281 | * @param array|Collection $collection |
||||
282 | * @param int $totalCount |
||||
283 | * @param int $filteredCount |
||||
284 | * |
||||
285 | * @return array |
||||
286 | */ |
||||
287 | protected function prepareDatatablesStructure( |
||||
288 | \Illuminate\Http\Request $request, |
||||
289 | Collection $collection, |
||||
290 | $totalCount, |
||||
291 | $filteredCount |
||||
292 | ) { |
||||
293 | $columns = $this->getColumns(); |
||||
294 | |||||
295 | $result = []; |
||||
296 | $result['draw'] = $request->input('draw', 0); |
||||
297 | $result['recordsTotal'] = $totalCount; |
||||
298 | $result['recordsFiltered'] = $filteredCount; |
||||
299 | $result['data'] = []; |
||||
300 | |||||
301 | foreach ($collection as $instance) { |
||||
302 | $_row = []; |
||||
303 | |||||
304 | foreach ($columns->all() as $column) { |
||||
305 | $column->setModel($instance); |
||||
306 | |||||
307 | if ($column instanceof Control) { |
||||
308 | $column->initialize(); |
||||
309 | } |
||||
310 | |||||
311 | $_row[] = (string) $column; |
||||
312 | } |
||||
313 | if (is_callable($callback = $this->rowClassCallback)) { |
||||
314 | $class = $callback($instance); |
||||
315 | if (is_array($class)) { |
||||
316 | $class = implode(' ', $class); |
||||
317 | } |
||||
318 | $_row[] = (string) $class; |
||||
319 | } |
||||
320 | |||||
321 | $result['data'][] = $_row; |
||||
322 | } |
||||
323 | |||||
324 | return $result; |
||||
325 | } |
||||
326 | |||||
327 | /** |
||||
328 | * @return \Closure|mixed |
||||
329 | */ |
||||
330 | public function getRowClassCallback() |
||||
331 | { |
||||
332 | return $this->rowClassCallback; |
||||
333 | } |
||||
334 | |||||
335 | /** |
||||
336 | * @param \Closure $callback |
||||
337 | * |
||||
338 | * @return $this |
||||
339 | */ |
||||
340 | public function setRowClassCallback($callback) |
||||
341 | { |
||||
342 | $this->rowClassCallback = $callback; |
||||
343 | |||||
344 | return $this; |
||||
345 | } |
||||
346 | |||||
347 | /** |
||||
348 | * @return void |
||||
349 | */ |
||||
350 | public function getCollection() |
||||
351 | { |
||||
352 | } |
||||
353 | |||||
354 | /** |
||||
355 | * @param $payload |
||||
356 | */ |
||||
357 | public function setPayload($payload) |
||||
358 | { |
||||
359 | $this->payload = $payload; |
||||
360 | } |
||||
361 | |||||
362 | /** |
||||
363 | * @return mixed |
||||
364 | */ |
||||
365 | public function getPayload() |
||||
366 | { |
||||
367 | return $this->payload; |
||||
368 | } |
||||
369 | |||||
370 | /** |
||||
371 | * @return array |
||||
372 | * @throws \Exception |
||||
373 | */ |
||||
374 | public function toArray() |
||||
375 | { |
||||
376 | $params = parent::toArray(); |
||||
377 | $params['payload'] = $this->payload; |
||||
378 | |||||
379 | return $params; |
||||
380 | } |
||||
381 | } |
||||
382 |
If there is a route defined but the controller class cannot be found there are two options: 1. the controller class needs to be implemented or 2. the route is outdated and can be removed.
If ?FooController? was found and ?BarController? is missing for the following example, either the controller should be implemented or the route should be removed: