Completed
Pull Request — master (#30)
by ARCANEDEV
07:25
created

FormBuilder::hidden()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 0
Metric Value
dl 0
loc 4
rs 10
c 0
b 0
f 0
ccs 2
cts 2
cp 1
cc 1
nc 1
nop 3
crap 1
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Arcanedev\LaravelHtml;
6
7
use Arcanedev\Html\Elements\{Button, File, Form, Input, Label, Select, Textarea};
8
use Arcanedev\LaravelHtml\Contracts\FormBuilder as FormBuilderContract;
9
use DateTime;
10
use Illuminate\Contracts\Routing\UrlGenerator;
11
use Illuminate\Contracts\Session\Session;
12
use Illuminate\Support\{Arr, Collection, HtmlString, Str};
13
14
/**
15
 * Class     FormBuilder
16
 *
17
 * @package  Arcanedev\LaravelHtml
18
 * @author   ARCANEDEV <[email protected]>
19
 */
20
class FormBuilder extends AbstractBuilder implements FormBuilderContract
21
{
22
    /* -----------------------------------------------------------------
23
     |  Properties
24
     | -----------------------------------------------------------------
25
     */
26
27
    /**
28
    * The HTML builder instance.
29
    *
30
    * @var \Arcanedev\LaravelHtml\Contracts\HtmlBuilder
31
    */
32
    protected $html;
33
34
    /**
35
    * The URL generator instance.
36
    *
37
    * @var \Illuminate\Contracts\Routing\UrlGenerator
38
    */
39
    protected $url;
40
41
    /**
42
    * The CSRF token used by the form builder.
43
    *
44
    * @var string
45
    */
46
    protected $csrfToken;
47
48
    /**
49
    * The session store implementation.
50
    *
51
    * @var \Illuminate\Contracts\Session\Session|\Illuminate\Session\Store
52
    */
53
    protected $session;
54
55
    /**
56
    * The current model instance for the form.
57
    *
58
    * @var \Illuminate\Database\Eloquent\Model|null
59
    */
60
    protected $model;
61
62
    /**
63
    * An array of label names we've created.
64
    *
65
    * @var array
66
    */
67
    protected $labels = [];
68
69
    /**
70
    * The reserved form open attributes.
71
    *
72
    * @var array
73
    */
74
    protected $reserved = ['method', 'url', 'route', 'action', 'files'];
75
76
    /**
77
    * The form methods that should be spoofed, in uppercase.
78
    *
79
    * @var array
80
    */
81
    protected $spoofedMethods = ['DELETE', 'PATCH', 'PUT'];
82
83
    /**
84
    * The types of inputs to not fill values on by default.
85
    *
86
    * @var array
87
    */
88
    protected $skipValueTypes = ['file', 'password', 'checkbox', 'radio'];
89
90
    /* -----------------------------------------------------------------
91
     |  Constructor
92
     | -----------------------------------------------------------------
93
     */
94
95
    /**
96
    * Create a new form builder instance.
97
    *
98
    * @param  \Arcanedev\LaravelHtml\Contracts\HtmlBuilder  $html
99
    * @param  \Illuminate\Contracts\Routing\UrlGenerator    $url
100
    * @param  \Illuminate\Contracts\Session\Session         $session
101
    */
102 606
    public function __construct(Contracts\HtmlBuilder $html, UrlGenerator $url, Session $session)
103
    {
104 606
        $this->url       = $url;
105 606
        $this->html      = $html;
106 606
        $this->csrfToken = $session->token();
107
108 606
        $this->setSessionStore($session);
109 606
    }
110
111
    /* -----------------------------------------------------------------
112
     |  Getters & Setters
113
     | -----------------------------------------------------------------
114
     */
115
116
    /**
117
     * Get the session store implementation.
118
     *
119
     * @return  \Illuminate\Contracts\Session\Session|null
120
     */
121 468
    public function getSessionStore(): ?Session
122
    {
123 468
        return $this->session;
124
    }
125
126
    /**
127
     * Set the session store implementation.
128
     *
129
     * @param  \Illuminate\Contracts\Session\Session  $session
130
     *
131
     * @return $this
132
     */
133 606
    public function setSessionStore(Session $session)
134
    {
135 606
        $this->session = $session;
136
137 606
        return $this;
138
    }
139
140
    /**
141
     * Set the model instance on the form builder.
142
     *
143
     * @param  \Illuminate\Database\Eloquent\Model|mixed|null  $model
144
     *
145
     * @return $this
146
     */
147 66
    public function setModel($model)
148
    {
149 66
        $this->model = $model;
150
151 66
        return $this;
152
    }
153
154
    /**
155
     * Get the model instance on the form builder.
156
     *
157
     * @return \Illuminate\Database\Eloquent\Model|mixed|null
158
     */
159 264
    public function getModel()
160
    {
161 264
        return $this->model;
162
    }
163
164
    /**
165
     * Get the ID attribute for a field name.
166
     *
167
     * @param  string|null  $name
168
     * @param  array        $attributes
169
     *
170
     * @return string|null
171
     */
172 480
    public function getIdAttribute($name, array $attributes): ?string
173
    {
174 480
        if (array_key_exists('id', $attributes))
175 42
            return $attributes['id'];
176
177 456
        if ( ! is_null($name) && in_array($name, $this->labels))
178 12
            return $name;
179
180 444
        return null;
181
    }
182
183
    /**
184
     * Get the value that should be assigned to the field.
185
     *
186
     * @param  string  $name
187
     * @param  mixed   $value
188
     *
189
     * @return mixed
190
     */
191 450
    public function getValueAttribute($name, $value = null)
192
    {
193 450
        if (is_null($name))
194 6
            return $value;
195
196 444
        if ( ! is_null($this->old($name)) && $name !== '_method')
197 30
            return $this->old($name);
198
199 432
        if ( ! is_null($value))
200 252
            return $value;
201
202 234
        return $this->getModelValueAttribute($name);
203
    }
204
205
    /**
206
     * Get the model value that should be assigned to the field.
207
     *
208
     * @param  string                                          $name
209
     * @param  \Illuminate\Database\Eloquent\Model|mixed|null  $model
210
     *
211
     * @return mixed
212
     */
213 252
    private function getModelValueAttribute(string $name, $model = null)
214
    {
215 252
        $model = $model ?: $this->getModel();
216
217 252
        $key = self::transformKey($name);
218
219 252
        if (strpos($key, '.') !== false) {
220 30
            $keys = explode('.', $key, 2);
221
222 30
            return $this->getModelValueAttribute(
223 30
                $keys[1],
224 30
                $this->getModelValueAttribute($keys[0], $model)
225
            );
226
        }
227
228 252
        return method_exists($model, 'getFormValue')
229 6
            ? $model->getFormValue($key)
230 252
            : data_get($model, $key);
231
    }
232
233
    /**
234
     * Get a value from the session's old input.
235
     *
236
     * @param  string  $name
237
     *
238
     * @return mixed
239
     */
240 462
    public function old(string $name)
241
    {
242 462
        $session = $this->getSessionStore();
243
244 462
        if (is_null($session))
245
            return null;
246
247 462
        return $session->getOldInput(self::transformKey($name));
248
    }
249
250
    /**
251
     * Transform key from array to dot syntax.
252
     *
253
     * @param  string  $key
254
     *
255
     * @return string
256
     */
257 462
    private static function transformKey(string $key): string
258
    {
259 462
        return str_replace(
260 462
            ['.', '[]', '[', ']'],
261 462
            ['_', '', '.', ''],
262 154
            $key
263
        );
264
    }
265
266
    /**
267
     * Determine if the old input is empty.
268
     *
269
     * @return bool
270
     */
271 24
    public function oldInputIsEmpty(): bool
272
    {
273 24
        $session = $this->getSessionStore();
274
275 24
        return ! is_null($session)
276 24
            && (count($session->getOldInput()) === 0);
277
    }
278
279
    /* -----------------------------------------------------------------
280
     |  Main Methods
281
     | -----------------------------------------------------------------
282
     */
283
284
    /**
285
     * Open up a new HTML form.
286
     *
287
     * @param  array  $attributes
288
     *
289
     * @return \Illuminate\Support\HtmlString
290
     */
291 84
    public function open(array $attributes = []): HtmlString
292
    {
293 84
        $method = Str::upper(Arr::pull($attributes, 'method', 'POST'));
294
295 84
        return Form::make()
296 84
            ->method($method !== 'GET' ? 'POST' : $method)
297 84
            ->action($this->getAction($attributes))
298 84
            ->attributes(array_merge(
0 ignored issues
show
Documentation introduced by
array_merge(array('accep...utes, $this->reserved)) is of type array, but the function expects a object<Arcanedev\Html\Elements\Concerns\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...
299 84
                ['accept-charset' => 'UTF-8'],
300 84
                Arr::except($attributes, $this->reserved)
301
            ))
302
            ->if(Arr::pull($attributes, 'files', false), function (Form $form) {
303 6
                return $form->acceptsFiles();
304 84
            })
305
            ->if(in_array($method, $this->spoofedMethods), function (Form $form) use ($method) {
306 6
                return $form->addChild($this->hidden('_method', $method));
307 84
            })
308
            ->if($method !== 'GET', function (Form $form) {
309 48
                return $form->addChild($this->token());
310 84
            })
311 84
            ->open();
312
    }
313
314
    /**
315
     * Create a new model based form builder.
316
     *
317
     * @param  mixed  $model
318
     * @param  array  $attributes
319
     *
320
     * @return \Illuminate\Support\HtmlString
321
     */
322 30
    public function model($model, array $attributes = []): HtmlString
323
    {
324 30
        return $this->setModel($model)->open($attributes);
325
    }
326
327
    /**
328
     * Close the current form.
329
     *
330
     * @return \Illuminate\Support\HtmlString
331
     */
332 6
    public function close(): HtmlString
333
    {
334 6
        $this->labels = [];
335 6
        $this->setModel(null);
336
337 6
        return Form::make()->close();
338
    }
339
340
    /**
341
     * Generate a hidden field with the current CSRF token.
342
     *
343
     * @return \Arcanedev\Html\Elements\Input
344
     */
345 48
    public function token(): Input
346
    {
347 48
        $token = empty($this->csrfToken)
348
            ? $this->getSessionStore()->token()
349 48
            : $this->csrfToken;
350
351 48
        return $this->hidden('_token', $token);
352
    }
353
354
    /**
355
     * Create a form label element.
356
     *
357
     * @param  string        $name
358
     * @param  string|mixed  $value
359
     * @param  array         $attributes
360
     * @param  bool          $escaped
361
     *
362
     * @return \Arcanedev\Html\Elements\Label
363
     */
364 30
    public function label(string $name, $value = null, array $attributes = [], $escaped = true): Label
365
    {
366 30
        $this->labels[] = $name;
367
368 30
        $value = $value ?: Str::title(str_replace(['_', '-'], ' ', $name));
369
370 30
        return Label::make()
371 30
            ->for($name)
372 30
            ->attributes($attributes)
0 ignored issues
show
Documentation introduced by
$attributes is of type array, but the function expects a object<Arcanedev\Html\Elements\Concerns\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...
373 30
            ->html($escaped ? e($value) : $value);
374
    }
375
376
    /**
377
     * Create a form input field.
378
     *
379
     * @param  string        $type
380
     * @param  string|null   $name
381
     * @param  string|mixed  $value
382
     * @param  array         $attributes
383
     *
384
     * @return \Arcanedev\Html\Elements\Input
385
     */
386 354
    public function input(string $type, $name, $value = null, array $attributes = []): Input
387
    {
388 354
        if ( ! in_array($type, $this->skipValueTypes))
389 300
            $value = $this->getValueAttribute($name, $value);
390
391 354
        $id = $this->getIdAttribute($name, $attributes);
392
393 354
        return Input::make()
394 354
            ->type($type)
395 354
            ->attributeIfNotNull($name, 'name', $name)
0 ignored issues
show
Unused Code introduced by
The call to Input::attributeIfNotNull() has too many arguments starting with $name.

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.

In this case you can add the @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

Loading history...
396 354
            ->attributeIfNotNull($id, 'id', $id)
397 354
            ->attributeUnless(is_null($value) || empty($value), 'value', $value)
398 354
            ->attributes($attributes);
399
    }
400
401
    /**
402
     * Create a text input field.
403
     *
404
     * @param  string        $name
405
     * @param  string|mixed  $value
406
     * @param  array         $attributes
407
     *
408
     * @return \Arcanedev\Html\Elements\Input
409
     */
410 42
    public function text(string $name, $value = null, array $attributes = []): Input
411
    {
412 42
        return $this->input('text', $name, $value, $attributes);
413
    }
414
415
    /**
416
     * Create a password input field.
417
     *
418
     * @param  string  $name
419
     * @param  array   $attributes
420
     *
421
     * @return \Arcanedev\Html\Elements\Input
422
     */
423 18
    public function password(string $name, array $attributes = []): Input
424
    {
425 18
        return $this->input('password', $name, null, $attributes);
426
    }
427
428
    /**
429
     * Create a hidden input field.
430
     *
431
     * @param  string        $name
432
     * @param  string|mixed  $value
433
     * @param  array         $attributes
434
     *
435
     * @return \Arcanedev\Html\Elements\Input
436
     */
437 66
    public function hidden(string $name, $value = null, array $attributes = []): Input
438
    {
439 66
        return $this->input('hidden', $name, $value, $attributes);
440
    }
441
442
    /**
443
     * Create an e-mail input field.
444
     *
445
     * @param  string        $name
446
     * @param  string|mixed  $value
447
     * @param  array         $attributes
448
     *
449
     * @return \Arcanedev\Html\Elements\Input
450
     */
451 18
    public function email(string $name, $value = null, array $attributes = []): Input
452
    {
453 18
        return $this->input('email', $name, $value, $attributes);
454
    }
455
456
    /**
457
     * Create a tel input field.
458
     *
459
     * @param  string        $name
460
     * @param  string|mixed  $value
461
     * @param  array         $attributes
462
     *
463
     * @return \Arcanedev\Html\Elements\Input
464
     */
465 18
    public function tel(string $name, $value = null, array $attributes = []): Input
466
    {
467 18
        return $this->input('tel', $name, $value, $attributes);
468
    }
469
470
    /**
471
     * Create a number input field.
472
     *
473
     * @param  string        $name
474
     * @param  string|mixed  $value
475
     * @param  array         $attributes
476
     *
477
     * @return \Arcanedev\Html\Elements\Input
478
     */
479 18
    public function number(string $name, $value = null, array $attributes = []): Input
480
    {
481 18
        return $this->input('number', $name, $value, $attributes);
482
    }
483
484
    /**
485
     * Create a date input field.
486
     *
487
     * @param  string  $name
488
     * @param  string  $value
489
     * @param  array   $attributes
490
     *
491
     * @return \Arcanedev\Html\Elements\Input
492
     */
493 24
    public function date(string $name, $value = null, array $attributes = []): Input
494
    {
495 24
        if ($value instanceof DateTime)
496 6
            $value = $value->format('Y-m-d');
497
498 24
        return $this->input('date', $name, $value, $attributes);
499
    }
500
501
    /**
502
     * Create a datetime input field.
503
     *
504
     * @param  string        $name
505
     * @param  string|mixed  $value
506
     * @param  array         $attributes
507
     *
508
     * @return \Arcanedev\Html\Elements\Input
509
     */
510 24
    public function datetime(string $name, $value = null, array $attributes = []): Input
511
    {
512 24
        if ($value instanceof DateTime)
513 12
            $value = $value->format(DateTime::RFC3339);
514
515 24
        return $this->input('datetime', $name, $value, $attributes);
516
    }
517
518
    /**
519
     * Create a datetime-local input field.
520
     *
521
     * @param  string        $name
522
     * @param  string|mixed  $value
523
     * @param  array         $attributes
524
     *
525
     * @return \Arcanedev\Html\Elements\Input
526
     */
527 24
    public function datetimeLocal(string $name, $value = null, array $attributes = []): Input
528
    {
529 24
        if ($value instanceof DateTime)
530 12
            $value = $value->format('Y-m-d\TH:i');
531
532 24
        return $this->input('datetime-local', $name, $value, $attributes);
533
    }
534
535
    /**
536
     * Create a time input field.
537
     *
538
     * @param  string        $name
539
     * @param  string|mixed  $value
540
     * @param  array         $attributes
541
     *
542
     * @return \Arcanedev\Html\Elements\Input
543
     */
544 18
    public function time(string $name, $value = null, array $attributes = []): Input
545
    {
546 18
        return $this->input('time', $name, $value, $attributes);
547
    }
548
549
    /**
550
     * Create a url input field.
551
     *
552
     * @param  string  $name
553
     * @param  string  $value
554
     * @param  array   $attributes
555
     *
556
     * @return \Arcanedev\Html\Elements\Input
557
     */
558 12
    public function url(string $name, $value = null, array $attributes = []): Input
559
    {
560 12
        return $this->input('url', $name, $value, $attributes);
561
    }
562
563
    /**
564
     * Create a file input field.
565
     *
566
     * @param  string  $name
567
     * @param  array   $attributes
568
     *
569
     * @return \Arcanedev\Html\Elements\File
570
     */
571 18
    public function file(string $name, array $attributes = []): File
572
    {
573 18
        return File::make()->name($name)->attributes($attributes);
0 ignored issues
show
Documentation introduced by
$attributes is of type array, but the function expects a object<Arcanedev\Html\Elements\Concerns\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...
574
    }
575
576
    /**
577
     * Create a textarea input field.
578
     *
579
     * @param  string  $name
580
     * @param  string  $value
581
     * @param  array   $attributes
582
     *
583
     * @return \Arcanedev\Html\Elements\Textarea
584
     */
585 36
    public function textarea(string $name, $value = null, array $attributes = []): Textarea
586
    {
587 36
        $id    = $this->getIdAttribute($name, $attributes);
588 36
        $size  = Arr::pull($attributes, 'size');
589 36
        $value = (string) $this->getValueAttribute($name, $value);
590
591 36
        return Textarea::make()
592 36
            ->name($name)
593 36
            ->attributeUnless(is_null($id), 'id', $id)
594
            ->unless(is_null($size), function (Textarea $elt) use ($size) {
595 18
                return $elt->size($size);
596 36
            })
597 36
            ->attributes($attributes)
598 36
            ->html($this->html->escape($value));
599
    }
600
601
    /**
602
     * Create a select box field.
603
     *
604
     * @param  string                                         $name
605
     * @param  array|\Illuminate\Support\Collection|iterable  $list
606
     * @param  string|bool                                    $selected
607
     * @param  array                                          $attributes
608
     * @param  array                                          $optionsAttributes
609
     * @param  array                                          $optgroupsAttributes
610
     *
611
     * @return \Arcanedev\Html\Elements\Select
612
     */
613 90
    public function select(
614
        string $name,
615
        iterable $list = [],
616
        $selected = null,
617
        array $attributes = [],
618
        array $optionsAttributes = [],
619
        array $optgroupsAttributes = []
620
    ): Select {
621 90
        return Select::make()
622 90
            ->name($name)
623 90
            ->options($list, $optionsAttributes, $optgroupsAttributes)
0 ignored issues
show
Bug introduced by
It seems like $list defined by parameter $list on line 615 can also be of type array; however, Arcanedev\Html\Elements\Select::options() does only seem to accept object<Arcanedev\Html\Elements\iterable>, maybe add an additional type check?

This check looks at variables that have been passed in as parameters and are passed out again to other methods.

If the outgoing method call has stricter type requirements than the method itself, an issue is raised.

An additional type check may prevent trouble.

Loading history...
624 90
            ->attributes($attributes)
0 ignored issues
show
Documentation introduced by
$attributes is of type array, but the function expects a object<Arcanedev\Html\Elements\Concerns\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...
625 90
            ->attributeUnless(is_null($id = $this->getIdAttribute($name, $attributes)), 'id', $id)
626 90
            ->value($this->getValueAttribute($name, $selected));
627
    }
628
629
    /**
630
     * Create a select range field.
631
     *
632
     * @param  string  $name
633
     * @param  string  $begin
634
     * @param  string  $end
635
     * @param  string  $selected
636
     * @param  array   $attributes
637
     *
638
     * @return \Arcanedev\Html\Elements\Select
639
     */
640 12
    public function selectRange(string $name, $begin, $end, $selected = null, array $attributes = []): Select
641
    {
642 12
        $range = array_combine($range = range($begin, $end), $range);
643
644 12
        return $this->select($name, $range, $selected, $attributes);
645
    }
646
647
    /**
648
     * Create a select year field.
649
     *
650
     * @param  string  $name
651
     * @param  string  $begin
652
     * @param  string  $end
653
     * @param  string  $selected
654
     * @param  array   $attributes
655
     *
656
     * @return \Arcanedev\Html\Elements\Select
657
     */
658 6
    public function selectYear(string $name, $begin, $end, $selected = null, array $attributes = []): Select
659
    {
660 6
        return $this->selectRange($name, $begin, $end, $selected, $attributes);
661
    }
662
663
    /**
664
     * Create a select month field.
665
     *
666
     * @param  string  $name
667
     * @param  string  $selected
668
     * @param  array   $attributes
669
     * @param  string  $format
670
     *
671
     * @return \Arcanedev\Html\Elements\Select
672
     */
673 6
    public function selectMonth(string $name, $selected = null, array $attributes = [], $format = '%B'): Select
674
    {
675 6
        $months = [];
676
677 6
        foreach(range(1, 12) as $month) {
678 6
            $months[$month] = strftime($format, mktime(0, 0, 0, $month, 1));
679
        }
680
681 6
        return $this->select($name, $months, $selected, $attributes);
682
    }
683
684
    /**
685
     * Create a checkbox input field.
686
     *
687
     * @param  string     $name
688
     * @param  mixed      $value
689
     * @param  bool|null  $checked
690
     * @param  array      $attributes
691
     *
692
     * @return \Arcanedev\Html\Elements\Input
693
     */
694 24
    public function checkbox(string $name, $value = 1, $checked = null, array $attributes = []): Input
695
    {
696 24
        return $this->checkable('checkbox', $name, $value, $checked, $attributes);
697
    }
698
699
    /**
700
     * Create a radio button input field.
701
     *
702
     * @param  string  $name
703
     * @param  mixed   $value
704
     * @param  bool    $checked
705
     * @param  array   $attributes
706
     *
707
     * @return \Arcanedev\Html\Elements\Input
708
     */
709 12
    public function radio(string $name, $value = null, $checked = null, array $attributes = []): Input
710
    {
711 12
        return $this->checkable('radio', $name, $value ?: $name, $checked, $attributes);
712
    }
713
714
    /**
715
     * Create a HTML reset input element.
716
     *
717
     * @param  string|mixed  $value
718
     * @param  array         $attributes
719
     *
720
     * @return \Arcanedev\Html\Elements\Button
721
     */
722 6
    public function reset($value, array $attributes = []): Button
723
    {
724 6
        return $this->button($value, array_merge(['type' => 'reset'], $attributes));
725
    }
726
727
    /**
728
    * Create a HTML image input element.
729
    *
730
    * @param  string       $url
731
    * @param  string|null  $name
732
    * @param  array        $attributes
733
    *
734
     * @return \Arcanedev\Html\Elements\Input
735
    */
736 6
    public function image(string $url, $name = null, array $attributes = []): Input
737
    {
738 6
        return $this->input('image', $name, null, array_merge($attributes, [
739 6
            'src' => $this->url->asset($url),
740
        ]));
741
    }
742
743
    /**
744
     * Create a submit button element.
745
     *
746
     * @param  string|mixed  $value
747
     * @param  array         $attributes
748
     *
749
     * @return \Arcanedev\Html\Elements\Button
750
     */
751 6
    public function submit($value = null, array $attributes = []): Button
752
    {
753 6
        return $this->button($value, array_merge(['type' => 'submit'], $attributes));
754
    }
755
756
    /**
757
     * Create a button element.
758
     *
759
     * @param  string|mixed  $value
760
     * @param  array         $attributes
761
     *
762
     * @return \Arcanedev\Html\Elements\Button
763
     */
764 18
    public function button($value = null, array $attributes = []): Button
765
    {
766 18
        return Button::make()
767 18
            ->type(Arr::pull($attributes, 'type', 'button'))
768 18
            ->attributes($attributes)
0 ignored issues
show
Documentation introduced by
$attributes is of type array, but the function expects a object<Arcanedev\Html\Elements\Concerns\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...
769 18
            ->html($value);
770
    }
771
772
    /**
773
     * Create a color input field.
774
     *
775
     * @param  string        $name
776
     * @param  string|mixed  $value
777
     * @param  array         $attributes
778
     *
779
     * @return \Arcanedev\Html\Elements\Input
780
     */
781 18
    public function color(string $name, $value = null, array $attributes = []): Input
782
    {
783 18
        return $this->input('color', $name, $value, $attributes);
784
    }
785
786
    /* -----------------------------------------------------------------
787
     |  Other Methods
788
     | -----------------------------------------------------------------
789
     */
790
791
    /**
792
     * Create a checkable input field.
793
     *
794
     * @param  string     $type
795
     * @param  string     $name
796
     * @param  mixed      $value
797
     * @param  bool|null  $checked
798
     * @param  array      $attributes
799
     *
800
     * @return \Arcanedev\Html\Elements\Input
801
     */
802 42
    protected function checkable(string $type, string $name, $value, $checked, array $attributes): Input
803
    {
804 42
        $checked = $this->getCheckedState($type, $name, $value, $checked);
805
806 42
        if ( ! is_null($checked) && $checked)
807 36
            $attributes['checked'] = 'checked';
808
809 42
        return $this->input($type, $name, $value, $attributes);
810
    }
811
812
    /**
813
     * Get the check state for a checkable input.
814
     *
815
     * @param  string     $type
816
     * @param  string     $name
817
     * @param  mixed      $value
818
     * @param  bool|null  $checked
819
     *
820
     * @return bool
821
     */
822 42
    private function getCheckedState(string $type, string $name, $value, $checked): bool
823
    {
824 42
        switch($type) {
825 42
            case 'checkbox':
826 24
                return $this->getCheckboxCheckedState($name, $value, $checked);
827
828 18
            case 'radio':
829 12
                return $this->getRadioCheckedState($name, $value, $checked);
830
831
            default:
832 6
                return $this->getValueAttribute($name) === $value;
833
        }
834
    }
835
836
    /**
837
     * Get the check state for a checkbox input.
838
     *
839
     * @param  string     $name
840
     * @param  mixed      $value
841
     * @param  bool|null  $checked
842
     *
843
     * @return bool
844
     */
845 24
    private function getCheckboxCheckedState(string $name, $value, $checked): bool
846
    {
847
        if (
848 24
            isset($this->session) &&
849 24
            ! $this->oldInputIsEmpty() &&
850 24
            is_null($this->old($name))
851
        ) {
852 6
            return false;
853
        }
854
855 24
        if ($this->missingOldAndModel($name)) {
856 12
            return (bool) $checked;
857
        }
858
859 12
        $posted = $this->getValueAttribute($name, $checked);
860
861 12
        if (is_array($posted)) {
862 6
            return in_array($value, $posted);
863
        }
864
865 12
        if ($posted instanceof Collection) {
866 6
            return $posted->contains('id', $value);
867
        }
868
869 12
        return (bool) $posted;
870
    }
871
872
    /**
873
     * Get the check state for a radio input.
874
     *
875
     * @param  string     $name
876
     * @param  mixed      $value
877
     * @param  bool|null  $checked
878
     *
879
     * @return bool
880
     */
881 12
    private function getRadioCheckedState(string $name, $value, $checked): bool
882
    {
883 12
        if ($this->missingOldAndModel($name)) {
884 6
            return (bool) $checked;
885
        }
886
887 6
        return $this->getValueAttribute($name) === $value;
888
    }
889
890
    /**
891
     * Determine if old input or model input exists for a key.
892
     *
893
     * @param  string  $name
894
     *
895
     * @return bool
896
     */
897 36
    private function missingOldAndModel(string $name): bool
898
    {
899 36
        return is_null($this->old($name))
900 36
            && is_null($this->getModelValueAttribute($name));
901
    }
902
903
    /**
904
     * Get the form action from the options.
905
     *
906
     * @param  array  $attributes
907
     *
908
     * @return string
909
     */
910 84
    private function getAction(array $attributes): string
911
    {
912 84
        if (isset($attributes['url']))
913 6
            return $this->getUrlAction($attributes['url']);
914
915 78
        if (isset($attributes['route']))
916 12
            return $this->getRouteAction($attributes['route']);
917
918 72
        if (isset($attributes['action']))
919 12
            return $this->getControllerAction($attributes['action']);
920
921 60
        return $this->url->current();
922
    }
923
924
    /**
925
     * Get the action for a "url" option.
926
     *
927
     * @param  array|string  $attribute
928
     *
929
     * @return string
930
     */
931 6
    private function getUrlAction($attribute): string
932
    {
933 6
        return is_array($attribute)
934 6
            ? $this->url->to($attribute[0], array_slice($attribute, 1))
935 6
            : $this->url->to($attribute);
936
    }
937
938
    /**
939
     * Get the action for a "route" option.
940
     *
941
     * @param  array|string  $attribute
942
     *
943
     * @return string
944
     */
945 12
    private function getRouteAction($attribute): string
946
    {
947 12
        return is_array($attribute)
948 6
            ? $this->url->route($attribute[0], array_slice($attribute, 1))
949 12
            : $this->url->route($attribute);
950
    }
951
952
    /**
953
     * Get the action for an "action" option.
954
     *
955
     * @param  array|string  $attribute
956
     *
957
     * @return string
958
     */
959 12
    private function getControllerAction($attribute): string
960
    {
961 12
        return is_array($attribute)
962 6
            ? $this->url->action($attribute[0], array_slice($attribute, 1))
963 12
            : $this->url->action($attribute);
964
    }
965
}
966