Completed
Pull Request — master (#10)
by Arjay
06:23
created

DataTable::applyScopes()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 8
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

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