Completed
Push — master ( f06f95...cfadd2 )
by Song
03:17
created

Column::hasValueWrapper()   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 0
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
     * @param string $name
88
     * @param string $label
89
     */
90
    public function __construct($name, $label)
91
    {
92
        $this->name = $name;
93
94
        $this->label = $this->formatLabel($label);
95
    }
96
97
    /**
98
     * @param Grid $grid
99
     */
100
    public function setGrid(Grid $grid)
101
    {
102
        $this->grid = $grid;
103
    }
104
105
    /**
106
     * Get name of this column.
107
     *
108
     * @return mixed
109
     */
110
    public function getName()
111
    {
112
        return $this->name;
113
    }
114
115
    /**
116
     * Format label.
117
     *
118
     * @param $label
119
     *
120
     * @return mixed
121
     */
122
    protected function formatLabel($label)
123
    {
124
        $label = $label ?: ucfirst($this->name);
125
126
        return str_replace(['.', '_'], ' ', $label);
127
    }
128
129
    /**
130
     * Get label of the column.
131
     *
132
     * @return mixed
133
     */
134
    public function getLabel()
135
    {
136
        return $this->label;
137
    }
138
139
    /**
140
     * Set relation.
141
     *
142
     * @param $relation
143
     *
144
     * @return $this
145
     */
146
    public function setRelation($relation)
147
    {
148
        $this->relation = $relation;
149
150
        return $this;
151
    }
152
153
    /**
154
     * If this column is relation column.
155
     *
156
     * @return bool
157
     */
158
    protected function isRelation()
159
    {
160
        return (bool) $this->relation;
161
    }
162
163
    /**
164
     * Mark this column as sortable.
165
     *
166
     * @return Column
167
     */
168
    public function sortable()
169
    {
170
        $this->sortable = true;
171
172
        return $this;
173
    }
174
175
    /**
176
     * Wrap value with badge.
177
     *
178
     * @param string $style
179
     *
180
     * @return $this
181
     */
182
    public function badge($style = 'red')
183
    {
184
        $callback = "<span class='badge bg-{$style}'>{value}</span>";
185
186
        $this->htmlCallback($callback);
187
188
        return $this;
189
    }
190
191
    /**
192
     * Wrap value with label.
193
     *
194
     * @param string $style
195
     *
196
     * @return $this
197
     */
198
    public function label($style = 'success')
199
    {
200
        $callback = "<span class='label label-{$style}'>{value}</span>";
201
202
        $this->htmlCallback($callback);
203
204
        return $this;
205
    }
206
207
    /**
208
     * Wrap value as a link.
209
     *
210
     * @param $href
211
     * @param string $target
212
     *
213
     * @return $this
214
     */
215
    public function link($href = '', $target = '_blank')
216
    {
217
        if (empty($href)) {
218
            $href = '{$value}';
219
        }
220
221
        $callback = "<a href='$href' target='$target'>{value}</a>";
222
223
        $this->htmlCallback($callback);
224
225
        return $this;
226
    }
227
228
    /**
229
     * Wrap value as a button.
230
     *
231
     * @param string $style
232
     *
233
     * @return $this
234
     */
235 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...
236
    {
237
        if (is_array($style)) {
238
            $style = array_map(function ($style) {
239
                return 'btn-'.$style;
240
            }, $style);
241
242
            $style = implode(' ', $style);
243
        } elseif (is_string($style)) {
244
            $style = 'btn-'.$style;
245
        }
246
247
        $callback = "<span class='btn $style'>{value}</span>";
248
249
        $this->htmlCallback($callback);
250
251
        return $this;
252
    }
253
254
    /**
255
     * Wrap value as a progressbar.
256
     *
257
     * @param string $style
258
     * @param string $size
259
     * @param int    $max
260
     *
261
     * @return $this
262
     */
263 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...
264
    {
265
        if (is_array($style)) {
266
            $style = array_map(function ($style) {
267
                return 'progress-bar-'.$style;
268
            }, $style);
269
270
            $style = implode(' ', $style);
271
        } elseif (is_string($style)) {
272
            $style = 'progress-bar-'.$style;
273
        }
274
275
        $callback = <<<EOT
276
277
<div class="progress progress-$size">
278
    <div class="progress-bar $style" role="progressbar" aria-valuenow="{value}" aria-valuemin="0" aria-valuemax="$max" style="width: {value}%">
279
      <span class="sr-only">{value}</span>
280
    </div>
281
</div>
282
283
EOT;
284
285
        $this->htmlCallback($callback);
286
287
        return $this;
288
    }
289
290
    /**
291
     * Wrap value as a image.
292
     *
293
     * @param string $server
294
     * @param int    $width
295
     * @param int    $height
296
     *
297
     * @return $this
298
     */
299
    public function image($server = '', $width = 200, $height = 200)
300
    {
301
        $server = $server ?: config('admin.upload.host');
302
303
        $callback = "<img src='$server/{\$value}' style='max-width:{$width}px;max-height:{$height}px' class='img img-thumbnail' />";
304
305
        $this->htmlCallback($callback);
306
307
        return $this;
308
    }
309
310
    /**
311
     * Make the column editable.
312
     *
313
     * @return $this
314
     */
315
    public function editable()
316
    {
317
        $editable = new Editable($this->name, func_get_args());
318
        $editable->setResource($this->grid->resource());
319
320
        $this->htmlCallback($editable->html());
321
322
        return $this;
323
    }
324
325
    /**
326
     * Add a value callback.
327
     *
328
     * @param callable $callable
329
     *
330
     * @return $this
331
     */
332
    public function value(Closure $callable)
333
    {
334
        $this->valueCallback = $callable->bindTo($this);
335
336
        return $this;
337
    }
338
339
    /**
340
     * Alias for value method.
341
     *
342
     * @param callable $callable
343
     *
344
     * @return $this
345
     */
346
    public function display(Closure $callable)
347
    {
348
        return $this->value($callable);
349
    }
350
351
    /**
352
     * If has a value callback.
353
     *
354
     * @return bool
355
     */
356
    protected function hasValueCallback()
357
    {
358
        return (bool) $this->valueCallback;
359
    }
360
361
    /**
362
     * Set html callback.
363
     *
364
     * @param $callback
365
     */
366
    protected function htmlCallback($callback)
367
    {
368
        $this->htmlCallbacks[] = $callback;
369
    }
370
371
    /**
372
     * If column has html callback.
373
     *
374
     * @return bool
375
     */
376
    protected function hasHtmlCallback()
377
    {
378
        return !empty($this->htmlCallbacks);
379
    }
380
381
    /**
382
     * Wrap value with callback.
383
     *
384
     * @param $value
385
     *
386
     * @return mixed
387
     */
388
    protected function htmlWrap($value, $row = [])
389
    {
390
        foreach ($this->htmlCallbacks as $callback) {
391
            $value = str_replace('{value}', $value, $callback);
392
        }
393
394
        $value = str_replace(
395
            '{$value}',
396
            is_null($this->original) ? 'NULL' : $this->htmlEntityEncode($this->original),
397
            $value
398
        );
399
        $value = str_replace('{pk}', array_get($row, $this->grid->getKeyName()), $value);
400
401
        return $value;
402
    }
403
404
    /**
405
     * Fill all data to every column.
406
     *
407
     * @param array $data
408
     *
409
     * @return mixed
410
     */
411
    public function fill(array $data)
412
    {
413
        foreach ($data as &$item) {
414
            $this->original = $value = array_get($item, $this->name);
415
416
            $value = $this->htmlEntityEncode($value);
417
418
            array_set($item, $this->name, $value);
419
420
            if ($this->hasValueCallback()) {
421
                $value = call_user_func($this->valueCallback, $this->original);
422
                array_set($item, $this->name, $value);
423
            }
424
425
            if ($this->hasHtmlCallback()) {
426
                $value = $this->htmlWrap($value, $item);
427
                array_set($item, $this->name, $value);
428
            }
429
        }
430
431
        return $data;
432
    }
433
434
    /**
435
     * Convert characters to HTML entities recursively.
436
     *
437
     * @param array|string $item
438
     *
439
     * @return mixed
440
     */
441
    protected function htmlEntityEncode($item)
442
    {
443
        if (is_array($item)) {
444
            array_walk_recursive($item, function (&$value) {
445
                $value = htmlentities($value);
446
            });
447
        } else {
448
            $item = htmlentities($item);
449
        }
450
451
        return $item;
452
    }
453
454
    /**
455
     * Create the column sorter.
456
     *
457
     * @return string|void
458
     */
459
    public function sorter()
460
    {
461
        if (!$this->sortable) {
462
            return;
463
        }
464
465
        $icon = 'fa-sort';
466
        $type = 'desc';
467
468
        if ($this->isSorted()) {
469
            $type = $this->sort['type'] == 'desc' ? 'asc' : 'desc';
470
            $icon .= "-amount-{$this->sort['type']}";
471
        }
472
473
        $query = app('request')->all();
474
        $query = array_merge($query, [$this->grid->model()->getSortName() => ['column' => $this->name, 'type' => $type]]);
475
476
        $url = Url::current().'?'.http_build_query($query);
477
478
        return "<a class=\"fa fa-fw $icon\" href=\"$url\"></a>";
479
    }
480
481
    /**
482
     * Determine if this column is currently sorted.
483
     *
484
     * @return bool
485
     */
486
    protected function isSorted()
487
    {
488
        $this->sort = app('request')->get($this->grid->model()->getSortName());
489
490
        if (empty($this->sort)) {
491
            return false;
492
        }
493
494
        return isset($this->sort['column']) && $this->sort['column'] == $this->name;
495
    }
496
497
    /**
498
     * @param string $method
499
     * @param array  $arguments
500
     *
501
     * @return $this
502
     */
503
    public function __call($method, $arguments)
504
    {
505
        if ($this->isRelation()) {
506
            $this->name = "{$this->relation}.$method";
507
            $this->label = isset($arguments[0]) ? $arguments[0] : ucfirst($method);
508
509
            $this->relationColumn = $method;
510
511
            return $this;
512
        }
513
    }
514
}
515