Completed
Push — master ( 470d6a...134215 )
by ARCANEDEV
13s queued 11s
created

src/FormBuilder.php (1 issue)

Severity

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

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 = static::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
        return is_null($session) ? null : $session->getOldInput(static::transformKey($name));
245
    }
246
247
    /**
248
     * Transform key from array to dot syntax.
249
     *
250
     * @param  string  $key
251
     *
252
     * @return string
253
     */
254 462
    private static function transformKey(string $key): string
255
    {
256 462
        return str_replace(
257 462
            ['.', '[]', '[', ']'],
258 462
            ['_', '', '.', ''],
259 154
            $key
260
        );
261
    }
262
263
    /**
264
     * Determine if the old input is empty.
265
     *
266
     * @return bool
267
     */
268 24
    public function oldInputIsEmpty(): bool
269
    {
270 24
        $session = $this->getSessionStore();
271
272 24
        return ! is_null($session)
273 24
            && (count($session->getOldInput()) === 0);
274
    }
275
276
    /* -----------------------------------------------------------------
277
     |  Main Methods
278
     | -----------------------------------------------------------------
279
     */
280
281
    /**
282
     * Open up a new HTML form.
283
     *
284
     * @param  array  $attributes
285
     *
286
     * @return \Illuminate\Support\HtmlString
287
     */
288 84
    public function open(array $attributes = []): HtmlString
289
    {
290 84
        $method = Str::upper(Arr::pull($attributes, 'method', 'POST'));
291
292 84
        return Form::make()
293 84
            ->method($method !== 'GET' ? 'POST' : $method)
294 84
            ->action($this->getAction($attributes))
295 84
            ->attributes(array_merge(
296 84
                ['accept-charset' => 'UTF-8'],
297 84
                Arr::except($attributes, $this->reserved)
298
            ))
299
            ->if(Arr::pull($attributes, 'files', false), function (Form $form) {
300 6
                return $form->acceptsFiles();
301 84
            })
302
            ->if(in_array($method, $this->spoofedMethods), function (Form $form) use ($method) {
303 6
                return $form->addChild($this->hidden('_method', $method));
304 84
            })
305
            ->if($method !== 'GET', function (Form $form) {
306 48
                return $form->addChild($this->token());
307 84
            })
308 84
            ->open();
309
    }
310
311
    /**
312
     * Create a new model based form builder.
313
     *
314
     * @param  mixed  $model
315
     * @param  array  $attributes
316
     *
317
     * @return \Illuminate\Support\HtmlString
318
     */
319 30
    public function model($model, array $attributes = []): HtmlString
320
    {
321 30
        return $this->setModel($model)->open($attributes);
322
    }
323
324
    /**
325
     * Close the current form.
326
     *
327
     * @return \Illuminate\Support\HtmlString
328
     */
329 6
    public function close(): HtmlString
330
    {
331 6
        $this->labels = [];
332 6
        $this->setModel(null);
333
334 6
        return Form::make()->close();
335
    }
336
337
    /**
338
     * Generate a hidden field with the current CSRF token.
339
     *
340
     * @return \Arcanedev\Html\Elements\Input
341
     */
342 48
    public function token(): Input
343
    {
344 48
        $token = empty($this->csrfToken)
345
            ? $this->getSessionStore()->token()
346 48
            : $this->csrfToken;
347
348 48
        return $this->hidden('_token', $token);
349
    }
350
351
    /**
352
     * Create a form label element.
353
     *
354
     * @param  string        $name
355
     * @param  string|mixed  $value
356
     * @param  array         $attributes
357
     * @param  bool          $escaped
358
     *
359
     * @return \Arcanedev\Html\Elements\Label
360
     */
361 30
    public function label(string $name, $value = null, array $attributes = [], $escaped = true): Label
362
    {
363 30
        $this->labels[] = $name;
364
365 30
        $value = $value ?: Str::title(str_replace(['_', '-'], ' ', $name));
366
367 30
        return Label::make()
368 30
            ->for($name)
369 30
            ->attributes($attributes)
370 30
            ->html($escaped ? e($value) : $value);
371
    }
372
373
    /**
374
     * Create a form input field.
375
     *
376
     * @param  string        $type
377
     * @param  string|null   $name
378
     * @param  string|mixed  $value
379
     * @param  array         $attributes
380
     *
381
     * @return \Arcanedev\Html\Elements\Input
382
     */
383 354
    public function input(string $type, $name, $value = null, array $attributes = []): Input
384
    {
385 354
        if ( ! in_array($type, $this->skipValueTypes))
386 300
            $value = $this->getValueAttribute($name, $value);
387
388 354
        $id = $this->getIdAttribute($name, $attributes);
389
390 354
        return Input::make()
391 354
            ->type($type)
392 354
            ->attributeIfNotNull($name, 'name', $name)
0 ignored issues
show
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...
393 354
            ->attributeIfNotNull($id, 'id', $id)
394 354
            ->attributeUnless(is_null($value) || empty($value), 'value', $value)
395 354
            ->attributes($attributes);
396
    }
397
398
    /**
399
     * Create a text input field.
400
     *
401
     * @param  string        $name
402
     * @param  string|mixed  $value
403
     * @param  array         $attributes
404
     *
405
     * @return \Arcanedev\Html\Elements\Input
406
     */
407 42
    public function text(string $name, $value = null, array $attributes = []): Input
408
    {
409 42
        return $this->input('text', $name, $value, $attributes);
410
    }
411
412
    /**
413
     * Create a password input field.
414
     *
415
     * @param  string  $name
416
     * @param  array   $attributes
417
     *
418
     * @return \Arcanedev\Html\Elements\Input
419
     */
420 18
    public function password(string $name, array $attributes = []): Input
421
    {
422 18
        return $this->input('password', $name, null, $attributes);
423
    }
424
425
    /**
426
     * Create a hidden input field.
427
     *
428
     * @param  string        $name
429
     * @param  string|mixed  $value
430
     * @param  array         $attributes
431
     *
432
     * @return \Arcanedev\Html\Elements\Input
433
     */
434 66
    public function hidden(string $name, $value = null, array $attributes = []): Input
435
    {
436 66
        return $this->input('hidden', $name, $value, $attributes);
437
    }
438
439
    /**
440
     * Create an e-mail input field.
441
     *
442
     * @param  string        $name
443
     * @param  string|mixed  $value
444
     * @param  array         $attributes
445
     *
446
     * @return \Arcanedev\Html\Elements\Input
447
     */
448 18
    public function email(string $name, $value = null, array $attributes = []): Input
449
    {
450 18
        return $this->input('email', $name, $value, $attributes);
451
    }
452
453
    /**
454
     * Create a tel input field.
455
     *
456
     * @param  string        $name
457
     * @param  string|mixed  $value
458
     * @param  array         $attributes
459
     *
460
     * @return \Arcanedev\Html\Elements\Input
461
     */
462 18
    public function tel(string $name, $value = null, array $attributes = []): Input
463
    {
464 18
        return $this->input('tel', $name, $value, $attributes);
465
    }
466
467
    /**
468
     * Create a number input field.
469
     *
470
     * @param  string        $name
471
     * @param  string|mixed  $value
472
     * @param  array         $attributes
473
     *
474
     * @return \Arcanedev\Html\Elements\Input
475
     */
476 18
    public function number(string $name, $value = null, array $attributes = []): Input
477
    {
478 18
        return $this->input('number', $name, $value, $attributes);
479
    }
480
481
    /**
482
     * Create a date input field.
483
     *
484
     * @param  string  $name
485
     * @param  string  $value
486
     * @param  array   $attributes
487
     *
488
     * @return \Arcanedev\Html\Elements\Input
489
     */
490 24
    public function date(string $name, $value = null, array $attributes = []): Input
491
    {
492 24
        if ($value instanceof DateTime)
493 6
            $value = $value->format('Y-m-d');
494
495 24
        return $this->input('date', $name, $value, $attributes);
496
    }
497
498
    /**
499
     * Create a datetime input field.
500
     *
501
     * @param  string        $name
502
     * @param  string|mixed  $value
503
     * @param  array         $attributes
504
     *
505
     * @return \Arcanedev\Html\Elements\Input
506
     */
507 24
    public function datetime(string $name, $value = null, array $attributes = []): Input
508
    {
509 24
        if ($value instanceof DateTime)
510 12
            $value = $value->format(DateTime::RFC3339);
511
512 24
        return $this->input('datetime', $name, $value, $attributes);
513
    }
514
515
    /**
516
     * Create a datetime-local input field.
517
     *
518
     * @param  string        $name
519
     * @param  string|mixed  $value
520
     * @param  array         $attributes
521
     *
522
     * @return \Arcanedev\Html\Elements\Input
523
     */
524 24
    public function datetimeLocal(string $name, $value = null, array $attributes = []): Input
525
    {
526 24
        if ($value instanceof DateTime)
527 12
            $value = $value->format('Y-m-d\TH:i');
528
529 24
        return $this->input('datetime-local', $name, $value, $attributes);
530
    }
531
532
    /**
533
     * Create a time input field.
534
     *
535
     * @param  string        $name
536
     * @param  string|mixed  $value
537
     * @param  array         $attributes
538
     *
539
     * @return \Arcanedev\Html\Elements\Input
540
     */
541 18
    public function time(string $name, $value = null, array $attributes = []): Input
542
    {
543 18
        return $this->input('time', $name, $value, $attributes);
544
    }
545
546
    /**
547
     * Create a url input field.
548
     *
549
     * @param  string  $name
550
     * @param  string  $value
551
     * @param  array   $attributes
552
     *
553
     * @return \Arcanedev\Html\Elements\Input
554
     */
555 12
    public function url(string $name, $value = null, array $attributes = []): Input
556
    {
557 12
        return $this->input('url', $name, $value, $attributes);
558
    }
559
560
    /**
561
     * Create a file input field.
562
     *
563
     * @param  string  $name
564
     * @param  array   $attributes
565
     *
566
     * @return \Arcanedev\Html\Elements\File
567
     */
568 18
    public function file(string $name, array $attributes = []): File
569
    {
570 18
        return File::make()->name($name)->attributes($attributes);
571
    }
572
573
    /**
574
     * Create a textarea input field.
575
     *
576
     * @param  string  $name
577
     * @param  string  $value
578
     * @param  array   $attributes
579
     *
580
     * @return \Arcanedev\Html\Elements\Textarea
581
     */
582 36
    public function textarea(string $name, $value = null, array $attributes = []): Textarea
583
    {
584 36
        $id    = $this->getIdAttribute($name, $attributes);
585 36
        $size  = Arr::pull($attributes, 'size');
586 36
        $value = (string) $this->getValueAttribute($name, $value);
587
588 36
        return Textarea::make()
589 36
            ->name($name)
590 36
            ->attributeUnless(is_null($id), 'id', $id)
591
            ->unless(is_null($size), function (Textarea $elt) use ($size) {
592 18
                return $elt->size($size);
593 36
            })
594 36
            ->attributes($attributes)
595 36
            ->html($this->html->escape($value));
596
    }
597
598
    /**
599
     * Create a select box field.
600
     *
601
     * @param  string                                         $name
602
     * @param  array|\Illuminate\Support\Collection|iterable  $list
603
     * @param  string|bool                                    $selected
604
     * @param  array                                          $attributes
605
     * @param  array                                          $optionsAttributes
606
     * @param  array                                          $optgroupsAttributes
607
     *
608
     * @return \Arcanedev\Html\Elements\Select
609
     */
610 90
    public function select(
611
        string $name,
612
        iterable $list = [],
613
        $selected = null,
614
        array $attributes = [],
615
        array $optionsAttributes = [],
616
        array $optgroupsAttributes = []
617
    ): Select {
618 90
        return Select::make()
619 90
            ->name($name)
620 90
            ->options($list, $optionsAttributes, $optgroupsAttributes)
621 90
            ->attributes($attributes)
622 90
            ->attributeUnless(is_null($id = $this->getIdAttribute($name, $attributes)), 'id', $id)
623 90
            ->value($this->getValueAttribute($name, $selected));
624
    }
625
626
    /**
627
     * Create a select range field.
628
     *
629
     * @param  string  $name
630
     * @param  string  $begin
631
     * @param  string  $end
632
     * @param  string  $selected
633
     * @param  array   $attributes
634
     *
635
     * @return \Arcanedev\Html\Elements\Select
636
     */
637 12
    public function selectRange(string $name, $begin, $end, $selected = null, array $attributes = []): Select
638
    {
639 12
        $range = array_combine($range = range($begin, $end), $range);
640
641 12
        return $this->select($name, $range, $selected, $attributes);
642
    }
643
644
    /**
645
     * Create a select year field.
646
     *
647
     * @param  string  $name
648
     * @param  string  $begin
649
     * @param  string  $end
650
     * @param  string  $selected
651
     * @param  array   $attributes
652
     *
653
     * @return \Arcanedev\Html\Elements\Select
654
     */
655 6
    public function selectYear(string $name, $begin, $end, $selected = null, array $attributes = []): Select
656
    {
657 6
        return $this->selectRange($name, $begin, $end, $selected, $attributes);
658
    }
659
660
    /**
661
     * Create a select month field.
662
     *
663
     * @param  string  $name
664
     * @param  string  $selected
665
     * @param  array   $attributes
666
     * @param  string  $format
667
     *
668
     * @return \Arcanedev\Html\Elements\Select
669
     */
670 6
    public function selectMonth(string $name, $selected = null, array $attributes = [], $format = '%B'): Select
671
    {
672 6
        $months = [];
673
674 6
        foreach(range(1, 12) as $month) {
675 6
            $months[$month] = strftime($format, mktime(0, 0, 0, $month, 1));
676
        }
677
678 6
        return $this->select($name, $months, $selected, $attributes);
679
    }
680
681
    /**
682
     * Create a checkbox input field.
683
     *
684
     * @param  string     $name
685
     * @param  mixed      $value
686
     * @param  bool|null  $checked
687
     * @param  array      $attributes
688
     *
689
     * @return \Arcanedev\Html\Elements\Input
690
     */
691 24
    public function checkbox(string $name, $value = 1, $checked = null, array $attributes = []): Input
692
    {
693 24
        return $this->checkable('checkbox', $name, $value, $checked, $attributes);
694
    }
695
696
    /**
697
     * Create a radio button input field.
698
     *
699
     * @param  string  $name
700
     * @param  mixed   $value
701
     * @param  bool    $checked
702
     * @param  array   $attributes
703
     *
704
     * @return \Arcanedev\Html\Elements\Input
705
     */
706 12
    public function radio(string $name, $value = null, $checked = null, array $attributes = []): Input
707
    {
708 12
        return $this->checkable('radio', $name, $value ?: $name, $checked, $attributes);
709
    }
710
711
    /**
712
     * Create a HTML reset input element.
713
     *
714
     * @param  string|mixed  $value
715
     * @param  array         $attributes
716
     *
717
     * @return \Arcanedev\Html\Elements\Button
718
     */
719 6
    public function reset($value, array $attributes = []): Button
720
    {
721 6
        return $this->button($value, array_merge(['type' => 'reset'], $attributes));
722
    }
723
724
    /**
725
    * Create a HTML image input element.
726
    *
727
    * @param  string       $url
728
    * @param  string|null  $name
729
    * @param  array        $attributes
730
    *
731
     * @return \Arcanedev\Html\Elements\Input
732
    */
733 6
    public function image(string $url, $name = null, array $attributes = []): Input
734
    {
735 6
        return $this->input('image', $name, null, array_merge($attributes, [
736 6
            'src' => $this->url->asset($url),
737
        ]));
738
    }
739
740
    /**
741
     * Create a submit button element.
742
     *
743
     * @param  string|mixed  $value
744
     * @param  array         $attributes
745
     *
746
     * @return \Arcanedev\Html\Elements\Button
747
     */
748 6
    public function submit($value = null, array $attributes = []): Button
749
    {
750 6
        return $this->button($value, array_merge(['type' => 'submit'], $attributes));
751
    }
752
753
    /**
754
     * Create a button element.
755
     *
756
     * @param  string|mixed  $value
757
     * @param  array         $attributes
758
     *
759
     * @return \Arcanedev\Html\Elements\Button
760
     */
761 18
    public function button($value = null, array $attributes = []): Button
762
    {
763 18
        return Button::make()
764 18
            ->type(Arr::pull($attributes, 'type', 'button'))
765 18
            ->attributes($attributes)
766 18
            ->html($value);
767
    }
768
769
    /**
770
     * Create a color input field.
771
     *
772
     * @param  string        $name
773
     * @param  string|mixed  $value
774
     * @param  array         $attributes
775
     *
776
     * @return \Arcanedev\Html\Elements\Input
777
     */
778 18
    public function color(string $name, $value = null, array $attributes = []): Input
779
    {
780 18
        return $this->input('color', $name, $value, $attributes);
781
    }
782
783
    /* -----------------------------------------------------------------
784
     |  Other Methods
785
     | -----------------------------------------------------------------
786
     */
787
788
    /**
789
     * Create a checkable input field.
790
     *
791
     * @param  string     $type
792
     * @param  string     $name
793
     * @param  mixed      $value
794
     * @param  bool|null  $checked
795
     * @param  array      $attributes
796
     *
797
     * @return \Arcanedev\Html\Elements\Input
798
     */
799 42
    protected function checkable(string $type, string $name, $value, $checked, array $attributes): Input
800
    {
801 42
        $checked = $this->getCheckedState($type, $name, $value, $checked);
802
803 42
        if ( ! is_null($checked) && $checked)
804 36
            $attributes['checked'] = 'checked';
805
806 42
        return $this->input($type, $name, $value, $attributes);
807
    }
808
809
    /**
810
     * Get the check state for a checkable input.
811
     *
812
     * @param  string     $type
813
     * @param  string     $name
814
     * @param  mixed      $value
815
     * @param  bool|null  $checked
816
     *
817
     * @return bool
818
     */
819 42
    private function getCheckedState(string $type, string $name, $value, $checked): bool
820
    {
821 42
        switch($type) {
822 42
            case 'checkbox':
823 24
                return $this->getCheckboxCheckedState($name, $value, $checked);
824
825 18
            case 'radio':
826 12
                return $this->getRadioCheckedState($name, $value, $checked);
827
828
            default:
829 6
                return $this->getValueAttribute($name) === $value;
830
        }
831
    }
832
833
    /**
834
     * Get the check state for a checkbox input.
835
     *
836
     * @param  string     $name
837
     * @param  mixed      $value
838
     * @param  bool|null  $checked
839
     *
840
     * @return bool
841
     */
842 24
    private function getCheckboxCheckedState(string $name, $value, $checked): bool
843
    {
844
        if (
845 24
            isset($this->session) &&
846 24
            ! $this->oldInputIsEmpty() &&
847 24
            is_null($this->old($name))
848
        ) {
849 6
            return false;
850
        }
851
852 24
        if ($this->missingOldAndModel($name)) {
853 12
            return (bool) $checked;
854
        }
855
856 12
        $posted = $this->getValueAttribute($name, $checked);
857
858 12
        if (is_array($posted)) {
859 6
            return in_array($value, $posted);
860
        }
861
862 12
        if ($posted instanceof Collection) {
863 6
            return $posted->contains('id', $value);
864
        }
865
866 12
        return (bool) $posted;
867
    }
868
869
    /**
870
     * Get the check state for a radio input.
871
     *
872
     * @param  string     $name
873
     * @param  mixed      $value
874
     * @param  bool|null  $checked
875
     *
876
     * @return bool
877
     */
878 12
    private function getRadioCheckedState(string $name, $value, $checked): bool
879
    {
880 12
        if ($this->missingOldAndModel($name)) {
881 6
            return (bool) $checked;
882
        }
883
884 6
        return $this->getValueAttribute($name) === $value;
885
    }
886
887
    /**
888
     * Determine if old input or model input exists for a key.
889
     *
890
     * @param  string  $name
891
     *
892
     * @return bool
893
     */
894 36
    private function missingOldAndModel(string $name): bool
895
    {
896 36
        return is_null($this->old($name))
897 36
            && is_null($this->getModelValueAttribute($name));
898
    }
899
900
    /**
901
     * Get the form action from the options.
902
     *
903
     * @param  array  $attributes
904
     *
905
     * @return string
906
     */
907 84
    private function getAction(array $attributes): string
908
    {
909 84
        if (isset($attributes['url']))
910 6
            return $this->getUrlAction($attributes['url']);
911
912 78
        if (isset($attributes['route']))
913 12
            return $this->getRouteAction($attributes['route']);
914
915 72
        if (isset($attributes['action']))
916 12
            return $this->getControllerAction($attributes['action']);
917
918 60
        return $this->url->current();
919
    }
920
921
    /**
922
     * Get the action for a "url" option.
923
     *
924
     * @param  array|string  $attribute
925
     *
926
     * @return string
927
     */
928 6
    private function getUrlAction($attribute): string
929
    {
930 6
        return is_array($attribute)
931 6
            ? $this->url->to($attribute[0], array_slice($attribute, 1))
932 6
            : $this->url->to($attribute);
933
    }
934
935
    /**
936
     * Get the action for a "route" option.
937
     *
938
     * @param  array|string  $attribute
939
     *
940
     * @return string
941
     */
942 12
    private function getRouteAction($attribute): string
943
    {
944 12
        return is_array($attribute)
945 6
            ? $this->url->route($attribute[0], array_slice($attribute, 1))
946 12
            : $this->url->route($attribute);
947
    }
948
949
    /**
950
     * Get the action for an "action" option.
951
     *
952
     * @param  array|string  $attribute
953
     *
954
     * @return string
955
     */
956 12
    private function getControllerAction($attribute): string
957
    {
958 12
        return is_array($attribute)
959 6
            ? $this->url->action($attribute[0], array_slice($attribute, 1))
960 12
            : $this->url->action($attribute);
961
    }
962
}
963