Completed
Pull Request — master (#13)
by Arjay
01:42
created

DataTable::response()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

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