Passed
Pull Request — master (#29)
by
unknown
02:27
created

Panel::color()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 11
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 7
CRAP Score 2

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 2
eloc 6
c 1
b 0
f 0
nc 2
nop 1
dl 0
loc 11
ccs 7
cts 7
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 Yiisoft\Arrays\ArrayHelper;
9
use Yiisoft\Html\Html;
10
11
final class Panel extends Widget
12
{
13
    public const COLOR_PRIMARY = 'is-primary';
14
    public const COLOR_LINK = 'is-link';
15
    public const COLOR_INFO = 'is-info';
16
    public const COLOR_SUCCESS = 'is-success';
17
    public const COLOR_WARNING = 'is-warning';
18
    public const COLOR_DANGER = 'is-danger';
19
    private const COLOR_ALL = [
20
        self::COLOR_PRIMARY,
21
        self::COLOR_LINK,
22
        self::COLOR_INFO,
23
        self::COLOR_SUCCESS,
24
        self::COLOR_WARNING,
25
        self::COLOR_DANGER,
26
    ];
27
28
    private array $options = [];
29
    private array $headingOptions = [];
30
    private ?string $heading = null;
31
    private string $color = '';
32
    private array $tabs = [];
33
    private array $tabsOptions = [];
34
    private bool $encodeLabels = true;
35
    private string $template = '{panelBegin}{panelHeading}{panelTabs}{panelItems}{panelEnd}';
36
    private array $items = [];
37
38 10
    protected function run(): string
39
    {
40 10
        $this->buildOptions();
41
42 10
        return strtr($this->template, [
43 10
            '{panelBegin}' => Html::beginTag('nav', $this->options),
44 10
            '{panelHeading}' => $this->renderHeading(),
45 10
            '{panelTabs}' => $this->renderTabs(),
46 10
            '{panelItems}' => implode("\n", $this->items),
47 10
            '{panelEnd}' => Html::endTag('nav'),
48
        ]);
49
    }
50
51 10
    private function buildOptions(): void
52
    {
53 10
        Html::addCssClass($this->options, 'panel');
54
55 10
        $this->options['id'] ??= $this->getId();
56
57 10
        if ($this->color !== '') {
58 1
            Html::addCssClass($this->options, $this->color);
59
        }
60 10
    }
61
62
    /**
63
     * String the template for rendering panel.
64
     *
65
     * - `{panelBegin}`: _string_, which will render the panel container begin.
66
     * - `{panelHeading}`: _string_, which will render the panel heading.
67
     * - `{panelTabs}`: _string_, which will render the panel tabs.
68
     * - `{panelItems}`: _string_, which will render the panel items.
69
     * - `{panelEnd}`: _string_, which will render the panel container end.
70
     *
71
     * @param string $value
72
     *
73
     * @return self
74
     */
75
    public function template(string $value): self
76
    {
77
        $new = clone $this;
78
        $new->template = $value;
79
80
        return $new;
81
    }
82
83
    /**
84
     * @param array $value
85
     *
86
     * @return self
87
     */
88 1
    public function options(array $value): self
89
    {
90 1
        $new = clone $this;
91 1
        $new->options = $value;
92
93 1
        return $new;
94
    }
95
96
    /**
97
     * @param string $value
98
     *
99
     * @return self
100
     */
101 3
    public function heading(string $value): self
102
    {
103 3
        $new = clone $this;
104 3
        $new->heading = $value;
105
106 3
        return $new;
107
    }
108
109
    /**
110
     * @param array $value
111
     *
112
     * @return self
113
     */
114 1
    public function headingOptions(array $value): self
115
    {
116 1
        $new = clone $this;
117 1
        $new->headingOptions = $value;
118
119 1
        return $new;
120
    }
121
122
    /**
123
     * Set progress bar color.
124
     *
125
     * @var string $value Color class.
126
     *
127
     * @return self
128
     */
129 2
    public function color(string $value): self
130
    {
131 2
        if (!in_array($value, self::COLOR_ALL)) {
132 1
            $values = implode('", "', self::COLOR_ALL);
133 1
            throw new InvalidArgumentException("Invalid color. Valid values are: \"$values\".");
134
        }
135
136 1
        $new = clone $this;
137 1
        $new->color = $value;
138
139 1
        return $new;
140
    }
141
142
    /**
143
     * @param array $value
144
     *
145
     * @return self
146
     */
147 5
    public function tabs(array $value): self
148
    {
149 5
        $new = clone $this;
150 5
        $new->tabs = $value;
151
152 5
        return $new;
153
    }
154
155
    /**
156
     * @param array $value
157
     *
158
     * @return self
159
     */
160 1
    public function tabsOptions(array $value): self
161
    {
162 1
        $new = clone $this;
163 1
        $new->tabsOptions = $value;
164
165 1
        return $new;
166
    }
167
168
    /**
169
     * @throws \JsonException
170
     *
171
     * @return string
172
     */
173 10
    private function renderHeading(): string
174
    {
175 10
        if ($this->heading !== null) {
176 3
            Html::addCssClass($this->headingOptions, 'panel-heading');
177 3
            return "\n" . Html::tag('p', $this->heading, $this->headingOptions) . "\n";
178
        }
179
180 7
        return '';
181
    }
182
183
    /**
184
     * @throws \JsonException
185
     *
186
     * @return string
187
     */
188 10
    private function renderTabs(): string
189
    {
190 10
        if (!empty($this->tabs)) {
191 5
            $tabs = '';
192 5
            foreach ($this->tabs as $index => $item) {
193 5
                $tabs .= $this->renderTab($index, $item) . "\n";
194
            }
195
196 5
            Html::addCssClass($this->tabsOptions, 'panel-tabs');
197
198 5
            return "\n" . Html::tag('p', "\n" . $tabs, $this->tabsOptions) . "\n";
199
        }
200
201 5
        return '';
202
    }
203
204
    /**
205
     * @param int $index
206
     * @param array $item
207
     *
208
     * @throws \JsonException
209
     *
210
     * @return string
211
     */
212 5
    private function renderTab(int $index, array $item): string
213
    {
214 5
        $id = $this->getId() . '-c' . $index;
215 5
        $url = ArrayHelper::getValue($item, 'url', '');
216 5
        $label = ArrayHelper::getValue($item, 'label', '');
217 5
        $encode = ArrayHelper::getValue($item, 'encode', $this->encodeLabels);
218 5
        $linkOptions = ArrayHelper::getValue($item, 'linkOptions', []);
219 5
        $items = ArrayHelper::getValue($item, 'items', []);
220 5
        $itemsContainerOptions = ArrayHelper::getValue($item, 'itemsContainerOptions', []);
221
222 5
        if ($url !== '') {
223
            $linkOptions['href'] = $url;
224
        }
225
226 5
        if ($label === '') {
227
            throw new InvalidArgumentException("The 'label' option is required.");
228
        }
229
230 5
        if ($encode === true) {
231 5
            $label = Html::encode($label);
232
        }
233
234 5
        if ($this->isActive($item)) {
235 3
            Html::addCssClass($linkOptions, 'is-active');
236
        }
237
238 5
        if (is_array($items) && !empty($items)) {
239 2
            $linkOptions['href'] ??= '#' . $id;
240 2
            $itemsContainerOptions['id'] ??= $id;
241
242 2
            $itemsContainer = Html::beginTag('div', $itemsContainerOptions) . "\n";
243 2
            foreach ($items as $item) {
244 2
                $itemsContainer .= $this->renderItem($item) . "\n";
245
            }
246 2
            $itemsContainer .= Html::endTag('div');
247
248 2
            $this->items[$index] = $itemsContainer;
249
        }
250
251 5
        return Html::tag('a', $label, $linkOptions);
252
    }
253
254 2
    private function renderItem(array $item): string
255
    {
256 2
        $options = ArrayHelper::getValue($item, 'options', []);
257 2
        $label = ArrayHelper::getValue($item, 'label', '');
258 2
        $icon = ArrayHelper::getValue($item, 'icon', '');
259 2
        $encode = ArrayHelper::getValue($item, 'encode', $this->encodeLabels);
260
261 2
        if ($label === '') {
262
            throw new InvalidArgumentException("The 'label' option is required.");
263
        }
264
265 2
        if ($encode === true) {
266 2
            $label = Html::encode($label);
267
        }
268
269 2
        Html::addCssClass($options, 'panel-block');
270
271 2
        if ($this->isActive($item)) {
272 2
            Html::addCssClass($options, 'is-active');
273
        }
274
275 2
        if ($icon !== '') {
276 2
            $icon = "\n" . Html::tag('i', '', ['class' => $icon, 'aria-hidden' => 'true']) . "\n";
277 2
            $label = "\n" . Html::tag('span', $icon, ['class' => 'panel-icon']) . "\n" . $label . "\n";
278
        }
279
280 2
        return Html::tag('a', $label, $options);
281
    }
282
283
    /**
284
     * Checking if active item.
285
     *
286
     * @param array $item
287
     *
288
     * @return bool
289
     */
290 5
    private function isActive(array $item): bool
291
    {
292 5
        return (bool)ArrayHelper::getValue($item, 'active', false);
293
    }
294
295
    /**
296
     * Returns the Id of the widget.
297
     *
298
     * @return string|null Id of the widget.
299
     */
300 10
    protected function getId(): ?string
301
    {
302 10
        return parent::getId() . '-panel';
303
    }
304
}
305