Passed
Push — master ( c202e1...34af4b )
by Alexander
20:59 queued 18:00
created

ButtonGroup::renderButtons()   A

Complexity

Conditions 4
Paths 4

Size

Total Lines 37
Code Lines 17

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 17
CRAP Score 4

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 4
eloc 17
nc 4
nop 0
dl 0
loc 37
ccs 17
cts 17
cp 1
crap 4
rs 9.7
c 1
b 0
f 0
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Yiisoft\Form\Widget;
6
7
use Yiisoft\Form\Widget\Attribute\ButtonAttributes;
8
use Yiisoft\Html\Tag\Input;
9
use Yiisoft\Html\Tag\Div;
10
11
use function array_merge;
12
use function implode;
13
use function is_array;
14
15
/**
16
 * ButtonGroup renders a button group widget.
17
 *
18
 * For example,
19
 *
20
 * ```php
21
 * // a button group with items configuration
22
 * echo ButtonGroup::widget()
23
 *     ->buttons([
24
 *         ['label' => 'A'],
25
 *         ['label' => 'B'],
26
 *         ['label' => 'C', 'visible' => false],
27
 *     ]);
28
 *
29
 * // button group with an item as a string
30
 * echo ButtonGroup::widget()
31
 *     ->buttons([
32
 *         SubmitButton::widget()->content('A')->render(),
33
 *         ['label' => 'B'],
34
 *     ]);
35
 * ```
36
 *
37
 * Pressing on the button should be handled via JavaScript. See the following for details:
38
 */
39
final class ButtonGroup extends ButtonAttributes
40
{
41
    private array $buttons = [];
42
    private bool $container = true;
43
    private array $containerAttributes = [];
44
    private string $containerClass = '';
45
    /** @psalm-var array[] */
46
    private array $individualButtonAttributes = [];
47
48
    /**
49
     * List of buttons. Each array element represents a single button which can be specified as a string or an array of
50
     * the following structure:
51
     *
52
     * - label: string, required, the button label.
53
     * - attributes: array, optional, the HTML attributes of the button.
54
     * - type: string, optional, the button type.
55
     * - visible: bool, optional, whether this button is visible. Defaults to true.
56
     *
57
     * @param array $values The buttons' configuration.
58
     *
59
     * @return self
60
     */
61 31
    public function buttons(array $values): self
62
    {
63 31
        $new = clone $this;
64 31
        $new->buttons = $values;
65 31
        return $new;
66
    }
67
68
    /**
69
     * Enable, disabled container for field.
70
     *
71
     * @param bool $value Is the container disabled or not.
72
     *
73
     * @return self
74
     */
75 4
    public function container(bool $value): self
76
    {
77 4
        $new = clone $this;
78 4
        $new->container = $value;
79 4
        return $new;
80
    }
81
82
    /**
83
     * Set container attributes.
84
     *
85
     * @param array $values Attribute values indexed by attribute names.
86
     *
87
     * ```php
88
     * ['class' => 'test-class']
89
     * ```
90
     *
91
     * @return self
92
     *
93
     * @psalm-param array<string, string> $values
94
     */
95 2
    public function containerAttributes(array $values): self
96
    {
97 2
        $new = clone $this;
98 2
        $new->containerAttributes = array_merge($new->containerAttributes, $values);
99 2
        return $new;
100
    }
101
102
    /**
103
     * Set container css class.
104
     *
105
     * @param string $value
106
     *
107
     * @return self
108
     */
109 4
    public function containerClass(string $value): self
110
    {
111 4
        $new = clone $this;
112 4
        $new->containerClass = $value;
113 4
        return $new;
114
    }
115
116
    /**
117
     * Set the ID of the container field.
118
     *
119
     * @param string|null $id
120
     *
121
     * @return self
122
     */
123 2
    public function containerId(?string $id): self
124
    {
125 2
        $new = clone $this;
126 2
        $new->containerAttributes['id'] = $id;
127 2
        return $new;
128
    }
129
130
    /**
131
     * Set the name of the container field.
132
     *
133
     * @param string|null $id
134
     *
135
     * @return self
136
     */
137 2
    public function containerName(?string $id): self
138
    {
139 2
        $new = clone $this;
140 2
        $new->containerAttributes['name'] = $id;
141 2
        return $new;
142
    }
143
144
    /**
145
     * The specified attributes for button.
146
     *
147
     * @param array $values The button attributes.
148
     *
149
     * @return self
150
     *
151
     * @psalm-param array[] $values
152
     */
153 3
    public function individualButtonAttributes(array $values = []): self
154
    {
155 3
        $new = clone $this;
156 3
        $new->individualButtonAttributes = $values;
157 3
        return $new;
158
    }
159
160 30
    protected function run(): string
161
    {
162 30
        $div = Div::tag();
163
164 30
        if ($this->containerClass !== '') {
165 3
            $div = $div->class($this->containerClass);
166
        }
167
168 30
        if ($this->containerAttributes !== []) {
169 3
            $div = $div->attributes($this->containerAttributes);
170
        }
171
172 30
        return $this->container ?
173 30
            $div->content(PHP_EOL . $this->renderButtons() . PHP_EOL)->encode(false)->render() : $this->renderButtons();
174
    }
175
176
    /**
177
     * Generates the buttons that compound the group as specified on {@see buttons}.
178
     *
179
     * @return string the rendering result.
180
     */
181 30
    private function renderButtons(): string
182
    {
183 30
        $htmlButtons = [];
184
185
        /** @psalm-var array<string, array|string> */
186 30
        $buttons = $this->buttons;
187
188 30
        foreach ($buttons as $key => $button) {
189 30
            if (is_array($button)) {
190
                /** @var array */
191 29
                $attributes = $button['attributes'] ?? [];
192 29
                $attributes = array_merge($attributes, $this->build($this->attributes, '-button'));
193
194
                // Set individual button attributes.
195 29
                $individualButtonAttributes = $this->individualButtonAttributes[$key] ?? [];
196 29
                $attributes = array_merge($attributes, $individualButtonAttributes);
197
198
                /** @var string */
199 29
                $label = $button['label'] ?? '';
200
201
                /** @var string */
202 29
                $type = $button['type'] ?? 'button';
203
204
                /** @var bool */
205 29
                $visible = $button['visible'] ?? true;
206
207 29
                if ($visible === false) {
208 1
                    continue;
209
                }
210
211 29
                $htmlButtons[] = Input::tag()->attributes($attributes)->value($label)->type($type)->render();
212
            } else {
213 1
                $htmlButtons[] = $button;
214
            }
215
        }
216
217 30
        return implode("\n", $htmlButtons);
218
    }
219
}
220