Completed
Pull Request — master (#836)
by Iman
03:18
created

Column::_resolveClassName()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 16
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Importance

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