Completed
Pull Request — master (#30)
by ARCANEDEV
01:57
created

FormBuilder::old()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 8

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 4
CRAP Score 2.032

Importance

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

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

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

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

function acceptsInteger($int) { }

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

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
298 84
                ['accept-charset' => 'UTF-8'],
299 84
                Arr::except($attributes, $this->reserved)
300
            ))
301
            ->if(Arr::pull($attributes, 'files', false), function (Form $form) {
302 6
                return $form->acceptsFiles();
303 84
            })
304
            ->if(in_array($method, $this->spoofedMethods), function (Form $form) use ($method) {
305 6
                return $form->addChild($this->hidden('_method', $method));
306 84
            })
307
            ->if($method !== 'GET', function (Form $form) {
308 48
                return $form->addChild($this->token());
309 84
            })
310 84
            ->open();
311
    }
312
313
    /**
314
     * Create a new model based form builder.
315
     *
316
     * @param  mixed  $model
317
     * @param  array  $attributes
318
     *
319
     * @return \Illuminate\Support\HtmlString
320
     */
321 30
    public function model($model, array $attributes = []): HtmlString
322
    {
323 30
        return $this->setModel($model)->open($attributes);
324
    }
325
326
    /**
327
     * Close the current form.
328
     *
329
     * @return \Illuminate\Support\HtmlString
330
     */
331 6
    public function close(): HtmlString
332
    {
333 6
        $this->labels = [];
334 6
        $this->setModel(null);
335
336 6
        return Form::make()->close();
337
    }
338
339
    /**
340
     * Generate a hidden field with the current CSRF token.
341
     *
342
     * @return \Arcanedev\Html\Elements\Input
343
     */
344 48
    public function token(): Input
345
    {
346 48
        $token = empty($this->csrfToken)
347
            ? $this->getSessionStore()->token()
348 48
            : $this->csrfToken;
349
350 48
        return $this->hidden('_token', $token);
351
    }
352
353
    /**
354
     * Create a form label element.
355
     *
356
     * @param  string        $name
357
     * @param  string|mixed  $value
358
     * @param  array         $attributes
359
     * @param  bool          $escaped
360
     *
361
     * @return \Arcanedev\Html\Elements\Label
362
     */
363 30
    public function label(string $name, $value = null, array $attributes = [], $escaped = true): Label
364
    {
365 30
        $this->labels[] = $name;
366
367 30
        $value = $value ?: Str::title(str_replace(['_', '-'], ' ', $name));
368
369 30
        return Label::make()
370 30
            ->for($name)
371 30
            ->attributes($attributes)
0 ignored issues
show
Documentation introduced by
$attributes is of type array, but the function expects a object<Arcanedev\Html\Elements\Concerns\iterable>.

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

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

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

function acceptsInteger($int) { }

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

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
372 30
            ->html($escaped ? e($value) : $value);
373
    }
374
375
    /**
376
     * Create a form input field.
377
     *
378
     * @param  string        $type
379
     * @param  string|null   $name
380
     * @param  string|mixed  $value
381
     * @param  array         $attributes
382
     *
383
     * @return \Arcanedev\Html\Elements\Input
384
     */
385 354
    public function input(string $type, $name, $value = null, array $attributes = []): Input
386
    {
387 354
        if ( ! in_array($type, $this->skipValueTypes))
388 300
            $value = $this->getValueAttribute($name, $value);
389
390 354
        $id = $this->getIdAttribute($name, $attributes);
391
392 354
        return Input::make()
393 354
            ->type($type)
394 354
            ->attributeIfNotNull($name, 'name', $name)
0 ignored issues
show
Unused Code introduced by
The call to Input::attributeIfNotNull() has too many arguments starting with $name.

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

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

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

Loading history...
395 354
            ->attributeIfNotNull($id, 'id', $id)
396 354
            ->attributeUnless(is_null($value) || empty($value), 'value', $value)
397 354
            ->attributes($attributes);
398
    }
399
400
    /**
401
     * Create a text input field.
402
     *
403
     * @param  string        $name
404
     * @param  string|mixed  $value
405
     * @param  array         $attributes
406
     *
407
     * @return \Arcanedev\Html\Elements\Input
408
     */
409 42
    public function text(string $name, $value = null, array $attributes = []): Input
410
    {
411 42
        return $this->input('text', $name, $value, $attributes);
412
    }
413
414
    /**
415
     * Create a password input field.
416
     *
417
     * @param  string  $name
418
     * @param  array   $attributes
419
     *
420
     * @return \Arcanedev\Html\Elements\Input
421
     */
422 18
    public function password(string $name, array $attributes = []): Input
423
    {
424 18
        return $this->input('password', $name, null, $attributes);
425
    }
426
427
    /**
428
     * Create a hidden input field.
429
     *
430
     * @param  string        $name
431
     * @param  string|mixed  $value
432
     * @param  array         $attributes
433
     *
434
     * @return \Arcanedev\Html\Elements\Input
435
     */
436 66
    public function hidden(string $name, $value = null, array $attributes = []): Input
437
    {
438 66
        return $this->input('hidden', $name, $value, $attributes);
439
    }
440
441
    /**
442
     * Create an e-mail input field.
443
     *
444
     * @param  string        $name
445
     * @param  string|mixed  $value
446
     * @param  array         $attributes
447
     *
448
     * @return \Arcanedev\Html\Elements\Input
449
     */
450 18
    public function email(string $name, $value = null, array $attributes = []): Input
451
    {
452 18
        return $this->input('email', $name, $value, $attributes);
453
    }
454
455
    /**
456
     * Create a tel input field.
457
     *
458
     * @param  string        $name
459
     * @param  string|mixed  $value
460
     * @param  array         $attributes
461
     *
462
     * @return \Arcanedev\Html\Elements\Input
463
     */
464 18
    public function tel(string $name, $value = null, array $attributes = []): Input
465
    {
466 18
        return $this->input('tel', $name, $value, $attributes);
467
    }
468
469
    /**
470
     * Create a number input field.
471
     *
472
     * @param  string        $name
473
     * @param  string|mixed  $value
474
     * @param  array         $attributes
475
     *
476
     * @return \Arcanedev\Html\Elements\Input
477
     */
478 18
    public function number(string $name, $value = null, array $attributes = []): Input
479
    {
480 18
        return $this->input('number', $name, $value, $attributes);
481
    }
482
483
    /**
484
     * Create a date input field.
485
     *
486
     * @param  string  $name
487
     * @param  string  $value
488
     * @param  array   $attributes
489
     *
490
     * @return \Arcanedev\Html\Elements\Input
491
     */
492 24
    public function date(string $name, $value = null, array $attributes = []): Input
493
    {
494 24
        if ($value instanceof DateTime)
495 6
            $value = $value->format('Y-m-d');
496
497 24
        return $this->input('date', $name, $value, $attributes);
498
    }
499
500
    /**
501
     * Create a datetime input field.
502
     *
503
     * @param  string        $name
504
     * @param  string|mixed  $value
505
     * @param  array         $attributes
506
     *
507
     * @return \Arcanedev\Html\Elements\Input
508
     */
509 24
    public function datetime(string $name, $value = null, array $attributes = []): Input
510
    {
511 24
        if ($value instanceof DateTime)
512 12
            $value = $value->format(DateTime::RFC3339);
513
514 24
        return $this->input('datetime', $name, $value, $attributes);
515
    }
516
517
    /**
518
     * Create a datetime-local input field.
519
     *
520
     * @param  string        $name
521
     * @param  string|mixed  $value
522
     * @param  array         $attributes
523
     *
524
     * @return \Arcanedev\Html\Elements\Input
525
     */
526 24
    public function datetimeLocal(string $name, $value = null, array $attributes = []): Input
527
    {
528 24
        if ($value instanceof DateTime)
529 12
            $value = $value->format('Y-m-d\TH:i');
530
531 24
        return $this->input('datetime-local', $name, $value, $attributes);
532
    }
533
534
    /**
535
     * Create a time input field.
536
     *
537
     * @param  string        $name
538
     * @param  string|mixed  $value
539
     * @param  array         $attributes
540
     *
541
     * @return \Arcanedev\Html\Elements\Input
542
     */
543 18
    public function time(string $name, $value = null, array $attributes = []): Input
544
    {
545 18
        return $this->input('time', $name, $value, $attributes);
546
    }
547
548
    /**
549
     * Create a url input field.
550
     *
551
     * @param  string  $name
552
     * @param  string  $value
553
     * @param  array   $attributes
554
     *
555
     * @return \Arcanedev\Html\Elements\Input
556
     */
557 12
    public function url(string $name, $value = null, array $attributes = []): Input
558
    {
559 12
        return $this->input('url', $name, $value, $attributes);
560
    }
561
562
    /**
563
     * Create a file input field.
564
     *
565
     * @param  string  $name
566
     * @param  array   $attributes
567
     *
568
     * @return \Arcanedev\Html\Elements\File
569
     */
570 18
    public function file(string $name, array $attributes = []): File
571
    {
572 18
        return File::make()->name($name)->attributes($attributes);
0 ignored issues
show
Documentation introduced by
$attributes is of type array, but the function expects a object<Arcanedev\Html\Elements\Concerns\iterable>.

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

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

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

function acceptsInteger($int) { }

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

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
573
    }
574
575
    /**
576
     * Create a textarea input field.
577
     *
578
     * @param  string  $name
579
     * @param  string  $value
580
     * @param  array   $attributes
581
     *
582
     * @return \Arcanedev\Html\Elements\Textarea
583
     */
584 36
    public function textarea(string $name, $value = null, array $attributes = []): Textarea
585
    {
586 36
        $id    = $this->getIdAttribute($name, $attributes);
587 36
        $size  = Arr::pull($attributes, 'size');
588 36
        $value = (string) $this->getValueAttribute($name, $value);
589
590 36
        return Textarea::make()
591 36
            ->name($name)
592 36
            ->attributeUnless(is_null($id), 'id', $id)
593
            ->unless(is_null($size), function (Textarea $elt) use ($size) {
594 18
                return $elt->size($size);
595 36
            })
596 36
            ->attributes($attributes)
597 36
            ->html($this->html->escape($value));
598
    }
599
600
    /**
601
     * Create a select box field.
602
     *
603
     * @param  string                                         $name
604
     * @param  array|\Illuminate\Support\Collection|iterable  $list
605
     * @param  string|bool                                    $selected
606
     * @param  array                                          $attributes
607
     * @param  array                                          $optionsAttributes
608
     * @param  array                                          $optgroupsAttributes
609
     *
610
     * @return \Arcanedev\Html\Elements\Select
611
     */
612 90
    public function select(
613
        string $name,
614
        iterable $list = [],
615
        $selected = null,
616
        array $attributes = [],
617
        array $optionsAttributes = [],
618
        array $optgroupsAttributes = []
619
    ): Select {
620 90
        return Select::make()
621 90
            ->name($name)
622 90
            ->options($list, $optionsAttributes, $optgroupsAttributes)
0 ignored issues
show
Bug introduced by
It seems like $list defined by parameter $list on line 614 can also be of type array; however, Arcanedev\Html\Elements\Select::options() does only seem to accept object<Arcanedev\Html\Elements\iterable>, maybe add an additional type check?

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

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

An additional type check may prevent trouble.

Loading history...
623 90
            ->attributes($attributes)
0 ignored issues
show
Documentation introduced by
$attributes is of type array, but the function expects a object<Arcanedev\Html\Elements\Concerns\iterable>.

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

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

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

function acceptsInteger($int) { }

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

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
624 90
            ->attributeUnless(is_null($id = $this->getIdAttribute($name, $attributes)), 'id', $id)
625 90
            ->value($this->getValueAttribute($name, $selected));
626
    }
627
628
    /**
629
     * Create a select range field.
630
     *
631
     * @param  string  $name
632
     * @param  string  $begin
633
     * @param  string  $end
634
     * @param  string  $selected
635
     * @param  array   $attributes
636
     *
637
     * @return \Arcanedev\Html\Elements\Select
638
     */
639 12
    public function selectRange(string $name, $begin, $end, $selected = null, array $attributes = []): Select
640
    {
641 12
        $range = array_combine($range = range($begin, $end), $range);
642
643 12
        return $this->select($name, $range, $selected, $attributes);
644
    }
645
646
    /**
647
     * Create a select year field.
648
     *
649
     * @param  string  $name
650
     * @param  string  $begin
651
     * @param  string  $end
652
     * @param  string  $selected
653
     * @param  array   $attributes
654
     *
655
     * @return \Arcanedev\Html\Elements\Select
656
     */
657 6
    public function selectYear(string $name, $begin, $end, $selected = null, array $attributes = []): Select
658
    {
659 6
        return $this->selectRange($name, $begin, $end, $selected, $attributes);
660
    }
661
662
    /**
663
     * Create a select month field.
664
     *
665
     * @param  string  $name
666
     * @param  string  $selected
667
     * @param  array   $attributes
668
     * @param  string  $format
669
     *
670
     * @return \Arcanedev\Html\Elements\Select
671
     */
672 6
    public function selectMonth(string $name, $selected = null, array $attributes = [], $format = '%B'): Select
673
    {
674 6
        $months = [];
675
676 6
        foreach(range(1, 12) as $month) {
677 6
            $months[$month] = strftime($format, mktime(0, 0, 0, $month, 1));
678
        }
679
680 6
        return $this->select($name, $months, $selected, $attributes);
681
    }
682
683
    /**
684
     * Create a checkbox input field.
685
     *
686
     * @param  string     $name
687
     * @param  mixed      $value
688
     * @param  bool|null  $checked
689
     * @param  array      $attributes
690
     *
691
     * @return \Arcanedev\Html\Elements\Input
692
     */
693 24
    public function checkbox(string $name, $value = 1, $checked = null, array $attributes = []): Input
694
    {
695 24
        return $this->checkable('checkbox', $name, $value, $checked, $attributes);
696
    }
697
698
    /**
699
     * Create a radio button input field.
700
     *
701
     * @param  string  $name
702
     * @param  mixed   $value
703
     * @param  bool    $checked
704
     * @param  array   $attributes
705
     *
706
     * @return \Arcanedev\Html\Elements\Input
707
     */
708 12
    public function radio(string $name, $value = null, $checked = null, array $attributes = []): Input
709
    {
710 12
        return $this->checkable('radio', $name, $value ?: $name, $checked, $attributes);
711
    }
712
713
    /**
714
     * Create a HTML reset input element.
715
     *
716
     * @param  string|mixed  $value
717
     * @param  array         $attributes
718
     *
719
     * @return \Arcanedev\Html\Elements\Button
720
     */
721 6
    public function reset($value, array $attributes = []): Button
722
    {
723 6
        return $this->button($value, array_merge(['type' => 'reset'], $attributes));
724
    }
725
726
    /**
727
    * Create a HTML image input element.
728
    *
729
    * @param  string       $url
730
    * @param  string|null  $name
731
    * @param  array        $attributes
732
    *
733
     * @return \Arcanedev\Html\Elements\Input
734
    */
735 6
    public function image(string $url, $name = null, array $attributes = []): Input
736
    {
737 6
        return $this->input('image', $name, null, array_merge($attributes, [
738 6
            'src' => $this->url->asset($url),
739
        ]));
740
    }
741
742
    /**
743
     * Create a submit button element.
744
     *
745
     * @param  string|mixed  $value
746
     * @param  array         $attributes
747
     *
748
     * @return \Arcanedev\Html\Elements\Button
749
     */
750 6
    public function submit($value = null, array $attributes = []): Button
751
    {
752 6
        return $this->button($value, array_merge(['type' => 'submit'], $attributes));
753
    }
754
755
    /**
756
     * Create a button element.
757
     *
758
     * @param  string|mixed  $value
759
     * @param  array         $attributes
760
     *
761
     * @return \Arcanedev\Html\Elements\Button
762
     */
763 18
    public function button($value = null, array $attributes = []): Button
764
    {
765 18
        return Button::make()
766 18
            ->type(Arr::pull($attributes, 'type', 'button'))
767 18
            ->attributes($attributes)
0 ignored issues
show
Documentation introduced by
$attributes is of type array, but the function expects a object<Arcanedev\Html\Elements\Concerns\iterable>.

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

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

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

function acceptsInteger($int) { }

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

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
768 18
            ->html($value);
769
    }
770
771
    /**
772
     * Create a color input field.
773
     *
774
     * @param  string        $name
775
     * @param  string|mixed  $value
776
     * @param  array         $attributes
777
     *
778
     * @return \Arcanedev\Html\Elements\Input
779
     */
780 18
    public function color(string $name, $value = null, array $attributes = []): Input
781
    {
782 18
        return $this->input('color', $name, $value, $attributes);
783
    }
784
785
    /* -----------------------------------------------------------------
786
     |  Other Methods
787
     | -----------------------------------------------------------------
788
     */
789
790
    /**
791
     * Create a checkable input field.
792
     *
793
     * @param  string     $type
794
     * @param  string     $name
795
     * @param  mixed      $value
796
     * @param  bool|null  $checked
797
     * @param  array      $attributes
798
     *
799
     * @return \Arcanedev\Html\Elements\Input
800
     */
801 42
    protected function checkable(string $type, string $name, $value, $checked, array $attributes): Input
802
    {
803 42
        $checked = $this->getCheckedState($type, $name, $value, $checked);
804
805 42
        if ( ! is_null($checked) && $checked)
806 36
            $attributes['checked'] = 'checked';
807
808 42
        return $this->input($type, $name, $value, $attributes);
809
    }
810
811
    /**
812
     * Get the check state for a checkable input.
813
     *
814
     * @param  string     $type
815
     * @param  string     $name
816
     * @param  mixed      $value
817
     * @param  bool|null  $checked
818
     *
819
     * @return bool
820
     */
821 42
    private function getCheckedState(string $type, string $name, $value, $checked): bool
822
    {
823 42
        switch($type) {
824 42
            case 'checkbox':
825 24
                return $this->getCheckboxCheckedState($name, $value, $checked);
826
827 18
            case 'radio':
828 12
                return $this->getRadioCheckedState($name, $value, $checked);
829
830
            default:
831 6
                return $this->getValueAttribute($name) === $value;
832
        }
833
    }
834
835
    /**
836
     * Get the check state for a checkbox input.
837
     *
838
     * @param  string     $name
839
     * @param  mixed      $value
840
     * @param  bool|null  $checked
841
     *
842
     * @return bool
843
     */
844 24
    private function getCheckboxCheckedState(string $name, $value, $checked): bool
845
    {
846
        if (
847 24
            isset($this->session) &&
848 24
            ! $this->oldInputIsEmpty() &&
849 24
            is_null($this->old($name))
850
        ) {
851 6
            return false;
852
        }
853
854 24
        if ($this->missingOldAndModel($name)) {
855 12
            return (bool) $checked;
856
        }
857
858 12
        $posted = $this->getValueAttribute($name, $checked);
859
860 12
        if (is_array($posted)) {
861 6
            return in_array($value, $posted);
862
        }
863
864 12
        if ($posted instanceof Collection) {
865 6
            return $posted->contains('id', $value);
866
        }
867
868 12
        return (bool) $posted;
869
    }
870
871
    /**
872
     * Get the check state for a radio input.
873
     *
874
     * @param  string     $name
875
     * @param  mixed      $value
876
     * @param  bool|null  $checked
877
     *
878
     * @return bool
879
     */
880 12
    private function getRadioCheckedState(string $name, $value, $checked): bool
881
    {
882 12
        if ($this->missingOldAndModel($name)) {
883 6
            return (bool) $checked;
884
        }
885
886 6
        return $this->getValueAttribute($name) === $value;
887
    }
888
889
    /**
890
     * Determine if old input or model input exists for a key.
891
     *
892
     * @param  string  $name
893
     *
894
     * @return bool
895
     */
896 36
    private function missingOldAndModel(string $name): bool
897
    {
898 36
        return is_null($this->old($name))
899 36
            && is_null($this->getModelValueAttribute($name));
900
    }
901
902
    /**
903
     * Get the form action from the options.
904
     *
905
     * @param  array  $attributes
906
     *
907
     * @return string
908
     */
909 84
    private function getAction(array $attributes): string
910
    {
911 84
        if (isset($attributes['url']))
912 6
            return $this->getUrlAction($attributes['url']);
913
914 78
        if (isset($attributes['route']))
915 12
            return $this->getRouteAction($attributes['route']);
916
917 72
        if (isset($attributes['action']))
918 12
            return $this->getControllerAction($attributes['action']);
919
920 60
        return $this->url->current();
921
    }
922
923
    /**
924
     * Get the action for a "url" option.
925
     *
926
     * @param  array|string  $attribute
927
     *
928
     * @return string
929
     */
930 6
    private function getUrlAction($attribute): string
931
    {
932 6
        return is_array($attribute)
933 6
            ? $this->url->to($attribute[0], array_slice($attribute, 1))
934 6
            : $this->url->to($attribute);
935
    }
936
937
    /**
938
     * Get the action for a "route" option.
939
     *
940
     * @param  array|string  $attribute
941
     *
942
     * @return string
943
     */
944 12
    private function getRouteAction($attribute): string
945
    {
946 12
        return is_array($attribute)
947 6
            ? $this->url->route($attribute[0], array_slice($attribute, 1))
948 12
            : $this->url->route($attribute);
949
    }
950
951
    /**
952
     * Get the action for an "action" option.
953
     *
954
     * @param  array|string  $attribute
955
     *
956
     * @return string
957
     */
958 12
    private function getControllerAction($attribute): string
959
    {
960 12
        return is_array($attribute)
961 6
            ? $this->url->action($attribute[0], array_slice($attribute, 1))
962 12
            : $this->url->action($attribute);
963
    }
964
}
965