Completed
Push — master ( f1041c...bdfeaf )
by Arjay
01:46
created

DataTable::__get()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 8
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 8
rs 9.4285
cc 2
eloc 4
nc 2
nop 1
1
<?php
2
3
namespace Yajra\Datatables\Services;
4
5
use Illuminate\Contracts\View\Factory;
6
use Illuminate\Http\JsonResponse;
7
use Maatwebsite\Excel\Classes\LaravelExcelWorksheet;
8
use Maatwebsite\Excel\Writers\LaravelExcelWriter;
9
use Yajra\Datatables\Contracts\DataTableButtonsContract;
10
use Yajra\Datatables\Contracts\DataTableContract;
11
use Yajra\Datatables\Contracts\DataTableScopeContract;
12
use Yajra\Datatables\Datatables;
13
use Yajra\Datatables\Transformers\DataTransformer;
14
15
/**
16
 * Class DataTable.
17
 *
18
 * @package Yajra\Datatables\Services
19
 * @author  Arjay Angeles <[email protected]>
20
 */
21
abstract class DataTable implements DataTableContract, DataTableButtonsContract
22
{
23
    /**
24
     * @var \Yajra\Datatables\Datatables
25
     */
26
    protected $datatables;
27
28
    /**
29
     * @var \Illuminate\Contracts\View\Factory
30
     */
31
    protected $viewFactory;
32
33
    /**
34
     * Datatables print preview view.
35
     *
36
     * @var string
37
     */
38
    protected $printPreview = 'datatables::print';
39
40
    /**
41
     * List of columns to be exported.
42
     *
43
     * @var string|array
44
     */
45
    protected $exportColumns = '*';
46
47
    /**
48
     * List of columns to be printed.
49
     *
50
     * @var string|array
51
     */
52
    protected $printColumns = '*';
53
54
    /**
55
     * Query scopes.
56
     *
57
     * @var \Yajra\Datatables\Contracts\DataTableScopeContract[]
58
     */
59
    protected $scopes = [];
60
61
    /**
62
     * Html builder.
63
     *
64
     * @var \Yajra\Datatables\Html\Builder
65
     */
66
    protected $htmlBuilder;
67
68
    /**
69
     * Export filename.
70
     *
71
     * @var string
72
     */
73
    protected $filename = '';
74
75
    /**
76
     * Custom attributes set on the class.
77
     *
78
     * @var array
79
     */
80
    protected $attributes = [];
81
82
    /**
83
     * Callback before sending the response.
84
     *
85
     * @var callable
86
     */
87
    protected $beforeCallback;
88
89
    /**
90
     * Callback after processing the response.
91
     *
92
     * @var callable
93
     */
94
    protected $afterCallback;
95
96
    /**
97
     * DataTable constructor.
98
     *
99
     * @param \Yajra\Datatables\Datatables $datatables
100
     * @param \Illuminate\Contracts\View\Factory $viewFactory
101
     */
102
    public function __construct(Datatables $datatables, Factory $viewFactory)
103
    {
104
        $this->datatables  = $datatables;
105
        $this->viewFactory = $viewFactory;
106
    }
107
108
    /**
109
     * Process dataTables needed render output.
110
     *
111
     * @param string $view
112
     * @param array $data
113
     * @param array $mergeData
114
     * @return \Illuminate\Http\JsonResponse|\Illuminate\View\View
115
     */
116
    public function render($view, $data = [], $mergeData = [])
117
    {
118
        if ($this->request()->ajax() && $this->request()->wantsJson()) {
119
            return $this->ajax();
120
        }
121
122
        if ($action = $this->request()->get('action') AND in_array($action, ['print', 'csv', 'excel', 'pdf'])) {
123
            if ($action == 'print') {
124
                return $this->printPreview();
125
            }
126
127
            return call_user_func_array([$this, $action], []);
128
        }
129
130
        return $this->viewFactory->make($view, $data, $mergeData)->with('dataTable', $this->html());
131
    }
132
133
    /**
134
     * Get Datatables Request instance.
135
     *
136
     * @return \Yajra\Datatables\Request
137
     */
138
    public function request()
139
    {
140
        return $this->datatables->getRequest();
141
    }
142
143
    /**
144
     * Display ajax response.
145
     *
146
     * @return \Illuminate\Http\JsonResponse
147
     */
148
    public function ajax()
149
    {
150
        $dataTable = $this->dataTable();
0 ignored issues
show
Bug introduced by
The method dataTable() does not seem to exist on object<Yajra\Datatables\Services\DataTable>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
151
152
        if ($callback = $this->beforeCallback) {
153
            $dataTable = $callback($dataTable);
154
        }
155
156
        $response = $dataTable->make(true);
157
158
        if ($callback = $this->afterCallback) {
159
            $response = new JsonResponse($callback($response->getData(true)));
160
        }
161
162
        return $response;
163
    }
164
165
    /**
166
     * Display printable view of datatables.
167
     *
168
     * @return \Illuminate\Contracts\View\View
169
     */
170
    public function printPreview()
171
    {
172
        $data = $this->getDataForPrint();
173
174
        return $this->viewFactory->make($this->printPreview, compact('data'));
175
    }
176
177
    /**
178
     * Get mapped columns versus final decorated output.
179
     *
180
     * @return array
181
     */
182
    protected function getDataForPrint()
183
    {
184
        $columns = $this->printColumns();
185
186
        return $this->mapResponseToColumns($columns, 'printable');
187
    }
188
189
    /**
190
     * Get printable columns.
191
     *
192
     * @return array|string
193
     */
194
    protected function printColumns()
195
    {
196
        return is_array($this->printColumns) ? $this->printColumns : $this->getColumnsFromBuilder();
197
    }
198
199
    /**
200
     * Get columns definition from html builder.
201
     *
202
     * @return array
203
     */
204
    protected function getColumnsFromBuilder()
205
    {
206
        return $this->html()->getColumns();
207
    }
208
209
    /**
210
     * Optional method if you want to use html builder.
211
     *
212
     * @return \Yajra\Datatables\Html\Builder
213
     */
214
    public function html()
215
    {
216
        return $this->builder();
217
    }
218
219
    /**
220
     * Get Datatables Html Builder instance.
221
     *
222
     * @return \Yajra\Datatables\Html\Builder
223
     */
224
    public function builder()
225
    {
226
        return $this->htmlBuilder ?: $this->htmlBuilder = app('datatables.html');
227
    }
228
229
    /**
230
     * Map ajax response to columns definition.
231
     *
232
     * @param mixed $columns
233
     * @param string $type
234
     * @return array
235
     */
236
    protected function mapResponseToColumns($columns, $type)
237
    {
238
        return array_map(function ($row) use ($columns, $type) {
239
            if ($columns) {
240
                return (new DataTransformer())->transform($row, $columns, $type);
241
            }
242
243
            return $row;
244
        }, $this->getAjaxResponseData());
245
    }
246
247
    /**
248
     * Get decorated data as defined in datatables ajax response.
249
     *
250
     * @return array
251
     */
252
    protected function getAjaxResponseData()
253
    {
254
        $this->datatables->getRequest()->merge(['length' => -1]);
255
256
        $response = $this->ajax();
257
        $data     = $response->getData(true);
258
259
        return $data['data'];
260
    }
261
262
    /**
263
     * Add callback before sending the response.
264
     *
265
     * @param callable $callback
266
     * @return $this
267
     */
268
    public function before(callable $callback)
269
    {
270
        $this->beforeCallback = $callback;
271
272
        return $this;
273
    }
274
275
    /**
276
     * Add callback after the response was processed.
277
     *
278
     * @param callable $callback
279
     * @return $this
280
     */
281
    public function after(callable $callback)
282
    {
283
        $this->afterCallback = $callback;
284
285
        return $this;
286
    }
287
288
    /**
289
     * Export results to Excel file.
290
     *
291
     * @return void
292
     */
293
    public function excel()
294
    {
295
        $this->buildExcelFile()->download('xls');
296
    }
297
298
    /**
299
     * Build excel file and prepare for export.
300
     *
301
     * @return \Maatwebsite\Excel\Writers\LaravelExcelWriter
302
     */
303
    protected function buildExcelFile()
304
    {
305
        /** @var \Maatwebsite\Excel\Excel $excel */
306
        $excel = app('excel');
307
308
        return $excel->create($this->getFilename(), function (LaravelExcelWriter $excel) {
309
            $excel->sheet('exported-data', function (LaravelExcelWorksheet $sheet) {
310
                $sheet->fromArray($this->getDataForExport());
311
            });
312
        });
313
    }
314
315
    /**
316
     * Get export filename.
317
     *
318
     * @return string
319
     */
320
    public function getFilename()
321
    {
322
        return $this->filename ?: $this->filename();
323
    }
324
325
    /**
326
     * Set export filename.
327
     *
328
     * @param string $filename
329
     * @return DataTable
330
     */
331
    public function setFilename($filename)
332
    {
333
        $this->filename = $filename;
334
335
        return $this;
336
    }
337
338
    /**
339
     * Get filename for export.
340
     *
341
     * @return string
342
     */
343
    protected function filename()
344
    {
345
        return 'export_' . time();
346
    }
347
348
    /**
349
     * Get mapped columns versus final decorated output.
350
     *
351
     * @return array
352
     */
353
    protected function getDataForExport()
354
    {
355
        $columns = $this->exportColumns();
356
357
        return $this->mapResponseToColumns($columns, 'exportable');
358
    }
359
360
    /**
361
     * Get export columns definition.
362
     *
363
     * @return array|string
364
     */
365
    private function exportColumns()
366
    {
367
        return is_array($this->exportColumns) ? $this->exportColumns : $this->getColumnsFromBuilder();
368
    }
369
370
    /**
371
     * Export results to CSV file.
372
     *
373
     * @return void
374
     */
375
    public function csv()
376
    {
377
        $this->buildExcelFile()->download('csv');
378
    }
379
380
    /**
381
     * Export results to PDF file.
382
     *
383
     * @return mixed
384
     */
385
    public function pdf()
386
    {
387
        if ('snappy' == config('datatables-buttons.pdf_generator', 'excel')) {
388
            return $this->snappyPdf();
389
        } else {
390
            $this->buildExcelFile()->download('pdf');
391
        }
392
    }
393
394
    /**
395
     * PDF version of the table using print preview blade template.
396
     *
397
     * @return mixed
398
     */
399
    public function snappyPdf()
400
    {
401
        /** @var \Barryvdh\Snappy\PdfWrapper $snappy */
402
        $snappy = app('snappy.pdf.wrapper');
403
404
        $options     = config('datatables-buttons.snappy.options', [
405
            'no-outline'    => true,
406
            'margin-left'   => '0',
407
            'margin-right'  => '0',
408
            'margin-top'    => '10mm',
409
            'margin-bottom' => '10mm',
410
        ]);
411
        $orientation = config('datatables-buttons.snappy.orientation', 'landscape');
412
413
        $snappy->setOptions($options)
414
               ->setOrientation($orientation);
415
416
        return $snappy->loadHTML($this->printPreview())
417
                      ->download($this->getFilename() . ".pdf");
418
    }
419
420
    /**
421
     * Add basic array query scopes.
422
     *
423
     * @param \Yajra\Datatables\Contracts\DataTableScopeContract $scope
424
     * @return $this
425
     */
426
    public function addScope(DataTableScopeContract $scope)
427
    {
428
        $this->scopes[] = $scope;
429
430
        return $this;
431
    }
432
433
    /**
434
     * Set a custom class attribute.
435
     *
436
     * @param mixed $key
437
     * @param mixed|null $value
438
     * @return $this
439
     */
440
    public function with($key, $value = null)
441
    {
442
        if (is_array($key)) {
443
            $this->attributes = array_merge($this->attributes, $key);
444
        } else {
445
            $this->attributes[$key] = $value;
446
        }
447
448
        return $this;
449
    }
450
451
    /**
452
     * Dynamically retrieve the value of an attribute.
453
     *
454
     * @param string $key
455
     * @return mixed|null
456
     */
457
    public function __get($key)
458
    {
459
        if (array_key_exists($key, $this->attributes)) {
460
            return $this->attributes[$key];
461
        }
462
463
        return null;
464
    }
465
466
    /**
467
     * Apply query scopes.
468
     *
469
     * @param \Illuminate\Database\Query\Builder|\Illuminate\Database\Eloquent\Builder $query
470
     * @return mixed
471
     */
472
    protected function applyScopes($query)
473
    {
474
        foreach ($this->scopes as $scope) {
475
            $scope->apply($query);
476
        }
477
478
        return $query;
479
    }
480
481
    /**
482
     * Get default builder parameters.
483
     *
484
     * @return array
485
     */
486
    protected function getBuilderParameters()
487
    {
488
        return [
489
            'order'   => [[0, 'desc']],
490
            'buttons' => [
491
                'create',
492
                'export',
493
                'print',
494
                'reset',
495
                'reload',
496
            ],
497
        ];
498
    }
499
}
500