Completed
Push — master ( e23ec4...bcf727 )
by Terzi
04:42
created

Generic::getAttributes()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
cc 1
eloc 1
nc 1
nop 0
dl 0
loc 3
ccs 0
cts 2
cp 0
crap 2
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\AutoTranslatable;
9
use Terranet\Administrator\Contracts\Sortable;
10
use Terranet\Administrator\Field\Traits\AcceptsCustomFormat;
11
use Terranet\Administrator\Field\Traits\AppliesSorting;
12
use Terranet\Administrator\Field\Traits\HandlesVisibility;
13
use Terranet\Administrator\Field\Traits\HasValuePresenter;
14
use Terranet\Administrator\Scaffolding;
15
use Terranet\Administrator\Traits\AutoTranslatesInstances;
16
17
abstract class Generic implements Sortable, AutoTranslatable
18
{
19
    use AcceptsCustomFormat, AppliesSorting, AutoTranslatesInstances, HasValuePresenter, HandlesVisibility;
20
21
    /** @var string */
22
    protected $id;
23
24
    /** @var string */
25
    protected $title;
26
27
    /** @var string */
28
    protected $name;
29
30
    /** @var mixed */
31
    protected $value;
32
33
    /** @var string */
34
    protected $description;
35
36
    /** @var Model */
37
    protected $model;
38
39
    /** @var bool */
40
    protected $showLabel = true;
41
42
    /** @var array */
43
    protected $visibility = [
44
        Scaffolding::PAGE_INDEX => true,
45
        Scaffolding::PAGE_EDIT => true,
46
        Scaffolding::PAGE_VIEW => true,
47
    ];
48
49
    /** @var array */
50
    protected $attributes = [
51
        'class' => 'form-control',
52
    ];
53
54
    /**
55
     * Generic constructor.
56
     *
57
     * @param string $title
58
     * @param null|string $id
59
     */
60 11
    private function __construct(string $title, string $id = null)
61
    {
62 11
        $this->setId(
63 11
            snake_case($id ?: $title)
64
        );
65
66 11
        if ($this->translator()->has($key = $this->translationKey())) {
67
            $this->setTitle((string) $this->translator()->trans($key));
68
        } else {
69 11
            $this->setTitle(
70 11
                'id' === $this->id
71
                    ? 'ID'
72 11
                    : StringHumanizer::humanize(str_replace(['_id', '-', '_'], ['', ' ', ' '], $this->id))
73
            );
74
        }
75
76 11
        if ($this->translator()->has($key = $this->descriptionKey())) {
77
            $this->setDescription((string) $this->translator()->trans($key));
78
        }
79 11
    }
80
81
    /**
82
     * @param $title
83
     * @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...
84
     * @param \Closure $callback
85
     *
86
     * @return static
87
     */
88 11
    public static function make($title, $id = null, \Closure $callback = null): self
89
    {
90 11
        $instance = new static($title, $id);
91
92 11
        if (null !== $callback) {
93
            $callback->call($instance, $instance);
94
        }
95
96 11
        return $instance;
97
    }
98
99
    /**
100
     * Create new element from another.
101
     *
102
     * @param Generic $element
103
     *
104
     * @return static
105
     */
106
    public static function makeFrom(self $element): self
107
    {
108
        return static::make($element->title(), $element->id());
109
    }
110
111
    /**
112
     * Switch to a new element type.
113
     *
114
     * @param string $className
115
     *
116
     * @return mixed
117
     */
118
    public function switchTo(string $className)
119
    {
120
        return forward_static_call_array([$className, 'make'], [$this->title(), $this->id()]);
121
    }
122
123
    /**
124
     * @param Model $model
125
     *
126
     * @return static
127
     */
128
    public function setModel(Model $model): self
129
    {
130
        $this->model = $model;
131
132
        return $this;
133
    }
134
135
    /**
136
     * @return Model
137
     */
138
    public function getModel()
139
    {
140
        return $this->model;
141
    }
142
143
    /**
144
     * Render Element.
145
     *
146
     * @param string $page
147
     *
148
     * @return mixed
149
     */
150
    final public function render(string $page = 'index')
151
    {
152
        if (\in_array($page, [Scaffolding::PAGE_INDEX, Scaffolding::PAGE_VIEW], true)) {
153
            if ($this->hasCustomFormat()) {
154
                return $this->callFormatter($this->model, $page);
155
            }
156
157
            if ($presenter = $this->hasPresenter($this->model, $this->id())) {
158
                return $this->callPresenter($presenter);
159
            }
160
        }
161
162
        $data = [
163
            'field' => $this,
164
            'model' => $this->model,
165
            'attributes' => $this->getAttributes(),
166
        ];
167
168
        if (method_exists($this, $dataGetter = 'on'.title_case($page))) {
169
            $data += \call_user_func([$this, $dataGetter]);
170
        }
171
172
        if (View::exists($view = $this->template($page))) {
173
            return View::make($view, $data);
174
        }
175
176
        return View::make($this->template($page, 'Key'), $data);
177
    }
178
179
    /**
180
     * Return Element ID.
181
     *
182
     * @return string
183
     */
184 24
    public function id(): string
185
    {
186 24
        return $this->id;
187
    }
188
189
    /**
190
     * Form name.
191
     *
192
     * @return string
193
     */
194
    public function name(): string
195
    {
196
        if (null === $this->name) {
197
            $parts = explode('.', $this->id());
198
199
            if (\count($parts) > 1) {
200
                $first = array_first($parts);
201
                $other = \array_slice($parts, 1);
202
203
                $other = array_map(function ($part) {
204
                    return "[$part]";
205
                }, $other);
206
207
                return $this->name = implode('', array_merge([$first], $other));
208
            }
209
210
            return $this->name = $this->id();
211
        }
212
213
        return $this->name;
214
    }
215
216
    /**
217
     * @param string $name
218
     *
219
     * @return Generic
220
     */
221
    public function setName(string $name): self
222
    {
223
        $this->name = $name;
224
225
        return $this;
226
    }
227
228
    /**
229
     * @param string $id
230
     *
231
     * @return static
232
     */
233 11
    public function setId(string $id): self
234
    {
235 11
        $this->id = $id;
236
237 11
        return $this;
238
    }
239
240
    /**
241
     * Return Element title.
242
     *
243
     * @return string
244
     */
245 6
    public function title(): string
246
    {
247 6
        return $this->title;
248
    }
249
250
    /**
251
     * @return string
252
     */
253 1
    public function getDescription(): ?string
254
    {
255 1
        return $this->description;
256
    }
257
258
    /**
259
     * @param string $title
260
     *
261
     * @return static
262
     */
263 16
    public function setTitle(string $title): self
264
    {
265 16
        $this->title = $title;
266
267 16
        return $this;
268
    }
269
270
    /**
271
     * @param null|string $description
272
     *
273
     * @return static
274
     */
275 1
    public function setDescription(?string $description): self
276
    {
277 1
        $this->description = $description;
278
279 1
        return $this;
280
    }
281
282
    /**
283
     * Make element translatable.
284
     *
285
     * @return Translatable
286
     */
287
    public function translatable()
288
    {
289
        return Translatable::make($this);
290
    }
291
292
    /**
293
     * @param bool $showLabel
294
     *
295
     * @return static
296
     */
297
    public function hideLabel(bool $hideLabel): self
298
    {
299
        $this->showLabel = !$hideLabel;
300
301
        return $this;
302
    }
303
304
    /**
305
     * @return bool
306
     */
307
    public function isHiddenLabel(): bool
308
    {
309
        return !$this->showLabel;
310
    }
311
312
    /**
313
     * string $page.
314
     *
315
     * @return bool
316
     */
317
    public function isVisibleOnPage(string $page): bool
318
    {
319
        return (bool) $this->visibility[$page] ?? false;
320
    }
321
322
    /**
323
     * @param array|string $pages
324
     *
325
     * @return static
326
     */
327
    public function hideOnPages($pages): self
328
    {
329
        return $this->setPagesVisibility((array) $pages, false);
330
    }
331
332
    /**
333
     * @param array|string $pages
334
     *
335
     * @return static
336
     */
337
    public function showOnPages($pages): self
338
    {
339
        return $this->setPagesVisibility((array) $pages, true);
340
    }
341
342
    /**
343
     * Make column sortable.
344
     *
345
     * @param null|\Closure $callback
346
     *
347
     * @return static
348
     */
349 1
    public function sortable(\Closure $callback = null): self
350
    {
351 1
        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

351
        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...
352 1
            $this->id(),
353 1
            $callback
354
        );
355
356 1
        return $this;
357
    }
358
359
    /**
360
     * Remove column from Sortable collection.
361
     *
362
     * @return static
363
     */
364 1
    public function disableSorting(): self
365
    {
366 1
        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

366
        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...
367
368 1
        return $this;
369
    }
370
371
    /**
372
     * Set value.
373
     *
374
     * @param $value
375
     *
376
     * @return Generic
377
     */
378
    public function setValue($value): self
379
    {
380
        $this->value = $value;
381
382
        return $this;
383
    }
384
385
    /**
386
     * Extract Element value.
387
     *
388
     * @return mixed
389
     */
390
    public function value()
391
    {
392
        if (null !== $this->value) {
393
            return $this->value;
394
        }
395
396
        if (!$this->model) {
397
            return null;
398
        }
399
400
        return $this->model->getAttribute($this->id);
401
    }
402
403
    /**
404
     * @param $key
405
     * @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...
406
     * @param mixed $attribute
407
     *
408
     * @return static
409
     */
410
    public function setAttribute($attribute, $value = null): self
411
    {
412
        if (\is_array($attribute)) {
413
            foreach ($attribute as $key => $value) {
414
                $this->setAttribute($key, $value);
415
            }
416
        } else {
417
            $this->attributes[$attribute] = $value;
418
        }
419
420
        return $this;
421
    }
422
423
    /**
424
     * @return array
425
     */
426
    public function getAttributes(): array
427
    {
428
        return $this->attributes;
429
    }
430
431
    /**
432
     * @return string
433
     */
434 11
    public function translationKey()
435
    {
436 11
        $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

436
        $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...
437
438 11
        if (!$this->translator()->has($key)) {
439 11
            $key = sprintf('administrator::columns.%s.%s', 'global', $this->id);
440
        }
441
442 11
        return $key;
443
    }
444
445
    /**
446
     * @return string
447
     */
448 11
    public function descriptionKey()
449
    {
450 11
        $key = sprintf('administrator::hints.%s.%s', $this->translatableModule()->url(), $this->id);
451
452 11
        if (!$this->translator()->has($key)) {
453 11
            $key = sprintf('administrator::hints.%s.%s', 'global', $this->id);
454
        }
455
456 11
        return $key;
457
    }
458
459
    /**
460
     * @param \Closure $condition
461
     *
462
     * @return self
463
     */
464
    public function when(\Closure $condition): self
465
    {
466
        $this->when = $condition;
467
468
        return $this;
469
    }
470
471
    /**
472
     * @param mixed $pages
473
     * @param bool $visibility
474
     *
475
     * @return $this
476
     */
477
    protected function setPagesVisibility($pages, bool $visibility): self
478
    {
479
        $pages = array_intersect($pages, array_keys($this->visibility));
480
481
        foreach ($pages as $page) {
482
            $this->visibility[$page] = $visibility;
483
        }
484
485
        return $this;
486
    }
487
488
    /**
489
     * @param string $page
490
     * @param string $field
491
     *
492
     * @return string
493
     */
494
    protected function template(string $page, string $field = null): string
495
    {
496
        return sprintf(
497
            'administrator::fields.%s.%s',
498
            snake_case($field ?? class_basename($this)),
499
            $page
500
        );
501
    }
502
}
503