Passed
Push — master ( 34e66c...44dbec )
by Sergei
03:09
created

Toast   A

Complexity

Total Complexity 19

Size/Duplication

Total Lines 199
Duplicated Lines 0 %

Test Coverage

Coverage 100%

Importance

Changes 4
Bugs 2 Features 0
Metric Value
eloc 66
dl 0
loc 199
ccs 70
cts 70
cp 1
rs 10
c 4
b 2
f 0
wmc 19

15 Methods

Rating   Name   Duplication   Size   Complexity  
A headerOptions() 0 6 1
A renderBodyBegin() 0 4 1
A getId() 0 3 1
A initOptions() 0 13 4
A bodyOptions() 0 6 1
A dateTime() 0 6 1
A title() 0 6 1
A render() 0 3 1
A titleOptions() 0 6 1
A begin() 0 10 1
A options() 0 6 1
A toggleComponent() 0 3 1
A renderHeader() 0 20 2
A dateTimeOptions() 0 6 1
A renderBodyEnd() 0 3 1
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
 * Toasts renders a toast bootstrap widget.
13
 *
14
 * For example,
15
 *
16
 * ```php
17
 * echo Toast::widget()
18
 *     ->title('Hello world!')
19
 *     ->dateTime('a minute ago')
20
 *     ->body('Say hello...')
21
 *     ->begin();
22
 * ```
23
 *
24
 * The following example will show the content enclosed between the {@see begin()}
25
 * and {@see end()} calls within the toast box:
26
 *
27
 * ```php
28
 * echo Toast::widget()
29
 *     ->title('Hello world!')
30
 *     ->dateTime('a minute ago')
31
 *     ->begin();
32
 *
33
 * echo 'Say hello...';
34
 *
35
 * echo Toast::end();
36
 * ```
37
 *
38
 * @see https://getbootstrap.com/docs/5.0/components/toasts/
39
 */
40
final class Toast extends Widget
41
{
42
    use CloseButtonTrait;
43
44
    private string $body = '';
45
    private string $title = '';
46
    private string $dateTime = '';
47
    private array $titleOptions = [];
48
    private array $dateTimeOptions = [];
49
    private array $headerOptions = [];
50
    private array $bodyOptions = [];
51
    private array $options = [];
52
    private bool $encodeTags = false;
53
54 7
    public function getId(?string $suffix = '-toast'): ?string
55
    {
56 7
        return $this->options['id'] ?? parent::getId($suffix);
0 ignored issues
show
Unused Code introduced by
The call to Yiisoft\Yii\Bootstrap5\CloseButtonTrait::getId() has too many arguments starting with $suffix. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

56
        return $this->options['id'] ?? parent::/** @scrutinizer ignore-call */ getId($suffix);

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress. Please note the @ignore annotation hint above.

Loading history...
57
    }
58
59 7
    protected function toggleComponent(): string
60
    {
61 7
        return 'toast';
62
    }
63
64 7
    public function begin(): string
65
    {
66 7
        parent::begin();
67
68 7
        $this->initOptions();
69
70 7
        return
71 7
            Html::openTag('div', $this->options) . "\n" .
72 7
            $this->renderHeader() . "\n" .
73 7
            $this->renderBodyBegin();
74
    }
75
76 7
    public function render(): string
77
    {
78 7
        return $this->renderBodyEnd() . Html::closeTag('div');
79
    }
80
81
    /**
82
     * {@see Html::renderTagAttributes()} for details on how attributes are being rendered.
83
     *
84
     * @param array $value Body options.
85
     */
86 1
    public function bodyOptions(array $value): self
87
    {
88 1
        $new = clone $this;
89 1
        $new->bodyOptions = $value;
90
91 1
        return $new;
92
    }
93
94
    /**
95
     * The date/time content in the toast window.
96
     */
97 2
    public function dateTime(string $value): self
98
    {
99 2
        $new = clone $this;
100 2
        $new->dateTime = $value;
101
102 2
        return $new;
103
    }
104
105
    /**
106
     * Additional DateTime options.
107
     *
108
     * {@see Html::renderTagAttributes()} for details on how attributes are being rendered.
109
     */
110 1
    public function dateTimeOptions(array $value): self
111
    {
112 1
        $new = clone $this;
113 1
        $new->dateTimeOptions = $value;
114
115 1
        return $new;
116
    }
117
118
    /**
119
     * Additional header options.
120
     *
121
     * {@see Html::renderTagAttributes()} for details on how attributes are being rendered.
122
     */
123 2
    public function headerOptions(array $value): self
124
    {
125 2
        $new = clone $this;
126 2
        $new->headerOptions = $value;
127
128 2
        return $new;
129
    }
130
131
    /**
132
     * @param array $value the HTML attributes for the widget container tag. The following special options are
133
     * recognized.
134
     *
135
     * {@see Html::renderTagAttributes()} for details on how attributes are being rendered.
136
     */
137 1
    public function options(array $value): self
138
    {
139 1
        $new = clone $this;
140 1
        $new->options = $value;
141
142 1
        return $new;
143
    }
144
145
    /**
146
     * The title content in the toast window.
147
     */
148 6
    public function title(string $value): self
149
    {
150 6
        $new = clone $this;
151 6
        $new->title = $value;
152
153 6
        return $new;
154
    }
155
156
    /**
157
     * Additional title options.
158
     *
159
     * {@see Html::renderTagAttributes()} for details on how attributes are being rendered.
160
     */
161 3
    public function titleOptions(array $value): self
162
    {
163 3
        $new = clone $this;
164 3
        $new->titleOptions = $value;
165
166 3
        return $new;
167
    }
168
169
    /**
170
     * Renders the header HTML markup of the toast.
171
     *
172
     * @throws JsonException
173
     *
174
     * @return string the rendering result
175
     */
176 7
    private function renderHeader(): string
177
    {
178 7
        $button = $this->renderCloseButton(true);
179 7
        $tag = ArrayHelper::remove($this->titleOptions, 'tag', 'strong');
180 7
        Html::addCssClass($this->titleOptions, ['widget' => 'me-auto']);
181 7
        $title = Html::tag($tag, $this->title, $this->titleOptions)
182 7
            ->encode($this->encodeTags)
183 7
            ->render();
184
185 7
        if ($this->dateTime !== '') {
186 2
            $tag = ArrayHelper::remove($this->dateTimeOptions, 'tag', 'small');
187 2
            $title .= "\n" . Html::tag($tag, $this->dateTime, $this->dateTimeOptions)->encode($this->encodeTags);
188
        }
189
190 7
        $title .= "\n" . $button;
191
192 7
        Html::addCssClass($this->headerOptions, ['widget' => 'toast-header']);
193 7
        return Html::div("\n" . $title . "\n", $this->headerOptions)
194 7
            ->encode($this->encodeTags)
195 7
            ->render();
196
    }
197
198
    /**
199
     * Renders the opening tag of the toast body.
200
     *
201
     * @throws JsonException
202
     *
203
     * @return string the rendering result
204
     */
205 7
    private function renderBodyBegin(): string
206
    {
207 7
        Html::addCssClass($this->bodyOptions, ['widget' => 'toast-body']);
208 7
        return Html::openTag('div', $this->bodyOptions);
209
    }
210
211
    /**
212
     * Renders the closing tag of the toast body.
213
     *
214
     * @return string the rendering result
215
     */
216 7
    private function renderBodyEnd(): string
217
    {
218 7
        return $this->body . "\n" . Html::closeTag('div');
219
    }
220
221
    /**
222
     * Initializes the widget options.
223
     *
224
     * This method sets the default values for various options.
225
     */
226 7
    private function initOptions(): void
227
    {
228 7
        $this->options['id'] = $this->getId();
229 7
        Html::addCssClass($this->options, ['widget' => 'toast']);
230
231 7
        if (!isset($this->options['role'])) {
232 7
            $this->options['role'] = 'alert';
233
        }
234
235 7
        if (!isset($this->options['aria']) && !isset($this->options['aria-live'])) {
236 7
            $this->options['aria'] = [
237 7
                'live' => 'assertive',
238 7
                'atomic' => 'true',
239 7
            ];
240
        }
241
    }
242
}
243