Passed
Pull Request — master (#57)
by Wilmer
02:11
created

Modal::modalButtonClass()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 4
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
eloc 3
nc 1
nop 1
dl 0
loc 6
ccs 4
cts 4
cp 1
crap 1
rs 10
c 0
b 0
f 0
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Yiisoft\Yii\Bulma;
6
7
use InvalidArgumentException;
8
use Yiisoft\Html\Html;
9
use Yiisoft\Html\Tag\Div;
10
use Yiisoft\Html\Tag\Button;
11
use Yiisoft\Widget\Widget;
0 ignored issues
show
Bug introduced by
This use statement conflicts with another class in this namespace, Yiisoft\Yii\Bulma\Widget. Consider defining an alias.

Let?s assume that you have a directory layout like this:

.
|-- OtherDir
|   |-- Bar.php
|   `-- Foo.php
`-- SomeDir
    `-- Foo.php

and let?s assume the following content of Bar.php:

// Bar.php
namespace OtherDir;

use SomeDir\Foo; // This now conflicts the class OtherDir\Foo

If both files OtherDir/Foo.php and SomeDir/Foo.php are loaded in the same runtime, you will see a PHP error such as the following:

PHP Fatal error:  Cannot use SomeDir\Foo as Foo because the name is already in use in OtherDir/Foo.php

However, as OtherDir/Foo.php does not necessarily have to be loaded and the error is only triggered if it is loaded before OtherDir/Bar.php, this problem might go unnoticed for a while. In order to prevent this error from surfacing, you must import the namespace with a different alias:

// Bar.php
namespace OtherDir;

use SomeDir\Foo as SomeDirFoo; // There is no conflict anymore.
Loading history...
12
13
use function implode;
14
use function in_array;
15
16
/**
17
 * Modal renders a modal window that can be toggled by clicking on a button.
18
 *
19
 * The following example will show the content enclosed between the {@see Widget::begin()} and {@see Widget::end()}
20
 * calls within the modal window:
21
 *
22
 * ```php
23
 * echo Modal::widget()->begin();
24
 *
25
 * echo 'Say hello...';
26
 *
27
 * echo Modal::end();
28
 * ```
29
 *
30
 * @link https://bulma.io/documentation/components/modal/
31
 */
32
final class Modal extends Widget
33
{
34
    public const SIZE_SMALL = 'is-small';
35
    public const SIZE_MEDIUM = 'is-medium';
36
    public const SIZE_LARGE = 'is-large';
37
    private const SIZE_ALL = [
38
        self::SIZE_SMALL,
39
        self::SIZE_MEDIUM,
40
        self::SIZE_LARGE,
41
    ];
42
43
    public const COLOR_PRIMARY = 'is-primary';
44
    public const COLOR_LINK = 'is-link';
45
    public const COLOR_INFO = 'is-info';
46
    public const COLOR_SUCCESS = 'is-success';
47
    public const COLOR_WARNING = 'is-warning';
48
    public const COLOR_DANGER = 'is-danger';
49
    private const COLOR_ALL = [
50
        self::COLOR_PRIMARY,
51
        self::COLOR_LINK,
52
        self::COLOR_INFO,
53
        self::COLOR_SUCCESS,
54
        self::COLOR_WARNING,
55
        self::COLOR_DANGER,
56
    ];
57
    private array $attributes = [];
58
    private string $autoIdPrefix = 'w';
59
    private array $closeButtonAttributes = [];
60
    private string $closeButtonClass = 'modal-close';
61
    private string $closeButtonSize = '';
62
    private array $contentAttributes = [];
63
    private string $modalBackgroundClass = 'modal-background';
64
    private string $modalButtonClass = 'button modal-button';
65
    private string $modalClass = 'modal';
66
    private string $modalContentClass = 'modal-content';
67
    private array $toggleButtonAttributes = [];
68
    private string $toggleButtonLabel = 'Toggle button';
69
    private string $toggleButtonSize = '';
70
    private string $toggleButtonColor = '';
71
    private bool $withoutCloseButton = false;
72
    private bool $withoutToggleButton = false;
73
74
    /**
75
     * The HTML attributes.
76
     *
77
     * @param array $values Attribute values indexed by attribute names.
78
     *
79
     * @return self
80
     *
81
     * See {@see \Yiisoft\Html\Html::renderTagAttributes()} for details on how attributes are being rendered.
82
     */
83 2
    public function attributes(array $values): self
84
    {
85 2
        $new = clone $this;
86 2
        $new->attributes = $values;
87 2
        return $new;
88
    }
89
90
    /**
91
     * Returns a new instance with the specified prefix to the automatically generated widget IDs.
92
     *
93
     * @param string $value The prefix to the automatically generated widget IDs.
94
     *
95
     * @return self
96
     */
97 1
    public function autoIdPrefix(string $value): self
98
    {
99 1
        $new = clone $this;
100 1
        $new->autoIdPrefix = $value;
101 1
        return $new;
102
    }
103
104
    /**
105
     * Returns a new instance with the specified close button options.
106
     *
107
     * @param array $value The close button options.
108
     *
109
     * {@see Html::renderTagAttributes()} for details on how attributes are being rendered.
110
     *
111
     * @return self
112
     */
113 2
    public function closeButtonAttributes(array $value): self
114
    {
115 2
        $new = clone $this;
116 2
        $new->closeButtonAttributes = $value;
117
118 2
        return $new;
119
    }
120
121
    /**
122
     * Returns a new instance with the specified close button size.
123
     *
124
     * @param string $value The close button size.
125
     *
126
     * @return self
127
     */
128 3
    public function closeButtonSize(string $value): self
129
    {
130 3
        if (!in_array($value, self::SIZE_ALL, true)) {
131 1
            $values = implode('"', self::SIZE_ALL);
132 1
            throw new InvalidArgumentException("Invalid size. Valid values are: \"$values\".");
133
        }
134
135 2
        $new = clone $this;
136 2
        $new->closeButtonSize = $value;
137
138 2
        return $new;
139
    }
140
141
    /**
142
     * Returns a new instance with the specified content options.
143
     *
144
     * @param array $value The content options.
145
     *
146
     * {@see Html::renderTagAttributes()} for details on how attributes are being rendered.
147
     *
148
     * @return self
149
     */
150 2
    public function contentAttributes(array $value): self
151
    {
152 2
        $new = clone $this;
153 2
        $new->contentAttributes = $value;
154
155 2
        return $new;
156
    }
157
158
    /**
159
     * Returns a new instance with the specified ID of the widget.
160
     *
161
     * @param string $value The ID of the widget.
162
     *
163
     * @return self
164
     */
165 1
    public function id(string $value): self
166
    {
167 1
        $new = clone $this;
168 1
        $new->attributes['id'] = $value;
169 1
        return $new;
170
    }
171
172
    /**
173
     * Returns a new instance with the specified modal background class.
174
     *
175
     * @param string $value The modal background class.
176
     *
177
     * @return self
178
     */
179 2
    public function modalBackgroundClass(string $value): self
180
    {
181 2
        $new = clone $this;
182 2
        $new->modalBackgroundClass = $value;
183
184 2
        return $new;
185
    }
186
187
    /**
188
     * Returns a new instance with the specified modal button class.
189
     *
190
     * @param string $value The modal button class.
191
     *
192
     * @return self
193
     */
194 2
    public function modalButtonClass(string $value): self
195
    {
196 2
        $new = clone $this;
197 2
        $new->modalButtonClass = $value;
198
199 2
        return $new;
200
    }
201
202
    /**
203
     * Returns a new instance with the specified modal class.
204
     *
205
     * @param string $value The modal class.
206
     *
207
     * @return self
208
     */
209 2
    public function modalClass(string $value): self
210
    {
211 2
        $new = clone $this;
212 2
        $new->modalClass = $value;
213
214 2
        return $new;
215
    }
216
217
    /**
218
     * Returns a new instance with the specified modal content class.
219
     *
220
     * @param string $value The modal content class.
221
     *
222
     * @return self
223
     */
224 2
    public function modalContentClass(string $value): self
225
    {
226 2
        $new = clone $this;
227 2
        $new->modalContentClass = $value;
228
229 2
        return $new;
230
    }
231
232
    /**
233
     * Returns a new instance with the specified toggle button options.
234
     *
235
     * @param array $values Attribute values indexed by attribute names.
236
     *
237
     * {@see Html::renderTagAttributes()} for details on how attributes are being rendered.
238
     *
239
     * @return self
240
     */
241 2
    public function toggleButtonAttributes(array $values): self
242
    {
243 2
        $new = clone $this;
244 2
        $new->toggleButtonAttributes = $values;
245
246 2
        return $new;
247
    }
248
249
    /**
250
     * Returns a new instance with the specified toggle button color.
251
     *
252
     * @param string $value The toggle button color. $value Setting default is empty.
253
     * Possible values: 'is-dark', 'is-primary', 'is-link', 'is-info', 'is-success', 'is-warning', 'is-danger'.
254
     *
255
     * @return self
256
     */
257 3
    public function toggleButtonColor(string $value): self
258
    {
259 3
        if (!in_array($value, self::COLOR_ALL, true)) {
260 1
            $values = implode(' ', self::COLOR_ALL);
261 1
            throw new InvalidArgumentException("Invalid color. Valid values are: \"$values\".");
262
        }
263
264 2
        $new = clone $this;
265 2
        $new->toggleButtonColor = $value;
266
267 2
        return $new;
268
    }
269
270
    /**
271
     * Returns a new instance with the specified toggle button label.
272
     *
273
     * @param string $value The toggle button label.
274
     *
275
     * @return self
276
     */
277 2
    public function toggleButtonLabel(string $value): self
278
    {
279 2
        $new = clone $this;
280 2
        $new->toggleButtonLabel = $value;
281
282 2
        return $new;
283
    }
284
285
    /**
286
     * Returns a new instance with the specified toggle button size.
287
     *
288
     * @param string $value The toggle button size. Default setting empty normal.
289
     * Possible values: 'is-small', 'is-medium', 'is-large'.
290
     *
291
     * @return self
292
     */
293 3
    public function toggleButtonSize(string $value): self
294
    {
295 3
        if (!in_array($value, self::SIZE_ALL, true)) {
296 1
            $values = implode(' ', self::SIZE_ALL);
297 1
            throw new InvalidArgumentException("Invalid size. Valid values are: \"$values\".");
298
        }
299
300 2
        $new = clone $this;
301 2
        $new->toggleButtonSize = $value;
302
303 2
        return $new;
304
    }
305
306
    /**
307
     * Returns a new instance with the specified options for rendering the close button tag.
308
     *
309
     * @param bool $value Whether the close button is disabled.
310
     *
311
     * @return self
312
     */
313 2
    public function withoutCloseButton(bool $value): self
314
    {
315 2
        $new = clone $this;
316 2
        $new->withoutCloseButton = $value;
317
318 2
        return $new;
319
    }
320
321
    /**
322
     * Returns a new instance with the disabled toggle button.
323
     *
324
     * @param bool $value Whether the toggle button is disabled.
325
     *
326
     * @return self
327
     */
328 2
    public function withoutToggleButton(bool $value): self
329
    {
330 2
        $new = clone $this;
331 2
        $new->withoutToggleButton = $value;
332
333 2
        return $new;
334
    }
335
336 15
    public function begin(): ?string
337
    {
338 15
        parent::begin();
339
340 15
        $attributes = $this->attributes;
341 15
        $contentAttributes = $this->contentAttributes;
342 15
        $html = '';
343
344 15
        if (!array_key_exists('id', $attributes)) {
345 15
            $attributes['id'] = Html::generateId($this->autoIdPrefix) . '-modal';
346
        }
347
348
        /** @var string */
349 15
        $id = $attributes['id'];
350
351 15
        Html::addCssClass($attributes, $this->modalClass);
352 15
        Html::addCssClass($contentAttributes, $this->modalContentClass);
353
354 15
        if ($this->withoutToggleButton == false) {
0 ignored issues
show
Coding Style Best Practice introduced by
It seems like you are loosely comparing two booleans. Considering using the strict comparison === instead.

When comparing two booleans, it is generally considered safer to use the strict comparison operator.

Loading history...
355 14
            $html .= $this->renderToggleButton($id) . "\n";
356
        }
357
358 15
        $html .= Html::openTag('div', $attributes) . "\n"; // .modal
359 15
        $html .= Div::tag()->class($this->modalBackgroundClass) . "\n";
360
361 15
        if ($this->withoutCloseButton === false) {
362 14
            $html .= $this->renderCloseButton() . "\n";
363
        }
364
365 15
        $html .= Html::openTag('div', $contentAttributes) . "\n"; // .modal-content
366
367 15
        return $html;
368
    }
369
370 15
    protected function run(): string
371
    {
372 15
        $html = Html::closeTag('div') . "\n"; // .modal-content
373 15
        $html .= Html::closeTag('div'); // .modal
374
375 15
        return $html;
376
    }
377
378
    /**
379
     * Renders the toggle button.
380
     *
381
     * @param string $id
382
     *
383
     * @return string
384
     */
385 14
    private function renderToggleButton(string $id): string
386
    {
387 14
        $toggleButtonAttributes = $this->toggleButtonAttributes;
388
389 14
        $toggleButtonAttributes['data-target'] = '#' . $id;
390 14
        $toggleButtonAttributes['aria-haspopup'] = 'true';
391
392 14
        if ($this->toggleButtonSize !== '') {
393 1
            Html::addCssClass($toggleButtonAttributes, $this->toggleButtonSize);
394
        }
395
396 14
        if ($this->toggleButtonColor !== '') {
397 1
            Html::addCssClass($toggleButtonAttributes, $this->toggleButtonColor);
398
        }
399
400 14
        Html::addCssClass($toggleButtonAttributes, $this->modalButtonClass);
401
402 14
        return Button::tag()->attributes($toggleButtonAttributes)->content($this->toggleButtonLabel)->render();
403
    }
404
405
    /**
406
     * Renders the close button.
407
     *
408
     * @return string
409
     */
410 14
    private function renderCloseButton(): string
411
    {
412 14
        $closeButtonAttributes = $this->closeButtonAttributes;
413 14
        $closeButtonAttributes['aria-label'] = 'close';
414
415 14
        if ($this->closeButtonSize !== '') {
416 1
            Html::addCssClass($closeButtonAttributes, $this->closeButtonSize);
417
        }
418
419 14
        Html::addCssClass($closeButtonAttributes, $this->closeButtonClass);
420
421 14
        return Button::tag()->attributes($closeButtonAttributes)->render();
422
    }
423
}
424