Test Failed
Pull Request — master (#35)
by Wilmer
02:56 queued 44s
created

Alert::withBody()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 1
CRAP Score 1

Importance

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