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

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