Completed
Push — master ( 5bd6a5...9e9952 )
by Terzi
08:06
created

Generic::setValue()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 2
nc 1
nop 1
dl 0
loc 5
rs 10
c 0
b 0
f 0
1
<?php
2
3
namespace Terranet\Administrator\Field;
4
5
use Coduo\PHPHumanizer\StringHumanizer;
6
use Illuminate\Database\Eloquent\Model;
7
use Illuminate\Support\Facades\View;
8
use Terranet\Administrator\Contracts\Sortable;
9
use Terranet\Administrator\Field\Traits\AcceptsCustomFormat;
10
use Terranet\Administrator\Field\Traits\AppliesSorting;
11
use Terranet\Administrator\Scaffolding;
12
use Terranet\Administrator\Contracts\AutoTranslatable;
13
use Terranet\Administrator\Traits\AutoTranslatesInstances;
14
15
abstract class Generic implements Sortable, AutoTranslatable
16
{
17
    use AcceptsCustomFormat, AppliesSorting, AutoTranslatesInstances;
18
19
    /** @var string */
20
    protected $id;
21
22
    /** @var string */
23
    protected $title;
24
25
    /** @var string */
26
    protected $description;
27
28
    /** @var Model */
29
    protected $model;
30
31
    /** @var bool */
32
    protected $showLabel = true;
33
34
    /** @var array */
35
    protected $visibility = [
36
        Scaffolding::PAGE_INDEX => true,
37
        Scaffolding::PAGE_EDIT => true,
38
        Scaffolding::PAGE_VIEW => true,
39
    ];
40
41
    /** @var array */
42
    protected $attributes = [];
43
44
    /**
45
     * Generic constructor.
46
     *
47
     * @param string $title
48
     * @param null|string $id
49
     */
50
    private function __construct(string $title, string $id = null)
51
    {
52
        $this->setId(
53
            snake_case($id ?: $title)
54
        );
55
56
        if ($this->translator()->has($key = $this->translationKey())) {
57
            $this->setTitle($this->translator()->trans($key));
0 ignored issues
show
Bug introduced by
It seems like $this->translator()->trans($key) can also be of type null and array; however, parameter $title of Terranet\Administrator\Field\Generic::setTitle() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

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

57
            $this->setTitle(/** @scrutinizer ignore-type */ $this->translator()->trans($key));
Loading history...
58
        } else {
59
            $this->setTitle(
60
                'id' === $this->id
61
                    ? 'ID'
62
                    : StringHumanizer::humanize(str_replace(['_id', '-', '_'], ['', ' ', ' '], $this->id))
63
            );
64
        }
65
66
        if ($this->translator()->has($key = $this->descriptionKey())) {
67
            $this->setDescription($this->translator()->trans($key));
0 ignored issues
show
Bug introduced by
It seems like $this->translator()->trans($key) can also be of type null and array; however, parameter $description of Terranet\Administrator\F...neric::setDescription() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

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

67
            $this->setDescription(/** @scrutinizer ignore-type */ $this->translator()->trans($key));
Loading history...
68
        }
69
    }
70
71
    /**
72
     * @param $title
73
     * @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...
74
     * @param \Closure $callback
75
     *
76
     * @return static
77
     */
78
    public static function make($title, $id = null, \Closure $callback = null): self
79
    {
80
        $instance = new static($title, $id);
81
82
        if (null !== $callback) {
83
            $callback->call($instance, $instance);
84
        }
85
86
        return $instance;
87
    }
88
89
    /**
90
     * Create new element from another.
91
     *
92
     * @param Generic $element
93
     * @return Generic
94
     */
95
    public static function makeFrom(Generic $element)
96
    {
97
        return static::make($element->title(), $element->id());
98
    }
99
100
    /**
101
     * Switch to a new element type.
102
     *
103
     * @param string $className
104
     * @return mixed
105
     */
106
    public function switchTo(string $className)
107
    {
108
        return forward_static_call_array([$className, "make"], [$this->title(), $this->id()]);
109
    }
110
111
    /**
112
     * @param Model $model
113
     *
114
     * @return self
115
     */
116
    public function setModel(Model $model): self
117
    {
118
        $this->model = $model;
119
120
        return $this;
121
    }
122
123
    /**
124
     * @return Model
125
     */
126
    public function getModel()
127
    {
128
        return $this->model;
129
    }
130
131
    /**
132
     * Render Element.
133
     *
134
     * @param string $page
135
     *
136
     * @return mixed
137
     */
138
    final public function render(string $page = 'index')
139
    {
140
        if ($this->format) {
141
            // Each Field can define its own data for custom formatter.
142
            $withData = method_exists($this, 'renderWith')
143
                ? $this->renderWith()
144
                : [$this->value(), $this->model];
145
146
            return $this->callFormatter($withData);
147
        }
148
149
        $data = [
150
            'field' => $this,
151
            'model' => $this->model,
152
        ];
153
154
        if (method_exists($this, $dataGetter = 'on'.title_case($page))) {
155
            $data += call_user_func([$this, $dataGetter]);
156
        }
157
158
        if (View::exists($view = $this->template($page))) {
159
            return View::make($view, $data);
160
        }
161
162
        return View::make($this->template($page, 'Key'), $data);
163
    }
164
165
    /**
166
     * Return Element ID.
167
     *
168
     * @return string
169
     */
170
    public function id(): string
171
    {
172
        return $this->id;
173
    }
174
175
    /**
176
     * Form name.
177
     *
178
     * @return string
179
     */
180
    public function name()
181
    {
182
        $parts = explode('.', $this->id());
183
184
        if (count($parts) > 1) {
185
            $first = array_first($parts);
186
            $other = array_slice($parts, 1);
187
188
            $other = array_map(function ($part) {
189
                return "[$part]";
190
            }, $other);
191
192
            return implode('', array_merge([$first], $other));
193
        }
194
195
        return $this->id();
196
    }
197
198
    /**
199
     * @param string $id
200
     *
201
     * @return self
202
     */
203
    public function setId(string $id): self
204
    {
205
        $this->id = $id;
206
207
        return $this;
208
    }
209
210
    /**
211
     * Return Element title.
212
     *
213
     * @return string
214
     */
215
    public function title(): string
216
    {
217
        return $this->title;
218
    }
219
220
    /**
221
     * @return string
222
     */
223
    public function getDescription(): ?string
224
    {
225
        return $this->description;
226
    }
227
228
    /**
229
     * @param string $title
230
     *
231
     * @return self
232
     */
233
    public function setTitle(string $title): self
234
    {
235
        $this->title = $title;
236
237
        return $this;
238
    }
239
240
    /**
241
     * @param string $description
242
     *
243
     * @return self
244
     */
245
    public function setDescription(string $description): self
246
    {
247
        $this->description = $description;
248
249
        return $this;
250
    }
251
252
    /**
253
     * @param bool $showLabel
254
     *
255
     * @return self
256
     */
257
    public function hideLabel(bool $hideLabel): self
258
    {
259
        $this->showLabel = !$hideLabel;
260
261
        return $this;
262
    }
263
264
    /**
265
     * @return bool
266
     */
267
    public function isHiddenLabel(): bool
268
    {
269
        return !$this->showLabel;
270
    }
271
272
    /**
273
     * string $page.
274
     *
275
     * @return bool
276
     */
277
    public function isVisibleOnPage(string $page): bool
278
    {
279
        return (bool) $this->visibility[$page] ?? false;
280
    }
281
282
    /**
283
     * @param array|string $pages
284
     *
285
     * @return self
286
     */
287
    public function hideOnPages($pages): self
288
    {
289
        return $this->setPagesVisibility((array) $pages, false);
290
    }
291
292
    /**
293
     * @param array|string $pages
294
     *
295
     * @return self
296
     */
297
    public function showOnPages($pages): self
298
    {
299
        return $this->setPagesVisibility((array) $pages, true);
300
    }
301
302
    /**
303
     * Make column sortable.
304
     *
305
     * @param null|\Closure $callback
306
     *
307
     * @return self
308
     */
309
    public function sortable(\Closure $callback = null): self
310
    {
311
        app('scaffold.module')->addSortable(
0 ignored issues
show
Bug introduced by
The method addSortable() does not exist on Illuminate\Foundation\Application. ( Ignorable by Annotation )

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

311
        app('scaffold.module')->/** @scrutinizer ignore-call */ addSortable(

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
312
            $this->id(),
313
            $callback
314
        );
315
316
        return $this;
317
    }
318
319
    /**
320
     * Remove column from Sortable collection.
321
     *
322
     * @return self
323
     */
324
    public function disableSorting(): self
325
    {
326
        app('scaffold.module')->removeSortable($this->id());
0 ignored issues
show
Bug introduced by
The method removeSortable() does not exist on Illuminate\Foundation\Application. ( Ignorable by Annotation )

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

326
        app('scaffold.module')->/** @scrutinizer ignore-call */ removeSortable($this->id());

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
327
328
        return $this;
329
    }
330
331
    /**
332
     * Set value.
333
     *
334
     * @param $value
335
     *
336
     * @return Generic
337
     */
338
    public function setValue($value): self
339
    {
340
        $this->value = $value;
0 ignored issues
show
Bug Best Practice introduced by
The property value does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
341
342
        return $this;
343
    }
344
345
    /**
346
     * Extract Element value.
347
     *
348
     * @return mixed
349
     */
350
    public function value()
351
    {
352
        if (!$this->model) {
353
            return null;
354
        }
355
356
        return $this->model->getAttribute($this->id);
357
    }
358
359
    /**
360
     * @param $key
361
     * @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...
362
     * @param mixed $attribute
363
     *
364
     * @return self
365
     */
366
    public function setAttribute($attribute, $value = null): self
367
    {
368
        if (is_array($attribute)) {
369
            foreach ($attribute as $key => $value) {
370
                $this->setAttribute($key, $value);
371
            }
372
        } else {
373
            if (!array_key_exists($key, $this->attributes)) {
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $key seems to be never defined.
Loading history...
374
                throw new Exception("Unknown attribute {$key}");
0 ignored issues
show
Bug introduced by
The type Terranet\Administrator\Field\Exception was not found. Did you mean Exception? If so, make sure to prefix the type with \.
Loading history...
375
            }
376
            $this->attributes[$key] = $value;
377
        }
378
379
        return $this;
380
    }
381
382
    /**
383
     * @param mixed $pages
384
     * @param bool $visibility
385
     *
386
     * @return $this
387
     */
388
    protected function setPagesVisibility($pages, bool $visibility): self
389
    {
390
        $pages = array_intersect($pages, array_keys($this->visibility));
391
392
        foreach ($pages as $page) {
393
            $this->visibility[$page] = $visibility;
394
        }
395
396
        return $this;
397
    }
398
399
    /**
400
     * @param string $page
401
     * @param string $field
402
     *
403
     * @return string
404
     */
405
    protected function template(string $page, string $field = null): string
406
    {
407
        return sprintf(
408
            'administrator::fields.%s.%s',
409
            snake_case($field ?? class_basename($this)),
410
            $page
411
        );
412
    }
413
414
    /**
415
     * @return string
416
     */
417
    public function translationKey()
418
    {
419
        $key = sprintf('administrator::columns.%s.%s', $this->translatableModule()->url(), $this->id);
0 ignored issues
show
Bug introduced by
The method url() does not exist on Illuminate\Foundation\Application. ( Ignorable by Annotation )

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

419
        $key = sprintf('administrator::columns.%s.%s', $this->translatableModule()->/** @scrutinizer ignore-call */ url(), $this->id);

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
420
421
        if (!$this->translator()->has($key)) {
422
            $key = sprintf('administrator::columns.%s.%s', 'global', $this->id);
423
        }
424
425
        return $key;
426
    }
427
428
    /**
429
     * @return string
430
     */
431
    public function descriptionKey()
432
    {
433
        $key = sprintf('administrator::hints.%s.%s', $this->translatableModule()->url(), $this->id);
434
435
        if (!$this->translator()->has($key)) {
436
            $key = sprintf('administrator::hints.%s.%s', 'global', $this->id);
437
        }
438
439
        return $key;
440
    }
441
}
442