Passed
Pull Request — master (#35)
by Wilmer
02:31
created

Alert::initOptions()   A

Complexity

Conditions 4
Paths 8

Size

Total Lines 24
Code Lines 13

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 13
CRAP Score 4

Importance

Changes 2
Bugs 0 Features 0
Metric Value
cc 4
eloc 13
c 2
b 0
f 0
nc 8
nop 0
dl 0
loc 24
ccs 13
cts 13
cp 1
crap 4
rs 9.8333
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Yiisoft\Yii\Bootstrap5;
6
7
use JsonException;
8
use Yiisoft\Arrays\ArrayHelper;
9
use Yiisoft\Html\Html;
10
11
/**
12
 * Alert renders an alert bootstrap component.
13
 *
14
 * For example,
15
 *
16
 * ```php
17
 * echo Alert::widget()
18
 *     ->withOptions([
19
 *         'class' => 'alert-info',
20
 *     ])
21
 *     ->withBody('Say hello...');
22
 * ```
23
 */
24
final class Alert extends Widget
25
{
26
    private ?string $body = null;
27
    private array $closeButton = [];
28
    private bool $closeButtonEnabled = true;
29
    private bool $encodeTags = false;
30
    private array $options = [];
31
32 5
    protected function run(): string
33
    {
34 5
        if (!isset($this->options['id'])) {
35 5
            $this->options['id'] = "{$this->getId()}-alert";
36
        }
37
38 5
        $this->initOptions();
39
40 5
        return Html::div($this->renderBodyEnd(), $this->options);
41
    }
42
43
    /**
44
     * The body content in the alert component. Alert widget will also be treated as the body content, and will be
45
     * rendered before this.
46
     *
47
     * @param string|null $value
48
     *
49
     * @return $this
50
     */
51 5
    public function withBody(?string $value): self
52
    {
53 5
        $new = clone $this;
54 5
        $new->body = $value;
55
56 5
        return $new;
57
    }
58
59
    /**
60
     * The options for rendering the close button tag.
61
     *
62
     * The close button is displayed in the header of the modal window. Clicking on the button will hide the modal
63
     * window. If {@see closeButtonEnabled} is false, no close button will be rendered.
64
     *
65
     * The following special options are supported:
66
     *
67
     * - tag: string, the tag name of the button. Defaults to 'button'.
68
     * - label: string, the label of the button. Defaults to '&times;'.
69
     *
70
     * The rest of the options will be rendered as the HTML attributes of the button tag.
71
     *
72
     * Please refer to the [Alert documentation](http://getbootstrap.com/components/#alerts) for the supported HTML
73
     * attributes.
74
     *
75
     * @param array $value
76
     *
77
     * @return $this
78
     */
79 1
    public function withCloseButton(array $value): self
80
    {
81 1
        $new = clone $this;
82 1
        $new->closeButton = $value;
83
84 1
        return $new;
85
    }
86
87
    /**
88
     * Disable close button.
89
     *
90
     * @param bool $value
91
     *
92
     * @return $this
93
     */
94 1
    public function withoutCloseButton(bool $value = false): self
95
    {
96 1
        $new = clone $this;
97 1
        $new->closeButtonEnabled = $value;
98
99 1
        return $new;
100
    }
101
102
    /**
103
     * The HTML attributes for the widget container tag. The following special options are recognized.
104
     *
105
     * {@see Html::renderTagAttributes()} for details on how attributes are being rendered.
106
     *
107
     * @param array $value
108
     *
109
     * @return $this
110
     */
111 1
    public function withOptions(array $value): self
112
    {
113 1
        $new = clone $this;
114 1
        $new->options = $value;
115
116 1
        return $new;
117
    }
118
119
    /**
120
     * Allows you to enable or disable the encoding tags html.
121
     *
122
     * @param bool $value
123
     *
124
     * @return self
125
     */
126 1
    public function withEncodeTags(bool $value = true): self
127
    {
128 1
        $new = clone $this;
129 1
        $new->encodeTags = $value;
130
131 1
        return $new;
132
    }
133
134
    /**
135
     * Renders the alert body and the close button (if any).
136
     *
137
     * @throws JsonException
138
     *
139
     * @return string the rendering result
140
     */
141 5
    private function renderBodyEnd(): string
142
    {
143 5
        return $this->body . "\n" . $this->renderCloseButton() . "\n";
144
    }
145
146
    /**
147
     * Renders the close button.
148
     *
149
     * @throws JsonException
150
     *
151
     * @return string the rendering result
152
     */
153 5
    private function renderCloseButton(): ?string
154
    {
155 5
        if ($this->closeButtonEnabled === false) {
156 1
            return null;
157
        }
158
159 4
        $tag = ArrayHelper::remove($this->closeButton, 'tag', 'button');
160 4
        $label = ArrayHelper::remove($this->closeButton, 'label', '');
161
162 4
        if ($tag === 'button' && !isset($this->closeButton['type'])) {
163 4
            $this->closeButton['type'] = 'button';
164
        }
165
166 4
        return Html::tag($tag, $label, $this->closeButton);
167
    }
168
169
    /**
170
     * Initializes the widget options.
171
     *
172
     * This method sets the default values for various options.
173
     */
174 5
    private function initOptions(): void
175
    {
176 5
        Html::addCssClass($this->options, ['widget' => 'alert']);
177
178 5
        if ($this->closeButtonEnabled !== false) {
179 4
            $this->closeButton = array_merge(
180 4
                $this->closeButton,
181
                [
182 4
                    'aria-label' => 'Close',
183
                    'data-bs-dismiss' => 'alert',
184
                ],
185
            );
186
187 4
            Html::addCssclass($this->closeButton, ['buttonOptions' => 'btn-close']);
188 4
            Html::addCssClass($this->options, ['alert-dismissible' => 'alert-dismissible']);
189
        }
190
191 5
        if ($this->encodeTags === false) {
192 4
            $this->closeButton = array_merge($this->closeButton, ['encode' => false]);
193 4
            $this->options = array_merge($this->options, ['encode' => false]);
194
        }
195
196 5
        if (!isset($this->options['role'])) {
197 5
            $this->options['role'] = 'alert';
198
        }
199 5
    }
200
}
201