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

Alert::withoutCloseButton()   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 0
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\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 = '';
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 $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
     * @return $this
91
     */
92 1
    public function withoutCloseButton(): self
93
    {
94 1
        $new = clone $this;
95 1
        $new->closeButtonEnabled = false;
96
97 1
        return $new;
98
    }
99
100
    /**
101
     * The HTML attributes for the widget container tag. The following special options are recognized.
102
     *
103
     * {@see Html::renderTagAttributes()} for details on how attributes are being rendered.
104
     *
105
     * @param array $value
106
     *
107
     * @return $this
108
     */
109 1
    public function withOptions(array $value): self
110
    {
111 1
        $new = clone $this;
112 1
        $new->options = $value;
113
114 1
        return $new;
115
    }
116
117
    /**
118
     * Allows you to enable or disable the encoding tags html.
119
     *
120
     * @return self
121
     */
122 1
    public function withEncodeTags(): self
123
    {
124 1
        $new = clone $this;
125 1
        $new->encodeTags = true;
126
127 1
        return $new;
128
    }
129
130
    /**
131
     * Renders the alert body and the close button (if any).
132
     *
133
     * @throws JsonException
134
     *
135
     * @return string the rendering result
136
     */
137 5
    private function renderBodyEnd(): string
138
    {
139 5
        return $this->body . "\n" . $this->renderCloseButton() . "\n";
140
    }
141
142
    /**
143
     * Renders the close button.
144
     *
145
     * @throws JsonException
146
     *
147
     * @return string the rendering result
148
     */
149 5
    private function renderCloseButton(): ?string
150
    {
151 5
        if ($this->closeButtonEnabled === false) {
152 1
            return null;
153
        }
154
155 4
        $tag = ArrayHelper::remove($this->closeButton, 'tag', 'button');
156 4
        $label = ArrayHelper::remove($this->closeButton, 'label', '');
157
158 4
        if ($tag === 'button' && !isset($this->closeButton['type'])) {
159 4
            $this->closeButton['type'] = 'button';
160
        }
161
162 4
        return Html::tag($tag, $label, $this->closeButton);
163
    }
164
165
    /**
166
     * Initializes the widget options.
167
     *
168
     * This method sets the default values for various options.
169
     */
170 5
    private function initOptions(): void
171
    {
172 5
        Html::addCssClass($this->options, ['widget' => 'alert']);
173
174 5
        if ($this->closeButtonEnabled !== false) {
175 4
            $this->closeButton = array_merge(
176 4
                $this->closeButton,
177
                [
178 4
                    'aria-label' => 'Close',
179
                    'data-bs-dismiss' => 'alert',
180
                ],
181
            );
182
183 4
            Html::addCssclass($this->closeButton, ['buttonOptions' => 'btn-close']);
184 4
            Html::addCssClass($this->options, ['alert-dismissible' => 'alert-dismissible']);
185
        }
186
187 5
        if ($this->encodeTags === false) {
188 4
            $this->closeButton = array_merge($this->closeButton, ['encode' => false]);
189 4
            $this->options = array_merge($this->options, ['encode' => false]);
190
        }
191
192 5
        if (!isset($this->options['role'])) {
193 5
            $this->options['role'] = 'alert';
194
        }
195 5
    }
196
}
197