Completed
Push — master ( 1a19db...c922a9 )
by Song
02:53
created

Column::setOriginalGridData()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 2
nc 1
nop 1
dl 0
loc 4
rs 10
c 0
b 0
f 0
1
<?php
2
3
namespace Encore\Admin\Grid;
4
5
use Closure;
6
use Encore\Admin\Grid;
7
use Illuminate\Support\Facades\URL;
8
9
class Column
10
{
11
    /**
12
     * @var Grid
13
     */
14
    protected $grid;
15
16
    /**
17
     * Name of column.
18
     *
19
     * @var string
20
     */
21
    protected $name;
22
23
    /**
24
     * Label of column.
25
     *
26
     * @var string
27
     */
28
    protected $label;
29
30
    /**
31
     * Original value of column.
32
     *
33
     * @var mixed
34
     */
35
    protected $original;
36
37
    /**
38
     * Is column sortable.
39
     *
40
     * @var bool
41
     */
42
    protected $sortable = false;
43
44
    /**
45
     * Sort arguments.
46
     *
47
     * @var array
48
     */
49
    protected $sort;
50
51
    /**
52
     * Attributes of column.
53
     *
54
     * @var array
55
     */
56
    protected $attributes = [];
57
58
    /**
59
     * Value callback.
60
     *
61
     * @var \Closure
62
     */
63
    protected $valueCallback;
64
65
    /**
66
     * Html callback.
67
     *
68
     * @var array
69
     */
70
    protected $htmlCallbacks = [];
71
72
    /**
73
     * Relation name.
74
     *
75
     * @var bool
76
     */
77
    protected $relation = false;
78
79
    /**
80
     * Relation column.
81
     *
82
     * @var string
83
     */
84
    protected $relationColumn;
85
86
    /**
87
     * Original grid data.
88
     *
89
     * @var array
90
     */
91
    protected static $originalGridData = [];
92
93
    /**
94
     * @param string $name
95
     * @param string $label
96
     */
97
    public function __construct($name, $label)
98
    {
99
        $this->name = $name;
100
101
        $this->label = $this->formatLabel($label);
102
    }
103
104
    /**
105
     * @param Grid $grid
106
     */
107
    public function setGrid(Grid $grid)
108
    {
109
        $this->grid = $grid;
110
    }
111
112
    /**
113
     * Get name of this column.
114
     *
115
     * @return mixed
116
     */
117
    public function getName()
118
    {
119
        return $this->name;
120
    }
121
122
    /**
123
     * Format label.
124
     *
125
     * @param $label
126
     *
127
     * @return mixed
128
     */
129
    protected function formatLabel($label)
130
    {
131
        $label = $label ?: ucfirst($this->name);
132
133
        return str_replace(['.', '_'], ' ', $label);
134
    }
135
136
    /**
137
     * Get label of the column.
138
     *
139
     * @return mixed
140
     */
141
    public function getLabel()
142
    {
143
        return $this->label;
144
    }
145
146
    /**
147
     * Set relation.
148
     *
149
     * @param $relation
150
     *
151
     * @return $this
152
     */
153
    public function setRelation($relation)
154
    {
155
        $this->relation = $relation;
156
157
        return $this;
158
    }
159
160
    /**
161
     * If this column is relation column.
162
     *
163
     * @return bool
164
     */
165
    protected function isRelation()
166
    {
167
        return (bool) $this->relation;
168
    }
169
170
    /**
171
     * Mark this column as sortable.
172
     *
173
     * @return Column
174
     */
175
    public function sortable()
176
    {
177
        $this->sortable = true;
178
179
        return $this;
180
    }
181
182
    /**
183
     * Wrap value with badge.
184
     *
185
     * @param string $style
186
     *
187
     * @return $this
188
     */
189
    public function badge($style = 'red')
190
    {
191
        $callback = "<span class='badge bg-{$style}'>{value}</span>";
192
193
        $this->htmlCallback($callback);
194
195
        return $this;
196
    }
197
198
    /**
199
     * Wrap value with label.
200
     *
201
     * @param string $style
202
     *
203
     * @return $this
204
     */
205
    public function label($style = 'success')
206
    {
207
        $callback = "<span class='label label-{$style}'>{value}</span>";
208
209
        $this->htmlCallback($callback);
210
211
        return $this;
212
    }
213
214
    /**
215
     * Wrap value as a link.
216
     *
217
     * @param $href
218
     * @param string $target
219
     *
220
     * @return $this
221
     */
222
    public function link($href = '', $target = '_blank')
223
    {
224
        if (empty($href)) {
225
            $href = '{$value}';
226
        }
227
228
        $callback = "<a href='$href' target='$target'>{value}</a>";
229
230
        $this->htmlCallback($callback);
231
232
        return $this;
233
    }
234
235
    /**
236
     * Wrap value as a button.
237
     *
238
     * @param string $style
239
     *
240
     * @return $this
241
     */
242 View Code Duplication
    public function button($style = 'default')
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
243
    {
244
        if (is_array($style)) {
245
            $style = array_map(function ($style) {
246
                return 'btn-'.$style;
247
            }, $style);
248
249
            $style = implode(' ', $style);
250
        } elseif (is_string($style)) {
251
            $style = 'btn-'.$style;
252
        }
253
254
        $callback = "<span class='btn $style'>{value}</span>";
255
256
        $this->htmlCallback($callback);
257
258
        return $this;
259
    }
260
261
    /**
262
     * Wrap value as a progressbar.
263
     *
264
     * @param string $style
265
     * @param string $size
266
     * @param int    $max
267
     *
268
     * @return $this
269
     */
270 View Code Duplication
    public function progressBar($style = 'primary', $size = 'sm', $max = 100)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
271
    {
272
        if (is_array($style)) {
273
            $style = array_map(function ($style) {
274
                return 'progress-bar-'.$style;
275
            }, $style);
276
277
            $style = implode(' ', $style);
278
        } elseif (is_string($style)) {
279
            $style = 'progress-bar-'.$style;
280
        }
281
282
        $callback = <<<EOT
283
284
<div class="progress progress-$size">
285
    <div class="progress-bar $style" role="progressbar" aria-valuenow="{value}" aria-valuemin="0" aria-valuemax="$max" style="width: {value}%">
286
      <span class="sr-only">{value}</span>
287
    </div>
288
</div>
289
290
EOT;
291
292
        $this->htmlCallback($callback);
293
294
        return $this;
295
    }
296
297
    /**
298
     * Wrap value as a image.
299
     *
300
     * @param string $server
301
     * @param int    $width
302
     * @param int    $height
303
     *
304
     * @return $this
305
     */
306
    public function image($server = '', $width = 200, $height = 200)
307
    {
308
        $server = $server ?: config('admin.upload.host');
309
310
        $callback = "<img src='$server/{\$value}' style='max-width:{$width}px;max-height:{$height}px' class='img img-thumbnail' />";
311
312
        $this->htmlCallback($callback);
313
314
        return $this;
315
    }
316
317
    /**
318
     * Make the column editable.
319
     *
320
     * @return $this
321
     */
322
    public function editable()
323
    {
324
        $editable = new Editable($this->name, func_get_args());
325
        $editable->setResource($this->grid->resource());
326
327
        $this->htmlCallback($editable->html());
328
329
        return $this;
330
    }
331
332
    /**
333
     * Add a value callback.
334
     *
335
     * @param callable $callable
336
     *
337
     * @return $this
338
     */
339
    public function value(Closure $callable)
340
    {
341
        $this->valueCallback = $callable;
342
343
        return $this;
344
    }
345
346
    /**
347
     * Alias for value method.
348
     *
349
     * @param callable $callable
350
     *
351
     * @return $this
352
     */
353
    public function display(Closure $callable)
354
    {
355
        return $this->value($callable);
356
    }
357
358
    /**
359
     * If has a value callback.
360
     *
361
     * @return bool
362
     */
363
    protected function hasValueCallback()
364
    {
365
        return (bool) $this->valueCallback;
366
    }
367
368
    /**
369
     * Set html callback.
370
     *
371
     * @param $callback
372
     */
373
    protected function htmlCallback($callback)
374
    {
375
        $this->htmlCallbacks[] = $callback;
376
    }
377
378
    /**
379
     * If column has html callback.
380
     *
381
     * @return bool
382
     */
383
    protected function hasHtmlCallback()
384
    {
385
        return !empty($this->htmlCallbacks);
386
    }
387
388
    /**
389
     * Wrap value with callback.
390
     *
391
     * @param $value
392
     *
393
     * @return mixed
394
     */
395
    protected function htmlWrap($value, $row = [])
396
    {
397
        foreach ($this->htmlCallbacks as $callback) {
398
            $value = str_replace('{value}', $value, $callback);
399
        }
400
401
        $value = str_replace(
402
            '{$value}',
403
            is_null($this->original) ? 'NULL' : $this->htmlEntityEncode($this->original),
404
            $value
405
        );
406
        $value = str_replace('{pk}', array_get($row, $this->grid->getKeyName()), $value);
407
408
        return $value;
409
    }
410
411
    /**
412
     * Fill all data to every column.
413
     *
414
     * @param array $data
415
     *
416
     * @return mixed
417
     */
418
    public function fill(array $data)
419
    {
420
        foreach ($data as $key => &$row) {
421
            $this->original = $value = array_get($row, $this->name);
422
423
            $isCustomColumn = !array_has($row, $this->name);
424
425
            $value = $this->htmlEntityEncode($value);
426
427
            array_set($row, $this->name, $value);
428
429
            if ($this->hasValueCallback()) {
430
431
                $input = $isCustomColumn ? $row : $this->original;
432
433
                $callback = $this->bindOriginalRow($this->valueCallback, $key);
434
                $value = call_user_func($callback, $input);
435
                array_set($row, $this->name, $value);
436
            }
437
438
            if ($this->hasHtmlCallback()) {
439
                $value = $this->htmlWrap($value, $row);
440
                array_set($row, $this->name, $value);
441
            }
442
        }
443
444
        return $data;
445
    }
446
447
    /**
448
     * Set original grid data to column.
449
     *
450
     * @param Closure $callback
451
     * @param int     $key
452
     *
453
     * @return Closure
454
     */
455
    protected function bindOriginalRow(Closure $callback, $key)
456
    {
457
        $originalRow = static::$originalGridData[$key];
458
459
        return $callback->bindTo((object)$originalRow);
460
    }
461
462
    /**
463
     * Set original data for column.
464
     *
465
     * @param array $input
466
     */
467
    public static function setOriginalGridData(array $input)
468
    {
469
        static::$originalGridData = $input;
470
    }
471
472
    /**
473
     * Convert characters to HTML entities recursively.
474
     *
475
     * @param array|string $item
476
     *
477
     * @return mixed
478
     */
479
    protected function htmlEntityEncode($item)
480
    {
481
        if (is_array($item)) {
482
            array_walk_recursive($item, function (&$value) {
483
                $value = htmlentities($value);
484
            });
485
        } else {
486
            $item = htmlentities($item);
487
        }
488
489
        return $item;
490
    }
491
492
    /**
493
     * Create the column sorter.
494
     *
495
     * @return string|void
496
     */
497
    public function sorter()
498
    {
499
        if (!$this->sortable) {
500
            return;
501
        }
502
503
        $icon = 'fa-sort';
504
        $type = 'desc';
505
506
        if ($this->isSorted()) {
507
            $type = $this->sort['type'] == 'desc' ? 'asc' : 'desc';
508
            $icon .= "-amount-{$this->sort['type']}";
509
        }
510
511
        $query = app('request')->all();
512
        $query = array_merge($query, [$this->grid->model()->getSortName() => ['column' => $this->name, 'type' => $type]]);
513
514
        $url = Url::current().'?'.http_build_query($query);
515
516
        return "<a class=\"fa fa-fw $icon\" href=\"$url\"></a>";
517
    }
518
519
    /**
520
     * Determine if this column is currently sorted.
521
     *
522
     * @return bool
523
     */
524
    protected function isSorted()
525
    {
526
        $this->sort = app('request')->get($this->grid->model()->getSortName());
527
528
        if (empty($this->sort)) {
529
            return false;
530
        }
531
532
        return isset($this->sort['column']) && $this->sort['column'] == $this->name;
533
    }
534
535
    /**
536
     * @param string $method
537
     * @param array  $arguments
538
     *
539
     * @return $this
540
     */
541
    public function __call($method, $arguments)
542
    {
543
        if ($this->isRelation()) {
544
            $this->name = "{$this->relation}.$method";
545
            $this->label = isset($arguments[0]) ? $arguments[0] : ucfirst($method);
546
547
            $this->relationColumn = $method;
548
549
            return $this;
550
        }
551
    }
552
}
553