Passed
Pull Request — master (#56)
by Wilmer
02:08
created

Message::bodyAttributes()   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;
0 ignored issues
show
Bug introduced by
This use statement conflicts with another class in this namespace, Yiisoft\Yii\Bulma\Widget. Consider defining an alias.

Let?s assume that you have a directory layout like this:

.
|-- OtherDir
|   |-- Bar.php
|   `-- Foo.php
`-- SomeDir
    `-- Foo.php

and let?s assume the following content of Bar.php:

// Bar.php
namespace OtherDir;

use SomeDir\Foo; // This now conflicts the class OtherDir\Foo

If both files OtherDir/Foo.php and SomeDir/Foo.php are loaded in the same runtime, you will see a PHP error such as the following:

PHP Fatal error:  Cannot use SomeDir\Foo as Foo because the name is already in use in OtherDir/Foo.php

However, as OtherDir/Foo.php does not necessarily have to be loaded and the error is only triggered if it is loaded before OtherDir/Bar.php, this problem might go unnoticed for a while. In order to prevent this error from surfacing, you must import the namespace with a different alias:

// Bar.php
namespace OtherDir;

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