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: