Completed
Push — master ( 733a94...d72b67 )
by ARCANEDEV
10s
created

FormBuilder::select()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 24

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 9
CRAP Score 1

Importance

Changes 0
Metric Value
dl 0
loc 24
ccs 9
cts 9
cp 1
rs 9.536
c 0
b 0
f 0
cc 1
nc 1
nop 6
crap 1
1
<?php namespace Arcanedev\LaravelHtml;
2
3
use Arcanedev\Html\Elements;
4
use Arcanedev\LaravelHtml\Bases\Builder;
5
use Arcanedev\LaravelHtml\Contracts\FormBuilder as FormBuilderContract;
6
use DateTime;
7
use Illuminate\Contracts\Routing\UrlGenerator;
8
use Illuminate\Contracts\Session\Session;
9
use Illuminate\Support\Arr;
10
use Illuminate\Support\Collection;
11
use Illuminate\Support\Str;
12
13
/**
14
 * Class     FormBuilder
15
 *
16
 * @package  Arcanedev\LaravelHtml
17
 * @author   ARCANEDEV <[email protected]>
18
 */
19
class FormBuilder extends Builder implements FormBuilderContract
20
{
21
    /* -----------------------------------------------------------------
22
     |  Properties
23
     | -----------------------------------------------------------------
24
     */
25
26
    /**
27
    * The HTML builder instance.
28
    *
29
    * @var \Arcanedev\LaravelHtml\Contracts\HtmlBuilder
30
    */
31
    protected $html;
32
33
    /**
34
    * The URL generator instance.
35
    *
36
    * @var \Illuminate\Contracts\Routing\UrlGenerator
37
    */
38
    protected $url;
39
40
    /**
41
    * The CSRF token used by the form builder.
42
    *
43
    * @var string
44
    */
45
    protected $csrfToken;
46
47
    /**
48
    * The session store implementation.
49
    *
50
    * @var \Illuminate\Contracts\Session\Session|\Illuminate\Session\Store
51
    */
52
    protected $session;
53
54
    /**
55
    * The current model instance for the form.
56
    *
57
    * @var \Illuminate\Database\Eloquent\Model|null
58
    */
59
    protected $model;
60
61
    /**
62
    * An array of label names we've created.
63
    *
64
    * @var array
65
    */
66
    protected $labels = [];
67
68
    /**
69
    * The reserved form open attributes.
70
    *
71
    * @var array
72
    */
73
    protected $reserved = ['method', 'url', 'route', 'action', 'files'];
74
75
    /**
76
    * The form methods that should be spoofed, in uppercase.
77
    *
78
    * @var array
79
    */
80
    protected $spoofedMethods = ['DELETE', 'PATCH', 'PUT'];
81
82
    /**
83
    * The types of inputs to not fill values on by default.
84
    *
85
    * @var array
86
    */
87
    protected $skipValueTypes = ['file', 'password', 'checkbox', 'radio'];
88
89
    /* -----------------------------------------------------------------
90
     |  Constructor
91
     | -----------------------------------------------------------------
92
     */
93
94
    /**
95
    * Create a new form builder instance.
96
    *
97
    * @param  \Arcanedev\LaravelHtml\Contracts\HtmlBuilder  $html
98
    * @param  \Illuminate\Contracts\Routing\UrlGenerator    $url
99
    * @param  \Illuminate\Contracts\Session\Session         $session
100
    */
101 321
    public function __construct(Contracts\HtmlBuilder $html, UrlGenerator $url, Session $session)
102
    {
103 321
        $this->url       = $url;
104 321
        $this->html      = $html;
105 321
        $this->csrfToken = $session->token();
106
107 321
        $this->setSessionStore($session);
108 321
    }
109
110
    /* -----------------------------------------------------------------
111
     |  Getters & Setters
112
     | -----------------------------------------------------------------
113
     */
114
115
    /**
116
     * Get the session store implementation.
117
     *
118
     * @return  \Illuminate\Contracts\Session\Session
119
     */
120 3
    public function getSessionStore()
121
    {
122 3
        return $this->session;
123
    }
124
125
    /**
126
     * Set the session store implementation.
127
     *
128
     * @param  \Illuminate\Contracts\Session\Session  $session
129
     *
130
     * @return self
131
     */
132 321
    public function setSessionStore(Session $session)
133
    {
134 321
        $this->session = $session;
135
136 321
        return $this;
137
    }
138
139
    /**
140
     * Set the model instance on the form builder.
141
     *
142
     * @param  \Illuminate\Database\Eloquent\Model|null  $model
143
     *
144
     * @return self
145
     */
146 36
    public function setModel($model)
147
    {
148 36
        $this->model = $model;
149
150 36
        return $this;
151
    }
152
153
    /**
154
     * Get the model instance on the form builder.
155
     *
156
     * @return \Illuminate\Database\Eloquent\Model
157
     */
158 138
    public function getModel()
159
    {
160 138
        return $this->model;
161
    }
162
163
    /**
164
     * Get the ID attribute for a field name.
165
     *
166
     * @param  string  $name
167
     * @param  array   $attributes
168
     *
169
     * @return string
170
     */
171 261
    public function getIdAttribute($name, array $attributes)
172
    {
173 261
        if (array_key_exists('id', $attributes))
174 21
            return $attributes['id'];
175
176 249
        if (in_array($name, $this->labels))
177 6
            return $name;
178
179 243
        return null;
180
    }
181
182
    /**
183
     * Get the value that should be assigned to the field.
184
     *
185
     * @param  string  $name
186
     * @param  mixed   $value
187
     *
188
     * @return mixed
189
     */
190 237
    public function getValueAttribute($name, $value = null)
191
    {
192 237
        if (is_null($name))
193 9
            return $value;
194
195 228
        if ( ! is_null($this->old($name)) && $name !== '_method')
196 15
            return $this->old($name);
197
198 222
        if ( ! is_null($value))
199 129
            return $value;
200
201 123
        return $this->getModelValueAttribute($name);
202
    }
203
204
    /**
205
     * Get the model value that should be assigned to the field.
206
     *
207
     * @param  string                               $name
208
     * @param  \Illuminate\Database\Eloquent\Model  $model
209
     *
210
     * @return mixed
211
     */
212 132
    private function getModelValueAttribute($name, $model = null)
213
    {
214 132
        $model = $model ?: $this->getModel();
215
216 132
        $key = $this->transformKey($name);
217
218 132
        if (strpos($key, '.') !== false) {
219 15
            $keys = explode('.', $key, 2);
220
221 15
            return $this->getModelValueAttribute(
222 15
                $keys[1],
223 15
                $this->getModelValueAttribute($keys[0], $model)
224
            );
225
        }
226
227 132
        return method_exists($model, 'getFormValue')
228 3
            ? $model->getFormValue($key)
229 132
            : data_get($model, $key);
230
    }
231
232
    /**
233
     * Get a value from the session's old input.
234
     *
235
     * @param  string  $name
236
     *
237
     * @return mixed
238
     */
239 237
    public function old($name)
240
    {
241 237
        return ! is_null($this->session)
242 237
            ? $this->session->getOldInput($this->transformKey($name))
243 237
            : null;
244
    }
245
246
    /**
247
     * Transform key from array to dot syntax.
248
     *
249
     * @param  string  $key
250
     *
251
     * @return string
252
     */
253 237
    private function transformKey($key)
254
    {
255 237
        return str_replace(
256 237
            ['.', '[]', '[', ']'],
257 237
            ['_', '', '.', ''],
258 79
            $key
259
        );
260
    }
261
262
    /**
263
     * Determine if the old input is empty.
264
     *
265
     * @return bool
266
     */
267 12
    public function oldInputIsEmpty()
268
    {
269 12
        return ! is_null($this->session)
270 12
            && (count($this->session->getOldInput()) === 0);
271
    }
272
273
    /* -----------------------------------------------------------------
274
     |  Main Methods
275
     | -----------------------------------------------------------------
276
     */
277
278
    /**
279
     * Open up a new HTML form.
280
     *
281
     * @param  array  $attributes
282
     *
283
     * @return \Illuminate\Support\HtmlString
284
     */
285 57
    public function open(array $attributes = [])
286
    {
287 57
        $method = strtoupper(Arr::pull($attributes, 'method', 'POST'));
288
289 57
        $form = Elements\Form::make()
290 57
            ->method($method !== 'GET' ? 'POST' : $method)
291 57
            ->action($this->getAction($attributes))
292 57
            ->attributes(array_merge(
293 57
                ['accept-charset' => 'UTF-8'],
294 57
                Arr::except($attributes, $this->reserved)
295
            ));
296
297 57
        if (Arr::pull($attributes, 'files', false))
298 6
            $form = $form->acceptsFiles();
299
300 57
        if (in_array($method, $this->spoofedMethods))
301 6
            $form = $form->addChild($this->hidden('_method', $method));
302
303 57
        if ($method !== 'GET')
304 30
            $form = $form->addChild($this->token());
305
306 57
        return $form->open();
307
    }
308
309
    /**
310
     * Create a new model based form builder.
311
     *
312
     * @param  mixed  $model
313
     * @param  array  $attributes
314
     *
315
     * @return \Illuminate\Support\HtmlString
316
     */
317 15
    public function model($model, array $attributes = [])
318
    {
319 15
        return $this->setModel($model)
320 15
                    ->open($attributes);
321
    }
322
323
    /**
324
     * Close the current form.
325
     *
326
     * @return \Illuminate\Support\HtmlString
327
     */
328 6
    public function close()
329
    {
330 6
        $this->labels = [];
331 6
        $this->setModel(null);
332
333 6
        return Elements\Form::make()->close();
334
    }
335
336
    /**
337
     * Generate a hidden field with the current CSRF token.
338
     *
339
     * @return \Illuminate\Support\HtmlString
340
     */
341 30
    public function token()
342
    {
343 30
        return $this->hidden(
344 30
            '_token',
345 30
            empty($this->csrfToken) ? $this->session->token() : $this->csrfToken
346
        );
347
    }
348
349
    /**
350
     * Create a form label element.
351
     *
352
     * @param  string        $name
353
     * @param  string|mixed  $value
354
     * @param  array         $attributes
355
     * @param  bool          $escaped
356
     *
357
     * @return \Illuminate\Support\HtmlString
358
     */
359 15
    public function label($name, $value = null, array $attributes = [], $escaped = true)
360
    {
361 15
        $this->labels[] = $name;
362
363 15
        $value = $value ?: Str::title(str_replace(['_', '-'], ' ', $name));
364
365 15
        return Elements\Label::make()
366 15
            ->for($name)
367 15
            ->attributes($attributes)
368 15
            ->html($escaped ? e($value) : $value)
369 15
            ->render();
370
    }
371
372
    /**
373
     * Create a form input field.
374
     *
375
     * @param  string        $type
376
     * @param  string        $name
377
     * @param  string|mixed  $value
378
     * @param  array         $attributes
379
     *
380
     * @return \Illuminate\Support\HtmlString
381
     */
382 198
    public function input($type, $name, $value = null, array $attributes = [])
383
    {
384 198
        $id = $this->getIdAttribute($name, $attributes);
385
386 198
        if ( ! in_array($type, $this->skipValueTypes))
387 162
            $value = $this->getValueAttribute($name, $value);
388
389 198
        return Elements\Input::make()
390 198
            ->type($type)
391 198
            ->attributeUnless(is_null($name), 'name', $name)
392 198
            ->attributeUnless(is_null($id), 'id', $id)
393 198
            ->attributeUnless(is_null($value) || empty($value), 'value', $value)
394 198
            ->attributes($attributes)
395 198
            ->render();
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 \Illuminate\Support\HtmlString
406
     */
407 21
    public function text($name, $value = null, array $attributes = [])
408
    {
409 21
        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 \Illuminate\Support\HtmlString
419
     */
420 9
    public function password($name, array $attributes = [])
421
    {
422 9
        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 \Illuminate\Support\HtmlString
433
     */
434 39
    public function hidden($name, $value = null, array $attributes = [])
435
    {
436 39
        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 \Illuminate\Support\HtmlString
447
     */
448 9
    public function email($name, $value = null, array $attributes = [])
449
    {
450 9
        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 \Illuminate\Support\HtmlString
461
     */
462 9
    public function tel($name, $value = null, array $attributes = [])
463
    {
464 9
        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 \Illuminate\Support\HtmlString
475
     */
476 9
    public function number($name, $value = null, array $attributes = [])
477
    {
478 9
        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 \Illuminate\Support\HtmlString
489
     */
490 12
    public function date($name, $value = null, array $attributes = [])
491
    {
492 12
        if ($value instanceof DateTime)
493 3
            $value = $value->format('Y-m-d');
494
495 12
        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 \Illuminate\Support\HtmlString
506
     */
507 12
    public function datetime($name, $value = null, array $attributes = [])
508
    {
509 12
        if ($value instanceof DateTime)
510 6
            $value = $value->format(DateTime::RFC3339);
511
512 12
        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 \Illuminate\Support\HtmlString
523
     */
524 12
    public function datetimeLocal($name, $value = null, array $attributes = [])
525
    {
526 12
        if ($value instanceof DateTime)
527 6
            $value = $value->format('Y-m-d\TH:i');
528
529 12
        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         $options
538
     *
539
     * @return \Illuminate\Support\HtmlString
540
     */
541 9
    public function time($name, $value = null, array $options = [])
542
    {
543 9
        return $this->input('time', $name, $value, $options);
544
    }
545
546
    /**
547
     * Create a url input field.
548
     *
549
     * @param  string  $name
550
     * @param  string  $value
551
     * @param  array   $options
552
     *
553
     * @return \Illuminate\Support\HtmlString
554
     */
555 6
    public function url($name, $value = null, array $options = [])
556
    {
557 6
        return $this->input('url', $name, $value, $options);
558
    }
559
560
    /**
561
     * Create a file input field.
562
     *
563
     * @param  string  $name
564
     * @param  array   $options
565
     *
566
     * @return \Illuminate\Support\HtmlString
567
     */
568 9
    public function file($name, array $options = [])
569
    {
570 9
        return $this->input('file', $name, null, $options);
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 \Illuminate\Support\HtmlString
581
     */
582 18
    public function textarea($name, $value = null, array $attributes = [])
583
    {
584
        // Next we will look for the rows and cols attributes, as each of these are put
585
        // on the textarea element definition. If they are not present, we will just
586
        // assume some sane default values for these attributes for the developer.
587 18
        $attributes = $this->setTextAreaSize($attributes);
588 18
        $id      = $this->getIdAttribute($name, $attributes);
589 18
        $value   = (string) $this->getValueAttribute($name, $value);
590
591 18
        unset($attributes['size']);
592
593 18
        return Elements\Textarea::make()
594 18
            ->name($name)
595 18
            ->attributeUnless(is_null($id), 'id', $id)
596 18
            ->attributes($attributes)
597 18
            ->html($this->html->escape($value))
598 18
            ->render();
599
    }
600
601
    /**
602
     * Set the text area size on the attributes.
603
     *
604
     * @param  array  $attributes
605
     *
606
     * @return array
607
     */
608 18
    private function setTextAreaSize(array $attributes)
609
    {
610 18
        if (isset($attributes['size']))
611 9
            return $this->setQuickTextAreaSize($attributes);
612
613
        // If the "size" attribute was not specified, we will just look for the regular
614
        // columns and rows attributes, using sane defaults if these do not exist on
615
        // the attributes array. We'll then return this entire options array back.
616 9
        $cols = Arr::get($attributes, 'cols', 50);
617 9
        $rows = Arr::get($attributes, 'rows', 10);
618
619 9
        return array_merge($attributes, compact('cols', 'rows'));
620
    }
621
622
    /**
623
     * Set the text area size using the quick "size" attribute.
624
     *
625
     * @param  array  $attributes
626
     *
627
     * @return array
628
     */
629 9
    protected function setQuickTextAreaSize(array $attributes)
630
    {
631 9
        list($cols, $rows) = explode('x', $attributes['size']);
632
633 9
        return array_merge($attributes, compact('cols', 'rows'));
634
    }
635
636
    /**
637
     * Create a select box field.
638
     *
639
     * @param  string                                $name
640
     * @param  array|\Illuminate\Support\Collection  $list
641
     * @param  string|bool                           $selected
642
     * @param  array                                 $attributes
643
     * @param  array                                 $optionsAttributes
644
     * @param  array                                 $optgroupsAttributes
645
     *
646
     * @return \Illuminate\Support\HtmlString
647
     */
648 45
    public function select(
649
        $name,
650
        $list = [],
651
        $selected = null,
652
        array $attributes = [],
653
        array $optionsAttributes = [],
654
        array $optgroupsAttributes = []
655
    ) {
656
657 45
        $select = Elements\Select::make()->name($name);
658
659
        // When building a select box the "value" attribute is really the selected one
660
        // so we will use that when checking the model or session for a value which
661
        // should provide a convenient method of re-populating the forms on post.
662 45
        $selected = $this->getValueAttribute($name, $selected);
663 45
        $id       = $this->getIdAttribute($name, $attributes);
664
665
        return $select
666 45
            ->options($list, $optionsAttributes, $optgroupsAttributes)
667 45
            ->attributes($attributes)
668 45
            ->attributeUnless(is_null($id), 'id', $id)
669 45
            ->value($selected)
670 45
            ->render();
671
    }
672
673
    /**
674
     * Create a select range field.
675
     *
676
     * @param  string  $name
677
     * @param  string  $begin
678
     * @param  string  $end
679
     * @param  string  $selected
680
     * @param  array   $attributes
681
     *
682
     * @return \Illuminate\Support\HtmlString
683
     */
684 6
    public function selectRange($name, $begin, $end, $selected = null, array $attributes = [])
685
    {
686 6
        $range = array_combine($range = range($begin, $end), $range);
687
688 6
        return $this->select($name, $range, $selected, $attributes);
689
    }
690
691
    /**
692
     * Create a select year field.
693
     *
694
     * @param  string  $name
695
     * @param  string  $begin
696
     * @param  string  $end
697
     * @param  string  $selected
698
     * @param  array   $attributes
699
     *
700
     * @return \Illuminate\Support\HtmlString
701
     */
702 3
    public function selectYear($name, $begin, $end, $selected = null, array $attributes = [])
703
    {
704 3
        return $this->selectRange($name, $begin, $end, $selected, $attributes);
705
    }
706
707
    /**
708
     * Create a select month field.
709
     *
710
     * @param  string  $name
711
     * @param  string  $selected
712
     * @param  array   $attributes
713
     * @param  string  $format
714
     *
715
     * @return \Illuminate\Support\HtmlString
716
     */
717 3
    public function selectMonth($name, $selected = null, array $attributes = [], $format = '%B')
718
    {
719 3
        $months = [];
720
721 3
        foreach(range(1, 12) as $month) {
722 3
            $months[$month] = strftime($format, mktime(0, 0, 0, $month, 1));
723
        }
724
725 3
        return $this->select($name, $months, $selected, $attributes);
726
    }
727
728
    /**
729
     * Create a checkbox input field.
730
     *
731
     * @param  string     $name
732
     * @param  mixed      $value
733
     * @param  bool|null  $checked
734
     * @param  array      $attributes
735
     *
736
     * @return \Illuminate\Support\HtmlString
737
     */
738 12
    public function checkbox($name, $value = 1, $checked = null, array $attributes = [])
739
    {
740 12
        return $this->checkable('checkbox', $name, $value, $checked, $attributes);
741
    }
742
743
    /**
744
     * Create a radio button input field.
745
     *
746
     * @param  string  $name
747
     * @param  mixed   $value
748
     * @param  bool    $checked
749
     * @param  array   $options
750
     *
751
     * @return \Illuminate\Support\HtmlString
752
     */
753 6
    public function radio($name, $value = null, $checked = null, array $options = [])
754
    {
755 6
        return $this->checkable('radio', $name, $value ?: $name, $checked, $options);
756
    }
757
758
    /**
759
     * Create a HTML reset input element.
760
     *
761
     * @param  string|mixed  $value
762
     * @param  array         $attributes
763
     *
764
     * @return \Illuminate\Support\HtmlString
765
     */
766 3
    public function reset($value, array $attributes = [])
767
    {
768 3
        return $this->input('reset', null, $value, $attributes);
769
    }
770
771
    /**
772
    * Create a HTML image input element.
773
    *
774
    * @param  string       $url
775
    * @param  string|null  $name
776
    * @param  array        $attributes
777
    *
778
     * @return \Illuminate\Support\HtmlString
779
    */
780 3
    public function image($url, $name = null, array $attributes = [])
781
    {
782 3
        return $this->input('image', $name, null, array_merge($attributes, [
783 3
            'src' => $this->url->asset($url),
784
        ]));
785
    }
786
787
    /**
788
     * Create a submit button element.
789
     *
790
     * @param  string|mixed  $value
791
     * @param  array         $attributes
792
     *
793
     * @return \Illuminate\Support\HtmlString
794
     */
795 3
    public function submit($value = null, array $attributes = [])
796
    {
797 3
        return $this->input('submit', null, $value, $attributes);
798
    }
799
800
    /**
801
     * Create a button element.
802
     *
803
     * @param  string|mixed  $value
804
     * @param  array         $attributes
805
     *
806
     * @return \Illuminate\Support\HtmlString
807
     */
808 3
    public function button($value = null, array $attributes = [])
809
    {
810 3
        return Elements\Button::make()
811 3
            ->type(Arr::pull($attributes, 'type', 'button'))
812 3
            ->attributes($attributes)
813 3
            ->html($value)
814 3
            ->render();
815
    }
816
817
    /**
818
     * Create a color input field.
819
     *
820
     * @param  string        $name
821
     * @param  string|mixed  $value
822
     * @param  array         $attributes
823
     *
824
     * @return \Illuminate\Support\HtmlString
825
     */
826 9
    public function color($name, $value = null, array $attributes = [])
827
    {
828 9
        return $this->input('color', $name, $value, $attributes);
829
    }
830
831
    /* -----------------------------------------------------------------
832
     |  Other Methods
833
     | -----------------------------------------------------------------
834
     */
835
836
    /**
837
     * Create a checkable input field.
838
     *
839
     * @param  string     $type
840
     * @param  string     $name
841
     * @param  mixed      $value
842
     * @param  bool|null  $checked
843
     * @param  array      $attributes
844
     *
845
     * @return \Illuminate\Support\HtmlString
846
     */
847 21
    protected function checkable($type, $name, $value, $checked, array $attributes)
848
    {
849 21
        $checked = $this->getCheckedState($type, $name, $value, $checked);
850
851 21
        if ( ! is_null($checked) && $checked)
852 18
            $attributes['checked'] = 'checked';
853
854 21
        return $this->input($type, $name, $value, $attributes);
855
    }
856
857
    /**
858
     * Get the check state for a checkable input.
859
     *
860
     * @param  string     $type
861
     * @param  string     $name
862
     * @param  mixed      $value
863
     * @param  bool|null  $checked
864
     *
865
     * @return bool
866
     */
867 21
    private function getCheckedState($type, $name, $value, $checked)
868
    {
869
        switch($type) {
870 21
            case 'checkbox':
871 12
                return $this->getCheckboxCheckedState($name, $value, $checked);
872
873 9
            case 'radio':
874 6
                return $this->getRadioCheckedState($name, $value, $checked);
875
876
            default:
877 3
                return $this->getValueAttribute($name) === $value;
878
        }
879
    }
880
881
    /**
882
     * Get the check state for a checkbox input.
883
     *
884
     * @param  string     $name
885
     * @param  mixed      $value
886
     * @param  bool|null  $checked
887
     *
888
     * @return bool
889
     */
890 12
    private function getCheckboxCheckedState($name, $value, $checked)
891
    {
892
        if (
893 12
            isset($this->session) &&
894 12
            ! $this->oldInputIsEmpty() &&
895 6
            is_null($this->old($name))
896
        )
897 3
            return false;
898
899 12
        if ($this->missingOldAndModel($name))
900 6
            return $checked;
901
902 6
        $posted = $this->getValueAttribute($name, $checked);
903
904 6
        if (is_array($posted))
905 3
            return in_array($value, $posted);
906
907 6
        if ($posted instanceof Collection)
908 3
            return $posted->contains('id', $value);
909
910 6
        return (bool) $posted;
911
    }
912
913
    /**
914
     * Get the check state for a radio input.
915
     *
916
     * @param  string     $name
917
     * @param  mixed      $value
918
     * @param  bool|null  $checked
919
     *
920
     * @return bool
921
     */
922 6
    private function getRadioCheckedState($name, $value, $checked)
923
    {
924 6
        return $this->missingOldAndModel($name)
925 1
            ? $checked
926 6
            : $this->getValueAttribute($name) === $value;
927
    }
928
929
    /**
930
     * Determine if old input or model input exists for a key.
931
     *
932
     * @param  string  $name
933
     *
934
     * @return bool
935
     */
936 18
    private function missingOldAndModel($name)
937
    {
938 18
        return is_null($this->old($name))
939 18
            && is_null($this->getModelValueAttribute($name));
940
    }
941
942
    /**
943
     * Get the form action from the options.
944
     *
945
     * @param  array  $attributes
946
     *
947
     * @return string
948
     */
949 57
    private function getAction(array $attributes)
950
    {
951 57
        if (isset($attributes['url']))
952 18
            return $this->getUrlAction($attributes['url']);
953
954 39
        if (isset($attributes['route']))
955 6
            return $this->getRouteAction($attributes['route']);
956
957 36
        if (isset($attributes['action']))
958 6
            return $this->getControllerAction($attributes['action']);
959
960 30
        return $this->url->current();
961
    }
962
963
    /**
964
     * Get the action for a "url" option.
965
     *
966
     * @param  array|string  $attribute
967
     *
968
     * @return string
969
     */
970 18
    private function getUrlAction($attribute)
971
    {
972 18
        return is_array($attribute)
973 3
            ? $this->url->to($attribute[0], array_slice($attribute, 1))
974 18
            : $this->url->to($attribute);
975
    }
976
977
    /**
978
     * Get the action for a "route" option.
979
     *
980
     * @param  array|string  $attribute
981
     *
982
     * @return string
983
     */
984 6
    private function getRouteAction($attribute)
985
    {
986 6
        return is_array($attribute)
987 3
            ? $this->url->route($attribute[0], array_slice($attribute, 1))
988 6
            : $this->url->route($attribute);
989
    }
990
991
    /**
992
     * Get the action for an "action" option.
993
     *
994
     * @param  array|string  $attribute
995
     *
996
     * @return string
997
     */
998 6
    private function getControllerAction($attribute)
999
    {
1000 6
        return is_array($attribute)
1001 3
            ? $this->url->action($attribute[0], array_slice($attribute, 1))
1002 6
            : $this->url->action($attribute);
1003
    }
1004
}
1005