Passed
Push — master ( d5255e...189602 )
by Alexander
04:22 queued 02:10
created

Modal::contentAttributes()   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
    public const COLOR_DARK = 'is-dark';
50
    private const COLOR_ALL = [
51
        self::COLOR_PRIMARY,
52
        self::COLOR_LINK,
53
        self::COLOR_INFO,
54
        self::COLOR_SUCCESS,
55
        self::COLOR_WARNING,
56
        self::COLOR_DANGER,
57
        self::COLOR_DARK,
58
    ];
59
    private array $attributes = [];
60
    private string $autoIdPrefix = 'w';
61
    private string $backgroundClass = 'modal-background';
62
    private string $buttonClass = 'button modal-button';
63
    private array $closeButtonAttributes = [];
64
    private string $closeButtonClass = 'modal-close';
65
    private string $closeButtonSize = '';
66
    private array $contentAttributes = [];
67
    private string $contentClass = 'modal-content';
68
    private string $modalClass = 'modal';
69
    private array $toggleButtonAttributes = [];
70
    private string $toggleButtonLabel = 'Toggle button';
71
    private string $toggleButtonSize = '';
72
    private string $toggleButtonColor = '';
73
    private bool $withoutCloseButton = false;
74
    private bool $withoutToggleButton = false;
75
76
    /**
77
     * The HTML attributes.
78
     *
79
     * @param array $values Attribute values indexed by attribute names.
80
     *
81
     * @return self
82
     *
83
     * See {@see \Yiisoft\Html\Html::renderTagAttributes()} for details on how attributes are being rendered.
84
     */
85 2
    public function attributes(array $values): self
86
    {
87 2
        $new = clone $this;
88 2
        $new->attributes = $values;
89 2
        return $new;
90
    }
91
92
    /**
93
     * Returns a new instance with the specified prefix to the automatically generated widget IDs.
94
     *
95
     * @param string $value The prefix to the automatically generated widget IDs.
96
     *
97
     * @return self
98
     */
99 1
    public function autoIdPrefix(string $value): self
100
    {
101 1
        $new = clone $this;
102 1
        $new->autoIdPrefix = $value;
103 1
        return $new;
104
    }
105
106
    /**
107
     * Returns a new instance with the specified close button options.
108
     *
109
     * @param array $value The close button options.
110
     *
111
     * {@see Html::renderTagAttributes()} for details on how attributes are being rendered.
112
     *
113
     * @return self
114
     */
115 2
    public function closeButtonAttributes(array $value): self
116
    {
117 2
        $new = clone $this;
118 2
        $new->closeButtonAttributes = $value;
119
120 2
        return $new;
121
    }
122
123
    /**
124
     * Returns a new instance with the specified close button size.
125
     *
126
     * @param string $value The close button size. Default setting empty normal.
127
     * Possible values: Modal::SIZE_SMALL, Modal::SIZE_MEDIUM, Model::SIZE_LARGE.
128
     *
129
     * @return self
130
     */
131 3
    public function closeButtonSize(string $value): self
132
    {
133 3
        if (!in_array($value, self::SIZE_ALL, true)) {
134 1
            $values = implode('", "', self::SIZE_ALL);
135 1
            throw new InvalidArgumentException("Invalid size. Valid values are: \"$values\".");
136
        }
137
138 2
        $new = clone $this;
139 2
        $new->closeButtonSize = $value;
140
141 2
        return $new;
142
    }
143
144
    /**
145
     * Returns a new instance with the specified content options.
146
     *
147
     * @param array $value The content options.
148
     *
149
     * {@see Html::renderTagAttributes()} for details on how attributes are being rendered.
150
     *
151
     * @return self
152
     */
153 2
    public function contentAttributes(array $value): self
154
    {
155 2
        $new = clone $this;
156 2
        $new->contentAttributes = $value;
157
158 2
        return $new;
159
    }
160
161
    /**
162
     * Returns a new instance with the specified ID of the widget.
163
     *
164
     * @param string $value The ID of the widget.
165
     *
166
     * @return self
167
     */
168 1
    public function id(string $value): self
169
    {
170 1
        $new = clone $this;
171 1
        $new->attributes['id'] = $value;
172 1
        return $new;
173
    }
174
175
    /**
176
     * Returns a new instance with the specified modal background class.
177
     *
178
     * @param string $value The modal background class.
179
     *
180
     * @return self
181
     */
182 2
    public function backgroundClass(string $value): self
183
    {
184 2
        $new = clone $this;
185 2
        $new->backgroundClass = $value;
186
187 2
        return $new;
188
    }
189
190
    /**
191
     * Returns a new instance with the specified modal button class.
192
     *
193
     * @param string $value The modal button class.
194
     *
195
     * @return self
196
     */
197 2
    public function buttonClass(string $value): self
198
    {
199 2
        $new = clone $this;
200 2
        $new->buttonClass = $value;
201
202 2
        return $new;
203
    }
204
205
    /**
206
     * Returns a new instance with the specified modal class.
207
     *
208
     * @param string $value The modal class.
209
     *
210
     * @return self
211
     */
212 2
    public function modalClass(string $value): self
213
    {
214 2
        $new = clone $this;
215 2
        $new->modalClass = $value;
216
217 2
        return $new;
218
    }
219
220
    /**
221
     * Returns a new instance with the specified modal content class.
222
     *
223
     * @param string $value The modal content class.
224
     *
225
     * @return self
226
     */
227 2
    public function contentClass(string $value): self
228
    {
229 2
        $new = clone $this;
230 2
        $new->contentClass = $value;
231
232 2
        return $new;
233
    }
234
235
    /**
236
     * Returns a new instance with the specified toggle button options.
237
     *
238
     * @param array $values Attribute values indexed by attribute names.
239
     *
240
     * {@see Html::renderTagAttributes()} for details on how attributes are being rendered.
241
     *
242
     * @return self
243
     */
244 2
    public function toggleButtonAttributes(array $values): self
245
    {
246 2
        $new = clone $this;
247 2
        $new->toggleButtonAttributes = $values;
248
249 2
        return $new;
250
    }
251
252
    /**
253
     * Returns a new instance with the specified toggle button color.
254
     *
255
     * @param string $value The toggle button color. Default setting is empty without color.
256
     * Possible values: Modal::COLOR_PRIMARY, Modal::COLOR_LINK, Modal::COLOR_INFO, Modal::COLOR_SUCCESS,
257
     * Modal::COLOR_WARNING, Modal::COLOR_DANGER, Modal::COLOR_DARK.
258
     *
259
     * @return self
260
     */
261 3
    public function toggleButtonColor(string $value): self
262
    {
263 3
        if (!in_array($value, self::COLOR_ALL, true)) {
264 1
            $values = implode('", "', self::COLOR_ALL);
265 1
            throw new InvalidArgumentException("Invalid color. Valid values are: \"$values\".");
266
        }
267
268 2
        $new = clone $this;
269 2
        $new->toggleButtonColor = $value;
270
271 2
        return $new;
272
    }
273
274
    /**
275
     * Returns a new instance with the specified toggle button label.
276
     *
277
     * @param string $value The toggle button label.
278
     *
279
     * @return self
280
     */
281 2
    public function toggleButtonLabel(string $value): self
282
    {
283 2
        $new = clone $this;
284 2
        $new->toggleButtonLabel = $value;
285
286 2
        return $new;
287
    }
288
289
    /**
290
     * Returns a new instance with the specified toggle button size.
291
     *
292
     * @param string $value The toggle button size. Default setting empty normal.
293
     * Possible values: Modal::SIZE_SMALL, Modal::SIZE_MEDIUM, Model::SIZE_LARGE.
294
     *
295
     * @return self
296
     */
297 3
    public function toggleButtonSize(string $value): self
298
    {
299 3
        if (!in_array($value, self::SIZE_ALL, true)) {
300 1
            $values = implode('", "', self::SIZE_ALL);
301 1
            throw new InvalidArgumentException("Invalid size. Valid values are: \"$values\".");
302
        }
303
304 2
        $new = clone $this;
305 2
        $new->toggleButtonSize = $value;
306
307 2
        return $new;
308
    }
309
310
    /**
311
     * Returns a new instance with the specified options for rendering the close button tag.
312
     *
313
     * @param bool $value Whether the close button is disabled.
314
     *
315
     * @return self
316
     */
317 2
    public function withoutCloseButton(bool $value): self
318
    {
319 2
        $new = clone $this;
320 2
        $new->withoutCloseButton = $value;
321
322 2
        return $new;
323
    }
324
325
    /**
326
     * Returns a new instance with the disabled toggle button.
327
     *
328
     * @param bool $value Whether the toggle button is disabled.
329
     *
330
     * @return self
331
     */
332 2
    public function withoutToggleButton(bool $value): self
333
    {
334 2
        $new = clone $this;
335 2
        $new->withoutToggleButton = $value;
336
337 2
        return $new;
338
    }
339
340 15
    public function begin(): ?string
341
    {
342 15
        parent::begin();
343
344 15
        $attributes = $this->attributes;
345 15
        $contentAttributes = $this->contentAttributes;
346 15
        $html = '';
347
348 15
        if (!array_key_exists('id', $attributes)) {
349 15
            $attributes['id'] = Html::generateId($this->autoIdPrefix) . '-modal';
350
        }
351
352
        /** @var string */
353 15
        $id = $attributes['id'];
354
355 15
        Html::addCssClass($attributes, $this->modalClass);
356 15
        Html::addCssClass($contentAttributes, $this->contentClass);
357
358 15
        if ($this->withoutToggleButton === false) {
359 14
            $html .= $this->renderToggleButton($id) . "\n";
360
        }
361
362 15
        $html .= Html::openTag('div', $attributes) . "\n"; // .modal
363 15
        $html .= Div::tag()->class($this->backgroundClass) . "\n";
364
365 15
        if ($this->withoutCloseButton === false) {
366 14
            $html .= $this->renderCloseButton() . "\n";
367
        }
368
369 15
        $html .= Html::openTag('div', $contentAttributes) . "\n"; // .modal-content
370
371 15
        return $html;
372
    }
373
374 15
    protected function run(): string
375
    {
376 15
        $html = Html::closeTag('div') . "\n"; // .modal-content
377 15
        $html .= Html::closeTag('div'); // .modal
378
379 15
        return $html;
380
    }
381
382
    /**
383
     * Renders the toggle button.
384
     *
385
     * @param string $id
386
     *
387
     * @return string
388
     */
389 14
    private function renderToggleButton(string $id): string
390
    {
391 14
        $toggleButtonAttributes = $this->toggleButtonAttributes;
392
393 14
        $toggleButtonAttributes['data-target'] = '#' . $id;
394 14
        $toggleButtonAttributes['aria-haspopup'] = 'true';
395
396 14
        if ($this->toggleButtonSize !== '') {
397 1
            Html::addCssClass($toggleButtonAttributes, $this->toggleButtonSize);
398
        }
399
400 14
        if ($this->toggleButtonColor !== '') {
401 1
            Html::addCssClass($toggleButtonAttributes, $this->toggleButtonColor);
402
        }
403
404 14
        Html::addCssClass($toggleButtonAttributes, $this->buttonClass);
405
406 14
        return Button::tag()->attributes($toggleButtonAttributes)->content($this->toggleButtonLabel)->render();
407
    }
408
409
    /**
410
     * Renders the close button.
411
     *
412
     * @return string
413
     */
414 14
    private function renderCloseButton(): string
415
    {
416 14
        $closeButtonAttributes = $this->closeButtonAttributes;
417 14
        $closeButtonAttributes['aria-label'] = 'close';
418
419 14
        if ($this->closeButtonSize !== '') {
420 1
            Html::addCssClass($closeButtonAttributes, $this->closeButtonSize);
421
        }
422
423 14
        Html::addCssClass($closeButtonAttributes, $this->closeButtonClass);
424
425 14
        return Button::tag()->attributes($closeButtonAttributes)->render();
426
    }
427
}
428