Passed
Pull Request — master (#192)
by Alexander
02:31
created

Checkbox::generateInput()   B

Complexity

Conditions 11
Paths 7

Size

Total Lines 45
Code Lines 27

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 26
CRAP Score 11.0061

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 11
eloc 27
nc 7
nop 0
dl 0
loc 45
ccs 26
cts 27
cp 0.963
crap 11.0061
rs 7.3166
c 1
b 0
f 0

How to fix   Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
declare(strict_types=1);
4
5
namespace Yiisoft\Form\Field;
6
7
use InvalidArgumentException;
8
use Stringable;
9
use Yiisoft\Form\Field\Base\AbstractField;
10
use Yiisoft\Html\Html;
11
12
use function is_bool;
13
use function is_object;
14
use function is_string;
15
16
/**
17
 * The input element with a type attribute whose value is "checkbox" represents a state or option that can be toggled.
18
 *
19
 * @link https://html.spec.whatwg.org/multipage/input.html#checkbox-state-(type=checkbox)
20
 */
21
final class Checkbox extends AbstractField
22
{
23
    private ?string $uncheckValue = '0';
24
    private bool $enclosedByLabel = true;
25
    private ?string $inputLabel = null;
26
    private array $inputLabelAttributes = [];
27
    private bool $inputLabelEncode = true;
28
    private ?string $inputValue = null;
29
30
    /**
31
     * @param bool|float|int|string|Stringable|null $value Value that corresponds to "unchecked" state of the input.
32
     */
33 8
    public function uncheckValue(bool|float|int|string|Stringable|null $value): self
34
    {
35 8
        $new = clone $this;
36 8
        $new->uncheckValue = $this->prepareValue($value);
37 8
        return $new;
38
    }
39
40
    /**
41
     * If the input should be enclosed by label.
42
     *
43
     * @param bool $value If the input should be en closed by label.
44
     */
45 5
    public function enclosedByLabel(bool $value): self
46
    {
47 5
        $new = clone $this;
48 5
        $new->enclosedByLabel = $value;
49 5
        return $new;
50
    }
51
52
    /**
53
     * Label displayed next to the checkbox.
54
     *
55
     * When this option is specified, the checkbox will be enclosed by a label tag.
56
     *
57
     * @param string|null $value
58
     *
59
     * @return self
60
     *
61
     * @link https://www.w3.org/TR/html52/sec-forms.html#the-label-element
62
     */
63 7
    public function inputLabel(?string $value): self
64
    {
65 7
        $new = clone $this;
66 7
        $new->inputLabel = $value;
67 7
        return $new;
68
    }
69
70
    /**
71
     * HTML attributes for the label tag.
72
     *
73
     * {@see \Yiisoft\Html\Html::renderTagAttributes()} for details on how attributes are being rendered.
74
     */
75 2
    public function inputLabelAttributes(array $attributes): self
76
    {
77 2
        $new = clone $this;
78 2
        $new->inputLabelAttributes = $attributes;
79 2
        return $new;
80
    }
81
82 2
    public function inputLabelEncode(bool $encode): self
83
    {
84 2
        $new = clone $this;
85 2
        $new->inputLabelEncode = $encode;
86 2
        return $new;
87
    }
88
89 3
    public function inputValue(bool|float|int|string|Stringable|null $value): self
90
    {
91 3
        $new = clone $this;
92 3
        $new->inputValue = $this->prepareValue($value);
93 3
        return $new;
94
    }
95
96 20
    protected function generateInput(): string
97
    {
98 20
        $value = $this->getAttributeValue();
99
100 20
        if (!is_bool($value)
101 20
            && !is_string($value)
102 20
            && !is_numeric($value)
103 20
            && $value !== null
104 20
            && (!is_object($value) || !method_exists($value, '__toString'))
105
        ) {
106
            throw new InvalidArgumentException(
107
                'Checkbox widget requires a string, numeric, bool, Stringable or null value.'
108
            );
109
        }
110
111 20
        $value = $this->prepareValue($value);
112
113 20
        $tagAttributes = $this->getInputTagAttributes();
114
115 20
        $inputValue = $this->inputValue;
116 20
        $inputValue = $inputValue ?? $this->prepareValue($tagAttributes['value'] ?? null);
117 20
        unset($tagAttributes['value']);
118 20
        $inputValue = $inputValue ?? '1';
119
120
        /** @psalm-suppress MixedArgumentTypeCoercion */
121 20
        $checkbox = Html::checkbox($this->getInputName(), $inputValue, $tagAttributes);
122
123 20
        $label = $this->inputLabel ?? $this->getAttributeLabel();
124
125 20
        if ($this->enclosedByLabel) {
126 16
            $checkbox = $checkbox
127 16
                ->label($label, $this->inputLabelAttributes)
128 16
                ->labelEncode($this->inputLabelEncode);
129
        }
130
131 20
        $html = $checkbox
132 20
            ->checked($inputValue === $value)
133 20
            ->uncheckValue($this->uncheckValue)
134 20
            ->render();
135
136 20
        if (!$this->enclosedByLabel && $this->inputLabel !== null) {
137 3
            $html .= ' ' . ($this->inputLabelEncode ? Html::encode($this->inputLabel) : $this->inputLabel);
138
        }
139
140 20
        return $html;
141
    }
142
143 18
    protected function shouldHideLabel(): bool
144
    {
145 18
        return $this->enclosedByLabel;
146
    }
147
148 21
    private function prepareValue(bool|float|int|string|Stringable|null $value): ?string
149
    {
150 21
        if ($value === null) {
151 19
            return null;
152
        }
153
154 20
        if (is_bool($value)) {
155 19
            return $value ? '1' : '0';
156
        }
157
158 6
        return (string)$value;
159
    }
160
}
161