Passed
Push — master ( 73cd93...7a270d )
by Alexander
30:15 queued 27:55
created

Dropdown::encodeLabels()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 1

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 2
c 1
b 0
f 0
nc 1
nop 1
dl 0
loc 4
ccs 3
cts 3
cp 1
crap 1
rs 10
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Yiisoft\Yii\Bulma;
6
7
use Yiisoft\Arrays\ArrayHelper;
8
use Yiisoft\Html\Html;
9
use Yiisoft\Widget\Exception\InvalidConfigException;
10
11
final class Dropdown extends Widget
12
{
13
    private string $cssOptions = 'dropdown-menu';
14
    private string $cssDivider = 'dropdown-divider';
15
    private string $cssItem = 'dropdown-item';
16
    private bool $encodeLabels = true;
17
    private array $items = [];
18
    private array $options = [];
19
    private array $optionsLink = ['aria-haspopup' => 'true', 'aria-expanded' => 'false'];
20
21 10
    protected function run(): string
22
    {
23 10
        if (!isset($this->options['id'])) {
24 9
            $this->options['id'] = "{$this->getId()}-dropdown";
25
        }
26
27 10
        $this->options = $this->addOptions($this->options, $this->cssOptions);
28
29 10
        return $this->renderItems($this->items, $this->options);
30
    }
31
32 10
    public function cssDivider(string $value): self
33
    {
34 10
        $this->cssDivider  = $value;
35 10
        return $this;
36
    }
37
38 10
    public function cssItem(string $value): self
39
    {
40 10
        $this->cssItem  = $value;
41 10
        return $this;
42
    }
43
44 10
    public function cssOptions(string $value): self
45
    {
46 10
        $this->cssOptions  = $value;
47 10
        return $this;
48
    }
49
50
    /**
51
     * Whether the labels for header items should be HTML-encoded.
52
     *
53
     * @param bool $value
54
     *
55
     * @return self
56
     */
57 10
    public function encodeLabels(bool $value): self
58
    {
59 10
        $this->encodeLabels = $value;
60 10
        return $this;
61
    }
62
63
    /**
64
     * List of menu items in the dropdown. Each array element can be either an HTML string, or an array representing a
65
     * single menu with the following structure:
66
     *
67
     * - label: string, required, the label of the item link.
68
     * - encode: bool, optional, whether to HTML-encode item label.
69
     * - url: string|array, optional, the URL of the item link. This will be processed by {@see currentPath}.
70
     *   If not set, the item will be treated as a menu header when the item has no sub-menu.
71
     * - visible: bool, optional, whether this menu item is visible. Defaults to true.
72
     * - linkOptions: array, optional, the HTML attributes of the item link.
73
     * - options: array, optional, the HTML attributes of the item.
74
     * - items: array, optional, the submenu items. The structure is the same as this property.
75
     *
76
     * To insert divider use `-`.
77
     */
78 10
    public function items(array $value): self
79
    {
80 10
        $this->items = $value;
81 10
        return $this;
82
    }
83
84
    /**
85
     * @param array $value the HTML attributes for the widget container tag. The following special options are
86
     * recognized.
87
     *
88
     * @return self
89
     *
90
     * {@see \Yiisoft\Html\Html::renderTagAttributes()} for details on how attributes are being rendered.
91
     */
92 10
    public function options(array $value): self
93
    {
94 10
        $this->options = $value;
95 10
        return $this;
96
    }
97
98
    /**
99
     * Renders menu items.
100
     *
101
     * @param array $items the menu items to be rendered
102
     * @param array $options the container HTML attributes
103
     *
104
     * @return string the rendering result.
105
     *
106
     * @throws InvalidConfigException if the label option is not specified in one of the items.
107
     */
108 10
    private function renderItems(array $items, array $options = []): string
109
    {
110 10
        $lines = [];
111
112 10
        foreach ($items as $item) {
113 9
            if ($item === '-') {
114 3
                $lines[] = Html::tag('div', '', ['class' => $this->cssDivider]);
115 3
                continue;
116
            }
117
118 9
            if (!isset($item['label']) && $item !== '-') {
119 1
                throw new InvalidConfigException("The 'label' option is required.");
120
            }
121
122 8
            $this->encodeLabels = $item['encode'] ?? $this->encodeLabels;
123
124 8
            if ($this->encodeLabels) {
125 7
                $label = Html::encode($item['label']);
126
            } else {
127 1
                $label = $item['label'];
128
            }
129
130 8
            $linkOptions = ArrayHelper::getValue($item, 'linkOptions', []);
131 8
            $active = ArrayHelper::getValue($item, 'active', false);
132 8
            $disabled = ArrayHelper::getValue($item, 'disabled', false);
133
134 8
            Html::addCssClass($linkOptions, $this->cssItem);
135
136 8
            if ($disabled) {
137 1
                Html::addCssStyle($linkOptions, 'opacity:.65; pointer-events:none;');
138
            }
139
140 8
            if ($active) {
141 3
                Html::addCssClass($linkOptions, 'is-active');
142
            }
143
144 8
            $url = $item['url'] ?? null;
145
146 8
            if (empty($item['items'])) {
147 8
                $lines[] = Html::a($label, $url, $linkOptions);
148
            } else {
149 1
                $lines[] = Html::a($label, $url, array_merge($this->optionsLink, $linkOptions));
150
151 1
                $lines[] = Dropdown::widget()
152 1
                    ->cssDivider($this->cssDivider)
0 ignored issues
show
Bug introduced by
The method cssDivider() does not exist on Yiisoft\Widget\Widget. It seems like you code against a sub-type of Yiisoft\Widget\Widget such as Yiisoft\Yii\Bulma\Dropdown. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

152
                    ->/** @scrutinizer ignore-call */ cssDivider($this->cssDivider)
Loading history...
153 1
                    ->cssItem($this->cssItem)
154 1
                    ->cssOptions($this->cssOptions)
155 1
                    ->items($item['items'])
156 1
                    ->encodeLabels($this->encodeLabels)
157 1
                    ->render();
158
            }
159
        }
160
161 9
        return Html::tag('div', implode("\n", $lines), $options);
162
    }
163
}
164