Completed
Push — master ( 354c04...4e6a57 )
by Arjay
02:34
created

DataTable   B

Complexity

Total Complexity 40

Size/Duplication

Total Lines 359
Duplicated Lines 15.04 %

Coupling/Cohesion

Components 2
Dependencies 10

Importance

Changes 4
Bugs 0 Features 1
Metric Value
wmc 40
c 4
b 0
f 1
lcom 2
cbo 10
dl 54
loc 359
rs 8.2608

22 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 5 1
C render() 0 23 7
A request() 0 4 1
A excel() 0 4 1
A buildExcelFile() 0 8 1
A filename() 0 4 1
A getDataForExport() 12 12 2
A getAjaxResponseData() 0 9 1
A exportColumns() 0 4 2
A getColumnsFromBuilder() 0 4 1
A html() 0 4 1
A builder() 0 4 1
A buildExportColumn() 15 15 4
A csv() 0 4 1
A pdf() 0 4 1
A printPreview() 0 7 2
A getDataForPrint() 12 12 2
A printColumns() 0 4 2
A buildPrintColumn() 15 15 4
A addScope() 0 6 1
A applyScopes() 0 8 2
A getBuilderParameters() 0 21 1

How to fix   Duplicated Code    Complexity   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

Complex Class

 Tip:   Before tackling complexity, make sure that you eliminate any duplication first. This often can reduce the size of classes significantly.

Complex classes like DataTable often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use DataTable, and based on these observations, apply Extract Interface, too.

1
<?php
2
3
namespace Yajra\Datatables\Services;
4
5
use Illuminate\Contracts\View\Factory;
6
use Maatwebsite\Excel\Classes\LaravelExcelWorksheet;
7
use Maatwebsite\Excel\Writers\LaravelExcelWriter;
8
use Yajra\Datatables\Contracts\DataTableButtonsContract;
9
use Yajra\Datatables\Contracts\DataTableContract;
10
use Yajra\Datatables\Contracts\DataTableScopeContract;
11
use Yajra\Datatables\Datatables;
12
use Yajra\Datatables\Html\Column;
13
14
abstract class DataTable implements DataTableContract, DataTableButtonsContract
15
{
16
    /**
17
     * @var \Yajra\Datatables\Datatables
18
     */
19
    protected $datatables;
20
21
    /**
22
     * @var \Illuminate\Contracts\View\Factory
23
     */
24
    protected $viewFactory;
25
26
    /**
27
     * Datatables print preview view.
28
     *
29
     * @var string
30
     */
31
    protected $printPreview;
32
33
    /**
34
     * List of columns to be exported.
35
     *
36
     * @var string|array
37
     */
38
    protected $exportColumns = '*';
39
40
    /**
41
     * List of columns to be printed.
42
     *
43
     * @var string|array
44
     */
45
    protected $printColumns = '*';
46
47
    /**
48
     * Query scopes.
49
     *
50
     * @var \Yajra\Datatables\Contracts\DataTableScopeContract[]
51
     */
52
    protected $scopes = [];
53
54
    /**
55
     * @param \Yajra\Datatables\Datatables $datatables
56
     * @param \Illuminate\Contracts\View\Factory $viewFactory
57
     */
58
    public function __construct(Datatables $datatables, Factory $viewFactory)
59
    {
60
        $this->datatables  = $datatables;
61
        $this->viewFactory = $viewFactory;
62
    }
63
64
    /**
65
     * Render view.
66
     *
67
     * @param $view
68
     * @param array $data
69
     * @param array $mergeData
70
     * @return \Illuminate\Http\JsonResponse|\Illuminate\View\View
71
     */
72
    public function render($view, $data = [], $mergeData = [])
73
    {
74
        if ($this->request()->ajax() && $this->request()->wantsJson()) {
75
            return $this->ajax();
76
        }
77
78
        switch ($this->datatables->getRequest()->get('action')) {
79
            case 'excel':
80
                return $this->excel();
81
82
            case 'csv':
83
                return $this->csv();
84
85
            case 'pdf':
86
                return $this->pdf();
87
88
            case 'print':
89
                return $this->printPreview();
90
91
            default:
92
                return $this->viewFactory->make($view, $data, $mergeData)->with('dataTable', $this->html());
93
        }
94
    }
95
96
    /**
97
     * Get Datatables Request instance.
98
     *
99
     * @return \Yajra\Datatables\Request
100
     */
101
    public function request()
102
    {
103
        return $this->datatables->getRequest();
104
    }
105
106
    /**
107
     * Export results to Excel file.
108
     *
109
     * @return mixed
110
     */
111
    public function excel()
112
    {
113
        return $this->buildExcelFile()->download('xls');
114
    }
115
116
    /**
117
     * Build excel file and prepare for export.
118
     *
119
     * @return mixed
120
     */
121
    protected function buildExcelFile()
122
    {
123
        return app('excel')->create($this->filename(), function (LaravelExcelWriter $excel) {
124
            $excel->sheet('exported-data', function (LaravelExcelWorksheet $sheet) {
125
                $sheet->fromArray($this->getDataForExport());
126
            });
127
        });
128
    }
129
130
    /**
131
     * Get filename for export.
132
     *
133
     * @return string
134
     */
135
    protected function filename()
136
    {
137
        return 'export_' . time();
138
    }
139
140
    /**
141
     * Get mapped columns versus final decorated output.
142
     *
143
     * @return array
144
     */
145 View Code Duplication
    protected function getDataForExport()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
146
    {
147
        $decoratedData = $this->getAjaxResponseData();
148
149
        return array_map(function ($row) {
150
            if ($columns = $this->exportColumns()) {
151
                return $this->buildExportColumn($row, $columns);
152
            }
153
154
            return $row;
155
        }, $decoratedData);
156
    }
157
158
    /**
159
     * Get decorated data as defined in datatables ajax response.
160
     *
161
     * @return mixed
162
     */
163
    protected function getAjaxResponseData()
164
    {
165
        $this->datatables->getRequest()->merge(['length' => -1]);
166
167
        $response = $this->ajax();
168
        $data     = $response->getData(true);
169
170
        return $data['data'];
171
    }
172
173
    /**
174
     * Get export columns definition.
175
     *
176
     * @return array|string
177
     */
178
    private function exportColumns()
179
    {
180
        return is_array($this->exportColumns) ? $this->exportColumns : $this->getColumnsFromBuilder();
181
    }
182
183
    /**
184
     * Get columns definition from html builder.
185
     *
186
     * @return array
187
     */
188
    protected function getColumnsFromBuilder()
189
    {
190
        return $this->html()->getColumns()->all();
191
    }
192
193
    /**
194
     * Optional method if you want to use html builder.
195
     *
196
     * @return \Yajra\Datatables\Html\Builder
197
     */
198
    public function html()
199
    {
200
        return $this->builder();
201
    }
202
203
    /**
204
     * Get Datatables Html Builder instance.
205
     *
206
     * @return \Yajra\Datatables\Html\Builder
207
     */
208
    public function builder()
209
    {
210
        return $this->datatables->getHtmlBuilder();
211
    }
212
213
    /**
214
     * @param array $row
215
     * @param array|Column[] $columns
216
     * @return array
217
     */
218 View Code Duplication
    protected function buildExportColumn(array $row, array $columns)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
219
    {
220
        $results = [];
221
        foreach ($columns as $column) {
222
            if ($column instanceof Column) {
223
                if ($column['exportable']) {
224
                    $results[$column['title']] = strip_tags(array_get($row, $column['name']));
225
                }
226
            } else {
227
                $results[] = array_get($row, $column);
228
            }
229
        }
230
231
        return $results;
232
    }
233
234
    /**
235
     * Export results to CSV file.
236
     *
237
     * @return mixed
238
     */
239
    public function csv()
240
    {
241
        return $this->buildExcelFile()->download('csv');
242
    }
243
244
    /**
245
     * Export results to PDF file.
246
     *
247
     * @return mixed
248
     */
249
    public function pdf()
250
    {
251
        return $this->buildExcelFile()->download('pdf');
252
    }
253
254
    /**
255
     * Display printable view of datatables.
256
     *
257
     * @return \Illuminate\Contracts\View\View
258
     */
259
    public function printPreview()
260
    {
261
        $data = $this->getDataForPrint();
262
        $view = $this->printPreview ?: 'datatables::print';
263
264
        return $this->viewFactory->make($view, compact('data'));
265
    }
266
267
    /**
268
     * Get mapped columns versus final decorated output.
269
     *
270
     * @return array
271
     */
272 View Code Duplication
    protected function getDataForPrint()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
273
    {
274
        $decoratedData = $this->getAjaxResponseData();
275
276
        return array_map(function ($row) {
277
            if ($columns = $this->printColumns()) {
278
                return $this->buildPrintColumn($row, $columns);
279
            }
280
281
            return $row;
282
        }, $decoratedData);
283
    }
284
285
    /**
286
     * Get printable columns.
287
     *
288
     * @return array|string
289
     */
290
    protected function printColumns()
291
    {
292
        return is_array($this->printColumns) ? $this->printColumns : $this->getColumnsFromBuilder();
293
    }
294
295
    /**
296
     * Build printable column.
297
     *
298
     * @param array $row
299
     * @param array|Column[] $columns
300
     * @return array
301
     */
302 View Code Duplication
    protected function buildPrintColumn(array $row, array $columns)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
303
    {
304
        $results = [];
305
        foreach ($columns as $column) {
306
            if ($column instanceof Column) {
307
                if ($column['printable']) {
308
                    $results[$column['title']] = array_get($row, $column['name']);
309
                }
310
            } else {
311
                $results[] = array_get($row, $column);
312
            }
313
        }
314
315
        return $results;
316
    }
317
318
    /**
319
     * Add basic array query scopes.
320
     *
321
     * @param \Yajra\Datatables\Contracts\DataTableScopeContract $scope
322
     * @return $this
323
     */
324
    public function addScope(DataTableScopeContract $scope)
325
    {
326
        $this->scopes[] = $scope;
327
328
        return $this;
329
    }
330
331
    /**
332
     * Apply query scopes.
333
     *
334
     * @param \Illuminate\Database\Query\Builder|\Illuminate\Database\Eloquent\Builder $query
335
     * @return mixed
336
     */
337
    protected function applyScopes($query)
338
    {
339
        foreach ($this->scopes as $scope) {
340
            $scope->apply($query);
341
        }
342
343
        return $query;
344
    }
345
346
    /**
347
     * Get default builder parameters.
348
     *
349
     * @return array
350
     */
351
    protected function getBuilderParameters()
352
    {
353
        return [
354
            'order'   => [[0, 'desc']],
355
            'buttons' => [
356
                'create',
357
                [
358
                    'extend'  => 'collection',
359
                    'text'    => '<i class="fa fa-download"></i> Export',
360
                    'buttons' => [
361
                        'csv',
362
                        'excel',
363
                        'pdf',
364
                    ],
365
                ],
366
                'print',
367
                'reset',
368
                'reload',
369
            ],
370
        ];
371
    }
372
}
373