Passed
Push — master ( e80b4e...741461 )
by Alexander
02:19
created

Modal::renderCloseButton()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 7
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 4
CRAP Score 2

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 2
eloc 3
c 1
b 0
f 0
nc 2
nop 0
dl 0
loc 7
ccs 4
cts 4
cp 1
crap 2
rs 10
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Yiisoft\Yii\Bulma;
6
7
use InvalidArgumentException;
8
use JsonException;
9
use Yiisoft\Html\Html;
10
11
/**
12
 * Modal renders a modal window that can be toggled by clicking on a button.
13
 *
14
 * The following example will show the content enclosed between the {@see begin()} and {@see end()} calls within the
15
 * modal window:
16
 *
17
 * ```php
18
 * echo Modal::widget()->begin();
19
 *
20
 * echo 'Say hello...';
21
 *
22
 * echo Modal::end();
23
 * ```
24
 *
25
 * @link https://bulma.io/documentation/components/modal/
26
 */
27
final class Modal extends Widget
28
{
29
    public const SIZE_SMALL = 'is-small';
30
    public const SIZE_MEDIUM = 'is-medium';
31
    public const SIZE_LARGE = 'is-large';
32
    private const SIZE_ALL = [
33
        self::SIZE_SMALL,
34
        self::SIZE_MEDIUM,
35
        self::SIZE_LARGE,
36
    ];
37
38
    public const COLOR_PRIMARY = 'is-primary';
39
    public const COLOR_LINK = 'is-link';
40
    public const COLOR_INFO = 'is-info';
41
    public const COLOR_SUCCESS = 'is-success';
42
    public const COLOR_WARNING = 'is-warning';
43
    public const COLOR_DANGER = 'is-danger';
44
    private const COLOR_ALL = [
45
        self::COLOR_PRIMARY,
46
        self::COLOR_LINK,
47
        self::COLOR_INFO,
48
        self::COLOR_SUCCESS,
49
        self::COLOR_WARNING,
50
        self::COLOR_DANGER,
51
    ];
52
53
    private array $options = [];
54
    private array $contentOptions = [];
55
    private array $closeButtonOptions = [];
56
    private string $closeButtonSize = '';
57
    private bool $withoutCloseButton = true;
58
    private string $toggleButtonLabel = 'Toggle button';
59
    private string $toggleButtonSize = '';
60
    private string $toggleButtonColor = '';
61
    private array $toggleButtonOptions = [];
62
    private bool $withoutToggleButton = true;
63
64 11
    public function begin(): ?string
65
    {
66 11
        parent::begin();
67
68 11
        $this->buildOptions();
69
70 11
        $html = '';
71 11
        $html .= $this->renderToggleButton() . "\n";
72 11
        $html .= Html::beginTag('div', $this->options) . "\n"; // .modal
73 11
        $html .= Html::tag('div', '', ['class' => 'modal-background']) . "\n";
74 11
        $html .= $this->renderCloseButton() . "\n";
75 11
        $html .= Html::beginTag('div', $this->contentOptions) . "\n"; // .modal-content
76
77 11
        return $html;
78
    }
79
80 11
    protected function run(): string
81
    {
82 11
        $html = '';
83 11
        $html .= Html::endTag('div') . "\n"; // .modal-content
84 11
        $html .= Html::endTag('div'); // .modal
85
86 11
        return $html;
87
    }
88
89
    /**
90
     * Main container options.
91
     *
92
     * {@see Html::renderTagAttributes()} for details on how attributes are being rendered.
93
     *
94
     * @param array $value
95
     *
96
     * @return self
97
     */
98 1
    public function options(array $value): self
99
    {
100 1
        $new = clone $this;
101 1
        $new->options = $value;
102
103 1
        return $new;
104
    }
105
106
    /**
107
     * Toggle button label.
108
     *
109
     * @param string $value
110
     *
111
     * @return self
112
     */
113 1
    public function toggleButtonLabel(string $value): self
114
    {
115 1
        $new = clone $this;
116 1
        $new->toggleButtonLabel = $value;
117
118 1
        return $new;
119
    }
120
121
    /**
122
     * Toggle button options.
123
     *
124
     * {@see Html::renderTagAttributes()} for details on how attributes are being rendered.
125
     *
126
     * @param array $value
127
     *
128
     * @return self
129
     */
130 1
    public function toggleButtonOptions(array $value): self
131
    {
132 1
        $new = clone $this;
133 1
        $new->toggleButtonOptions = $value;
134
135 1
        return $new;
136
    }
137
138
    /**
139
     * Toggle button size.
140
     *
141
     * @param string $value
142
     *
143
     * @return self
144
     */
145 2
    public function toggleButtonSize(string $value): self
146
    {
147 2
        if (!in_array($value, self::SIZE_ALL)) {
148 1
            $values = implode('", "', self::SIZE_ALL);
149 1
            throw new InvalidArgumentException("Invalid size. Valid values are: \"$values\".");
150
        }
151
152 1
        $new = clone $this;
153 1
        $new->toggleButtonSize = $value;
154
155 1
        return $new;
156
    }
157
158
    /**
159
     * Toggle button color.
160
     *
161
     * @param string $value
162
     *
163
     * @return self
164
     */
165 2
    public function toggleButtonColor(string $value): self
166
    {
167 2
        if (!in_array($value, self::COLOR_ALL)) {
168 1
            $values = implode('", "', self::COLOR_ALL);
169 1
            throw new InvalidArgumentException("Invalid color. Valid values are: \"$values\".");
170
        }
171
172 1
        $new = clone $this;
173 1
        $new->toggleButtonColor = $value;
174
175 1
        return $new;
176
    }
177
178
    /**
179
     * Disable toggle button.
180
     *
181
     * @return self
182
     */
183 3
    public function withoutToggleButton(): self
184
    {
185 3
        $new = clone $this;
186 3
        $new->withoutToggleButton = false;
187
188 3
        return $new;
189
    }
190
191
    /**
192
     * Close button size.
193
     *
194
     * @param string $value
195
     *
196
     * @return self
197
     */
198 2
    public function closeButtonSize(string $value): self
199
    {
200 2
        if (!in_array($value, self::SIZE_ALL)) {
201 1
            $values = implode('"', self::SIZE_ALL);
202 1
            throw new InvalidArgumentException("Invalid size. Valid values are: \"$values\".");
203
        }
204
205 1
        $new = clone $this;
206 1
        $new->closeButtonSize = $value;
207
208 1
        return $new;
209
    }
210
211
    /**
212
     * Close button options
213
     *
214
     * {@see Html::renderTagAttributes()} for details on how attributes are being rendered.
215
     *
216
     * @param array $value
217
     *
218
     * @return self
219
     */
220 1
    public function closeButtonOptions(array $value): self
221
    {
222 1
        $new = clone $this;
223 1
        $new->closeButtonOptions = $value;
224
225 1
        return $new;
226
    }
227
228
    /**
229
     * Disable close button.
230
     *
231
     * @param bool $value
232
     *
233
     * @return self
234
     */
235 4
    public function withoutCloseButton(): self
236
    {
237 4
        $new = clone $this;
238 4
        $new->withoutCloseButton = false;
239
240 4
        return $new;
241
    }
242
243
    /**
244
     * Content options.
245
     *
246
     * {@see Html::renderTagAttributes()} for details on how attributes are being rendered.
247
     *
248
     * @param array $value
249
     *
250
     * @return self
251
     */
252 1
    public function contentOptions(array $value): self
253
    {
254 1
        $new = clone $this;
255 1
        $new->contentOptions = $value;
256
257 1
        return $new;
258
    }
259
260
    /**
261
     * Renders the toggle button.
262
     *
263
     * @throws JsonException
264
     *
265
     * @return string
266
     */
267 11
    private function renderToggleButton(): string
268
    {
269 11
        if ($this->withoutToggleButton) {
270 8
            return Html::button($this->toggleButtonLabel, $this->toggleButtonOptions);
271
        }
272
273 3
        return '';
274
    }
275
276
    /**
277
     * Renders the close button.
278
     *
279
     * @throws JsonException
280
     *
281
     * @return string
282
     */
283 11
    private function renderCloseButton(): string
284
    {
285 11
        if ($this->withoutCloseButton) {
286 7
            return Html::button('', $this->closeButtonOptions);
287
        }
288
289 4
        return '';
290
    }
291
292 11
    private function buildOptions(): void
293
    {
294 11
        $this->options['id'] ??= "{$this->getId()}-modal";
295 11
        $this->options = $this->addOptions($this->options, 'modal');
296
297 11
        $this->contentOptions = $this->addOptions($this->contentOptions, 'modal-content');
298
299 11
        $this->closeButtonOptions = $this->addOptions($this->closeButtonOptions, 'modal-close');
300 11
        $this->closeButtonOptions['aria-label'] = 'close';
301
302 11
        if ($this->closeButtonSize !== '') {
303 1
            Html::addCssClass($this->closeButtonOptions, $this->closeButtonSize);
304
        }
305
306 11
        $this->toggleButtonOptions = $this->addOptions($this->toggleButtonOptions, 'button');
307 11
        $this->toggleButtonOptions['data-target'] = '#' . $this->options['id'];
308 11
        $this->toggleButtonOptions['aria-haspopup'] = 'true';
309
310 11
        if ($this->toggleButtonSize !== '') {
311 1
            Html::addCssClass($this->toggleButtonOptions, $this->toggleButtonSize);
312
        }
313
314 11
        if ($this->toggleButtonColor !== '') {
315 1
            Html::addCssClass($this->toggleButtonOptions, $this->toggleButtonColor);
316
        }
317 11
    }
318
}
319