EloquentDatatable::addOptions()   C
last analyzed

Complexity

Conditions 13
Paths 18

Size

Total Lines 36
Code Lines 20

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 14
CRAP Score 19.2573

Importance

Changes 2
Bugs 0 Features 1
Metric Value
eloc 20
c 2
b 0
f 1
dl 0
loc 36
ccs 14
cts 21
cp 0.6667
rs 6.6166
cc 13
nc 18
nop 0
crap 19.2573

How to fix   Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
namespace Distilleries\DatatableBuilder;
4
5
use Route;
6
use Schema;
7
use Request;
8
use Datatable;
9
use FormBuilder;
10
use ReflectionClass;
11
use Illuminate\Database\Eloquent\Model;
12
13
abstract class EloquentDatatable
14
{
15
    /**
16
     * Eloquent model.
17
     * 
18
     * @var \Illuminate\Database\Eloquent\Model
19
     */
20
    protected $model;
21
22
    /**
23
     * Eloquent model underlying table.
24
     * 
25
     * @var string
26
     */
27
    protected $table = '';
28
    
29
    /**
30
     * Datatable columns.
31
     * 
32
     * @var array
33
     */
34
    protected $colomns;
35
    
36
    /**
37
     * Form implementation.
38
     *
39
     * @var \Kris\LaravelFormBuilder\Form|null
40
     */
41
    protected $form = null;
42
43
    /**
44
     * Datatable columns to display.
45
     *
46
     * @var array
47
     */
48
    protected $colomnsDisplay = [];
49
50
    /**
51
     * Datatable columns orderable state.
52
     *
53
     * @var array
54
     */
55
    protected $columnsOrderable = [];
56
57
    /**
58
     * Datatable extra options.
59
     *
60
     * @var array
61
     */
62
    protected $datatableOptions = [];
63
64
    /**
65
     * Datatable order data (0 can be an integer to represents the column's number or it can be a string that references the column's name).
66
     *
67
     * @var array
68
     */
69
    protected $defaultOrder = [[0, 'desc']];
70
71
    /**
72
     * EloquentDatatable constructor.
73
     *
74
     * @param \Illuminate\Database\Eloquent\Model|null $model
75
     */
76 4
    public function __construct(Model $model = null)
77
    {
78 4
        if (!empty($model)) {
79
            $this->setModel($model);
80
        }
81
    }
82
83
    /**
84
     * Model setter.
85
     *
86
     * @param \Illuminate\Database\Eloquent\Model $model
87
     * @return void
88
     */
89 2
    public function setModel(Model $model)
90
    {
91 2
        $this->model = $model;
92 2
        $this->table = $this->model->getTable();
93
    }
94
95
    /**
96
     * Add column to datatable.
97
     *
98
     * @param string $name
99
     * @param \Closure|null $closure
100
     * @param string|\Symfony\Component\Translation\TranslatorInterface $translation
101
     * @param bool $orderable
102
     * @return $this
103
     */
104 4
    public function add($name, $closure = null, $translation = '', $orderable = true)
105
    {
106 4
        if (! empty($closure)) {
107 4
            $this->colomns[] = [
108 4
                $name,
109 4
                $closure,
110
            ];
111
        } else {
112 4
            $this->colomns[] = $name;
113
        }
114
115 4
        $this->addTranslation($name, $translation);
116 4
        $this->addOrderable($name, $orderable);
117
118 4
        return $this;
119
    }
120
121
    /**
122
     * Add translation column.
123
     *
124
     * @param string $name
125
     * @param string|\Symfony\Component\Translation\TranslatorInterface $translation
126
     * @return void
127
     */
128 4
    public function addTranslation($name, $translation)
129
    {
130 4
        $this->colomnsDisplay[] = ! empty($translation) ? $translation : ucfirst($name);
131
    }
132
133
    /**
134
     * Add orderable column.
135
     *
136
     * @param string $name
137
     * @param bool $translation
138
     * @return void
139
     */
140 4
    public function addOrderable($name, $orderable)
141
    {
142 4
        $this->columnsOrderable[$name] = $orderable;
143
    }
144
145
    /**
146
     * Generate specified columns for current datatable.
147
     *
148
     * @return mixed
149
     */
150 2
    public function generateColomns()
151
    {
152 2
        $this->model = $this->baseQuery();
0 ignored issues
show
Documentation Bug introduced by
It seems like $this->baseQuery() of type Illuminate\Database\Eloquent\Builder is incompatible with the declared type Illuminate\Database\Eloquent\Model of property $model.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
153
154 2
        $this->applyFilters();
155
156 2
        $datatable = Datatable::query($this->model);
157 2
        $colSearchAndSort = [];
158 2
        $sortOnly = [];
159
160 2
        if (! empty($this->colomns)) {
161 2
            foreach ($this->colomns as $key => $value) {
162
163 2
                if (is_string($value)) {
164 2
                    $datatable->showColumns($value);
165 2
                    $colSearchAndSort[] = $value;
166
                } else {
167 2
                    if (is_array($value) && (count($value) === 2)) {
168 2
                        $datatable->addColumn($value[0], $value[1]);
169 2
                        $sortOnly[] = $value[0];
170
                    }
171
                }
172
            }
173
        }
174
175 2
        $datatable = $this->setClassRow($datatable);
176 2
        $datatable->orderColumns(array_merge($colSearchAndSort, $sortOnly));
177 2
        $datatable->searchColumns($colSearchAndSort);
178
179 2
        return $datatable->make();
180
    }
181
182
    /**
183
     * Return Datatable base query.
184
     *
185
     * @return \Illuminate\Database\Eloquent\Builder
186
     */
187 2
    protected function baseQuery()
188
    {
189 2
        return $this->model->query();
190
    }
191
192
    /**
193
     * Set DT_RowClass for given datatable.
194
     *
195
     * @param \Chumper\Datatable\Engines\QueryEngine $datatable
196
     * @return \Chumper\Datatable\Engines\QueryEngine
197
     */
198 2
    public function setClassRow($datatable)
199
    {
200
        $datatable->setRowClass(function ($row) {
201 2
            return (isset($row->status) && empty($row->status)) ? 'danger' : '';
202 2
        });
203
204 2
        return $datatable;
205
    }
206
207
    /**
208
     * Generate rendered HTML view for current datatable.
209
     *
210
     * @param string $template
211
     * @param string $route
212
     * @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View
213
     */
214 4
    public function generateHtmlRender($template = 'datatable-builder::part.datatable', $route = '')
215
    {
216 4
        return view($template, [
217 4
            'colomns_display' => $this->colomnsDisplay,
218 4
            'datatable_options' => $this->addOptions(),
219 4
            'id' => strtolower(str_replace('\\', '_', get_class($this))),
220 4
            'route' => ! empty($route) ? $route : $this->getControllerNameForAction() . '@getDatatable',
221 4
            'filters' => $this->addFilter(),
222
        ]);
223
    }
224
225
    /**
226
     * Add default actions to datatable.
227
     *
228
     * @param string $template
229
     * @param string $route
230
     * @return void
231
     */
232 4
    public function addDefaultAction($template = 'datatable-builder::form.components.datatable.actions', $route = '')
233
    {
234 4
        $reflection = new ReflectionClass(get_class($this));
235
236
        $this->add('actions', function ($model) use ($template, $reflection, $route) {
0 ignored issues
show
Unused Code introduced by
The import $reflection is not used and could be removed.

This check looks for imports that have been defined, but are not used in the scope.

Loading history...
237 2
            return view($template, [
238 2
                'data' => $model->toArray(),
239 2
                'route' => ! empty($route) ? $route . '@' : $this->getControllerNameForAction() . '@',
240 2
            ])->render();
241 4
        }, 'Actions', false);
242
    }
243
244
    /**
245
     * Add filters form to current datatable.
246
     *
247
     * @param string $template
248
     * @return string
249
     * @throws \Exception
250
     * @throws \Throwable
251
     */
252 4
    protected function addFilter($template = 'datatable-builder::form.components.datatable.filter')
253
    {
254 4
        $this->form = FormBuilder::plain();
255 4
        $this->filters();
256
257 4
        $filter_content = view($template, [
258 4
            'form' => $this->form,
259 4
        ])->render();
260
261 4
        return $filter_content;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $filter_content also could return the type array which is incompatible with the documented return type string.
Loading history...
262
    }
263
264
    /**
265
     * Add default options to current datatable.
266
     *
267
     * @return array
268
     */
269 4
    protected function addOptions()
270
    {
271 4
        if (! array_key_exists('order', $this->datatableOptions) && ! empty($this->defaultOrder)) {
272 4
            if (is_array($this->defaultOrder)) {
0 ignored issues
show
introduced by
The condition is_array($this->defaultOrder) is always true.
Loading history...
273 4
                foreach ($this->defaultOrder as $keyOrder => $order) {
274 4
                    if (is_string($order[0])) {
275
                        foreach ($this->colomns as $key => $colomn) {
276
                            if (is_array($colomn)) {
277
                                $colomn = $colomn[0];
278
                            }
279
                            if ($colomn == $order[0]) {
280
                                $this->defaultOrder[$keyOrder][0] = $key;
281
                            }
282
                        }
283
                        if (is_string($this->defaultOrder[$keyOrder][0])) {
284
                            $this->defaultOrder[$keyOrder][0] = 0;
285
                        }
286
                    }
287
                }
288 4
                $this->datatableOptions['order'] = $this->defaultOrder;
289
            }
290
        }
291
292 4
        $nonOrderableColumns = [];
293 4
        foreach (array_values($this->columnsOrderable) as $index => $orderableState) {
294 4
            if (!$orderableState) {
295 4
                $nonOrderableColumns[] = $index;
296
            }
297
        }
298 4
        if (!empty($nonOrderableColumns)) {
299 4
            $this->datatableOptions['columnDefs'] = [
300 4
                ['orderable' => false, 'targets' => $nonOrderableColumns],
301
            ];
302
        }
303
304 4
        return $this->datatableOptions;
305
    }
306
307
    /**
308
     * Get controller name for action based on current route.
309
     *
310
     * @return string
311
     */
312 4
    protected function getControllerNameForAction()
313
    {
314 4
        $action = explode('@', Route::currentRouteAction());
315
316 4
        return '\\' . $action[0];
317
    }
318
319
    /**
320
     * Add the fields filters form here.
321
     *
322
     * @return void
323
     */
324
    public function filters()
325
    {
326
        //
327
    }
328
329
    /**
330
     * Apply filters by default on each fields of setted model.
331
     *
332
     * @return void
333
     */
334 2
    public function applyFilters()
335
    {
336 2
        $columns = Schema::getColumnListing($this->table);
337
338 2
        $allInput = Request::all();
339 2
        foreach ($allInput as $name => $input) {
340 2
            if (in_array($name, $columns) && ($input != '')) {
341 2
                $this->model = $this->model->where($this->table . '.' . $name, '=', $input);
0 ignored issues
show
Documentation Bug introduced by
It seems like $this->model->where($thi...' . $name, '=', $input) of type Illuminate\Database\Eloquent\Builder is incompatible with the declared type Illuminate\Database\Eloquent\Model of property $model.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
342
            }
343
        }
344
    }
345
346
    /**
347
     * Compile all added columns and build datatable.
348
     *
349
     * @return void
350
     */
351
    abstract public function build();
352
}