Completed
Push — master ( bd0b16...b0d73a )
by Song
02:57
created

Field::__call()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 13

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 3
nc 3
nop 2
dl 0
loc 13
rs 9.8333
c 0
b 0
f 0
1
<?php
2
3
namespace Encore\Admin\Show;
4
5
use Encore\Admin\Show;
6
use Illuminate\Contracts\Support\Arrayable;
7
use Illuminate\Contracts\Support\Renderable;
8
use Illuminate\Database\Eloquent\Model;
9
use Illuminate\Support\Collection;
10
use Illuminate\Support\Facades\File;
11
use Illuminate\Support\Facades\Storage;
12
use Illuminate\Support\Traits\Macroable;
13
14
class Field implements Renderable
15
{
16
    use Macroable {
17
        __call as macroCall;
18
    }
19
20
    /**
21
     * @var string
22
     */
23
    protected $view = 'admin::show.field';
24
25
    /**
26
     * Name of column.
27
     *
28
     * @var string
29
     */
30
    protected $name;
31
32
    /**
33
     * Label of column.
34
     *
35
     * @var string
36
     */
37
    protected $label;
38
39
    /**
40
     * Field value.
41
     *
42
     * @var mixed
43
     */
44
    protected $value;
45
46
    /**
47
     * @var Collection
48
     */
49
    protected $showAs = [];
50
51
    /**
52
     * Parent show instance.
53
     *
54
     * @var Show
55
     */
56
    protected $parent;
57
58
    /**
59
     * Relation name.
60
     *
61
     * @var string
62
     */
63
    protected $relation;
64
65
    /**
66
     * If show contents in box.
67
     *
68
     * @var bool
69
     */
70
    public $wrapped = true;
71
72
    /**
73
     * @var array
74
     */
75
    protected $fileTypes = [
76
        'image'      => 'png|jpg|jpeg|tmp|gif',
77
        'word'       => 'doc|docx',
78
        'excel'      => 'xls|xlsx|cvs',
79
        'powerpoint' => 'ppt|pptx',
80
        'pdf'        => 'pdf',
81
        'code'       => 'php|js|java|python|ruby|go|c|cpp|sql|m|h|json|html|aspx',
82
        'archive'    => 'zip|tar\.gz|rar|rpm',
83
        'txt'        => 'txt|pac|log|md',
84
        'audio'      => 'mp3|wav|flac|3pg|aa|aac|ape|au|m4a|mpc|ogg',
85
        'video'      => 'mkv|rmvb|flv|mp4|avi|wmv|rm|asf|mpeg'
86
    ];
87
88
    /**
89
     * Field constructor.
90
     *
91
     * @param string $name
92
     * @param string $label
93
     */
94
    public function __construct($name = '', $label = '')
95
    {
96
        $this->name = $name;
97
98
        $this->label = $this->formatLabel($label);
99
100
        $this->showAs = new Collection();
101
    }
102
103
    /**
104
     * Set parent show instance.
105
     *
106
     * @param Show $show
107
     *
108
     * @return $this
109
     */
110
    public function setParent(Show $show)
111
    {
112
        $this->parent = $show;
113
114
        return $this;
115
    }
116
117
    /**
118
     * Get name of this column.
119
     *
120
     * @return mixed
121
     */
122
    public function getName()
123
    {
124
        return $this->name;
125
    }
126
127
    /**
128
     * Format label.
129
     *
130
     * @param $label
131
     *
132
     * @return mixed
133
     */
134
    protected function formatLabel($label)
135
    {
136
        $label = $label ?: ucfirst($this->name);
137
138
        return str_replace(['.', '_'], ' ', $label);
139
    }
140
141
    /**
142
     * Get label of the column.
143
     *
144
     * @return mixed
145
     */
146
    public function getLabel()
147
    {
148
        return $this->label;
149
    }
150
151
    /**
152
     * Field display callback.
153
     *
154
     * @param callable $callable
155
     *
156
     * @return $this
157
     */
158
    public function as(callable $callable)
159
    {
160
        $this->showAs->push($callable);
161
162
        return $this;
163
    }
164
165
    /**
166
     * Display field using array value map.
167
     *
168
     * @param array $values
169
     * @param null  $default
170
     *
171
     * @return $this
172
     */
173 View Code Duplication
    public function using(array $values, $default = null)
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...
174
    {
175
        return $this->as(function ($value) use ($values, $default) {
176
            if (is_null($value)) {
177
                return $default;
178
            }
179
180
            return array_get($values, $value, $default);
181
        });
182
    }
183
184
    /**
185
     * Show field as a image.
186
     *
187
     * @param string $server
188
     * @param int    $width
189
     * @param int    $height
190
     *
191
     * @return $this
192
     */
193
    public function image($server = '', $width = 200, $height = 200)
194
    {
195 View Code Duplication
        return $this->as(function ($path) use ($server, $width, $height) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across 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...
196
            if (url()->isValidUrl($path)) {
197
                $src = $path;
198
            } elseif ($server) {
199
                $src = $server.$path;
200
            } else {
201
                $src = Storage::disk(config('admin.upload.disk'))->url($path);
202
            }
203
204
            return "<img src='$src' style='max-width:{$width}px;max-height:{$height}px' class='img' />";
205
        });
206
    }
207
208
    /**
209
     * Show field as a file.
210
     *
211
     * @param string $server
212
     * @param bool $download
213
     * @return Field
214
     */
215
    public function file($server = '', $download = true)
216
    {
217
        $field = $this;
218
219
        return $this->as(function ($path) use ($server, $download, $field) {
220
221
            $name = basename($path);
222
223
            $field->wrapped = false;
224
225
            $size = $url = '';
226
227
            if (url()->isValidUrl($path)) {
228
                $url = $path;
229
            } elseif ($server) {
230
                $url = $server.$path;
231
            } else {
232
                $storage = Storage::disk(config('admin.upload.disk'));
233
                if ($storage->exists($path)) {
234
                    $url = $storage->url($path);
235
                    $size = ($storage->size($path)/1000) . 'KB';
236
                }
237
            }
238
239
            return <<<HTML
240
<ul class="mailbox-attachments clearfix">
241
    <li style="margin-bottom: 0;">
242
      <span class="mailbox-attachment-icon"><i class="fa {$field->getFileIcon($name)}"></i></span>
243
      <div class="mailbox-attachment-info">
244
        <div class="mailbox-attachment-name">
245
            <i class="fa fa-paperclip"></i> {$name}
246
            </div>
247
            <span class="mailbox-attachment-size">
248
              {$size}&nbsp;
249
              <a href="{$url}" class="btn btn-default btn-xs pull-right" target="_blank"><i class="fa fa-cloud-download"></i></a>
250
            </span>
251
      </div>
252
    </li>
253
  </ul>
254
HTML;
255
256
        });
257
    }
258
259
    /**
260
     * Show field as a link.
261
     *
262
     * @param string $href
263
     * @param string $target
264
     *
265
     * @return Field
266
     */
267
    public function link($href = '', $target = '_blank')
268
    {
269
        return $this->as(function ($link) use ($href, $target) {
270
            $href = $href ?: $link;
0 ignored issues
show
Bug introduced by
Consider using a different name than the imported variable $href, or did you forget to import by reference?

It seems like you are assigning to a variable which was imported through a use statement which was not imported by reference.

For clarity, we suggest to use a different name or import by reference depending on whether you would like to have the change visibile in outer-scope.

Change not visible in outer-scope

$x = 1;
$callable = function() use ($x) {
    $x = 2; // Not visible in outer scope. If you would like this, how
            // about using a different variable name than $x?
};

$callable();
var_dump($x); // integer(1)

Change visible in outer-scope

$x = 1;
$callable = function() use (&$x) {
    $x = 2;
};

$callable();
var_dump($x); // integer(2)
Loading history...
271
272
            return "<a href='$href' target='{$target}'>{$link}</a>";
273
        });
274
    }
275
276
    /**
277
     * Show field as labels.
278
     *
279
     * @param string $style
280
     *
281
     * @return Field
282
     */
283 View Code Duplication
    public function label($style = 'success')
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...
284
    {
285
        return $this->as(function ($value) use ($style) {
286
            if ($value instanceof Arrayable) {
287
                $value = $value->toArray();
288
            }
289
290
            return collect((array) $value)->map(function ($name) use ($style) {
291
                return "<span class='label label-{$style}'>$name</span>";
292
            })->implode('&nbsp;');
293
        });
294
    }
295
296
    /**
297
     * Show field as badges.
298
     *
299
     * @param string $style
300
     *
301
     * @return Field
302
     */
303 View Code Duplication
    public function badge($style = 'blue')
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...
304
    {
305
        return $this->as(function ($value) use ($style) {
306
            if ($value instanceof Arrayable) {
307
                $value = $value->toArray();
308
            }
309
310
            return collect((array) $value)->map(function ($name) use ($style) {
311
                return "<span class='badge bg-{$style}'>$name</span>";
312
            })->implode('&nbsp;');
313
        });
314
    }
315
316
    /**
317
     * Show field as json code.
318
     *
319
     * @return Field
320
     */
321
    public function json()
322
    {
323
        $field = $this;
324
325
        return $this->as(function ($value) use ($field) {
326
327
            $content = json_decode($value, true);
328
329
            if (json_last_error() == 0) {
330
331
                $field->wrapped = false;
332
333
                return '<pre><code>'.json_encode($content, JSON_PRETTY_PRINT).'</code></pre>';
334
            }
335
336
            return $value;
337
        });
338
    }
339
340
    /**
341
     * Get file icon
342
     *
343
     * @param string $file
344
     * @return string
345
     */
346
    public function getFileIcon($file = '')
347
    {
348
        $extension = File::extension($file);
349
350
        foreach ($this->fileTypes as $type => $regex) {
351
            if (preg_match("/^($regex)$/i", $extension) !== 0) {
352
                return "fa-file-{$type}-o";
353
            }
354
        }
355
356
        return 'fa-file-o';
357
    }
358
359
    /**
360
     * Set value for this field.
361
     *
362
     * @param Model $model
363
     *
364
     * @return $this
365
     */
366
    public function setValue(Model $model)
367
    {
368
        if ($this->relation) {
369
            if (!$model->{$this->relation}) {
370
                return $this;
371
            }
372
373
            $this->value = $model->{$this->relation}->getAttribute($this->name);
374
        } else {
375
            $this->value = $model->getAttribute($this->name);
376
        }
377
378
        return $this;
379
    }
380
381
    /**
382
     * Set relation name for this field.
383
     *
384
     * @param string $relation
385
     *
386
     * @return $this
387
     */
388
    public function setRelation($relation)
389
    {
390
        $this->relation = $relation;
391
392
        return $this;
393
    }
394
395
    /**
396
     * @param string $method
397
     * @param array  $arguments
398
     *
399
     * @return $this
400
     */
401
    public function __call($method, $arguments = [])
402
    {
403
        if (static::hasMacro($method)) {
404
            return $this->macroCall($method, $arguments);
405
        }
406
407
        if ($this->relation) {
408
            $this->name = $method;
409
            $this->label = $this->formatLabel(array_get($arguments, 0));
410
        }
411
412
        return $this;
413
    }
414
415
    /**
416
     * Get all variables passed to field view.
417
     *
418
     * @return array
419
     */
420
    protected function variables()
421
    {
422
        return [
423
            'content'   => $this->value,
424
            'label'     => $this->getLabel(),
425
            'wrapped'   => $this->wrapped,
426
        ];
427
    }
428
429
    /**
430
     * Render this field.
431
     *
432
     * @return string
433
     */
434
    public function render()
435
    {
436
        if ($this->showAs->isNotEmpty()) {
437
            $this->showAs->each(function ($callable) {
438
                $this->value = $callable->call(
439
                    $this->parent->getModel(),
440
                    $this->value
441
                );
442
            });
443
        }
444
445
        return view($this->view, $this->variables());
0 ignored issues
show
Bug Compatibility introduced by
The expression view($this->view, $this->variables()); of type Illuminate\View\View|Ill...\Contracts\View\Factory adds the type Illuminate\Contracts\View\Factory to the return on line 445 which is incompatible with the return type declared by the interface Illuminate\Contracts\Support\Renderable::render of type string.
Loading history...
446
    }
447
}
448