Passed
Pull Request — master (#160)
by Wilmer
03:33
created

ButtonGroup::containerAttributes()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 4
CRAP Score 1

Importance

Changes 1
Bugs 0 Features 1
Metric Value
cc 1
eloc 3
nc 1
nop 1
dl 0
loc 5
ccs 4
cts 4
cp 1
crap 1
rs 10
c 1
b 0
f 1
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\Html;
9
use Yiisoft\Html\Tag\Input;
10
use Yiisoft\Html\Tag\Div;
11
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 26
    public function buttons(array $values): self
62
    {
63 26
        $new = clone $this;
64 26
        $new->buttons = $values;
65
66 26
        return $new;
67
    }
68
69
    /**
70
     * Enable, disabled container for field.
71
     *
72
     * @param bool $value Is the container disabled or not.
73
     *
74
     * @return static
75
     */
76 9
    public function container(bool $value): self
77
    {
78 9
        $new = clone $this;
79 9
        $new->container = $value;
80 9
        return $new;
81
    }
82
83
    /**
84
     * Set container attributes.
85
     *
86
     * @param array $values Attribute values indexed by attribute names.
87
     *
88
     * ```php
89
     * ['class' => 'test-class']
90
     * ```
91
     *
92
     * @return static
93
     *
94
     * @psalm-param array<string, string> $values
95
     */
96 1
    public function containerAttributes(array $values): self
97
    {
98 1
        $new = clone $this;
99 1
        $new->containerAttributes = array_merge($new->containerAttributes, $values);
100 1
        return $new;
101
    }
102
103
    /**
104
     * Set container css class.
105
     *
106
     * @return static
107
     */
108 1
    public function containerClass(string $value): self
109
    {
110 1
        $new = clone $this;
111 1
        $new->containerClass = $value;
112 1
        return $new;
113
    }
114
115
    /**
116
     * Set the ID of the container field.
117
     *
118
     * @param string|null $id
119
     *
120
     * @return static
121
     */
122 1
    public function containerId(?string $id): self
123
    {
124 1
        $new = clone $this;
125 1
        $new->containerAttributes['id'] = $id;
126 1
        return $new;
127
    }
128
129
    /**
130
     * Set the name of the container field.
131
     *
132
     * @param string|null $id
133
     *
134
     * @return static
135
     */
136 1
    public function containerName(?string $id): self
137
    {
138 1
        $new = clone $this;
139 1
        $new->containerAttributes['name'] = $id;
140 1
        return $new;
141
    }
142
143
    /**
144
     * The specified attributes for button.
145
     *
146
     * @param array $values The button attributes.
147
     *
148
     * @return static
149
     *
150
     * @psalm-param array[] $values
151
     */
152 1
    public function individualButtonAttributes(array $values = []): self
153
    {
154 1
        $new = clone $this;
155 1
        $new->individualButtonAttributes = $values;
156 1
        return $new;
157
    }
158
159 26
    protected function run(): string
160
    {
161 26
        $div = Div::tag();
162
163 26
        if ($this->containerClass !== '') {
164 1
            $div = $div->class($this->containerClass);
165
        }
166
167 26
        if ($this->containerAttributes !== []) {
168 3
            $div = $div->attributes($this->containerAttributes);
169
        }
170
171 26
        return $this->container ?
172 26
            $div->content(PHP_EOL . $this->renderButtons() . PHP_EOL)->encode(false)->render() : $this->renderButtons();
173
    }
174
175
    /**
176
     * Generates the buttons that compound the group as specified on {@see buttons}.
177
     *
178
     * @return string the rendering result.
179
     */
180 26
    private function renderButtons(): string
181
    {
182 26
        $htmlButtons = [];
183
184
        /** @psalm-var array<string, array|string> */
185 26
        $buttons = $this->buttons;
186
187 26
        foreach ($buttons as $key => $button) {
188 26
            if (is_array($button)) {
189
                /** @var array */
190 26
                $attributes = $button['attributes'] ?? [];
191 26
                $attributes = array_merge($attributes, $this->build($this->attributes, '-button'));
192
193
                // Set individual button attributes.
194 26
                $individualButtonAttributes = $this->individualButtonAttributes[$key] ?? [];
195 26
                $attributes = array_merge($attributes, $individualButtonAttributes);
196
197
                /** @var string */
198 26
                $label = $button['label'] ?? '';
199
200
                /** @var string */
201 26
                $type = $button['type'] ?? 'button';
202
203
                /** @var bool */
204 26
                $visible = $button['visible'] ?? true;
205
206 26
                if ($visible === false) {
207 1
                    continue;
208
                }
209
210 26
                $htmlButtons[] = Input::tag()->attributes($attributes)->value($label)->type($type)->render();
211
            } else {
212
                $htmlButtons[] = $button;
213
            }
214
        }
215
216 26
        return implode("\n", $htmlButtons);
217
    }
218
}
219