Completed
Push — master ( 1504b8...22bc8c )
by Arjay
02:35
created

Builder::getQualifiedTitle()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

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