Passed
Branch master (fbd372)
by Wilmer
02:37
created

Message::bodyCssClass()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
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 1
dl 0
loc 5
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\Bulma;
6
7
use InvalidArgumentException;
8
use Yiisoft\Html\Html;
9
use Yiisoft\Html\Tag\Button;
10
use Yiisoft\Html\Tag\Div;
11
use Yiisoft\Html\Tag\P;
12
use Yiisoft\Html\Tag\Span;
13
use Yiisoft\Widget\Widget;
14
15
/**
16
 * Message renders Bulma message component.
17
 *
18
 * For example,
19
 *
20
 * ```php
21
 * <?= Message::widget()->headerColor('success')->header('System info')->body('Say hello...') ?>
22
 * ```
23
 *
24
 * @link https://bulma.io/documentation/components/message/
25
 */
26
final class Message extends Widget
27
{
28
    public const SIZE_SMALL = 'is-small';
29
    public const SIZE_MEDIUM = 'is-medium';
30
    public const SIZE_LARGE = 'is-large';
31
    private const SIZE_ALL = [
32
        self::SIZE_SMALL,
33
        self::SIZE_MEDIUM,
34
        self::SIZE_LARGE,
35
    ];
36
    public const COLOR_PRIMARY = 'is-primary';
37
    public const COLOR_LINK = 'is-link';
38
    public const COLOR_INFO = 'is-info';
39
    public const COLOR_SUCCESS = 'is-success';
40
    public const COLOR_WARNING = 'is-warning';
41
    public const COLOR_DANGER = 'is-danger';
42
    public const COLOR_DARK = 'is-dark';
43
    private const COLOR_ALL = [
44
        self::COLOR_PRIMARY,
45
        self::COLOR_LINK,
46
        self::COLOR_INFO,
47
        self::COLOR_SUCCESS,
48
        self::COLOR_WARNING,
49
        self::COLOR_DANGER,
50
        self::COLOR_DARK,
51
    ];
52
    private array $attributes = [];
53
    private string $autoIdPrefix = 'w';
54
    private string $body = '';
55
    private array $bodyAttributes = [];
56
    private string $bodyCssClass = 'message-body';
57
    private array $buttonSpanAttributes = [];
58
    private string $buttonSpanAriaHidden = 'true';
59
    private string $buttonCssClass = 'delete';
60
    private string $cssClass = 'message';
61
    private bool $closedButton = false;
62
    private array $closeButtonAttributes = [];
63
    private bool $encode = false;
64
    private array $headerAttributes = [];
65
    private string $headerColor = self::COLOR_DARK;
66
    private string $headerMessage = '';
67
    private string $headerMessageCssClass = 'message-header';
68
    private string $size = '';
69
    private bool $withoutHeader = false;
70
71
    /**
72
     * The HTML attributes.
73
     *
74
     * @param array $values Attribute values indexed by attribute names.
75
     *
76
     * @return self
77
     *
78
     * {@see \Yiisoft\Html\Html::renderTagAttributes()} For details on how attributes are being rendered.
79
     */
80 2
    public function attributes(array $values): self
81
    {
82 2
        $new = clone $this;
83 2
        $new->attributes = $values;
84 2
        return $new;
85
    }
86
87
    /**
88
     * Returns a new instance with the specified prefix to the automatically generated widget IDs.
89
     *
90
     * @param string $value The prefix to the automatically generated widget IDs.
91
     *
92
     * @return self
93
     */
94 1
    public function autoIdPrefix(string $value): self
95
    {
96 1
        $new = clone $this;
97 1
        $new->autoIdPrefix = $value;
98 1
        return $new;
99
    }
100
101
    /**
102
     * The body content.
103
     *
104
     * @param string $value The body content.
105
     *
106
     * @return self
107
     */
108 12
    public function body(string $value): self
109
    {
110 12
        $new = clone $this;
111 12
        $new->body = $value;
112 12
        return $new;
113
    }
114
115
    /**
116
     * The HTML attributes for the widget body tag.
117
     *
118
     * @param array $values Attribute values indexed by attribute names.
119
     *
120
     * @return self
121
     *
122
     * {@see Html::renderTagAttributes()} for details on how attributes are being rendered.
123
     */
124 2
    public function bodyAttributes(array $values): self
125
    {
126 2
        $new = clone $this;
127 2
        $new->bodyAttributes = $values;
128 2
        return $new;
129
    }
130
131
    /**
132
     * The CSS class for the body container.
133
     *
134
     * @param string $value The CSS class for the body container.
135
     *
136
     * @return self
137
     */
138 1
    public function bodyCssClass(string $value): self
139
    {
140 1
        $new = clone $this;
141 1
        $new->bodyCssClass = $value;
142 1
        return $new;
143
    }
144
145
    /**
146
     * The attributes for rendering the close button tag.
147
     *
148
     * The close button is displayed in the header of the Message. Clicking on the button will hide the message.
149
     *
150
     * @param array $values Attribute values indexed by attribute names.
151
     *
152
     * @return self
153
     *
154
     * {@see Html::renderTagAttributes()} For details on how attributes are being rendered.
155
     */
156 2
    public function closeButtonAttributes(array $values): self
157
    {
158 2
        $new = clone $this;
159 2
        $new->closeButtonAttributes = $values;
160 2
        return $new;
161
    }
162
163
    /**
164
     * Set encode to true to encode the output.
165
     *
166
     * @param bool $value whether to encode the output.
167
     *
168
     * @return self
169
     */
170 1
    public function encode(bool $value): self
171
    {
172 1
        $new = clone $this;
173 1
        $new->encode = $value;
174 1
        return $new;
175
    }
176
177
    /**
178
     * The HTML attributes for the widget header tag.
179
     *
180
     * @param array $values Attribute values indexed by attribute names.
181
     *
182
     * @return self
183
     *
184
     * {@see Html::renderTagAttributes()} For details on how attributes are being rendered.
185
     */
186 2
    public function headerAttributes(array $values): self
187
    {
188 2
        $new = clone $this;
189 2
        $new->headerAttributes = $values;
190 2
        return $new;
191
    }
192
193
    /**
194
     * Set message header color.
195
     *
196
     * @param string $value The header color. Default is Message::COLOR_DARK.
197
     * Possible values: Message::COLOR_PRIMARY, Message::COLOR_LINK, Message::COLOR_INFO, Message::COLOR_SUCCESS,
198
     * Message::COLOR_WARNING, Message::COLOR_DANGER, Message::COLOR_DARK.
199
     *
200
     * @return self
201
     *
202
     * @link https://bulma.io/documentation/components/message/#colors
203
     */
204 3
    public function headerColor(string $value): self
205
    {
206 3
        if (!in_array($value, self::COLOR_ALL, true)) {
207 1
            $values = implode('", "', self::COLOR_ALL);
208 1
            throw new InvalidArgumentException("Invalid color. Valid values are: \"$values\".");
209
        }
210
211 2
        $new = clone $this;
212 2
        $new->headerColor = $value;
213 2
        return $new;
214
    }
215
216
    /**
217
     * The header message.
218
     *
219
     * @param string $value The header message.
220
     *
221
     * @return self
222
     */
223 12
    public function headerMessage(string $value): self
224
    {
225 12
        $new = clone $this;
226 12
        $new->headerMessage = $value;
227 12
        return $new;
228
    }
229
230
    /**
231
     * Returns a new instance with the specified ID of the widget.
232
     *
233
     * @param string $value The ID of the widget.
234
     *
235
     * @return self
236
     */
237 2
    public function id(string $value): self
238
    {
239 2
        $new = clone $this;
240 2
        $new->attributes['id'] = $value;
241 2
        return $new;
242
    }
243
244
    /**
245
     * Set size.
246
     *
247
     * @param string $value size class. By default, not class is added and the size is considered "normal".
248
     * Possible values: Message::SIZE_SMALL, Message::SIZE_MEDIUM, Message::SIZE_LARGE.
249
     *
250
     * @return self
251
     *
252
     * @link https://bulma.io/documentation/components/message/#sizes
253
     */
254 3
    public function size(string $value): self
255
    {
256 3
        if (!in_array($value, self::SIZE_ALL, true)) {
257 1
            $values = implode('", "', self::SIZE_ALL);
258 1
            throw new InvalidArgumentException("Invalid size. Valid values are: \"$values\".");
259
        }
260
261 2
        $new = clone $this;
262 2
        $new->size = $value;
263 2
        return $new;
264
    }
265
266
    /**
267
     * Allows you to remove the close button.
268
     *
269
     * @param bool $value Whether to remove the close button.
270
     *
271
     * @return self
272
     */
273 2
    public function withoutCloseButton(bool $value): self
274
    {
275 2
        $new = clone $this;
276 2
        $new->closedButton = $value;
277 2
        return $new;
278
    }
279
280
    /**
281
     * Allows you to disable header.
282
     *
283
     * @param bool $value Whether to disable header.
284
     *
285
     * @return self
286
     *
287
     * @link https://bulma.io/documentation/components/message/#message-body-only
288
     */
289 2
    public function withoutHeader(bool $value): self
290
    {
291 2
        $new = clone $this;
292 2
        $new->withoutHeader = $value;
293 2
        return $new;
294
    }
295
296 11
    protected function run(): string
297
    {
298 11
        return $this->renderMessage();
299
    }
300
301 11
    private function renderCloseButton(): string
302
    {
303 11
        $html = '';
304
305 11
        $buttonSpanAttributes = $this->buttonSpanAttributes;
306 11
        $closeButtonAttributes = $this->closeButtonAttributes;
307
308 11
        if ($this->closedButton === true) {
309 1
            return $html;
310
        }
311
312 10
        $buttonSpanAttributes['aria-hidden'] = $this->buttonSpanAriaHidden;
313 10
        $closeButtonAttributes['type'] = 'button';
314
315 10
        Html::addCssClass($closeButtonAttributes, $this->buttonCssClass);
316 10
        unset($closeButtonAttributes['label']);
317
318 10
        $label = Span::tag()->attributes($buttonSpanAttributes)->content('&times;')->encode(false)->render();
319
320 10
        if ($this->size !== '') {
321 1
            Html::addCssClass($closeButtonAttributes, $this->size);
322
        }
323
324 10
        return Button::tag()->attributes($closeButtonAttributes)->content($label)->encode(false)->render() . PHP_EOL;
325
    }
326
327 11
    private function renderHeader(): string
328
    {
329 11
        $html = '';
330
331 11
        $headerAttributes = $this->headerAttributes;
332 11
        $headerMessage = $this->headerMessage;
333
334 11
        Html::addCssClass($headerAttributes, $this->headerMessageCssClass);
335
336 11
        $renderCloseButton = $this->renderCloseButton();
337
338 11
        if ($this->encode) {
339 1
            $headerMessage = Html::encode($headerMessage);
340
        }
341
342 11
        if ($renderCloseButton !== '') {
343 10
            $headerMessage = PHP_EOL . P::tag()->content($headerMessage) . PHP_EOL . $renderCloseButton;
344
        }
345
346 11
        if ($this->withoutHeader === false) {
347 10
            $html = Div::tag()
348 10
                ->attributes($headerAttributes)
349 10
                ->content($headerMessage)
350 10
                ->encode(false)
351 10
                ->render() . PHP_EOL;
352
        }
353
354 11
        return $html;
355
    }
356
357 11
    private function renderMessage(): string
358
    {
359 11
        $attributes = $this->attributes;
360
361
        /** @var string */
362 11
        $id = $attributes['id'] ?? (Html::generateId($this->autoIdPrefix) . '-message');
363 11
        unset($attributes['id']);
364
365 11
        Html::addCssClass($attributes, $this->cssClass);
366 11
        Html::addCssClass($attributes, $this->headerColor);
367
368 11
        if ($this->size !== '') {
369 1
            Html::addCssClass($attributes, $this->size);
370
        }
371
372 11
        return Div::tag()
373 11
            ->attributes($attributes)
374 11
            ->content(PHP_EOL . $this->renderHeader() . $this->renderMessageBody())
375 11
            ->encode(false)
376 11
            ->id($id)
377 11
            ->render();
378
    }
379
380 11
    private function renderMessageBody(): string
381
    {
382 11
        $body = $this->body;
383 11
        $bodyAttributes = $this->bodyAttributes;
384
385 11
        Html::addCssClass($bodyAttributes, $this->bodyCssClass);
386
387 11
        if ($this->encode) {
388 1
            $body = Html::encode($body);
389
        }
390
391 11
        if ($body !== '') {
392 11
            $body = PHP_EOL . $body . PHP_EOL;
393
        }
394
395 11
        return Div::tag()->attributes($bodyAttributes)->content($body)->encode(false)->render() . PHP_EOL;
396
    }
397
}
398