Completed
Push — master ( 47c6ec...2934e3 )
by Arjay
06:39
created

DataTable::before()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 6
rs 9.4285
c 0
b 0
f 0
cc 1
eloc 3
nc 1
nop 1
1
<?php
2
3
namespace Yajra\DataTables\Services;
4
5
use Illuminate\Contracts\View\Factory;
6
use Illuminate\Http\JsonResponse;
7
use Illuminate\Support\Collection;
8
use Maatwebsite\Excel\Classes\LaravelExcelWorksheet;
9
use Maatwebsite\Excel\Writers\LaravelExcelWriter;
10
use Yajra\DataTables\Contracts\DataTableButtons;
11
use Yajra\DataTables\Contracts\DataTableService;
12
use Yajra\DataTables\Contracts\DataTableScopeContract;
13
use Yajra\DataTables\Datatables;
14
use Yajra\DataTables\Transformers\DataTransformer;
15
16
abstract class DataTable implements DataTableService, DataTableButtons
17
{
18
    /**
19
     * @var \Yajra\DataTables\Datatables
20
     */
21
    protected $datatables;
22
23
    /**
24
     * @var \Illuminate\Contracts\View\Factory
25
     */
26
    protected $viewFactory;
27
28
    /**
29
     * Datatables print preview view.
30
     *
31
     * @var string
32
     */
33
    protected $printPreview = 'datatables::print';
34
35
    /**
36
     * List of columns to be exported.
37
     *
38
     * @var string|array
39
     */
40
    protected $exportColumns = '*';
41
42
    /**
43
     * List of columns to be printed.
44
     *
45
     * @var string|array
46
     */
47
    protected $printColumns = '*';
48
49
    /**
50
     * Query scopes.
51
     *
52
     * @var \Yajra\DataTables\Contracts\DataTableScopeContract[]
53
     */
54
    protected $scopes = [];
55
56
    /**
57
     * Html builder.
58
     *
59
     * @var \Yajra\DataTables\Html\Builder
60
     */
61
    protected $htmlBuilder;
62
63
    /**
64
     * Html builder extension callback.
65
     *
66
     * @var callable
67
     */
68
    protected $htmlCallback;
69
70
    /**
71
     * Export filename.
72
     *
73
     * @var string
74
     */
75
    protected $filename = '';
76
77
    /**
78
     * Custom attributes set on the class.
79
     *
80
     * @var array
81
     */
82
    protected $attributes = [];
83
84
    /**
85
     * Callback before sending the response.
86
     *
87
     * @var callable
88
     */
89
    protected $beforeCallback;
90
91
    /**
92
     * Callback after processing the response.
93
     *
94
     * @var callable
95
     */
96
    protected $responseCallback;
97
98
    /**
99
     * Available button actions. When calling an action, the value will be used
100
     * as the function name (so it should be available)
101
     * If you want to add or disable an action, overload and modify this property
102
     *
103
     * @var array
104
     */
105
    protected $actions = ['print', 'csv', 'excel', 'pdf'];
106
107
    /**
108
     * DataTable constructor.
109
     *
110
     * @param \Yajra\DataTables\Datatables       $datatables
111
     * @param \Illuminate\Contracts\View\Factory $viewFactory
112
     */
113
    public function __construct(Datatables $datatables, Factory $viewFactory)
114
    {
115
        $this->datatables  = $datatables;
116
        $this->viewFactory = $viewFactory;
117
    }
118
119
    /**
120
     * Process dataTables needed render output.
121
     *
122
     * @param string $view
123
     * @param array  $data
124
     * @param array  $mergeData
125
     * @return \Illuminate\Http\JsonResponse|\Illuminate\View\View
126
     */
127
    public function render($view, $data = [], $mergeData = [])
128
    {
129
        if ($this->request()->ajax() && $this->request()->wantsJson()) {
130
            return $this->ajax();
131
        }
132
133
        if ($action = $this->request()->get('action') AND in_array($action, $this->actions)) {
134
            if ($action == 'print') {
135
                return $this->printPreview();
136
            }
137
138
            return call_user_func_array([$this, $action], []);
139
        }
140
141
        return $this->viewFactory->make($view, $data, $mergeData)->with('dataTable', $this->getHtmlBuilder());
142
    }
143
144
    /**
145
     * Get Datatables Request instance.
146
     *
147
     * @return \Yajra\DataTables\Request
148
     */
149
    public function request()
150
    {
151
        return $this->datatables->getRequest();
152
    }
153
154
    /**
155
     * Display ajax response.
156
     *
157
     * @return \Illuminate\Http\JsonResponse
158
     */
159
    public function ajax()
160
    {
161
        $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...
162
163
        if ($callback = $this->beforeCallback) {
164
            $callback($dataTable);
165
        }
166
167
        $response = $dataTable->make(true);
168
169
        if ($callback = $this->responseCallback) {
170
            $data     = new Collection($response->getData(true));
171
            $response = new JsonResponse($callback($data));
172
        }
173
174
        return $response;
175
    }
176
177
    /**
178
     * Display printable view of datatables.
179
     *
180
     * @return \Illuminate\Contracts\View\View
181
     */
182
    public function printPreview()
183
    {
184
        $data = $this->getDataForPrint();
185
186
        return $this->viewFactory->make($this->printPreview, compact('data'));
187
    }
188
189
    /**
190
     * Get mapped columns versus final decorated output.
191
     *
192
     * @return array
193
     */
194
    protected function getDataForPrint()
195
    {
196
        $columns = $this->printColumns();
197
198
        return $this->mapResponseToColumns($columns, 'printable');
199
    }
200
201
    /**
202
     * Get printable columns.
203
     *
204
     * @return array|string
205
     */
206
    protected function printColumns()
207
    {
208
        return is_array($this->printColumns) ? $this->printColumns : $this->getColumnsFromBuilder();
209
    }
210
211
    /**
212
     * Get columns definition from html builder.
213
     *
214
     * @return \Illuminate\Support\Collection
215
     */
216
    protected function getColumnsFromBuilder()
217
    {
218
        return $this->html()->getColumns();
219
    }
220
221
    /**
222
     * Optional method if you want to use html builder.
223
     *
224
     * @return \Yajra\DataTables\Html\Builder
225
     */
226
    public function html()
227
    {
228
        return $this->builder();
229
    }
230
231
    /**
232
     * Get Datatables Html Builder instance.
233
     *
234
     * @return \Yajra\DataTables\Html\Builder
235
     */
236
    public function builder()
237
    {
238
        return $this->htmlBuilder ?: $this->htmlBuilder = app('datatables.html');
239
    }
240
241
    /**
242
     * Map ajax response to columns definition.
243
     *
244
     * @param mixed  $columns
245
     * @param string $type
246
     * @return array
247
     */
248
    protected function mapResponseToColumns($columns, $type)
249
    {
250
        return array_map(function ($row) use ($columns, $type) {
251
            if ($columns) {
252
                return (new DataTransformer())->transform($row, $columns, $type);
253
            }
254
255
            return $row;
256
        }, $this->getAjaxResponseData());
257
    }
258
259
    /**
260
     * Get decorated data as defined in datatables ajax response.
261
     *
262
     * @return array
263
     */
264
    protected function getAjaxResponseData()
265
    {
266
        $this->datatables->getRequest()->merge(['length' => -1]);
267
268
        $response = $this->ajax();
269
        $data     = $response->getData(true);
270
271
        return $data['data'];
272
    }
273
274
    /**
275
     * @return \Yajra\DataTables\Html\Builder
276
     */
277
    protected function getHtmlBuilder()
278
    {
279
        $builder = $this->html();
280
        if ($this->htmlCallback) {
281
            call_user_func($this->htmlCallback, $builder);
282
        }
283
284
        return $builder;
285
    }
286
287
    /**
288
     * Add html builder callback hook.
289
     *
290
     * @param callable $callback
291
     * @return $this
292
     */
293
    public function withHtml(callable $callback)
294
    {
295
        $this->htmlCallback = $callback;
296
297
        return $this;
298
    }
299
300
    /**
301
     * Add callback before sending the response.
302
     *
303
     * @param callable $callback
304
     * @return $this
305
     */
306
    public function before(callable $callback)
307
    {
308
        $this->beforeCallback = $callback;
309
310
        return $this;
311
    }
312
313
    /**
314
     * Add callback after the response was processed.
315
     *
316
     * @param callable $callback
317
     * @return $this
318
     */
319
    public function response(callable $callback)
320
    {
321
        $this->responseCallback = $callback;
322
323
        return $this;
324
    }
325
326
    /**
327
     * Export results to Excel file.
328
     *
329
     * @return void
330
     */
331
    public function excel()
332
    {
333
        $this->buildExcelFile()->download('xls');
334
    }
335
336
    /**
337
     * Build excel file and prepare for export.
338
     *
339
     * @return \Maatwebsite\Excel\Writers\LaravelExcelWriter
340
     */
341
    protected function buildExcelFile()
342
    {
343
        /** @var \Maatwebsite\Excel\Excel $excel */
344
        $excel = app('excel');
345
346
        return $excel->create($this->getFilename(), function (LaravelExcelWriter $excel) {
347
            $excel->sheet('exported-data', function (LaravelExcelWorksheet $sheet) {
348
                $sheet->fromArray($this->getDataForExport());
349
            });
350
        });
351
    }
352
353
    /**
354
     * Get export filename.
355
     *
356
     * @return string
357
     */
358
    public function getFilename()
359
    {
360
        return $this->filename ?: $this->filename();
361
    }
362
363
    /**
364
     * Set export filename.
365
     *
366
     * @param string $filename
367
     * @return DataTable
368
     */
369
    public function setFilename($filename)
370
    {
371
        $this->filename = $filename;
372
373
        return $this;
374
    }
375
376
    /**
377
     * Get filename for export.
378
     *
379
     * @return string
380
     */
381
    protected function filename()
382
    {
383
        return 'export_' . time();
384
    }
385
386
    /**
387
     * Get mapped columns versus final decorated output.
388
     *
389
     * @return array
390
     */
391
    protected function getDataForExport()
392
    {
393
        $columns = $this->exportColumns();
394
395
        return $this->mapResponseToColumns($columns, 'exportable');
396
    }
397
398
    /**
399
     * Get export columns definition.
400
     *
401
     * @return array|string
402
     */
403
    private function exportColumns()
404
    {
405
        return is_array($this->exportColumns) ? $this->exportColumns : $this->getColumnsFromBuilder();
406
    }
407
408
    /**
409
     * Export results to CSV file.
410
     *
411
     * @return void
412
     */
413
    public function csv()
414
    {
415
        $this->buildExcelFile()->download('csv');
416
    }
417
418
    /**
419
     * Export results to PDF file.
420
     *
421
     * @return mixed
422
     */
423
    public function pdf()
424
    {
425
        if ('snappy' == config('datatables-buttons.pdf_generator', 'excel')) {
426
            return $this->snappyPdf();
427
        } else {
428
            $this->buildExcelFile()->download('pdf');
429
        }
430
    }
431
432
    /**
433
     * PDF version of the table using print preview blade template.
434
     *
435
     * @return mixed
436
     */
437
    public function snappyPdf()
438
    {
439
        /** @var \Barryvdh\Snappy\PdfWrapper $snappy */
440
        $snappy      = resolve('snappy.pdf.wrapper');
441
        $options     = config('datatables-buttons.snappy.options');
442
        $orientation = config('datatables-buttons.snappy.orientation');
443
444
        $snappy->setOptions($options)
445
               ->setOrientation($orientation);
446
447
        return $snappy->loadHTML($this->printPreview())
448
                      ->download($this->getFilename() . ".pdf");
449
    }
450
451
    /**
452
     * Add basic array query scopes.
453
     *
454
     * @param \Yajra\DataTables\Contracts\DataTableScopeContract $scope
455
     * @return $this
456
     */
457
    public function addScope(DataTableScopeContract $scope)
458
    {
459
        $this->scopes[] = $scope;
460
461
        return $this;
462
    }
463
464
    /**
465
     * Set a custom class attribute.
466
     *
467
     * @param mixed      $key
468
     * @param mixed|null $value
469
     * @return $this
470
     */
471
    public function with($key, $value = null)
472
    {
473
        if (is_array($key)) {
474
            $this->attributes = array_merge($this->attributes, $key);
475
        } else {
476
            $this->attributes[$key] = $value;
477
        }
478
479
        return $this;
480
    }
481
482
    /**
483
     * Dynamically retrieve the value of an attribute.
484
     *
485
     * @param string $key
486
     * @return mixed|null
487
     */
488
    public function __get($key)
489
    {
490
        if (array_key_exists($key, $this->attributes)) {
491
            return $this->attributes[$key];
492
        }
493
494
        return null;
495
    }
496
497
    /**
498
     * Apply query scopes.
499
     *
500
     * @param \Illuminate\Database\Query\Builder|\Illuminate\Database\Eloquent\Builder $query
501
     * @return mixed
502
     */
503
    protected function applyScopes($query)
504
    {
505
        foreach ($this->scopes as $scope) {
506
            $scope->apply($query);
507
        }
508
509
        return $query;
510
    }
511
512
    /**
513
     * Get default builder parameters.
514
     *
515
     * @return array
516
     */
517
    protected function getBuilderParameters()
518
    {
519
        return config('datatables-buttons.parameters');
520
    }
521
}
522