Issues (13)

src/ButtonDropdown.php (2 issues)

Labels
Severity
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Yiisoft\Yii\Bootstrap4;
6
7
use Yiisoft\Arrays\ArrayHelper;
8
use Yiisoft\Factory\Exceptions\InvalidConfigException;
9
use Yiisoft\Html\Html;
10
11
/**
12
 * ButtonDropdown renders a group or split button dropdown bootstrap component.
13
 *
14
 * For example,
15
 *
16
 * ```php
17
 * // a button group using Dropdown widget
18
 * echo ButtonDropdown::widget()
19
 *     ->label('Action')
20
 *     ->dropdown'([
21
 *         'items' => [
22
 *             ['label' => 'DropdownA', 'url' => '/'],
23
 *             ['label' => 'DropdownB', 'url' => '#'],
24
 *         ],
25
 *     ]);
26
 * ```
27
 */
28
class ButtonDropdown extends Widget
29
{
30
    /**
31
     * The css class part of dropdown
32
     */
33
    public const DIRECTION_DOWN = 'down';
34
35
    /**
36
     * The css class part of dropleft
37
     */
38
    public const DIRECTION_LEFT = 'left';
39
40
    /**
41
     * The css class part of dropright
42
     */
43
    public const DIRECTION_RIGHT = 'right';
44
45
    /**
46
     * The css class part of dropup
47
     */
48
    public const DIRECTION_UP = 'up';
49
50
    private string $label = 'Button';
51
    private array $options = [];
52
    private array $buttonOptions = [];
53
    private array $dropdown = [];
54
    private string $direction = self::DIRECTION_DOWN;
55
    private bool $split = false;
56
    private string $tagName = 'button';
57
    private bool $encodeLabels = true;
58
    private string $dropdownClass = Dropdown::class;
59
    private bool $renderContainer = true;
60
61 3
    protected function run(): string
62
    {
63
        /** Set options id to button options id to ensure correct css selector in plugin initialisation */
64 3
        if (empty($this->options['id'])) {
65 3
            $id = $this->getId();
66
67 3
            $this->options['id'] = "{$id}-button-dropdown";
68 3
            $this->buttonOptions['id'] = "{$id}-button";
69
        }
70
71 3
        $html = $this->renderButton() . "\n" . $this->renderDropdown();
72
73 3
        if ($this->renderContainer) {
74 3
            Html::addCssClass($this->options, ['widget' => 'drop' . $this->direction, 'btn-group']);
75
76 3
            $options = $this->options;
77 3
            $tag = ArrayHelper::remove($options, 'tag', 'div');
78 3
            $html = Html::tag($tag, $html, $options);
79
        }
80
81 3
        $this->registerPlugin('dropdown', $this->options);
82
83 3
        return $html;
84
    }
85
86
    /**
87
     * Generates the button dropdown.
88
     *
89
     * @throws InvalidConfigException
90
     *
91
     * @return string the rendering result.
92
     */
93 3
    protected function renderButton(): string
94
    {
95 3
        Html::addCssClass($this->buttonOptions, ['widget' => 'btn']);
96
97 3
        $label = $this->label;
98
99 3
        if ($this->encodeLabels) {
100 3
            $label = Html::encode($label);
101
        }
102
103 3
        if ($this->split) {
104 1
            $buttonOptions = $this->buttonOptions;
105
106 1
            $this->buttonOptions['data-toggle'] = 'dropdown';
107 1
            $this->buttonOptions['aria-haspopup'] = 'true';
108 1
            $this->buttonOptions['aria-expanded'] = 'false';
109
110 1
            Html::addCssClass($this->buttonOptions, ['toggle' => 'dropdown-toggle dropdown-toggle-split']);
111
112 1
            unset($buttonOptions['id']);
113
114 1
            $splitButton = Button::widget()
115 1
                ->label('<span class="sr-only">Toggle Dropdown</span>')
0 ignored issues
show
The method label() does not exist on Yiisoft\Widget\Widget. It seems like you code against a sub-type of Yiisoft\Widget\Widget such as Yiisoft\Yii\Bootstrap4\Progress or Yiisoft\Yii\Bootstrap4\Button or Yiisoft\Yii\Bootstrap4\Nav or Yiisoft\Yii\Bootstrap4\ButtonDropdown. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

115
                ->/** @scrutinizer ignore-call */ label('<span class="sr-only">Toggle Dropdown</span>')
Loading history...
116 1
                ->encodeLabels(false)
117 1
                ->options($this->buttonOptions)
118 1
                ->render();
119
        } else {
120 2
            $buttonOptions = $this->buttonOptions;
121
122 2
            Html::addCssClass($buttonOptions, ['toggle' => 'dropdown-toggle']);
123
124 2
            $buttonOptions['data-toggle'] = 'dropdown';
125 2
            $buttonOptions['aria-haspopup'] = 'true';
126 2
            $buttonOptions['aria-expanded'] = 'false';
127 2
            $splitButton = '';
128
        }
129
130 3
        if (!isset($buttonOptions['href']) && ($this->tagName === 'a')) {
131
            $buttonOptions['href'] = '#';
132
            $buttonOptions['role'] = 'button';
133
        }
134
135 3
        return Button::widget()
136 3
                ->tagName($this->tagName)
0 ignored issues
show
The method tagName() does not exist on Yiisoft\Widget\Widget. It seems like you code against a sub-type of Yiisoft\Widget\Widget such as Yiisoft\Yii\Bootstrap4\Button or Yiisoft\Yii\Bootstrap4\ButtonDropdown. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

136
                ->/** @scrutinizer ignore-call */ tagName($this->tagName)
Loading history...
137 3
                ->label($label)
138 3
                ->options($buttonOptions)
139 3
                ->encodeLabels(false)
140 3
                ->render()
141 3
                . "\n" . $splitButton;
142
    }
143
144
    /**
145
     * Generates the dropdown menu.
146
     *
147
     * @return string the rendering result.
148
     */
149 3
    protected function renderDropdown(): string
150
    {
151 3
        $dropdownClass = $this->dropdownClass;
152
153 3
        return $dropdownClass::widget()
154 3
            ->items($this->dropdown['items'])
155 3
            ->render();
156
    }
157
158
    /**
159
     * The HTML attributes of the button.
160
     *
161
     * {@see \Yiisoft\Html\Html::renderTagAttributes()} for details on how attributes are being rendered.
162
     *
163
     * @param array $value
164
     *
165
     * @return $this
166
     */
167
    public function buttonOptions(array $value): self
168
    {
169
        $this->buttonOptions = $value;
170
171
        return $this;
172
    }
173
174
    /**
175
     * The drop-direction of the widget.
176
     *
177
     * Possible values are 'left', 'right', 'up', or 'down' (default)
178
     *
179
     * @param string $value
180
     *
181
     * @return $this
182
     */
183 3
    public function direction(string $value): self
184
    {
185 3
        $this->direction = $value;
186
187 3
        return $this;
188
    }
189
190
    /**
191
     * The configuration array for example:
192
     *
193
     * ```php
194
     *    [
195
     *        'items' => [
196
     *            ['label' => 'DropdownA', 'url' => '/'],
197
     *            ['label' => 'DropdownB', 'url' => '#'],
198
     *        ],
199
     *    ]
200
     * ```
201
     *
202
     * {@see Dropdown}
203
     *
204
     * @param array $value
205
     *
206
     * @return $this
207
     */
208 3
    public function dropdown(array $value): self
209
    {
210 3
        $this->dropdown = $value;
211
212 3
        return $this;
213
    }
214
215
    /**
216
     * Name of a class to use for rendering dropdowns withing this widget. Defaults to {@see Dropdown}.
217
     *
218
     * @param string $value
219
     *
220
     * @return $this
221
     */
222
    public function dropdownClass(string $value): self
223
    {
224
        $this->dropdownClass = $value;
225
226
        return $this;
227
    }
228
229
    /**
230
     * Whether the label should be HTML-encoded.
231
     *
232
     * @param bool $value
233
     *
234
     * @return $this
235
     */
236
    public function encodeLabels(bool $value): self
237
    {
238
        $this->encodeLabels = $value;
239
240
        return $this;
241
    }
242
243
    /**
244
     * The button label.
245
     *
246
     * @param string $value
247
     *
248
     * @return $this
249
     */
250 3
    public function label(string $value): self
251
    {
252 3
        $this->label = $value;
253
254 3
        return $this;
255
    }
256
257
    /**
258
     * The HTML attributes for the container tag. The following special options are recognized.
259
     *
260
     * {@see \Yiisoft\Html\Html::renderTagAttributes()} for details on how attributes are being rendered.
261
     *
262
     * @param array $value
263
     *
264
     * @return $this
265
     */
266 1
    public function options(array $value): self
267
    {
268 1
        $this->options = $value;
269
270 1
        return $this;
271
    }
272
273
    /**
274
     * Whether to render the container using the {@see options} as HTML attributes. If set to `false`, the container
275
     * element enclosing the button and dropdown will NOT be rendered.
276
     *
277
     * @param bool $value
278
     *
279
     * @return $this
280
     */
281
    public function renderContainer(bool $value): self
282
    {
283
        $this->renderContainer = $value;
284
285
        return $this;
286
    }
287
288
    /**
289
     * Whether to display a group of split-styled button group.
290
     *
291
     * @param bool $value
292
     *
293
     * @return $this
294
     */
295 1
    public function split(bool $value): self
296
    {
297 1
        $this->split = $value;
298
299 1
        return $this;
300
    }
301
302
    /**
303
     * The tag to use to render the button.
304
     *
305
     * @param string $value
306
     *
307
     * @return $this
308
     */
309
    public function tagName(string $value): self
310
    {
311
        $this->tagName = $value;
312
313
        return $this;
314
    }
315
}
316