Completed
Push — master ( e3a629...db5cbc )
by Maxime
120:12 queued 118:24
created

EloquentDatatable::addFilter()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 11
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 7
CRAP Score 1

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 11
ccs 7
cts 7
cp 1
rs 9.4285
cc 1
eloc 7
nc 1
nop 1
crap 1
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
     * Datatable columns.
24
     * 
25
     * @var array
26
     */
27
    protected $colomns;
28
    
29
    /**
30
     * Form implementation.
31
     *
32
     * @var \Kris\LaravelFormBuilder\Form|null
33
     */
34
    protected $form = null;
35
36
    /**
37
     * Datatable columns to display.
38
     *
39
     * @var array
40
     */
41
    protected $colomnsDisplay = [];
42
43
    /**
44
     * Datatable extra options.
45
     *
46
     * @var array
47
     */
48
    protected $datatableOptions = [];
49
50
    /**
51
     * 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).
52
     *
53
     * @var array
54
     */
55
    protected $defaultOrder = [[0, 'desc']];
56
57
    /**
58
     * EloquentDatatable constructor.
59
     *
60
     * @param \Illuminate\Database\Eloquent\Model|null $model
61
     */
62 8
    public function __construct(Model $model = null)
63
    {
64 8
        $this->model = $model;
65
    }
66
67
    /**
68
     * Model setter.
69
     *
70
     * @param \Illuminate\Database\Eloquent\Model $model
71
     * @return void
72
     */
73 4
    public function setModel(Model $model)
74
    {
75 4
        $this->model = $model;
76
    }
77
78
    /**
79
     * Add column to datatable.
80
     *
81
     * @param string $name
82
     * @param \Closure|null $closure
83
     * @param string|\Symfony\Component\Translation\TranslatorInterface $translation
84
     * @return $this
85
     */
86 8
    public function add($name, $closure = null, $translation = '')
87
    {
88 8
        if (! empty($closure)) {
89 8
            $this->colomns[] = [
90 8
                $name,
91 8
                $closure,
92
            ];
93
        } else {
94 8
            $this->colomns[] = $name;
95
        }
96
97 8
        $this->addTranslation($name, $translation);
98
99 8
        return $this;
100
    }
101
102
    /**
103
     * Add translation column.
104
     *
105
     * @param string $name
106
     * @param string|\Symfony\Component\Translation\TranslatorInterface $translation
107
     * @return void
108
     */
109 8
    public function addTranslation($name, $translation)
110
    {
111 8
        $this->colomnsDisplay[] = ! empty($translation) ? $translation : ucfirst($name);
112
    }
113
114
    /**
115
     * Generate specified columns for current datatable.
116
     *
117
     * @return mixed
118
     */
119 4
    public function generateColomns()
120
    {
121 4
        $this->applyFilters();
122
123 4
        $datatable = Datatable::query($this->model);
124 4
        $colSearchAndSort = [];
125 4
        $sortOnly = [];
126
127 4
        if (! empty($this->colomns)) {
128 4
            foreach ($this->colomns as $key => $value) {
129
130 4
                if (is_string($value)) {
131 4
                    $datatable->showColumns($value);
132 4
                    $colSearchAndSort[] = $value;
133
                } else {
134 4
                    if (is_array($value) && (count($value) === 2)) {
135 4
                        $datatable->addColumn($value[0], $value[1]);
136 4
                        $sortOnly[] = $value[0];
137
                    }
138
                }
139
            }
140
        }
141
142 4
        $datatable = $this->setClassRow($datatable);
143 4
        $datatable->orderColumns(array_merge($colSearchAndSort, $sortOnly));
144 4
        $datatable->searchColumns($colSearchAndSort);
145
146 4
        return $datatable->make();
147
    }
148
149
    /**
150
     * Set DT_RowClass for given datatable.
151
     *
152
     * @param \Chumper\Datatable\Engines\QueryEngine $datatable
153
     * @return \Chumper\Datatable\Engines\QueryEngine
154
     */
155
    public function setClassRow($datatable)
156
    {
157 4
        $datatable->setRowClass(function ($row) {
158 4
            return (isset($row->status) && empty($row->status)) ? 'danger' : '';
159 4
        });
160
161 4
        return $datatable;
162
    }
163
164
    /**
165
     * Generate rendered HTML view for current datatable.
166
     *
167
     * @param string $template
168
     * @param string $route
169
     * @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View
170
     */
171 8
    public function generateHtmlRender($template = 'datatable-builder::part.datatable', $route = '')
172
    {
173 8
        return view($template, [
174 8
            'colomns_display' => $this->colomnsDisplay,
175 8
            'datatable_options' => $this->addOptions(),
176 8
            'id' => strtolower(str_replace('\\', '_', get_class($this))),
177 8
            'route' => ! empty($route) ? $route : $this->getControllerNameForAction() . '@getDatatable',
178 8
            'filters' => $this->addFilter(),
179
        ]);
180
    }
181
182
    /**
183
     * Add default actions to datatable.
184
     *
185
     * @param string $template
186
     * @param string $route
187
     * @return void
188
     */
189 8
    public function addDefaultAction($template = 'datatable-builder::form.components.datatable.actions', $route = '')
190
    {
191 8
        $reflection = new ReflectionClass(get_class($this));
192
193 8
        $this->add('actions', function ($model) use ($template, $reflection, $route) {
194 4
            return view($template, [
0 ignored issues
show
Bug introduced by
The method render does only exist in Illuminate\View\View, but not in Illuminate\Contracts\View\Factory.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
195 4
                'data' => $model->toArray(),
196 4
                'route' => ! empty($route) ? $route . '@' : $this->getControllerNameForAction() . '@',
197 4
            ])->render();
198 8
        });
199
    }
200
201
    /**
202
     * Add filters form to current datatable.
203
     *
204
     * @param string $template
205
     * @return string
206
     * @throws \Exception
207
     * @throws \Throwable
208
     */
209 8
    protected function addFilter($template = 'datatable-builder::form.components.datatable.filter')
210
    {
211 8
        $this->form = FormBuilder::plain();
212 8
        $this->filters();
213
214 8
        $filter_content = view($template, [
0 ignored issues
show
Bug introduced by
The method render does only exist in Illuminate\View\View, but not in Illuminate\Contracts\View\Factory.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
215 8
            'form' => $this->form,
216 8
        ])->render();
217
218 8
        return $filter_content;
219
    }
220
221
    /**
222
     * Add default options to current datatable.
223
     *
224
     * @return array
225
     */
226 8
    protected function addOptions()
227
    {
228 8
        if (! array_key_exists('order', $this->datatableOptions) && ! empty($this->defaultOrder)) {
229 8
            if (is_array($this->defaultOrder)) {
230 8
                foreach ($this->defaultOrder as $keyOrder => $order) {
231 8
                    if (is_string($order[0])) {
232
                        foreach ($this->colomns as $key => $colomn) {
233
                            if (is_array($colomn)) {
234
                                $colomn = $colomn[0];
235
                            }
236
                            if ($colomn == $order[0]) {
237
                                $this->defaultOrder[$keyOrder][0] = $key;
238
                            }
239
                        }
240
                        if (is_string($this->defaultOrder[$keyOrder][0])) {
241 8
                            $this->defaultOrder[$keyOrder][0] = 0;
242
                        }
243
                    }
244
                }
245 8
                $this->datatableOptions['order'] = $this->defaultOrder;
246
            }
247
        }
248
249 8
        return $this->datatableOptions;
250
    }
251
252
    /**
253
     * Get controller name for action based on current route.
254
     *
255
     * @return string
256
     */
257 8
    protected function getControllerNameForAction()
258
    {
259 8
        $action = explode('@', Route::currentRouteAction());
260
261 8
        return '\\' . $action[0];
262
    }
263
264
    /**
265
     * Add the fields filters form here.
266
     *
267
     * @return void
268
     */
269
    public function filters()
270
    {
271
        //
272
    }
273
274
    /**
275
     * Apply filters by default on each fields of setted model.
276
     *
277
     * @return void
278
     */
279 4
    public function applyFilters()
280
    {
281 4
        $columns = Schema::getColumnListing($this->model->getTable());
282
283 4
        $allInput = Request::all();
284 4
        foreach ($allInput as $name => $input) {
285 4
            if (in_array($name, $columns) && ($input != '')) {
286 4
                $this->model = $this->model->where($name, '=', $input);
287
            }
288
        }
289
    }
290
291
    /**
292
     * Compile all added columns and build datatable.
293
     *
294
     * @return void
295
     */
296
    abstract public function build();
297
}