Passed
Push — master ( b447a8...7d4083 )
by Dmitrijs
02:47
created

Collection::renderItems()   A

Complexity

Conditions 3
Paths 4

Size

Total Lines 14
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 1
Metric Value
eloc 8
c 1
b 0
f 1
dl 0
loc 14
rs 10
cc 3
nc 4
nop 0
1
<?php
2
namespace dmgpage\yii2materialize\widgets;
3
4
use dmgpage\yii2materialize\helpers\Html;
5
use yii\helpers\ArrayHelper;
6
7
/**
8
 * Collections allow you to group list objects together.
9
 *
10
 * ```php
11
 * echo Collection::widget([
12
 *     'items' => [
13
 *         [
14
 *             'label' => '<h5>Best Panda</h5>',
15
 *             'encode' => false,
16
 *             'header' => true
17
 *         ],
18
 *         [
19
 *             'label' => 'Kung Fu Panda',
20
 *             'secondary' => [
21
 *                 'icon' => [
22
 *                     'name' => 'favorite',
23
 *                     'options' =>  ['class' => 'red-text'],
24
 *                 ],
25
 *                 'url' => '#',
26
 *                 'options' => ['target' => '_blank']
27
 *             ]
28
 *         ],
29
 *         [
30
 *             'label' => 'Kung Fu Panda',
31
 *             'secondary' => ['icon' => 'favorite']
32
 *         ],
33
 *         [
34
 *             'label' => 'Kung Fu Panda',
35
 *             'secondary' => ['icon' => 'favorite']
36
 *         ],
37
 *         [
38
 *             'label' => 'Kung Fu Panda',
39
 *             'secondary' => ['icon' => 'favorite']
40
 *         ]
41
 *     ]
42
 * ]);
43
 * ```
44
 * @see https://materializecss.com/collections.html
45
 * @package widgets
46
 */
47
class Collection extends Widget
48
{
49
    /**
50
     * @var array list of items in the collection widget. Each array element represents a single
51
     * row with the following structure:
52
     *
53
     * - label: string, required, the item label.
54
     * - header: boolean, optional, whether this label should be formatted as header.
55
     * - encode: boolean, optional, whether this label should be HTML-encoded. This param will override
56
     *   global `$this->encodeLabels` param.
57
     * - options: array, optional, the HTML attributes of the item container (LI).
58
     * - url: array|string, optional, the URL for the hyperlink tag. Defaults to "#".
59
     * - linkOptions: array, optional, the HTML attributes of the item's link.
60
     * - active: boolean, optional, whether this item should be active.
61
     * - visible: boolean, optional, whether the item tab header and pane should be visible or not. Defaults to true.
62
     * - secondary: array, optional, options for creating secondary content. Available options are:
63
     *   - icon: string|array, required, the options for the icon. See [[Html::icon()]]
64
     *   - options: array, optional, the HTML attributes of the icon link.
65
     *     for more description.
66
     *   - url: array|string, optional, the URL for the icon. Defaults to "#".
67
     */
68
    public $items = [];
69
70
    /**
71
     * @var boolean whether the labels for items should be HTML-encoded.
72
     */
73
    public $encodeLabels = true;
74
75
    /**
76
     * @var boolean weather format each item as a link
77
     */
78
    public $asLinks = false;
79
80
    /**
81
     * Initializes the widget.
82
     */
83
    public function init()
84
    {
85
        parent::init();
86
87
        Html::addCssClass($this->options, ['widget' => 'collection']);
88
89
        if ($this->hasHeader()) {
90
            Html::addCssClass($this->options, ['header' => 'with-header']);
91
        }
92
    }
93
94
    /**
95
     * Renders the widget.
96
     */
97
    public function run()
98
    {
99
        $this->initializePlugin = true;
100
        $this->registerPlugin('collection');
101
        return $this->renderItems();
102
    }
103
104
    /**
105
     * Renders tab items as specified on [[items]].
106
     *
107
     * @return string the rendering result.
108
     * @throws InvalidConfigException.
109
     */
110
    protected function renderItems()
111
    {
112
        $rows = [];
113
114
        foreach ($this->items as $item) {
115
            $rows[] = $this->renderItem($item);
116
        }
117
        
118
        $containerTag = $this->asLinks ? 'div' : 'ul';
119
        $html = Html::beginTag($containerTag, $this->options);
120
        $html .= implode("\n", $rows);
121
        $html .= Html::endTag($containerTag);
122
123
        return $html;
124
    }
125
126
    /**
127
     * Renders single collection item as specified on [[items]].
128
     *
129
     * @param array $item single collection element
130
     * @return string the rendering result
131
     * @throws InvalidConfigException.
132
     */
133
    protected function renderItem($item)
134
    {
135
        if (!array_key_exists('label', $item)) {
136
            throw new InvalidConfigException("The 'label' option is required.");
0 ignored issues
show
Bug introduced by
The type dmgpage\yii2materialize\...\InvalidConfigException was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
137
        } elseif (ArrayHelper::remove($item, 'visible', true)) {
138
            $encodeLabel = isset($item['encode']) ? $item['encode'] : $this->encodeLabels;
139
            $label = $encodeLabel ? Html::encode($item['label']) : $item['label'];
140
            $isHeader = ArrayHelper::getValue($item, 'header', false);
141
            $defaultUrl = $this->asLinks ? '#' : null;
142
            $url = ArrayHelper::getValue($item, 'url', $defaultUrl);
143
            $linkOptions = ArrayHelper::getValue($item, 'linkOptions', []);
144
            $options = ArrayHelper::getValue($item, 'options', []);
145
            $isActive = ArrayHelper::getValue($item, 'active', false);
146
            $containerClass = $isHeader ? 'collection-header' : 'collection-item';
147
            Html::addCssClass($options, ['item' => $containerClass]);
148
149
            if ($isActive) {
150
                Html::addCssClass($options, ['active' => 'active']);
151
            }
152
153
            // Main content
154
            if (!$this->asLinks && !empty($url)) {
155
                $itemContent = Html::a($label, $url, $linkOptions);
156
            } else {
157
                $itemContent = $label;
158
            }
159
160
            // Secondary content
161
            if (!$isHeader && isset($item['secondary'])) {
162
                $itemContent .= $this->renderSecondary($item['secondary']);
163
            }
164
165
            // Item container
166
            if ($this->asLinks) {
167
                $html = Html::a($itemContent, $url, $options);
168
            } else {
169
                $html = Html::tag('li', $itemContent, $options);
170
            }
171
172
            return $html;
173
        }
174
    }
175
176
    /**
177
     * Renders single secondary content item as specified on [[secondary]].
178
     *
179
     * @param array $item single secondary content element
180
     * @return string the rendering result
181
     * @throws InvalidConfigException.
182
     * @see https://materializecss.com/collections.html#secondary
183
     */
184
    protected function renderSecondary($item)
185
    {
186
        if (!array_key_exists('icon', $item)) {
187
            throw new InvalidConfigException("The 'icon' option is required for secondary content.");
188
        } else {
189
            $url = ArrayHelper::getValue($item, 'url', '#');
190
            $options = ArrayHelper::getValue($item, 'options', []);
191
192
            Html::addCssClass($options, ['secondary' => 'secondary-content']);
193
194
            $icon = $this->renderIcon($item['icon']);
195
            $link = Html::a($icon, $url, $options);
196
197
            return $link;
198
        }
199
    }
200
201
    /**
202
     * Searches for header value in [[items]]
203
     * @return boolean if there's header defined
204
     */
205
    protected function hasHeader()
206
    {
207
        foreach ($this->items as $item) {
208
            if (isset($item['header']) && $item['header'] === true) {
209
                return true;
210
            }
211
        }
212
213
        return false;
214
    }
215
}
216