Issues (7)

Security Analysis    no request data  

This project does not seem to handle request data directly as such no vulnerable execution paths were found.

  Cross-Site Scripting
Cross-Site Scripting enables an attacker to inject code into the response of a web-request that is viewed by other users. It can for example be used to bypass access controls, or even to take over other users' accounts.
  File Exposure
File Exposure allows an attacker to gain access to local files that he should not be able to access. These files can for example include database credentials, or other configuration files.
  File Manipulation
File Manipulation enables an attacker to write custom data to files. This potentially leads to injection of arbitrary code on the server.
  Object Injection
Object Injection enables an attacker to inject an object into PHP code, and can lead to arbitrary code execution, file exposure, or file manipulation attacks.
  Code Injection
Code Injection enables an attacker to execute arbitrary code on the server.
  Response Splitting
Response Splitting can be used to send arbitrary responses.
  File Inclusion
File Inclusion enables an attacker to inject custom files into PHP's file loading mechanism, either explicitly passed to include, or for example via PHP's auto-loading mechanism.
  Command Injection
Command Injection enables an attacker to inject a shell command that is execute with the privileges of the web-server. This can be used to expose sensitive data, or gain access of your server.
  SQL Injection
SQL Injection enables an attacker to execute arbitrary SQL code on your database server gaining access to user data, or manipulating user data.
  XPath Injection
XPath Injection enables an attacker to modify the parts of XML document that are read. If that XML document is for example used for authentication, this can lead to further vulnerabilities similar to SQL Injection.
  LDAP Injection
LDAP Injection enables an attacker to inject LDAP statements potentially granting permission to run unauthorized queries, or modify content inside the LDAP tree.
  Header Injection
  Other Vulnerability
This category comprises other attack vectors such as manipulating the PHP runtime, loading custom extensions, freezing the runtime, or similar.
  Regex Injection
Regex Injection enables an attacker to execute arbitrary code in your PHP process.
  XML Injection
XML Injection enables an attacker to read files on your local filesystem including configuration files, or can be abused to freeze your web-server process.
  Variable Injection
Variable Injection enables an attacker to overwrite program variables with custom data, and can lead to further vulnerabilities.
Unfortunately, the security analysis is currently not available for your project. If you are a non-commercial open-source project, please contact support to gain access.

src/Services/DataTable.php (1 issue)

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

1
<?php
2
3
namespace Yajra\DataTables\Services;
4
5
use Illuminate\Http\JsonResponse;
6
use Illuminate\Support\Collection;
7
use Yajra\DataTables\Contracts\DataTableButtons;
8
use Yajra\DataTables\Contracts\DataTableScope;
9
use Yajra\DataTables\Html\Column;
10
use Yajra\DataTables\Transformers\DataArrayTransformer;
11
12
abstract class DataTable implements DataTableButtons
13
{
14
    /**
15
     * DataTables print preview view.
16
     *
17
     * @var string
18
     */
19
    protected $printPreview = 'datatables::print';
20
21
    /**
22
     * Name of the dataTable variable.
23
     *
24
     * @var string
25
     */
26
    protected $dataTableVariable = 'dataTable';
27
28
    /**
29
     * List of columns to be excluded from export.
30
     *
31
     * @var string|array
32
     */
33
    protected $excludeFromExport = [];
34
35
    /**
36
     * List of columns to be excluded from printing.
37
     *
38
     * @var string|array
39
     */
40
    protected $excludeFromPrint = [];
41
42
    /**
43
     * List of columns to be exported.
44
     *
45
     * @var string|array
46
     */
47
    protected $exportColumns = '*';
48
49
    /**
50
     * List of columns to be printed.
51
     *
52
     * @var string|array
53
     */
54
    protected $printColumns = '*';
55
56
    /**
57
     * Query scopes.
58
     *
59
     * @var \Yajra\DataTables\Contracts\DataTableScope[]
60
     */
61
    protected $scopes = [];
62
63
    /**
64
     * Html builder.
65
     *
66
     * @var \Yajra\DataTables\Html\Builder
67
     */
68
    protected $htmlBuilder;
69
70
    /**
71
     * Html builder extension callback.
72
     *
73
     * @var callable
74
     */
75
    protected $htmlCallback;
76
77
    /**
78
     * Export filename.
79
     *
80
     * @var string
81
     */
82
    protected $filename = '';
83
84
    /**
85
     * Custom attributes set on the class.
86
     *
87
     * @var array
88
     */
89
    protected $attributes = [];
90
91
    /**
92
     * Callback before sending the response.
93
     *
94
     * @var callable
95
     */
96
    protected $beforeCallback;
97
98
    /**
99
     * Callback after processing the response.
100
     *
101
     * @var callable
102
     */
103
    protected $responseCallback;
104
105
    /**
106
     * Available button actions. When calling an action, the value will be used
107
     * as the function name (so it should be available)
108
     * If you want to add or disable an action, overload and modify this property.
109
     *
110
     * @var array
111
     */
112
    protected $actions = ['print', 'csv', 'excel', 'pdf'];
113
114
    /**
115
     * @var \Yajra\DataTables\Utilities\Request
116
     */
117
    protected $request;
118
119
    /**
120
     * Export class handler.
121
     *
122
     * @var string
123
     */
124
    protected $exportClass = DataTablesExportHandler::class;
125
126
    /**
127
     * CSV export type writer.
128
     *
129
     * @var string
130
     */
131
    protected $csvWriter = 'Csv';
132
133
    /**
134
     * Excel export type writer.
135
     *
136
     * @var string
137
     */
138
    protected $excelWriter = 'Xlsx';
139
140
    /**
141
     * PDF export type writer.
142
     *
143
     * @var string
144
     */
145
    protected $pdfWriter = 'Dompdf';
146
147
    /**
148
     * Process dataTables needed render output.
149
     *
150
     * @param string $view
151
     * @param array $data
152
     * @param array $mergeData
153
     * @return mixed
154
     */
155
    public function render($view, $data = [], $mergeData = [])
156
    {
157
        if ($this->request()->ajax() && $this->request()->wantsJson()) {
158
            return app()->call([$this, 'ajax']);
159
        }
160
161
        if ($action = $this->request()->get('action') and in_array($action, $this->actions)) {
162
            if ($action == 'print') {
163
                return app()->call([$this, 'printPreview']);
164
            }
165
166
            return app()->call([$this, $action]);
167
        }
168
169
        return view($view, $data, $mergeData)->with($this->dataTableVariable, $this->getHtmlBuilder());
170
    }
171
172
    /**
173
     * Get DataTables Request instance.
174
     *
175
     * @return \Yajra\DataTables\Utilities\Request
176
     */
177
    public function request()
178
    {
179
        return $this->request ?: $this->request = app('datatables.request');
180
    }
181
182
    /**
183
     * Display ajax response.
184
     *
185
     * @return \Illuminate\Http\JsonResponse
186
     */
187
    public function ajax()
188
    {
189
        $query = null;
190
        if (method_exists($this, 'query')) {
191
            $query = app()->call([$this, 'query']);
192
            $query = $this->applyScopes($query);
193
        }
194
195
        /** @var \Yajra\DataTables\DataTableAbstract $dataTable */
196
        $dataTable = app()->call([$this, 'dataTable'], compact('query'));
197
198
        if ($callback = $this->beforeCallback) {
199
            $callback($dataTable);
200
        }
201
202
        if ($callback = $this->responseCallback) {
203
            $data = new Collection($dataTable->toArray());
204
205
            return new JsonResponse($callback($data));
206
        }
207
208
        return $dataTable->toJson();
209
    }
210
211
    /**
212
     * Display printable view of datatables.
213
     *
214
     * @return \Illuminate\Contracts\View\View
215
     */
216
    public function printPreview()
217
    {
218
        $data = $this->getDataForPrint();
219
220
        return view($this->printPreview, compact('data'));
221
    }
222
223
    /**
224
     * Get mapped columns versus final decorated output.
225
     *
226
     * @return array
227
     */
228
    protected function getDataForPrint()
229
    {
230
        $columns = $this->printColumns();
231
232
        return $this->mapResponseToColumns($columns, 'printable');
233
    }
234
235
    /**
236
     * Get printable columns.
237
     *
238
     * @return array|string
239
     */
240
    protected function printColumns()
241
    {
242
        return is_array($this->printColumns) ? $this->toColumnsCollection($this->printColumns) : $this->getPrintColumnsFromBuilder();
243
    }
244
245
    /**
246
     * Get filtered print columns definition from html builder.
247
     *
248
     * @return \Illuminate\Support\Collection
249
     */
250
    protected function getPrintColumnsFromBuilder()
251
    {
252
        return $this->html()->removeColumn(...$this->excludeFromPrint)->getColumns();
253
    }
254
255
    /**
256
     * Get filtered export columns definition from html builder.
257
     *
258
     * @return \Illuminate\Support\Collection
259
     */
260
    protected function getExportColumnsFromBuilder()
261
    {
262
        return $this->html()->removeColumn(...$this->excludeFromExport)->getColumns();
263
    }
264
265
    /**
266
     * Get columns definition from html builder.
267
     *
268
     * @return \Illuminate\Support\Collection
269
     */
270
    protected function getColumnsFromBuilder()
271
    {
272
        return $this->html()->getColumns();
273
    }
274
275
    /**
276
     * Optional method if you want to use html builder.
277
     *
278
     * @return \Yajra\DataTables\Html\Builder
279
     */
280
    public function html()
281
    {
282
        return $this->builder();
283
    }
284
285
    /**
286
     * Get DataTables Html Builder instance.
287
     *
288
     * @return \Yajra\DataTables\Html\Builder
289
     */
290
    public function builder()
291
    {
292
        if ($this->htmlBuilder) {
293
            return $this->htmlBuilder;
294
        }
295
296
        if (method_exists($this, 'htmlBuilder')) {
297
            return $this->htmlBuilder = app()->call([$this, 'htmlBuilder']);
298
        }
299
300
        return $this->htmlBuilder = app('datatables.html');
301
    }
302
303
    /**
304
     * Map ajax response to columns definition.
305
     *
306
     * @param mixed $columns
307
     * @param string $type
308
     * @return array
309
     */
310
    protected function mapResponseToColumns($columns, $type)
311
    {
312
        $transformer = new DataArrayTransformer;
313
314
        return array_map(function ($row) use ($columns, $type, $transformer) {
315
            return $transformer->transform($row, $columns, $type);
316
        }, $this->getAjaxResponseData());
317
    }
318
319
    /**
320
     * Get decorated data as defined in datatables ajax response.
321
     *
322
     * @return array
323
     */
324
    protected function getAjaxResponseData()
325
    {
326
        $this->request()->merge(['length' => -1]);
327
328
        $response = app()->call([$this, 'ajax']);
329
        $data     = $response->getData(true);
330
331
        return $data['data'];
332
    }
333
334
    /**
335
     * @return \Yajra\DataTables\Html\Builder
336
     */
337
    protected function getHtmlBuilder()
338
    {
339
        $builder = $this->html();
340
        if ($this->htmlCallback) {
341
            call_user_func($this->htmlCallback, $builder);
342
        }
343
344
        return $builder;
345
    }
346
347
    /**
348
     * Add html builder callback hook.
349
     *
350
     * @param callable $callback
351
     * @return $this
352
     */
353
    public function withHtml(callable $callback)
354
    {
355
        $this->htmlCallback = $callback;
356
357
        return $this;
358
    }
359
360
    /**
361
     * Add callback before sending the response.
362
     *
363
     * @param callable $callback
364
     * @return $this
365
     */
366
    public function before(callable $callback)
367
    {
368
        $this->beforeCallback = $callback;
369
370
        return $this;
371
    }
372
373
    /**
374
     * Add callback after the response was processed.
375
     *
376
     * @param callable $callback
377
     * @return $this
378
     */
379
    public function response(callable $callback)
380
    {
381
        $this->responseCallback = $callback;
382
383
        return $this;
384
    }
385
386
    /**
387
     * Export results to Excel file.
388
     *
389
     * @return void
390
     */
391
    public function excel()
392
    {
393
        $ext = '.' . strtolower($this->excelWriter);
394
395
        return $this->buildExcelFile()->download($this->getFilename() . $ext, $this->excelWriter);
396
    }
397
398
    /**
399
     * Build excel file and prepare for export.
400
     *
401
     * @return \Maatwebsite\Excel\Concerns\Exportable
0 ignored issues
show
Comprehensibility Bug introduced by
The return type \Maatwebsite\Excel\Concerns\Exportable is a trait, and thus cannot be used for type-hinting in PHP. Maybe consider adding an interface and use that for type-hinting?

In PHP traits cannot be used for type-hinting as they do not define a well-defined structure. This is because any class that uses a trait can rename that trait’s methods.

If you would like to return an object that has a guaranteed set of methods, you could create a companion interface that lists these methods explicitly.

Loading history...
402
     */
403
    protected function buildExcelFile()
404
    {
405
        $dataForExport = collect($this->getDataForExport());
406
407
        return new $this->exportClass($dataForExport);
408
    }
409
410
    /**
411
     * Get export filename.
412
     *
413
     * @return string
414
     */
415
    public function getFilename()
416
    {
417
        return $this->filename ?: $this->filename();
418
    }
419
420
    /**
421
     * Set export filename.
422
     *
423
     * @param string $filename
424
     * @return DataTable
425
     */
426
    public function setFilename($filename)
427
    {
428
        $this->filename = $filename;
429
430
        return $this;
431
    }
432
433
    /**
434
     * Get filename for export.
435
     *
436
     * @return string
437
     */
438
    protected function filename()
439
    {
440
        return class_basename($this) . '_' . date('YmdHis');
441
    }
442
443
    /**
444
     * Get mapped columns versus final decorated output.
445
     *
446
     * @return array
447
     */
448
    protected function getDataForExport()
449
    {
450
        $columns = $this->exportColumns();
451
452
        return $this->mapResponseToColumns($columns, 'exportable');
453
    }
454
455
    /**
456
     * Get export columns definition.
457
     *
458
     * @return array|string
459
     */
460
    private function exportColumns()
461
    {
462
        return is_array($this->exportColumns) ? $this->toColumnsCollection($this->exportColumns) : $this->getExportColumnsFromBuilder();
463
    }
464
465
    /**
466
     * Convert array to collection of Column class.
467
     *
468
     * @param array $columns
469
     * @return Collection
470
     */
471
    private function toColumnsCollection(array $columns)
472
    {
473
        $collection = collect();
474
        foreach ($columns as $column) {
475
            if (isset($column['data'])) {
476
                $column['title'] = $column['title'] ?? $column['data'];
477
                $collection->push(new Column($column));
478
            } else {
479
                $data          = [];
480
                $data['data']  = $column;
481
                $data['title'] = $column;
482
                $collection->push(new Column($data));
483
            }
484
        }
485
486
        return $collection;
487
    }
488
489
    /**
490
     * Export results to CSV file.
491
     *
492
     * @return mixed
493
     */
494
    public function csv()
495
    {
496
        $ext = '.' . strtolower($this->csvWriter);
497
498
        return $this->buildExcelFile()->download($this->getFilename() . $ext, $this->csvWriter);
499
    }
500
501
    /**
502
     * Export results to PDF file.
503
     *
504
     * @return mixed
505
     */
506
    public function pdf()
507
    {
508
        if ('snappy' == config('datatables-buttons.pdf_generator', 'snappy')) {
509
            return $this->snappyPdf();
510
        }
511
512
        return $this->buildExcelFile()->download($this->getFilename() . '.pdf', $this->pdfWriter);
513
    }
514
515
    /**
516
     * PDF version of the table using print preview blade template.
517
     *
518
     * @return mixed
519
     */
520
    public function snappyPdf()
521
    {
522
        /** @var \Barryvdh\Snappy\PdfWrapper $snappy */
523
        $snappy      = app('snappy.pdf.wrapper');
524
        $options     = config('datatables-buttons.snappy.options');
525
        $orientation = config('datatables-buttons.snappy.orientation');
526
527
        $snappy->setOptions($options)->setOrientation($orientation);
528
529
        return $snappy->loadHTML($this->printPreview())->download($this->getFilename() . '.pdf');
530
    }
531
532
    /**
533
     * Add basic array query scopes.
534
     *
535
     * @param \Yajra\DataTables\Contracts\DataTableScope $scope
536
     * @return $this
537
     */
538
    public function addScope(DataTableScope $scope)
539
    {
540
        $this->scopes[] = $scope;
541
542
        return $this;
543
    }
544
545
    /**
546
     * Push multiples scopes to array query scopes.
547
     *
548
     * @param array $scopes
549
     * @return $this
550
     */
551
    public function addScopes(array $scopes)
552
    {
553
        array_push($this->scopes, $scopes);
554
555
        return $this;
556
    }
557
558
    /**
559
     * Set a custom class attribute.
560
     *
561
     * @param mixed $key
562
     * @param mixed|null $value
563
     * @return $this
564
     */
565
    public function with($key, $value = null)
566
    {
567
        if (is_array($key)) {
568
            $this->attributes = array_merge($this->attributes, $key);
569
        } else {
570
            $this->attributes[$key] = $value;
571
        }
572
573
        return $this;
574
    }
575
576
    /**
577
     * Dynamically retrieve the value of an attribute.
578
     *
579
     * @param string $key
580
     * @return mixed|null
581
     */
582
    public function __get($key)
583
    {
584
        if (array_key_exists($key, $this->attributes)) {
585
            return $this->attributes[$key];
586
        }
587
    }
588
589
    /**
590
     * Apply query scopes.
591
     *
592
     * @param \Illuminate\Database\Query\Builder|\Illuminate\Database\Eloquent\Builder $query
593
     * @return mixed
594
     */
595
    protected function applyScopes($query)
596
    {
597
        foreach ($this->scopes as $scope) {
598
            $scope->apply($query);
599
        }
600
601
        return $query;
602
    }
603
604
    /**
605
     * Determine if the DataTable has scopes.
606
     *
607
     * @param  array $scopes
608
     * @param  bool $validateAll
609
     * @return bool
610
     */
611
    protected function hasScopes(array $scopes, $validateAll = false)
612
    {
613
        $filteredScopes = array_filter($this->scopes, function ($scope) use ($scopes) {
614
            return in_array(get_class($scope), $scopes);
615
        });
616
617
        return $validateAll ? count($filteredScopes) === count($scopes) : ! empty($filteredScopes);
618
    }
619
620
    /**
621
     * Get default builder parameters.
622
     *
623
     * @return array
624
     */
625
    protected function getBuilderParameters()
626
    {
627
        return config('datatables-buttons.parameters');
628
    }
629
}
630