Completed
Push — master ( 1d9e5d...041fdc )
by ARCANEDEV
7s
created

FormBuilder::time()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 4
rs 10
ccs 2
cts 2
cp 1
cc 1
eloc 2
nc 1
nop 3
crap 1
1
<?php namespace Arcanedev\LaravelHtml;
2
3
use Arcanedev\LaravelHtml\Bases\Builder;
4
use Arcanedev\LaravelHtml\Contracts\FormBuilderInterface;
5
use DateTime;
6
use Illuminate\Contracts\Routing\UrlGenerator;
7
use Illuminate\Session\SessionInterface as Session;
8
use Illuminate\Support\Collection;
9
10
/**
11
 * Class     FormBuilder
12
 *
13
 * @package  Arcanedev\LaravelHtml\Builders
14
 * @author   ARCANEDEV <[email protected]>
15
 */
16
class FormBuilder extends Builder implements FormBuilderInterface
17
{
18
    /* ------------------------------------------------------------------------------------------------
19
     |  Properties
20
     | ------------------------------------------------------------------------------------------------
21
     */
22
    /**
23
    * The HTML builder instance.
24
    *
25
    * @var \Arcanedev\LaravelHtml\Contracts\HtmlBuilderInterface
26
    */
27
    protected $html;
28
29
    /**
30
    * The URL generator instance.
31
    *
32
    * @var \Illuminate\Contracts\Routing\UrlGenerator
33
    */
34
    protected $url;
35
36
    /**
37
    * The CSRF token used by the form builder.
38
    *
39
    * @var string
40
    */
41
    protected $csrfToken;
42
43
    /**
44
    * The session store implementation.
45
    *
46
    * @var \Illuminate\Session\SessionInterface
47
    */
48
    protected $session;
49
50
    /**
51
    * The current model instance for the form.
52
    *
53
    * @var \Illuminate\Database\Eloquent\Model
54
    */
55
    protected $model;
56
57
    /**
58
    * An array of label names we've created.
59
    *
60
    * @var array
61
    */
62
    protected $labels = [];
63
64
    /**
65
    * The reserved form open attributes.
66
    *
67
    * @var array
68
    */
69
    protected $reserved = ['method', 'url', 'route', 'action', 'files'];
70
71
    /**
72
    * The form methods that should be spoofed, in uppercase.
73
    *
74
    * @var array
75
    */
76
    protected $spoofedMethods = ['DELETE', 'PATCH', 'PUT'];
77
78
    /**
79
    * The types of inputs to not fill values on by default.
80
    *
81
    * @var array
82
    */
83
    protected $skipValueTypes = ['file', 'password', 'checkbox', 'radio'];
84
85
    /* ------------------------------------------------------------------------------------------------
86
     |  Constructor
87
     | ------------------------------------------------------------------------------------------------
88
     */
89
    /**
90
    * Create a new form builder instance.
91
    *
92
    * @param  \Illuminate\Contracts\Routing\UrlGenerator             $url
93
    * @param  \Arcanedev\LaravelHtml\Contracts\HtmlBuilderInterface  $html
94
    * @param  string                                                 $csrfToken
95
    */
96 784
    public function __construct(
97
        Contracts\HtmlBuilderInterface $html,
98
        UrlGenerator $url,
99
        $csrfToken
100
    ) {
101 784
        $this->url       = $url;
102 784
        $this->html      = $html;
103 784
        $this->csrfToken = $csrfToken;
104 784
    }
105
106
    /* ------------------------------------------------------------------------------------------------
107
     |  Getters & Setters
108
     | ------------------------------------------------------------------------------------------------
109
     */
110
    /**
111
     * Get the session store implementation.
112
     *
113
     * @return  \Illuminate\Session\SessionInterface
114
     */
115 8
    public function getSessionStore()
116
    {
117 8
        return $this->session;
118
    }
119
120
    /**
121
     * Set the session store implementation.
122
     *
123
     * @param  \Illuminate\Session\SessionInterface  $session
124
     *
125
     * @return self
126
     */
127 128
    public function setSessionStore(Session $session)
128
    {
129 128
        $this->session = $session;
130
131 128
        return $this;
132
    }
133
134
    /**
135
     * Set the model instance on the form builder.
136
     *
137
     * @param  \Illuminate\Database\Eloquent\Model  $model
138
     *
139
     * @return self
140
     */
141 80
    public function setModel($model)
142
    {
143 80
        $this->model = $model;
144
145 80
        return $this;
146
    }
147
148
    /**
149
     * Get the ID attribute for a field name.
150
     *
151
     * @param  string  $name
152
     * @param  array   $attributes
153
     *
154
     * @return string
155
     */
156 648
    public function getIdAttribute($name, array $attributes)
157
    {
158 648
        if (array_key_exists('id', $attributes)) {
159 56
            return $attributes['id'];
160
        }
161
162 608
        if (in_array($name, $this->labels)) {
163 16
            return $name;
164
        }
165
166 592
        return null;
167
    }
168
169
    /**
170
     * Get the value that should be assigned to the field.
171
     *
172
     * @param  string  $name
173
     * @param  mixed   $value
174
     *
175
     * @return mixed
176
     */
177 576
    public function getValueAttribute($name, $value = null)
178
    {
179 576
        if (is_null($name)) {
180 24
            return $value;
181
        }
182
183 552
        if ( ! is_null($this->old($name)) && $name !== '_method') {
184 32
            return $this->old($name);
185
        }
186
187 536
        if ( ! is_null($value)) {
188 296
            return $value;
189
        }
190
191 320
        return isset($this->model)
192 250
            ? $this->getModelValueAttribute($name)
193 320
            : null;
194
    }
195
196
    /**
197
     * Get the model value that should be assigned to the field.
198
     *
199
     * @param  string  $name
200
     *
201
     * @return mixed
202
     */
203 64
    private function getModelValueAttribute($name)
204
    {
205 64
        return data_get($this->model, $this->transformKey($name));
206
    }
207
208
    /**
209
     * Get a value from the session's old input.
210
     *
211
     * @param  string  $name
212
     *
213
     * @return mixed
214
     */
215 576
    public function old($name)
216
    {
217 576
        return isset($this->session)
218 450
            ? $this->session->getOldInput($this->transformKey($name))
219 576
            : null;
220
    }
221
222
    /**
223
     * Transform key from array to dot syntax.
224
     *
225
     * @param  string  $key
226
     *
227
     * @return string
228
     */
229 104
    private function transformKey($key)
230
    {
231 104
        return str_replace(['.', '[]', '[', ']'], ['_', '', '.', ''], $key);
232
    }
233
234
    /**
235
     * Determine if the old input is empty.
236
     *
237
     * @return bool
238
     */
239 24
    public function oldInputIsEmpty()
240
    {
241 24
        return isset($this->session) && (count($this->session->getOldInput()) == 0);
242
    }
243
244
    /**
245
     * Parse the form action method.
246
     *
247
     * @param  string  $method
248
     *
249
     * @return string
250
     */
251 128
    private function getMethod($method)
252
    {
253 128
        $method = strtoupper($method);
254
255 128
        return $method !== 'GET' ? 'POST' : $method;
256
    }
257
258
    /* ------------------------------------------------------------------------------------------------
259
     |  Main Functions
260
     | ------------------------------------------------------------------------------------------------
261
     */
262
    /**
263
     * Open up a new HTML form.
264
     *
265
     * @param  array  $options
266
     *
267
     * @return \Illuminate\Support\HtmlString
268
     */
269 128
    public function open(array $options = [])
270
    {
271 128
        $method = array_get($options, 'method', 'post');
272
273
        // We need to extract the proper method from the attributes. If the method is
274
        // something other than GET or POST we'll use POST since we will spoof the
275
        // actual method since forms don't support the reserved methods in HTML.
276 128
        $attributes = [];
277 128
        $attributes['method']         = $this->getMethod($method);
278 128
        $attributes['action']         = $this->getAction($options);
279 128
        $attributes['accept-charset'] = 'UTF-8';
280
281 128
        if (isset($options['files']) && $options['files']) {
282 16
            $options['enctype'] = 'multipart/form-data';
283 12
        }
284
285
        // Finally we're ready to create the final form HTML field. We will attribute
286
        // format the array of attributes. We will also add on the appendage which
287
        // is used to spoof requests for this PUT, PATCH, etc. methods on forms.
288 128
        $attributes = array_merge(
289 128
            $attributes, array_except($options, $this->reserved)
290 96
        );
291
292
        // Finally, we will concatenate all of the attributes into a single string so
293
        // we can build out the final form open statement. We'll also append on an
294
        // extra value for the hidden _method field if it's needed for the form.
295 128
        $attributes = $this->html->attributes($attributes);
296
297
        // If the method is PUT, PATCH or DELETE we will need to add a spoofer hidden
298
        // field that will instruct the Symfony request to pretend the method is a
299
        // different method than it actually is, for convenience from the forms.
300 128
        $append = $this->getAppendage($method);
301
302 128
        return $this->toHtmlString('<form' . $attributes . '>' . $append);
303
    }
304
305
    /**
306
     * Create a new model based form builder.
307
     *
308
     * @param  mixed  $model
309
     * @param  array  $options
310
     *
311
     * @return \Illuminate\Support\HtmlString
312
     */
313 40
    public function model($model, array $options = [])
314
    {
315 40
        $this->setModel($model);
316
317 40
        return $this->open($options);
318
    }
319
320
    /**
321
     * Close the current form.
322
     *
323
     * @return \Illuminate\Support\HtmlString
324
     */
325 16
    public function close()
326
    {
327 16
        $this->labels = [];
328 16
        $this->setModel(null);
0 ignored issues
show
Documentation introduced by
null is of type null, but the function expects a object<Illuminate\Database\Eloquent\Model>.

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...
329
330 16
        return $this->toHtmlString('</form>');
331
    }
332
333
    /**
334
     * Generate a hidden field with the current CSRF token.
335
     *
336
     * @return \Illuminate\Support\HtmlString
337
     */
338 56
    public function token()
339
    {
340 56
        $token = ! empty($this->csrfToken)
341 52
            ? $this->csrfToken
342 56
            : $this->session->getToken();
343
344 56
        return $this->hidden('_token', $token);
345
    }
346
347
    /**
348
     * Create a form label element.
349
     *
350
     * @param  string  $name
351
     * @param  string  $value
352
     * @param  array   $options
353
     * @param  bool    $escaped
354
     *
355
     * @return \Illuminate\Support\HtmlString
356
     */
357 46
    public function label($name, $value = null, array $options = [], $escaped = true)
358
    {
359 46
        $this->labels[] = $name;
360
361 40
        return $this->toHtmlString(
362 40
            Helpers\Label::make($name, $value, $options, $escaped)
363 30
        );
364
    }
365
366
    /**
367
     * Create a form input field.
368
     *
369
     * @param  string  $type
370
     * @param  string  $name
371
     * @param  string  $value
372
     * @param  array   $options
373
     *
374
     * @return \Illuminate\Support\HtmlString
375
     */
376 504
    public function input($type, $name, $value = null, array $options = [])
377
    {
378 504
        if ( ! isset($options['name'])) {
379 504
            $options['name'] = $name;
380 378
        }
381
382
        // We will get the appropriate value for the given field. We will look for the
383
        // value in the session for the value in the old input data then we'll look
384
        // in the model instance if one is set. Otherwise we will just use empty.
385 504
        $id = $this->getIdAttribute($name, $options);
386
387 504
        if ( ! in_array($type, $this->skipValueTypes)) {
388 408
            $value = $this->getValueAttribute($name, $value);
389 306
        }
390
391
        // Once we have the type, value, and ID we can merge them into the rest of the
392
        // attributes array so we can convert them into their HTML attribute format
393
        // when creating the HTML element. Then, we will return the entire input.
394 504
        $options = array_merge($options, compact('type', 'value', 'id'));
395
396 504
        return $this->toHtmlString('<input' . $this->html->attributes($options) . '>');
397
    }
398
399
    /**
400
     * Create a text input field.
401
     *
402
     * @param  string  $name
403
     * @param  string  $value
404
     * @param  array   $options
405
     *
406
     * @return \Illuminate\Support\HtmlString
407
     */
408 56
    public function text($name, $value = null, array $options = [])
409
    {
410 56
        return $this->input('text', $name, $value, $options);
411
    }
412
413
    /**
414
     * Create a password input field.
415
     *
416
     * @param  string  $name
417
     * @param  array   $options
418
     *
419
     * @return \Illuminate\Support\HtmlString
420
     */
421 24
    public function password($name, array $options = [])
422
    {
423 24
        return $this->input('password', $name, '', $options);
424
    }
425
426
    /**
427
     * Create a hidden input field.
428
     *
429
     * @param  string  $name
430
     * @param  string  $value
431
     * @param  array   $options
432
     *
433
     * @return \Illuminate\Support\HtmlString
434
     */
435 80
    public function hidden($name, $value = null, array $options = [])
436
    {
437 80
        return $this->input('hidden', $name, $value, $options);
438
    }
439
440
    /**
441
     * Create an e-mail input field.
442
     *
443
     * @param  string  $name
444
     * @param  string  $value
445
     * @param  array   $options
446
     *
447
     * @return \Illuminate\Support\HtmlString
448
     */
449 24
    public function email($name, $value = null, array $options = [])
450
    {
451 24
        return $this->input('email', $name, $value, $options);
452
    }
453
454
    /**
455
     * Create a tel input field.
456
     *
457
     * @param  string  $name
458
     * @param  string  $value
459
     * @param  array   $options
460
     *
461
     * @return \Illuminate\Support\HtmlString
462
     */
463 24
    public function tel($name, $value = null, array $options = [])
464
    {
465 24
        return $this->input('tel', $name, $value, $options);
466
    }
467
468
    /**
469
     * Create a number input field.
470
     *
471
     * @param  string  $name
472
     * @param  string  $value
473
     * @param  array   $options
474
     *
475
     * @return \Illuminate\Support\HtmlString
476
     */
477 24
    public function number($name, $value = null, array $options = [])
478
    {
479 24
        return $this->input('number', $name, $value, $options);
480
    }
481
482
    /**
483
     * Create a date input field.
484
     *
485
     * @param  string  $name
486
     * @param  string  $value
487
     * @param  array   $options
488
     *
489
     * @return \Illuminate\Support\HtmlString
490
     */
491 32
    public function date($name, $value = null, array $options = [])
492
    {
493 32
        if ($value instanceof DateTime) {
494 8
            $value = $value->format('Y-m-d');
495 6
        }
496
497 32
        return $this->input('date', $name, $value, $options);
498
    }
499
500
    /**
501
     * Create a datetime input field.
502
     *
503
     * @param  string  $name
504
     * @param  string  $value
505
     * @param  array   $options
506
     *
507
     * @return \Illuminate\Support\HtmlString
508
     */
509 32
    public function datetime($name, $value = null, array $options = [])
510
    {
511 32
        if ($value instanceof DateTime) {
512 16
            $value = $value->format(DateTime::RFC3339);
513 12
        }
514
515 32
        return $this->input('datetime', $name, $value, $options);
516
    }
517
518
    /**
519
     * Create a datetime-local input field.
520
     *
521
     * @param  string  $name
522
     * @param  string  $value
523
     * @param  array   $options
524
     *
525
     * @return \Illuminate\Support\HtmlString
526
     */
527 32
    public function datetimeLocal($name, $value = null, array $options = [])
528
    {
529 32
        if ($value instanceof DateTime) {
530 16
            $value = $value->format('Y-m-d\TH:i');
531 12
        }
532
533 32
        return $this->input('datetime-local', $name, $value, $options);
534
    }
535
536
    /**
537
     * Create a time input field.
538
     *
539
     * @param  string  $name
540
     * @param  string  $value
541
     * @param  array   $options
542
     *
543
     * @return \Illuminate\Support\HtmlString
544
     */
545 24
    public function time($name, $value = null, array $options = [])
546
    {
547 24
        return $this->input('time', $name, $value, $options);
548
    }
549
550
    /**
551
     * Create a url input field.
552
     *
553
     * @param  string  $name
554
     * @param  string  $value
555
     * @param  array   $options
556
     *
557
     * @return \Illuminate\Support\HtmlString
558
     */
559 16
    public function url($name, $value = null, array $options = [])
560
    {
561 16
        return $this->input('url', $name, $value, $options);
562
    }
563
564
    /**
565
     * Create a file input field.
566
     *
567
     * @param  string  $name
568
     * @param  array   $options
569
     *
570
     * @return \Illuminate\Support\HtmlString
571
     */
572 24
    public function file($name, array $options = [])
573
    {
574 24
        return $this->input('file', $name, null, $options);
575
    }
576
577
    /**
578
     * Create a textarea input field.
579
     *
580
     * @param  string  $name
581
     * @param  string  $value
582
     * @param  array   $options
583
     *
584
     * @return \Illuminate\Support\HtmlString
585
     */
586 32
    public function textarea($name, $value = null, array $options = [])
587
    {
588 32
        if ( ! isset($options['name'])) {
589 32
            $options['name'] = $name;
590 24
        }
591
592
        // Next we will look for the rows and cols attributes, as each of these are put
593
        // on the textarea element definition. If they are not present, we will just
594
        // assume some sane default values for these attributes for the developer.
595 32
        $options       = $this->setTextAreaSize($options);
596 32
        $options['id'] = $this->getIdAttribute($name, $options);
597 32
        $value         = (string) $this->getValueAttribute($name, $value);
598
599 32
        unset($options['size']);
600
601
        // Next we will convert the attributes into a string form. Also we have removed
602
        // the size attribute, as it was merely a short-cut for the rows and cols on
603
        // the element. Then we'll create the final textarea elements HTML for us.
604 32
        $options = $this->html->attributes($options);
605
606 32
        return $this->toHtmlString('<textarea' . $options . '>' . e($value) . '</textarea>');
607
    }
608
609
    /**
610
     * Set the text area size on the attributes.
611
     *
612
     * @param  array  $options
613
     *
614
     * @return array
615
     */
616 32
    private function setTextAreaSize(array $options)
617
    {
618 32
        if (isset($options['size'])) {
619 8
            return $this->setQuickTextAreaSize($options);
620
        }
621
622
        // If the "size" attribute was not specified, we will just look for the regular
623
        // columns and rows attributes, using sane defaults if these do not exist on
624
        // the attributes array. We'll then return this entire options array back.
625 24
        $cols = array_get($options, 'cols', 50);
626 24
        $rows = array_get($options, 'rows', 10);
627
628 24
        return array_merge($options, compact('cols', 'rows'));
629
    }
630
631
    /**
632
     * Set the text area size using the quick "size" attribute.
633
     *
634
     * @param  array  $options
635
     *
636
     * @return array
637
     */
638 8
    protected function setQuickTextAreaSize(array $options)
639
    {
640 8
        list($cols, $rows) = explode('x', $options['size']);
641
642 8
        return array_merge($options, [
643 8
            'cols' => $cols,
644 2
            'rows' => $rows
645 6
        ]);
646
    }
647
648
    /**
649
     * Create a select box field.
650
     *
651
     * @param  string  $name
652
     * @param  array   $list
653
     * @param  string  $selected
654
     * @param  array   $options
655
     *
656
     * @return \Illuminate\Support\HtmlString
657
     */
658 112
    public function select($name, $list = [], $selected = null, array $options = [])
659
    {
660
        // When building a select box the "value" attribute is really the selected one
661
        // so we will use that when checking the model or session for a value which
662
        // should provide a convenient method of re-populating the forms on post.
663 112
        $selected      = $this->getValueAttribute($name, $selected);
664
665
        // Transform to array if it is a collection
666 112
        if ($selected instanceof Collection) {
667 8
            $selected = $selected->all();
668 6
        }
669
670 112
        $options['id'] = $this->getIdAttribute($name, $options);
671
672 112
        if ( ! isset($options['name'])) {
673 80
            $options['name'] = $name;
674 60
        }
675
676
        // We will simply loop through the options and build an HTML value for each of
677
        // them until we have an array of HTML declarations. Then we will join them
678
        // all together into one single HTML element that can be put on the form.
679 112
        $html = [];
680
681 112
        if (isset($options['placeholder'])) {
682 8
            $html[] = $this->placeholderOption($options['placeholder'], $selected);
683 8
            unset($options['placeholder']);
684 6
        }
685
686 112
        foreach($list as $value => $display) {
687 104
            $html[] = $this->getSelectOption($display, $value, $selected);
688 84
        }
689
690
        // Once we have all of this HTML, we can join this into a single element after
691
        // formatting the attributes into an HTML "attributes" string, then we will
692
        // build out a final select statement, which will contain all the values.
693 112
        $options = $this->html->attributes($options);
694
695 112
        return $this->toHtmlString("<select{$options}>" . implode('', $html) . "</select>");
696
    }
697
698
    /**
699
     * Create a select range field.
700
     *
701
     * @param  string  $name
702
     * @param  string  $begin
703
     * @param  string  $end
704
     * @param  string  $selected
705
     * @param  array   $options
706
     *
707
     * @return \Illuminate\Support\HtmlString
708
     */
709 16
    public function selectRange($name, $begin, $end, $selected = null, array $options = [])
710
    {
711 16
        $range = array_combine($range = range($begin, $end), $range);
712
713 16
        return $this->select($name, $range, $selected, $options);
714
    }
715
716
    /**
717
     * Create a select year field.
718
     *
719
     * @param  string  $name
720
     * @param  string  $begin
721
     * @param  string  $end
722
     * @param  string  $selected
723
     * @param  array   $options
724
     *
725
     * @return \Illuminate\Support\HtmlString
726
     */
727 8
    public function selectYear($name, $begin, $end, $selected = null, array $options = [])
728
    {
729 8
        return call_user_func_array(
730 8
            [$this, 'selectRange'],
731 8
            compact('name', 'begin', 'end', 'selected', 'options')
732 6
        );
733
    }
734
735
    /**
736
     * Create a select month field.
737
     *
738
     * @param  string  $name
739
     * @param  string  $selected
740
     * @param  array   $options
741
     * @param  string  $format
742
     *
743
     * @return \Illuminate\Support\HtmlString
744
     */
745 8
    public function selectMonth($name, $selected = null, array $options = [], $format = '%B')
746
    {
747 8
        $months = [];
748
749 8
        foreach(range(1, 12) as $month) {
750 8
            $months[$month] = strftime($format, mktime(0, 0, 0, $month, 1));
751 6
        }
752
753 8
        return $this->select($name, $months, $selected, $options);
754
    }
755
756
    /**
757
     * Get the select option for the given value.
758
     *
759
     * @param  string  $display
760
     * @param  string  $value
761
     * @param  string  $selected
762
     *
763
     * @return string
764
     */
765 104
    private function getSelectOption($display, $value, $selected)
766
    {
767 104
        if (is_array($display)) {
768 16
            return $this->optionGroup($display, $value, $selected);
769
        }
770
771 96
        return $this->option($display, $value, $selected);
772
    }
773
774
    /**
775
     * Create an option group form element.
776
     *
777
     * @param  array   $list
778
     * @param  string  $label
779
     * @param  string  $selected
780
     *
781
     * @return string
782
     */
783 16
    private function optionGroup(array $list, $label, $selected)
784
    {
785 16
        $html = [];
786
787 16
        foreach($list as $value => $display) {
788 16
            $html[] = $this->option($display, $value, $selected);
789 12
        }
790
791 16
        return '<optgroup label="' . e($label) . '">' . implode('', $html) . '</optgroup>';
792
    }
793
794
    /**
795
     * Create a select element option.
796
     *
797
     * @param  string  $display
798
     * @param  string  $value
799
     * @param  string  $selected
800
     *
801
     * @return string
802
     */
803 104
    private function option($display, $value, $selected)
804
    {
805 104
        $selected = $this->getSelectedValue($value, $selected);
806 104
        $options  = compact('value', 'selected');
807
808 104
        return '<option' . $this->html->attributes($options) . '>' . e($display) . '</option>';
809
    }
810
811
    /**
812
     * Create a placeholder select element option.
813
     *
814
     * @param  string  $display
815
     * @param  string  $selected
816
     *
817
     * @return string
818
     */
819 8
    private function placeholderOption($display, $selected)
820
    {
821 8
        $selected         = $this->getSelectedValue(null, $selected);
822 8
        $options          = compact('selected');
823 8
        $options['value'] = '';
824
825 8
        return '<option' . $this->html->attributes($options) . '>' . e($display) . '</option>';
826
    }
827
828
    /**
829
     * Determine if the value is selected.
830
     *
831
     * @param  string  $value
832
     * @param  string  $selected
833
     *
834
     * @return string|null
835
     */
836 104
    private function getSelectedValue($value, $selected)
837
    {
838 104
        if (is_array($selected)) {
839 32
            return in_array($value, $selected) ? 'selected' : null;
840
        }
841
842 80
        return ((string) $value == (string) $selected) ? 'selected' : null;
843
    }
844
845
    /**
846
     * Create a checkbox input field.
847
     *
848
     * @param  string     $name
849
     * @param  mixed      $value
850
     * @param  bool|null  $checked
851
     * @param  array      $options
852
     *
853
     * @return \Illuminate\Support\HtmlString
854
     */
855 32
    public function checkbox($name, $value = 1, $checked = null, array $options = [])
856
    {
857 32
        return $this->checkable('checkbox', $name, $value, $checked, $options);
858
    }
859
860
    /**
861
     * Create a radio button input field.
862
     *
863
     * @param  string  $name
864
     * @param  mixed   $value
865
     * @param  bool    $checked
866
     * @param  array   $options
867
     *
868
     * @return \Illuminate\Support\HtmlString
869
     */
870 16
    public function radio($name, $value = null, $checked = null, array $options = [])
871
    {
872 16
        if (is_null($value)) {
873 8
            $value = $name;
874 6
        }
875
876 16
        return $this->checkable('radio', $name, $value, $checked, $options);
877
    }
878
879
    /**
880
     * Create a checkable input field.
881
     *
882
     * @param  string     $type
883
     * @param  string     $name
884
     * @param  mixed      $value
885
     * @param  bool|null  $checked
886
     * @param  array      $options
887
     *
888
     * @return \Illuminate\Support\HtmlString
889
     */
890 56
    protected function checkable($type, $name, $value, $checked, array $options)
891
    {
892 56
        $checked = $this->getCheckedState($type, $name, $value, $checked);
893
894 56
        if ( ! is_null($checked) && $checked) {
895 48
            $options['checked'] = 'checked';
896 36
        }
897
898 56
        return $this->input($type, $name, $value, $options);
899
    }
900
901
    /**
902
     * Get the check state for a checkable input.
903
     *
904
     * @param  string     $type
905
     * @param  string     $name
906
     * @param  mixed      $value
907
     * @param  bool|null  $checked
908
     *
909
     * @return bool
910
     */
911 56
    private function getCheckedState($type, $name, $value, $checked)
912
    {
913
        switch($type) {
914 56
            case 'checkbox':
915 32
                return $this->getCheckboxCheckedState($name, $value, $checked);
916
917 24
            case 'radio':
918 16
                return $this->getRadioCheckedState($name, $value, $checked);
919
920 6
            default:
921 8
                return $this->getValueAttribute($name) == $value;
922 6
        }
923
    }
924
925
    /**
926
     * Get the check state for a checkbox input.
927
     *
928
     * @param  string     $name
929
     * @param  mixed      $value
930
     * @param  bool|null  $checked
931
     *
932
     * @return bool
933
     */
934 32
    private function getCheckboxCheckedState($name, $value, $checked)
935
    {
936
        if (
937 32
            isset($this->session) &&
938 32
            ! $this->oldInputIsEmpty() &&
939 14
            is_null($this->old($name))
940 24
        ) {
941 8
            return false;
942
        }
943
944 32
        if ($this->missingOldAndModel($name)) {
945 16
            return $checked;
946
        }
947
948 16
        $posted = $this->getValueAttribute($name, $checked);
949
950 16
        if (is_array($posted)) {
951 8
            return in_array($value, $posted);
952
        }
953
954 16
        if ($posted instanceof Collection) {
955 8
            return $posted->contains('id', $value);
956
        }
957
958 16
        return (bool) $posted;
959
    }
960
961
    /**
962
     * Get the check state for a radio input.
963
     *
964
     * @param  string     $name
965
     * @param  mixed      $value
966
     * @param  bool|null  $checked
967
     *
968
     * @return bool
969
     */
970 16
    private function getRadioCheckedState($name, $value, $checked)
971
    {
972 16
        return $this->missingOldAndModel($name)
973 14
            ? $checked
974 16
            : $this->getValueAttribute($name) == $value;
975
    }
976
977
    /**
978
     * Determine if old input or model input exists for a key.
979
     *
980
     * @param  string  $name
981
     *
982
     * @return bool
983
     */
984 48
    private function missingOldAndModel($name)
985
    {
986 48
        return (is_null($this->old($name)) && is_null($this->getModelValueAttribute($name)));
987
    }
988
989
    /**
990
     * Create a HTML reset input element.
991
     *
992
     * @param  string  $value
993
     * @param  array   $attributes
994
     *
995
     * @return \Illuminate\Support\HtmlString
996
     */
997 8
    public function reset($value, array $attributes = [])
998
    {
999 8
        return $this->input('reset', null, $value, $attributes);
1000
    }
1001
1002
    /**
1003
    * Create a HTML image input element.
1004
    *
1005
    * @param  string  $url
1006
    * @param  string  $name
1007
    * @param  array   $attributes
1008
    *
1009
     * @return \Illuminate\Support\HtmlString
1010
    */
1011 8
    public function image($url, $name = null, array $attributes = [])
1012
    {
1013 8
        $attributes['src'] = $this->url->asset($url);
1014
1015 8
        return $this->input('image', $name, null, $attributes);
1016
    }
1017
1018
    /**
1019
     * Create a submit button element.
1020
     *
1021
     * @param  string  $value
1022
     * @param  array   $options
1023
     *
1024
     * @return \Illuminate\Support\HtmlString
1025
     */
1026 8
    public function submit($value = null, array $options = [])
1027
    {
1028 8
        return $this->input('submit', null, $value, $options);
1029
    }
1030
1031
    /**
1032
     * Create a button element.
1033
     *
1034
     * @param  string  $value
1035
     * @param  array   $options
1036
     *
1037
     * @return \Illuminate\Support\HtmlString
1038
     */
1039 8
    public function button($value = null, array $options = [])
1040
    {
1041 8
        if ( ! array_key_exists('type', $options)) {
1042 8
            $options['type'] = 'button';
1043 6
        }
1044
1045 8
        return $this->toHtmlString(
1046 8
            '<button' . $this->html->attributes($options) . '>' . $value . '</button>'
1047 6
        );
1048
    }
1049
1050
    /**
1051
     * Create a color input field.
1052
     *
1053
     * @param  string  $name
1054
     * @param  string  $value
1055
     * @param  array   $options
1056
     *
1057
     * @return \Illuminate\Support\HtmlString
1058
     */
1059 24
    public function color($name, $value = null, array $options = [])
1060
    {
1061 24
        return $this->input('color', $name, $value, $options);
1062
    }
1063
1064
    /* ------------------------------------------------------------------------------------------------
1065
     |  Other Functions
1066
     | ------------------------------------------------------------------------------------------------
1067
     */
1068
    /**
1069
     * Get the form action from the options.
1070
     *
1071
     * @param  array  $options
1072
     *
1073
     * @return string
1074
     */
1075 128
    private function getAction(array $options)
1076
    {
1077
        // We will also check for a "route" or "action" parameter on the array so that
1078
        // developers can easily specify a route or controller action when creating
1079
        // a form providing a convenient interface for creating the form actions.
1080 128
        if (isset($options['url'])) {
1081 40
            return $this->getUrlAction($options['url']);
1082
        }
1083 88
        elseif (isset($options['route'])) {
1084 8
            return $this->getRouteAction($options['route']);
1085
        }
1086 88
        elseif (isset($options['action'])) {
1087
            // If an action is available, we are attempting to open a form to a controller
1088
            // action route. So, we will use the URL generator to get the path to these
1089
            // actions and return them from the method. Otherwise, we'll use current.
1090 8
            return $this->getControllerAction($options['action']);
1091
        }
1092
1093 80
        return $this->url->current();
1094
    }
1095
1096
    /**
1097
     * Get the action for a "url" option.
1098
     *
1099
     * @param  array|string  $options
1100
     *
1101
     * @return string
1102
     */
1103 40
    private function getUrlAction($options)
1104
    {
1105 40
        return is_array($options)
1106 30
            ? $this->url->to($options[0], array_slice($options, 1))
1107 40
            : $this->url->to($options);
1108
    }
1109
1110
    /**
1111
     * Get the action for a "route" option.
1112
     *
1113
     * @param  array|string  $options
1114
     *
1115
     * @return string
1116
     */
1117 8
    private function getRouteAction($options)
1118
    {
1119 8
        return is_array($options)
1120 6
            ? $this->url->route($options[0], array_slice($options, 1))
1121 8
            : $this->url->route($options);
1122
    }
1123
1124
    /**
1125
     * Get the action for an "action" option.
1126
     *
1127
     * @param  array|string  $options
1128
     *
1129
     * @return string
1130
     */
1131 8
    private function getControllerAction($options)
1132
    {
1133 8
        return is_array($options)
1134 6
            ? $this->url->action($options[0], array_slice($options, 1))
1135 8
            : $this->url->action($options);
1136
    }
1137
1138
    /**
1139
     * Get the form appendage for the given method.
1140
     *
1141
     * @param  string  $method
1142
     *
1143
     * @return string
1144
     */
1145 128
    private function getAppendage($method)
1146
    {
1147 128
        list($method, $appendage) = [strtoupper($method), ''];
1148
1149
        // If the HTTP method is in this list of spoofed methods, we will attach the
1150
        // method spoofer hidden input to the form. This allows us to use regular
1151
        // form to initiate PUT and DELETE requests in addition to the typical.
1152 128
        if (in_array($method, $this->spoofedMethods)) {
1153 16
            $appendage .= $this->hidden('_method', $method);
1154 12
        }
1155
1156
        // If the method is something other than GET we will go ahead and attach the
1157
        // CSRF token to the form, as this can't hurt and is convenient to simply
1158
        // always have available on every form the developers creates for them.
1159 128
        if ($method != 'GET') {
1160 56
            $appendage .= $this->token();
1161 42
        }
1162
1163 128
        return $appendage;
1164
    }
1165
}
1166