Completed
Push — master ( d114d2...bdd298 )
by Arjay
02:23
created

Builder::parameterize()   C

Complexity

Conditions 7
Paths 36

Size

Total Lines 35
Code Lines 20

Duplication

Lines 0
Ratio 0 %

Importance

Changes 6
Bugs 4 Features 3
Metric Value
c 6
b 4
f 3
dl 0
loc 35
rs 6.7272
cc 7
eloc 20
nc 36
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
 */
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 datatable js parameters.
153
     *
154
     * @param  array $attributes
155
     * @return string
156
     */
157
    public function parameterize($attributes = [])
158
    {
159
        $parameters        = (new Parameters($attributes))->toArray();
160
        $columnFunctions   = [];
161
        $callbackFunctions = [];
162
163
        foreach ($parameters['columns'] as $i => $column) {
164
            unset($parameters['columns'][$i]['exportable']);
165
            unset($parameters['columns'][$i]['printable']);
166
167
            if (isset($column['render'])) {
168
                $columnFunctions[$i]                 = $column['render'];
169
                $parameters['columns'][$i]['render'] = "#column_function.{$i}#";
170
            }
171
        }
172
173
        foreach ($parameters as $key => $callback) {
174
            if (in_array($key, $this->validCallbacks)) {
175
                $callbackFunctions[$key] = $this->compileCallback($callback);
176
                $parameters[$key]        = "#callback_function.{$key}#";
177
            }
178
        }
179
180
        $json = json_encode($parameters);
181
182
        foreach ($columnFunctions as $i => $function) {
183
            $json = str_replace("\"#column_function.{$i}#\"", $function, $json);
184
        }
185
186
        foreach ($callbackFunctions as $i => $function) {
187
            $json = str_replace("\"#callback_function.{$i}#\"", $function, $json);
188
        }
189
190
        return $json;
191
    }
192
193
    /**
194
     * Compile DataTable callback value.
195
     *
196
     * @param mixed $callback
197
     * @return mixed|string
198
     */
199
    private function compileCallback($callback)
200
    {
201
        if (is_callable($callback)) {
202
            return value($callback);
203
        } elseif ($this->view->exists($callback)) {
204
            return $this->view->make($callback)->render();
205
        }
206
207
        return $callback;
208
    }
209
210
    /**
211
     * Get javascript template to use.
212
     *
213
     * @return string
214
     */
215
    protected function template()
216
    {
217
        return $this->view->make(
218
            $this->template ?: $this->config->get('datatables.script_template', 'datatables::script')
219
        )->render();
220
    }
221
222
    /**
223
     * Add a column in collection using attributes.
224
     *
225
     * @param  array $attributes
226
     * @return $this
227
     */
228
    public function addColumn(array $attributes)
229
    {
230
        $this->collection->push(new Column($attributes));
231
232
        return $this;
233
    }
234
235
    /**
236
     * Add a Column object in collection.
237
     *
238
     * @param \Yajra\Datatables\Html\Column $column
239
     * @return $this
240
     */
241
    public function add(Column $column)
242
    {
243
        $this->collection->push($column);
244
245
        return $this;
246
    }
247
248
    /**
249
     * Set datatables columns from array definition.
250
     *
251
     * @param array $columns
252
     * @return $this
253
     */
254
    public function columns(array $columns)
255
    {
256
        foreach ($columns as $key => $value) {
257
            if (is_array($value)) {
258
                $attributes = array_merge(['name' => $key, 'data' => $key], $this->setTitle($key, $value));
259
            } else {
260
                $attributes = [
261
                    'name'  => $value,
262
                    'data'  => $value,
263
                    'title' => $this->getQualifiedTitle($value),
264
                ];
265
            }
266
267
            $this->collection->push(new Column($attributes));
268
        }
269
270
        return $this;
271
    }
272
273
    /**
274
     * Set title attribute of an array if not set.
275
     *
276
     * @param string $title
277
     * @param array $attributes
278
     * @return array
279
     */
280
    public function setTitle($title, array $attributes)
281
    {
282
        if (! isset($attributes['title'])) {
283
            $attributes['title'] = $this->getQualifiedTitle($title);
284
        }
285
286
        return $attributes;
287
    }
288
289
    /**
290
     * Convert string into a readable title.
291
     *
292
     * @param string $title
293
     * @return string
294
     */
295
    public function getQualifiedTitle($title)
296
    {
297
        return Str::title(str_replace(['.', '_'], ' ', Str::snake($title)));
298
    }
299
300
    /**
301
     * Add a checkbox column.
302
     *
303
     * @param  array $attributes
304
     * @return $this
305
     */
306
    public function addCheckbox(array $attributes = [])
307
    {
308
        $attributes = array_merge([
309
            'defaultContent' => '<input type="checkbox" ' . $this->html->attributes($attributes) . '/>',
310
            'title'          => $this->form->checkbox('', '', false, ['id' => 'dataTablesCheckbox']),
311
            'data'           => 'checkbox',
312
            'name'           => 'checkbox',
313
            'orderable'      => false,
314
            'searchable'     => false,
315
            'exportable'     => false,
316
            'printable'      => true,
317
            'width'          => '10px',
318
        ], $attributes);
319
        $this->collection->push(new Column($attributes));
320
321
        return $this;
322
    }
323
324
    /**
325
     * Add a action column.
326
     *
327
     * @param  array $attributes
328
     * @return $this
329
     */
330
    public function addAction(array $attributes = [])
331
    {
332
        $attributes = array_merge([
333
            'defaultContent' => '',
334
            'data'           => 'action',
335
            'name'           => 'action',
336
            'title'          => 'Action',
337
            'render'         => null,
338
            'orderable'      => false,
339
            'searchable'     => false,
340
            'exportable'     => false,
341
            'printable'      => true,
342
        ], $attributes);
343
        $this->collection->push(new Column($attributes));
344
345
        return $this;
346
    }
347
348
    /**
349
     * Setup ajax parameter
350
     *
351
     * @param  string|array $attributes
352
     * @return $this
353
     */
354
    public function ajax($attributes)
355
    {
356
        $this->ajax = $attributes;
357
358
        return $this;
359
    }
360
361
    /**
362
     * Generate DataTable's table html.
363
     *
364
     * @param  array $attributes
365
     * @return string
366
     */
367
    public function table(array $attributes = [])
368
    {
369
        $this->tableAttributes = array_merge($this->tableAttributes, $attributes);
370
371
        return '<table ' . $this->html->attributes($this->tableAttributes) . '></table>';
372
    }
373
374
    /**
375
     * Configure DataTable's parameters.
376
     *
377
     * @param  array $attributes
378
     * @return $this
379
     */
380
    public function parameters(array $attributes = [])
381
    {
382
        $this->attributes = array_merge($this->attributes, $attributes);
383
384
        return $this;
385
    }
386
387
    /**
388
     * Set custom javascript template.
389
     *
390
     * @param string $template
391
     * @return $this
392
     */
393
    public function setTemplate($template)
394
    {
395
        $this->template = $template;
396
397
        return $this;
398
    }
399
400
    /**
401
     * Get collection of columns.
402
     *
403
     * @return Collection
404
     */
405
    public function getColumns()
406
    {
407
        return $this->collection;
408
    }
409
}
410