1: <?php
  2: 
  3: namespace Yajra\Datatables\Services;
  4: 
  5: use Illuminate\Contracts\View\Factory;
  6: use Illuminate\Support\Facades\Config;
  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:  17:  18:  19:  20: 
 21: abstract class DataTable implements DataTableContract, DataTableButtonsContract
 22: {
 23:      24:  25: 
 26:     protected $datatables;
 27: 
 28:      29:  30: 
 31:     protected $viewFactory;
 32: 
 33:      34:  35:  36:  37: 
 38:     protected $printPreview = 'datatables::print';
 39: 
 40:      41:  42:  43:  44: 
 45:     protected $exportColumns = '*';
 46: 
 47:      48:  49:  50:  51: 
 52:     protected $printColumns = '*';
 53: 
 54:      55:  56:  57:  58: 
 59:     protected $scopes = [];
 60: 
 61:      62:  63:  64:  65: 
 66:     protected $htmlBuilder;
 67: 
 68:      69:  70:  71:  72: 
 73:     protected $filename = '';
 74: 
 75:      76:  77:  78:  79:  80: 
 81:     public function __construct(Datatables $datatables, Factory $viewFactory)
 82:     {
 83:         $this->datatables  = $datatables;
 84:         $this->viewFactory = $viewFactory;
 85:     }
 86: 
 87:      88:  89:  90:  91:  92:  93:  94: 
 95:     public function render($view, $data = [], $mergeData = [])
 96:     {
 97:         if ($this->request()->ajax() && $this->request()->wantsJson()) {
 98:             return $this->ajax();
 99:         }
100: 
101:         if ($action = $this->request()->get('action') AND in_array($action, ['print', 'csv', 'excel', 'pdf'])) {
102:             if ($action == 'print') {
103:                 return $this->printPreview();
104:             }
105: 
106:             return call_user_func_array([$this, $action], []);
107:         }
108: 
109:         return $this->viewFactory->make($view, $data, $mergeData)->with('dataTable', $this->html());
110:     }
111: 
112:     113: 114: 115: 116: 
117:     public function request()
118:     {
119:         return $this->datatables->getRequest();
120:     }
121: 
122:     123: 124: 125: 126: 
127:     public function printPreview()
128:     {
129:         $data = $this->getDataForPrint();
130: 
131:         return $this->viewFactory->make($this->printPreview, compact('data'));
132:     }
133: 
134:     135: 136: 137: 138: 
139:     protected function getDataForPrint()
140:     {
141:         $columns = $this->printColumns();
142: 
143:         return $this->mapResponseToColumns($columns, 'printable');
144:     }
145: 
146:     147: 148: 149: 150: 
151:     protected function printColumns()
152:     {
153:         return is_array($this->printColumns) ? $this->printColumns : $this->getColumnsFromBuilder();
154:     }
155: 
156:     157: 158: 159: 160: 
161:     protected function getColumnsFromBuilder()
162:     {
163:         return $this->html()->getColumns();
164:     }
165: 
166:     167: 168: 169: 170: 
171:     public function html()
172:     {
173:         return $this->builder();
174:     }
175: 
176:     177: 178: 179: 180: 
181:     public function builder()
182:     {
183:         return $this->htmlBuilder ?: $this->htmlBuilder = $this->datatables->getHtmlBuilder();
184:     }
185: 
186:     187: 188: 189: 190: 191: 192: 
193:     protected function mapResponseToColumns($columns, $type)
194:     {
195:         return array_map(function ($row) use ($columns, $type) {
196:             if ($columns) {
197:                 return (new DataTransformer())->transform($row, $columns, $type);
198:             }
199: 
200:             return $row;
201:         }, $this->getAjaxResponseData());
202:     }
203: 
204:     205: 206: 207: 208: 
209:     protected function getAjaxResponseData()
210:     {
211:         $this->datatables->getRequest()->merge(['length' => -1]);
212: 
213:         $response = $this->ajax();
214:         $data     = $response->getData(true);
215: 
216:         return $data['data'];
217:     }
218: 
219:     220: 221: 222: 223: 
224:     public function excel()
225:     {
226:         $this->buildExcelFile()->download('xls');
227:     }
228: 
229:     230: 231: 232: 233: 
234:     protected function buildExcelFile()
235:     {
236:         
237:         $excel = app('excel');
238: 
239:         return $excel->create($this->getFilename(), function (LaravelExcelWriter $excel) {
240:             $excel->sheet('exported-data', function (LaravelExcelWorksheet $sheet) {
241:                 $sheet->fromArray($this->getDataForExport());
242:             });
243:         });
244:     }
245: 
246:     247: 248: 249: 250: 
251:     public function getFilename()
252:     {
253:         return $this->filename ?: $this->filename();
254:     }
255: 
256:     257: 258: 259: 260: 261: 
262:     public function setFilename($filename)
263:     {
264:         $this->filename = $filename;
265: 
266:         return $this;
267:     }
268: 
269:     270: 271: 272: 273: 
274:     protected function filename()
275:     {
276:         return 'export_' . time();
277:     }
278: 
279:     280: 281: 282: 283: 
284:     protected function getDataForExport()
285:     {
286:         $columns = $this->exportColumns();
287: 
288:         return $this->mapResponseToColumns($columns, 'exportable');
289:     }
290: 
291:     292: 293: 294: 295: 
296:     private function exportColumns()
297:     {
298:         return is_array($this->exportColumns) ? $this->exportColumns : $this->getColumnsFromBuilder();
299:     }
300: 
301:     302: 303: 304: 305: 
306:     public function csv()
307:     {
308:         $this->buildExcelFile()->download('csv');
309:     }
310: 
311:     312: 313: 314: 315: 
316:     public function pdf()
317:     {
318:         if ('snappy' == Config::get('datatables.pdf_generator', 'excel')) {
319:             return $this->snappyPdf();
320:         } else {
321:             $this->buildExcelFile()->download('pdf');
322:         }
323:     }
324: 
325:     326: 327: 328: 329: 
330:     public function snappyPdf()
331:     {
332:         
333:         $snappy = app('snappy.pdf.wrapper');
334: 
335:         $options     = Config::get('datatables.snappy.options', [
336:             'no-outline'    => true,
337:             'margin-left'   => '0',
338:             'margin-right'  => '0',
339:             'margin-top'    => '10mm',
340:             'margin-bottom' => '10mm',
341:         ]);
342:         $orientation = Config::get('datatables.snappy.orientation', 'landscape');
343: 
344:         $snappy->setOptions($options)
345:                ->setOrientation($orientation);
346: 
347:         return $snappy->loadHTML($this->printPreview())
348:                       ->download($this->getFilename() . ".pdf");
349:     }
350: 
351:     352: 353: 354: 355: 356: 
357:     public function addScope(DataTableScopeContract $scope)
358:     {
359:         $this->scopes[] = $scope;
360: 
361:         return $this;
362:     }
363: 
364:     365: 366: 367: 368: 369: 
370:     protected function applyScopes($query)
371:     {
372:         foreach ($this->scopes as $scope) {
373:             $scope->apply($query);
374:         }
375: 
376:         return $query;
377:     }
378: 
379:     380: 381: 382: 383: 
384:     protected function getBuilderParameters()
385:     {
386:         return [
387:             'order'   => [[0, 'desc']],
388:             'buttons' => [
389:                 'create',
390:                 'export',
391:                 'print',
392:                 'reset',
393:                 'reload',
394:             ],
395:         ];
396:     }
397: }
398: