Passed
Push — master ( 566566...d0f53d )
by Alexander
02:18
created

Alert::renderCloseButton()   A

Complexity

Conditions 4
Paths 3

Size

Total Lines 14
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 8
CRAP Score 4

Importance

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