Completed
Push — master ( bdd298...368b40 )
by Arjay
02:14
created

Builder::decodeCallbackFunctions()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 8
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 8
rs 9.4285
cc 2
eloc 4
nc 2
nop 2
1
<?php
2
3
namespace Yajra\Datatables\Html;
4
5
use Collective\Html\FormBuilder;
6
use Collective\Html\HtmlBuilder;
7
use Illuminate\Contracts\Config\Repository;
8
use Illuminate\Contracts\View\Factory;
9
use Illuminate\Routing\UrlGenerator;
10
use Illuminate\Support\Collection;
11
use Illuminate\Support\Str;
12
13
/**
14
 * Class Builder
15
 *
16
 * @package Yajra\Datatables\Html
17
 */
18
class Builder
19
{
20
    /**
21
     * @var Collection
22
     */
23
    public $collection;
24
25
    /**
26
     * @var Repository
27
     */
28
    public $config;
29
30
    /**
31
     * @var Factory
32
     */
33
    public $view;
34
35
    /**
36
     * @var HtmlBuilder
37
     */
38
    public $html;
39
40
    /**
41
     * @var UrlGenerator
42
     */
43
    public $url;
44
45
    /**
46
     * @var FormBuilder
47
     */
48
    public $form;
49
50
    /**
51
     * @var string|array
52
     */
53
    protected $ajax = '';
54
55
    /**
56
     * @var array
57
     */
58
    protected $tableAttributes = ['class' => 'table', 'id' => 'dataTableBuilder'];
59
60
    /**
61
     * @var string
62
     */
63
    protected $template = '';
64
65
    /**
66
     * @var array
67
     */
68
    protected $attributes = [];
69
70
    /**
71
     * Lists of valid DataTables Callbacks.
72
     *
73
     * @link https://datatables.net/reference/option/.
74
     * @var array
75
     */
76
    protected $validCallbacks = [
77
        'createdRow',
78
        'drawCallback',
79
        'footerCallback',
80
        'formatNumber',
81
        'headerCallback',
82
        'infoCallback',
83
        'initComplete',
84
        'preDrawCallback',
85
        'rowCallback',
86
        'stateLoadCallback',
87
        'stateLoaded',
88
        'stateLoadParams',
89
        'stateSaveCallback',
90
        'stateSaveParams',
91
    ];
92
93
    /**
94
     * @param Repository $config
95
     * @param Factory $view
96
     * @param HtmlBuilder $html
97
     * @param UrlGenerator $url
98
     * @param FormBuilder $form
99
     */
100
    public function __construct(
101
        Repository $config,
102
        Factory $view,
103
        HtmlBuilder $html,
104
        UrlGenerator $url,
105
        FormBuilder $form
106
    ) {
107
        $this->config     = $config;
108
        $this->view       = $view;
109
        $this->html       = $html;
110
        $this->url        = $url;
111
        $this->collection = new Collection;
112
        $this->form       = $form;
113
    }
114
115
    /**
116
     * Generate DataTable javascript.
117
     *
118
     * @param  null $script
119
     * @param  array $attributes
120
     * @return string
121
     */
122
    public function scripts($script = null, array $attributes = ['type' => 'text/javascript'])
123
    {
124
        $script = $script ?: $this->generateScripts();
125
126
        return '<script' . $this->html->attributes($attributes) . '>' . $script . '</script>' . PHP_EOL;
127
    }
128
129
    /**
130
     * Get generated raw scripts.
131
     *
132
     * @return string
133
     */
134
    public function generateScripts()
135
    {
136
        $args = array_merge(
137
            $this->attributes, [
138
                'ajax'    => $this->ajax,
139
                'columns' => $this->collection->toArray(),
140
            ]
141
        );
142
143
        $parameters = $this->parameterize($args);
144
145
        return sprintf(
146
            $this->template(),
147
            $this->tableAttributes['id'], $parameters
148
        );
149
    }
150
151
    /**
152
     * Generate DataTables js parameters.
153
     *
154
     * @param  array $attributes
155
     * @return string
156
     */
157
    public function parameterize($attributes = [])
158
    {
159
        $parameters = (new Parameters($attributes))->toArray();
160
161
        list($columnFunctions, $parameters) = $this->encodeColumnFunctions($parameters);
162
        list($callbackFunctions, $parameters) = $this->encodeCallbackFunctions($parameters);
163
164
        $json = json_encode($parameters);
165
166
        $json = $this->decodeColumnFunctions($columnFunctions, $json);
167
        $json = $this->decodeCallbackFunctions($callbackFunctions, $json);
168
169
        return $json;
170
    }
171
172
    /**
173
     * Encode columns render function.
174
     *
175
     * @param array $parameters
176
     * @return array
177
     */
178
    protected function encodeColumnFunctions(array $parameters)
179
    {
180
        $columnFunctions = [];
181
        foreach ($parameters['columns'] as $i => $column) {
182
            unset($parameters['columns'][$i]['exportable']);
183
            unset($parameters['columns'][$i]['printable']);
184
185
            if (isset($column['render'])) {
186
                $columnFunctions[$i]                 = $column['render'];
187
                $parameters['columns'][$i]['render'] = "#column_function.{$i}#";
188
            }
189
        }
190
191
        return [$columnFunctions, $parameters];
192
    }
193
194
    /**
195
     * Encode DataTables callbacks function.
196
     *
197
     * @param array $parameters
198
     * @return array
199
     */
200
    protected function encodeCallbackFunctions(array $parameters)
201
    {
202
        $callbackFunctions = [];
203
        foreach ($parameters as $key => $callback) {
204
            if (in_array($key, $this->validCallbacks)) {
205
                $callbackFunctions[$key] = $this->compileCallback($callback);
206
                $parameters[$key]        = "#callback_function.{$key}#";
207
            }
208
        }
209
210
        return [$callbackFunctions, $parameters];
211
    }
212
213
    /**
214
     * Compile DataTable callback value.
215
     *
216
     * @param mixed $callback
217
     * @return mixed|string
218
     */
219
    private function compileCallback($callback)
220
    {
221
        if (is_callable($callback)) {
222
            return value($callback);
223
        } elseif ($this->view->exists($callback)) {
224
            return $this->view->make($callback)->render();
225
        }
226
227
        return $callback;
228
    }
229
230
    /**
231
     * Decode columns render functions.
232
     *
233
     * @param array $columnFunctions
234
     * @param string $json
235
     * @return string
236
     */
237
    protected function decodeColumnFunctions(array $columnFunctions, $json)
238
    {
239
        foreach ($columnFunctions as $i => $function) {
240
            $json = str_replace("\"#column_function.{$i}#\"", $function, $json);
241
        }
242
243
        return $json;
244
    }
245
246
    /**
247
     * Decode DataTables callbacks function.
248
     *
249
     * @param array $callbackFunctions
250
     * @param string $json
251
     * @return string
252
     */
253
    protected function decodeCallbackFunctions(array $callbackFunctions, $json)
254
    {
255
        foreach ($callbackFunctions as $i => $function) {
256
            $json = str_replace("\"#callback_function.{$i}#\"", $function, $json);
257
        }
258
259
        return $json;
260
    }
261
262
    /**
263
     * Get javascript template to use.
264
     *
265
     * @return string
266
     */
267
    protected function template()
268
    {
269
        return $this->view->make(
270
            $this->template ?: $this->config->get('datatables.script_template', 'datatables::script')
271
        )->render();
272
    }
273
274
    /**
275
     * Add a column in collection using attributes.
276
     *
277
     * @param  array $attributes
278
     * @return $this
279
     */
280
    public function addColumn(array $attributes)
281
    {
282
        $this->collection->push(new Column($attributes));
283
284
        return $this;
285
    }
286
287
    /**
288
     * Add a Column object in collection.
289
     *
290
     * @param \Yajra\Datatables\Html\Column $column
291
     * @return $this
292
     */
293
    public function add(Column $column)
294
    {
295
        $this->collection->push($column);
296
297
        return $this;
298
    }
299
300
    /**
301
     * Set datatables columns from array definition.
302
     *
303
     * @param array $columns
304
     * @return $this
305
     */
306
    public function columns(array $columns)
307
    {
308
        foreach ($columns as $key => $value) {
309
            if (is_array($value)) {
310
                $attributes = array_merge(['name' => $key, 'data' => $key], $this->setTitle($key, $value));
311
            } else {
312
                $attributes = [
313
                    'name'  => $value,
314
                    'data'  => $value,
315
                    'title' => $this->getQualifiedTitle($value),
316
                ];
317
            }
318
319
            $this->collection->push(new Column($attributes));
320
        }
321
322
        return $this;
323
    }
324
325
    /**
326
     * Set title attribute of an array if not set.
327
     *
328
     * @param string $title
329
     * @param array $attributes
330
     * @return array
331
     */
332
    public function setTitle($title, array $attributes)
333
    {
334
        if (! isset($attributes['title'])) {
335
            $attributes['title'] = $this->getQualifiedTitle($title);
336
        }
337
338
        return $attributes;
339
    }
340
341
    /**
342
     * Convert string into a readable title.
343
     *
344
     * @param string $title
345
     * @return string
346
     */
347
    public function getQualifiedTitle($title)
348
    {
349
        return Str::title(str_replace(['.', '_'], ' ', Str::snake($title)));
350
    }
351
352
    /**
353
     * Add a checkbox column.
354
     *
355
     * @param  array $attributes
356
     * @return $this
357
     */
358
    public function addCheckbox(array $attributes = [])
359
    {
360
        $attributes = array_merge([
361
            'defaultContent' => '<input type="checkbox" ' . $this->html->attributes($attributes) . '/>',
362
            'title'          => $this->form->checkbox('', '', false, ['id' => 'dataTablesCheckbox']),
363
            'data'           => 'checkbox',
364
            'name'           => 'checkbox',
365
            'orderable'      => false,
366
            'searchable'     => false,
367
            'exportable'     => false,
368
            'printable'      => true,
369
            'width'          => '10px',
370
        ], $attributes);
371
        $this->collection->push(new Column($attributes));
372
373
        return $this;
374
    }
375
376
    /**
377
     * Add a action column.
378
     *
379
     * @param  array $attributes
380
     * @return $this
381
     */
382
    public function addAction(array $attributes = [])
383
    {
384
        $attributes = array_merge([
385
            'defaultContent' => '',
386
            'data'           => 'action',
387
            'name'           => 'action',
388
            'title'          => 'Action',
389
            'render'         => null,
390
            'orderable'      => false,
391
            'searchable'     => false,
392
            'exportable'     => false,
393
            'printable'      => true,
394
        ], $attributes);
395
        $this->collection->push(new Column($attributes));
396
397
        return $this;
398
    }
399
400
    /**
401
     * Setup ajax parameter
402
     *
403
     * @param  string|array $attributes
404
     * @return $this
405
     */
406
    public function ajax($attributes)
407
    {
408
        $this->ajax = $attributes;
409
410
        return $this;
411
    }
412
413
    /**
414
     * Generate DataTable's table html.
415
     *
416
     * @param  array $attributes
417
     * @return string
418
     */
419
    public function table(array $attributes = [])
420
    {
421
        $this->tableAttributes = array_merge($this->tableAttributes, $attributes);
422
423
        return '<table ' . $this->html->attributes($this->tableAttributes) . '></table>';
424
    }
425
426
    /**
427
     * Configure DataTable's parameters.
428
     *
429
     * @param  array $attributes
430
     * @return $this
431
     */
432
    public function parameters(array $attributes = [])
433
    {
434
        $this->attributes = array_merge($this->attributes, $attributes);
435
436
        return $this;
437
    }
438
439
    /**
440
     * Set custom javascript template.
441
     *
442
     * @param string $template
443
     * @return $this
444
     */
445
    public function setTemplate($template)
446
    {
447
        $this->template = $template;
448
449
        return $this;
450
    }
451
452
    /**
453
     * Get collection of columns.
454
     *
455
     * @return Collection
456
     */
457
    public function getColumns()
458
    {
459
        return $this->collection;
460
    }
461
}
462