Field::setAttribute()   A
last analyzed

Complexity

Conditions 3
Paths 2

Size

Total Lines 11
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 3
eloc 6
nc 2
nop 2
dl 0
loc 11
rs 10
c 0
b 0
f 0
1
<?php
2
3
namespace Terranet\Administrator\Field;
4
5
use Illuminate\Database\Eloquent\Model;
0 ignored issues
show
Bug introduced by
The type Illuminate\Database\Eloquent\Model was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
6
use Illuminate\Support\Arr;
7
use Illuminate\Support\Facades\View;
8
use Illuminate\Support\Str;
9
use Terranet\Administrator\Architect;
10
use Terranet\Administrator\Contracts\AutoTranslatable;
11
use Terranet\Administrator\Contracts\Sortable;
12
use Terranet\Administrator\Field\Traits\AcceptsCustomFormat;
13
use Terranet\Administrator\Field\Traits\AppliesSorting;
14
use Terranet\Administrator\Field\Traits\HandlesVisibility;
15
use Terranet\Administrator\Field\Traits\HasValuePresenter;
16
use Terranet\Administrator\Scaffolding;
17
use Terranet\Administrator\Traits\AutoTranslatesInstances;
18
19
abstract class Field implements Sortable, AutoTranslatable
20
{
21
    use AcceptsCustomFormat, AppliesSorting, AutoTranslatesInstances, HasValuePresenter, HandlesVisibility;
22
23
    /** @var string */
24
    protected $id;
25
26
    /** @var string */
27
    protected $title;
28
29
    /** @var string */
30
    protected $name;
31
32
    /** @var mixed */
33
    protected $value;
34
35
    /** @var string */
36
    protected $description;
37
38
    /** @var Model */
39
    protected $model;
40
41
    /** @var bool */
42
    protected $showLabel = true;
43
44
    /** @var array */
45
    protected $visibility = [
46
        Scaffolding::PAGE_INDEX => true,
47
        Scaffolding::PAGE_EDIT => true,
48
        Scaffolding::PAGE_VIEW => true,
49
    ];
50
51
    /** @var array */
52
    protected $attributes = [
53
        'class' => 'form-control',
54
    ];
55
56
    /**
57
     * Field constructor.
58
     *
59
     * @param  string  $title
60
     * @param  null|string  $id
61
     */
62
    private function __construct(string $title, string $id = null)
63
    {
64
        $this->setId(
65
            $id ?: Str::snake($title)
66
        );
67
68
        if (trans()->has($key = $this->translationKey())) {
0 ignored issues
show
Bug introduced by
The function trans was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

68
        if (/** @scrutinizer ignore-call */ trans()->has($key = $this->translationKey())) {
Loading history...
69
            $this->setTitle((string) trans()->get($key));
70
        } else {
71
            $this->setTitle(Architect::humanize($title));
72
        }
73
74
        if (trans()->has($key = $this->descriptionKey())) {
75
            $this->setDescription((string) trans()->get($key));
76
        }
77
    }
78
79
    /**
80
     * @param $title
81
     * @param  null  $id
0 ignored issues
show
Documentation Bug introduced by
Are you sure the doc-type for parameter $id is correct as it would always require null to be passed?
Loading history...
82
     * @param  \Closure  $callback
83
     * @return static
84
     */
85
    public static function make($title, $id = null, \Closure $callback = null): self
86
    {
87
        $instance = new static($title, $id);
88
89
        if (null !== $callback) {
90
            $callback->call($instance, $instance);
91
        }
92
93
        return $instance;
94
    }
95
96
    /**
97
     * Create new element from another.
98
     *
99
     * @param  Field  $element
100
     * @return static
101
     */
102
    public static function makeFrom(self $element): self
103
    {
104
        return static::make($element->title(), $element->id());
105
    }
106
107
    /**
108
     * Switch to a new element type.
109
     *
110
     * @param  string  $className
111
     * @return mixed
112
     */
113
    public function switchTo(string $className)
114
    {
115
        return forward_static_call_array([$className, 'make'], [$this->title(), $this->id()]);
116
    }
117
118
    /**
119
     * @param  Model  $model
120
     * @return static
121
     */
122
    public function setModel(Model $model): self
123
    {
124
        $this->model = $model;
125
126
        return $this;
127
    }
128
129
    /**
130
     * @return Model
131
     */
132
    public function getModel()
133
    {
134
        return $this->model;
135
    }
136
137
    /**
138
     * Render Element.
139
     *
140
     * @param  string  $page
141
     * @return mixed
142
     */
143
    final public function render(string $page = 'index')
144
    {
145
        if (\in_array($page, [Scaffolding::PAGE_INDEX, Scaffolding::PAGE_VIEW], true)) {
146
            if ($this->hasCustomFormat()) {
147
                return $this->callFormatter($this->model, $page);
148
            }
149
150
            if ($presenter = $this->hasPresenter($this->model, $this->id())) {
151
                return $this->callPresenter($presenter);
152
            }
153
        }
154
155
        $data = [
156
            'field' => $this,
157
            'model' => $this->model,
158
            'attributes' => $this->getAttributes(),
159
        ];
160
161
        if (method_exists($this, $dataGetter = 'on'.Str::title($page))) {
162
            $data += \call_user_func([$this, $dataGetter]);
163
        }
164
165
        if (View::exists($view = $this->template($page))) {
166
            return View::make($view, $data);
167
        }
168
169
        return View::make($this->template($page, 'Key'), $data);
170
    }
171
172
    /**
173
     * Return Element ID.
174
     *
175
     * @return string
176
     */
177
    public function id(): string
178
    {
179
        return $this->id;
180
    }
181
182
    /**
183
     * Form name.
184
     *
185
     * @return string
186
     */
187
    public function name(): string
188
    {
189
        if (null === $this->name) {
190
            $parts = explode('.', $this->id());
191
192
            if (\count($parts) > 1) {
193
                $first = Arr::first($parts);
194
                $other = \array_slice($parts, 1);
195
196
                $other = array_map(function ($part) {
197
                    return "[$part]";
198
                }, $other);
199
200
                return $this->name = implode('', array_merge([$first], $other));
201
            }
202
203
            return $this->name = $this->id();
204
        }
205
206
        return $this->name;
207
    }
208
209
    /**
210
     * @param  string  $name
211
     * @return Field
212
     */
213
    public function setName(string $name): self
214
    {
215
        $this->name = $name;
216
217
        return $this;
218
    }
219
220
    /**
221
     * @param  string  $id
222
     * @return static
223
     */
224
    public function setId(string $id): self
225
    {
226
        $this->id = $id;
227
228
        return $this;
229
    }
230
231
    /**
232
     * Return Element title.
233
     *
234
     * @return string
235
     */
236
    public function title(): string
237
    {
238
        return $this->title;
239
    }
240
241
    /**
242
     * @return string
243
     */
244
    public function getDescription(): ?string
245
    {
246
        return $this->description;
247
    }
248
249
    /**
250
     * @param  string  $title
251
     * @return static
252
     */
253
    public function setTitle(string $title): self
254
    {
255
        $this->title = $title;
256
257
        return $this;
258
    }
259
260
    /**
261
     * @param  null|string  $description
262
     * @return static
263
     */
264
    public function setDescription(?string $description): self
265
    {
266
        $this->description = $description;
267
268
        return $this;
269
    }
270
271
    /**
272
     * Make element translatable.
273
     *
274
     * @return Translatable
275
     */
276
    public function translatable()
277
    {
278
        return Translatable::make($this);
279
    }
280
281
    /**
282
     * @param  bool  $hideLabel
283
     * @return static
284
     */
285
    public function hideLabel(bool $hideLabel): self
286
    {
287
        $this->showLabel = !$hideLabel;
288
289
        return $this;
290
    }
291
292
    /**
293
     * @return bool
294
     */
295
    public function isHiddenLabel(): bool
296
    {
297
        return !$this->showLabel;
298
    }
299
300
    /**
301
     * string $page.
302
     *
303
     * @param  string  $page
304
     * @return bool
305
     */
306
    public function isVisibleOnPage(string $page): bool
307
    {
308
        return (bool) $this->visibility[$page] ?? false;
309
    }
310
311
    /**
312
     * @param  array|string  $pages
313
     * @return static
314
     */
315
    public function hideOnPages($pages): self
316
    {
317
        return $this->setPagesVisibility((array) $pages, false);
318
    }
319
320
    /**
321
     * @param  array|string  $pages
322
     * @return static
323
     */
324
    public function showOnPages($pages): self
325
    {
326
        return $this->setPagesVisibility((array) $pages, true);
327
    }
328
329
    /**
330
     * Make column sortable.
331
     *
332
     * @param  null|\Closure  $callback
333
     * @return static
334
     */
335
    public function sortable(\Closure $callback = null): self
336
    {
337
        app('scaffold.module')->addSortable(
0 ignored issues
show
Bug introduced by
The function app was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

337
        /** @scrutinizer ignore-call */ 
338
        app('scaffold.module')->addSortable(
Loading history...
338
            $this->id(),
339
            $callback
340
        );
341
342
        return $this;
343
    }
344
345
    /**
346
     * Remove column from Sortable collection.
347
     *
348
     * @return static
349
     */
350
    public function disableSorting(): self
351
    {
352
        app('scaffold.module')->removeSortable($this->id());
0 ignored issues
show
Bug introduced by
The function app was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

352
        /** @scrutinizer ignore-call */ 
353
        app('scaffold.module')->removeSortable($this->id());
Loading history...
353
354
        return $this;
355
    }
356
357
    /**
358
     * Set value.
359
     *
360
     * @param $value
361
     * @return Field
362
     */
363
    public function setValue($value): self
364
    {
365
        $this->value = $value;
366
367
        return $this;
368
    }
369
370
    /**
371
     * Extract Element value.
372
     *
373
     * @return mixed
374
     */
375
    public function value()
376
    {
377
        if (null !== $this->value) {
378
            return $this->value;
379
        }
380
381
        if (!$this->model) {
382
            return null;
383
        }
384
385
        $property = last(explode('.', $this->id));
386
        $val = $this->model->getAttribute($property);
387
388
        if ($val instanceof \BenSampo\Enum\Enum) {
0 ignored issues
show
Bug introduced by
The type BenSampo\Enum\Enum was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
389
            $val = $val->value;
390
        }
391
392
        return $val;
393
    }
394
395
    /**
396
     * @param $key
397
     * @param  null  $value
0 ignored issues
show
Documentation Bug introduced by
Are you sure the doc-type for parameter $value is correct as it would always require null to be passed?
Loading history...
398
     * @param  mixed  $attribute
399
     * @return static
400
     */
401
    public function setAttribute($attribute, $value = null): self
402
    {
403
        if (\is_array($attribute)) {
404
            foreach ($attribute as $key => $value) {
405
                $this->setAttribute($key, $value);
406
            }
407
        } else {
408
            $this->attributes[$attribute] = $value;
409
        }
410
411
        return $this;
412
    }
413
414
    /**
415
     * @return array
416
     */
417
    public function getAttributes(): array
418
    {
419
        return $this->attributes;
420
    }
421
422
    /**
423
     * @return string
424
     */
425
    public function translationKey()
426
    {
427
        $key = sprintf('administrator::columns.%s.%s', $this->translatableModule()->url(), $this->id);
428
429
        if (!trans()->has($key)) {
0 ignored issues
show
Bug introduced by
The function trans was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

429
        if (!/** @scrutinizer ignore-call */ trans()->has($key)) {
Loading history...
430
            $key = sprintf('administrator::columns.%s.%s', 'global', $this->id);
431
        }
432
433
        return $key;
434
    }
435
436
    /**
437
     * @return string
438
     */
439
    public function descriptionKey()
440
    {
441
        $key = sprintf('administrator::hints.%s.%s', $this->translatableModule()->url(), $this->id);
442
443
        if (!trans()->has($key)) {
0 ignored issues
show
Bug introduced by
The function trans was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

443
        if (!/** @scrutinizer ignore-call */ trans()->has($key)) {
Loading history...
444
            $key = sprintf('administrator::hints.%s.%s', 'global', $this->id);
445
        }
446
447
        return $key;
448
    }
449
450
    /**
451
     * @param  \Closure  $condition
452
     * @return self
453
     */
454
    public function when(\Closure $condition): self
455
    {
456
        $this->when = $condition;
457
458
        return $this;
459
    }
460
461
    /**
462
     * @param  mixed  $pages
463
     * @param  bool  $visibility
464
     * @return $this
465
     */
466
    protected function setPagesVisibility($pages, bool $visibility): self
467
    {
468
        $pages = array_intersect($pages, array_keys($this->visibility));
469
470
        foreach ($pages as $page) {
471
            $this->visibility[$page] = $visibility;
472
        }
473
474
        return $this;
475
    }
476
477
    /**
478
     * @param  string  $page
479
     * @param  string  $field
480
     * @return string
481
     */
482
    protected function template(string $page, string $field = null): string
483
    {
484
        return sprintf(
485
            'administrator::fields.%s.%s',
486
            Str::snake($field ?? class_basename($this)),
487
            $page
488
        );
489
    }
490
}
491