Completed
Push — master ( 759acc...6a33ec )
by Denis
01:29
created

AbstractElement::help()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 3
nc 1
nop 1
dl 0
loc 6
rs 9.4285
c 0
b 0
f 0
1
<?php
2
3
namespace Ngtfkx\Laradeck\FormBuilder\Elements;
4
5
6
use Illuminate\Support\Collection;
7
use Ngtfkx\Laradeck\FormBuilder\Layouts\AbstractLayout;
8
9
abstract class AbstractElement
10
{
11
    /**
12
     * @var Collection|iterable $classes Коллекция классом элемента
13
     */
14
    protected $classes;
15
16
    /**
17
     * @var Collection|iterable $attributes Коллекция дополнительных атрибутов элемента
18
     */
19
    protected $attributes;
20
21
    /**
22
     * @var Collection|iterable $styles Коллекция inline-стилей элемента
23
     */
24
    protected $styles;
25
26
    /**
27
     * @var string $value Значение элемента
28
     */
29
    protected $value;
30
31
    /**
32
     * @var string $tag Тег элемента
33
     */
34
    protected $tag;
35
36
    /**
37
     * @var Collection|iterable $parts Набор атрибутов для генерации html-кода элементов
38
     */
39
    protected $parts;
40
41
    /**
42
     * @var string $label
43
     */
44
    protected $label;
45
46
    /**
47
     * @var string $help
48
     */
49
    protected $help;
50
51
    /**
52
     * @var AbstractLayout
53
     */
54
    protected $layout;
55
56
    protected $onlyTagRender = false;
57
58
    /**
59
     * @return void
60
     */
61
    abstract public function tag();
62
63
    public function __construct()
64
    {
65
        $this->classes = new Collection();
66
67
        $this->attributes = new Collection();
68
69
        $this->styles = new Collection();
70
71
        $this->parts = new Collection();
72
73
        $this->tag();
74
    }
75
76
    public function layout(?AbstractLayout $layout): self
77
    {
78
        $this->layout = $layout;
79
80
        return $this;
81
    }
82
83
    /**
84
     * Сеттер значения лейбла для элемента
85
     *
86
     * @param string|null $value
87
     * @return AbstractElement
88
     */
89
    public function label(?string $value): self
90
    {
91
        $this->label = $value;
92
93
        return $this;
94
    }
95
96
    /**
97
     * Сеттер значения подсказки для элемента
98
     *
99
     * @param string|null $value
100
     * @return AbstractElement
101
     */
102
    public function help(?string $value): self
103
    {
104
        $this->help = $value;
105
106
        return $this;
107
    }
108
109
    /**
110
     * Сеттер значения элемента
111
     *
112
     * @param string|null $value
113
     * @return AbstractElement
114
     */
115
    public function value(?string $value): self
116
    {
117
        $this->value = $value;
118
119
        return $this;
120
    }
121
122
    /**
123
     * Сеттер атрибута id элемента
124
     *
125
     * @param string|null $value
126
     * @return AbstractElement
127
     */
128
    public function id(?string $value): self
129
    {
130
        $this->attr('id', $value);
131
132
        return $this;
133
    }
134
135
    /**
136
     * Сеттер атрибута name элемента
137
     *
138
     * @param string|null $value
139
     * @return AbstractElement
140
     */
141
    public function name(?string $value): self
142
    {
143
        $this->attr('name', $value);
144
145
        return $this;
146
    }
147
148
    /**
149
     * Добавить элементу один или несколько классов
150
     *
151
     * @param array ...$classes
152
     * @return AbstractElement
153
     */
154
    public function class(...$classes): self
0 ignored issues
show
Coding Style introduced by
Possible parse error: non-abstract method defined as abstract
Loading history...
Coding Style introduced by
It is generally advisable to only define one property per statement.

Only declaring a single property per statement allows you to later on add doc comments more easily.

It is also recommended by PSR2, so it is a common style that many people expect.

Loading history...
155
    {
156
        $this->classes($classes);
0 ignored issues
show
Documentation introduced by
$classes is of type array<integer,array>, but the function expects a object<Ngtfkx\Laradeck\F...lder\Elements\iterable>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
157
158
        return $this;
0 ignored issues
show
Coding Style introduced by
The visibility should be declared for property $this.

The PSR-2 coding standard requires that all properties in a class have their visibility explicitly declared. If you declare a property using

class A {
    var $property;
}

the property is implicitly global.

To learn more about the PSR-2, please see the PHP-FIG site on the PSR-2.

Loading history...
159
    }
160
161
    /**
162
     *  Добавить элементу один или несколько классов из массива
163
     *
164
     * @param iterable $classes
165
     * @return AbstractElement
166
     */
167
    public function classes(iterable $classes): self
168
    {
169
        foreach ($classes as $class) {
170
            if (!$this->classes->contains($class)) {
171
                $this->classes->push($class);
172
            }
173
        }
174
175
        return $this;
176
    }
177
178
    /**
179
     * Добавить к элементу один или несколько inline-стилей
180
     *
181
     * @param string $key
182
     * @param string|null $value
183
     * @return AbstractElement
184
     */
185
    public function style(string $key, string $value = null): self
186
    {
187
        if (empty($value)) {
188
            $pos = strpos($key, ':', 2);
189
            if ($pos !== false) {
190
                $parts = explode(':', strrev($key));
191
                $key = strrev($parts[1]);
192
                $value = strrev($parts[0]);
193
            }
194
        }
195
196
        if ($key && $value) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $value of type null|string is loosely compared to true; this is ambiguous if the string can be empty. You might want to explicitly use !== null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
197
            $this->styles->put($key, $value);
198
        }
199
200
        return $this;
201
    }
202
203
    /**
204
     * Добавить к элементу один или несколько inline-стилей из массива
205
     *
206
     * @param iterable $styles
207
     * @return AbstractElement
208
     */
209
    public function styles(iterable $styles): self
210
    {
211
        foreach ($styles as $key => $value) {
212
            $this->styles->put($key, $value);
213
        }
214
215
        return $this;
216
    }
217
218
    /**
219
     * Добавить аттрибут к элементу
220
     *
221
     * @param string $key
222
     * @param string|null $value
223
     * @return AbstractElement
224
     */
225
    public function attr(string $key, $value = null): self
226
    {
227
        $this->attributes->put($key, $value);
228
229
        return $this;
230
    }
231
232
    /**
233
     * Добавить один или несколько атрибутов из массива к элементу
234
     *
235
     * @param iterable $attributes
236
     * @return AbstractElement
237
     */
238
    public function attrs(iterable $attributes): self
239
    {
240
        foreach ($attributes as $key => $value) {
241
            if ($key === 'class') {
242
                $this->class($value);
243
            } else if ($key === 'style') {
244
                $this->style($value);
245
            } else {
246
                $this->attributes->put($key, $value);
247
            }
248
        }
249
250
        return $this;
251
    }
252
253
    /**
254
     * Очистить классы элемента
255
     *
256
     * @return AbstractElement
257
     */
258
    public function clearClasses(): self
259
    {
260
        $this->classes = new Collection();
261
262
        return $this;
263
    }
264
265
    /**
266
     * Очистить классы стили
267
     *
268
     * @return AbstractElement
269
     */
270
    public function clearStyles(): self
271
    {
272
        $this->styles = new Collection();
273
274
        return $this;
275
    }
276
277
    /**
278
     * Очистить классы атрибуты
279
     *
280
     * @return AbstractElement
281
     */
282
    public function clearAttributes(): self
283
    {
284
        $this->attributes = new Collection();
285
286
        return $this;
287
    }
288
289
    protected function render(): string
290
    {
291
        $attributes = $this->generateAttributes();
292
293
        $tag = $this->getTagHtml();
294
295
        $tag = str_replace('**attributes**', $attributes, $tag);
296
297
        if (is_null($this->layout) === false) {
298
            $view = 'fb::' . $this->layout->getViewsDirPath() . '.base';
299
300
            if(view()->exists($view) && $this->onlyTagRender === false) {
301
                $data = [
302
                    'id' => 'idddd',
303
                    'help' => 'ggggggggggg',
304
                    'label' => '45345345',
305
                    'tag' => $tag,
306
                ];
307
308
                return view($view, $data);
309
            }
310
        }
311
312
        return $tag;
313
    }
314
315
    protected function getTagHtml()
316
    {
317
        return '<' . $this->tag . '**attributes**>';
318
    }
319
320
    protected function beforeToParts(): void
321
    {
322
        $this->addAttr('value');
323
324
        if (is_null($this->layout) === false && $this->layout->getElementClasses()) {
325
            $this->class($this->layout->getElementClasses());
326
        }
327
    }
328
329
    protected  function afterToParts(): void
330
    {
331
332
    }
333
334
    /**
335
     * Преобразовать в строку для вывода в HTML
336
     *
337
     * @return string
338
     */
339
    public function __toString(): string
340
    {
341
        $this->beforeToParts();
342
343
        $this->classesToParts();
344
345
        $this->stylesToParts();
346
347
        $this->attributesToParts();
348
349
        $this->afterToParts();
350
351
        return $this->render();
352
    }
353
354
    protected function generateAttributes(): string
355
    {
356
        $attributes = '';
357
358
        foreach ($this->parts as $key => $value) {
359
            if (is_null($value) || (is_bool($value) && $value === false)) {
360
                continue;
361
            }
362
363
            $attributes .= ' ' . $key . '="' . (is_bool($value) ? $key : $value) . '"';
364
        }
365
366
        return $attributes;
367
    }
368
369
    protected function stylesToParts(): void
370
    {
371
        if ($this->styles->isNotEmpty()) {
372
            $this->parts->put('style', $this->styles->pipe(function ($styles) {
373
                $styleAttr = '';
374
                foreach ($styles as $key => $value) {
375
                    $styleAttr .= $key . ':' . $value . ';';
376
                }
377
378
                return $styleAttr;
379
            }));
380
        }
381
    }
382
383
    protected function classesToParts(): void
384
    {
385
        if ($this->classes->isNotEmpty()) {
386
            $this->parts->put('class', $this->classes->implode(' '));
387
        }
388
    }
389
390
    public function attributesToParts(): void
391
    {
392
        foreach ($this->attributes as $key => $value) {
393
            $this->parts->put($key, $value);
394
        }
395
    }
396
397
    protected function addAttr(...$names): self
398
    {
399
        foreach ($names as $name) {
400
            if (!empty($this->$name)) {
401
                $this->parts[$name] = $this->$name;
402
            }
403
        }
404
405
        return $this;
406
    }
407
408
    protected function addAttrAs(...$names): self
409
    {
410
        foreach ($names as $name) {
411
            if (!empty($this->$name)) {
412
                $this->parts[$name] = $name;
413
            }
414
        }
415
416
        return $this;
417
    }
418
}