SelectCategoryForm   B
last analyzed

Complexity

Total Complexity 46

Size/Duplication

Total Lines 284
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
eloc 98
c 0
b 0
f 0
dl 0
loc 284
rs 8.72
wmc 46

13 Methods

Rating   Name   Duplication   Size   Complexity  
A getCategory() 0 10 1
A renderValidationJS() 0 20 4
A getValue() 0 11 4
A treeMenu() 0 19 4
A getSize() 0 3 1
A addOptionArray() 0 5 3
A render() 0 22 5
A isMultiple() 0 3 1
A addOption() 0 6 2
B populateList() 0 9 8
A __construct() 0 19 4
A setValue() 0 9 4
A getOptions() 0 11 5

How to fix   Complexity   

Complex Class

Complex classes like SelectCategoryForm often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use SelectCategoryForm, and based on these observations, apply Extract Interface, too.

1
<?php declare(strict_types=1);
2
3
namespace XoopsModules\Songlist\Form;
4
5
/*
6
 You may not change or alter any portion of this comment or credits
7
 of supporting developers from this source code or any supporting source code
8
 which is considered copyrighted (c) material of the original comment or credit authors.
9
10
 This program is distributed in the hope that it will be useful,
11
 but WITHOUT ANY WARRANTY; without even the implied warranty of
12
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13
*/
14
15
/*
16
Module: Xcenter
17
Version: 2.01
18
Description: Multilingual Content Module with tags and lists with search functions
19
Author: Written by Simon Roberts aka. Wishcraft ([email protected])
20
Owner: Chronolabs
21
License: See /docs - GPL 2.0
22
*/
23
24
use Xmf\Request;
25
use XoopsFormElement;
26
use XoopsModules\Songlist\Helper;
27
28
/**
29
 *  Xoops Form Class Elements
30
 *
31
 * @copyright       XOOPS Project (https://xoops.org)
32
 * @license         https://www.fsf.org/copyleft/gpl.html GNU public license
33
 * @author          Kazumi Ono <[email protected]>
34
 * @author          Taiwen Jiang <[email protected]>
35
 * @author          John Neill <[email protected]>
36
 * @version         $Id: formselect.php 3988 2009-12-05 15:46:47Z trabis $
37
 */
38
\xoops_load('XoopsFormElement');
39
40
/**
41
 * A select field
42
 *
43
 * @author      Kazumi Ono <[email protected]>
44
 * @author      Taiwen Jiang <[email protected]>
45
 * @author      John Neill <[email protected]>
46
 * @copyright   XOOPS Project (https://xoops.org)
47
 */
48
class SelectCategoryForm extends XoopsFormElement
49
{
50
    /**
51
     * Options
52
     *
53
     * @var array
54
     */
55
    public $_options = [];
56
    /**
57
     * Allow multiple selections?
58
     *
59
     * @var bool
60
     */
61
    public $_multiple = false;
62
    /**
63
     * Number of rows. "1" makes a dropdown list.
64
     *
65
     * @var int
66
     */
67
    public $_size;
68
    /**
69
     * Pre-selcted values
70
     *
71
     * @var array
72
     */
73
    public $_value = [];
74
75
    /**
76
     * Constructor
77
     *
78
     * @param string $caption  Caption
79
     * @param string $name     "name" attribute
80
     * @param mixed  $value    Pre-selected value (or array of them).
81
     * @param int    $size     Number of rows. "1" makes a drop-down-list
82
     * @param bool   $multiple Allow multiple selections?
83
     * @param int    $ownid
84
     */
85
    public function __construct($caption, $name, $value = null, $size = 1, $multiple = false, $ownid = 0)
86
    {
87
        global $_form_object_options;
88
        \xoops_loadLanguage('modinfo', 'songlist');
89
90
        $this->setCaption($caption);
91
        $this->setName($name);
92
        $this->_multiple = $multiple;
93
        $this->_size     = (int)$size;
94
        if (isset($value)) {
95
            $this->setValue($value);
96
        }
97
        $this->addOption('0', \_MI_SONGLIST_ALL);
98
        if (!isset($_form_object_options['category'])) {
99
            $_form_object_options['category'] = $this->getCategory(0);
100
        }
101
        //        if (Request::hasVar('category', 'form_object_options')) {
102
        if (isset($_form_object_options['category'])) {
103
            $this->populateList($_form_object_options['category'], $ownid);
104
        }
105
    }
106
107
    /**
108
     * @param     $vars
109
     * @param int $ownid
110
     */
111
    public function populateList($vars, $ownid = 0): void
112
    {
113
        foreach ($vars as $previd => $cats) {
114
            if ($previd != $ownid || 0 == $ownid) {
115
                foreach ($cats as $catid => $title) {
116
                    if ($catid != $ownid || 0 == $ownid) {
117
                        $this->addOption($catid, $title['item']);
118
                        if (isset($title['sub'])) {
119
                            $this->populateList($title['sub'], $ownid);
120
                        }
121
                    }
122
                }
123
            }
124
        }
125
    }
126
127
    /**
128
     * @param $ownid
129
     * @return array
130
     */
131
    public function getCategory($ownid): array
132
    {
133
        $categoryHandler = Helper::getInstance()->getHandler('Category');
134
        $criteria        = new \Criteria('pid', '0');
135
        $criteria->setSort('name');
136
        $criteria->setOrder('ASC');
137
        $categories  = $categoryHandler->getObjects($criteria, true);
138
        $langs_array = $this->treeMenu([], $categories, -1, $ownid);
139
140
        return $langs_array;
141
    }
142
143
    /**
144
     * @param     $langs_array
145
     * @param     $categories
146
     * @param     $level
147
     * @param     $ownid
148
     * @param int $previd
149
     * @return array
150
     */
151
    public function treeMenu($langs_array, $categories, $level, $ownid, $previd = 0): array
152
    {
153
        ++$level;
154
        $categoryHandler = Helper::getInstance()->getHandler('Category');
155
        foreach ($categories as $catid => $category) {
156
            if ($catid != $ownid) {
157
                $langs_array[$previd][$catid]['item'] = \str_repeat('--', $level) . $category->getVar('name');
158
                $criteria                             = new \Criteria('pid', $catid);
159
                $criteria->setSort('name');
160
                $criteria->setOrder('ASC');
161
                $categoriesb = $categoryHandler->getObjects($criteria, true);
162
                if ($categoriesb) {
163
                    $langs_array[$previd][$catid]['sub'] = $this->treeMenu($langs_array, $categoriesb, $level, $ownid, $catid);
164
                }
165
            }
166
        }
167
        $level--;
168
169
        return $langs_array;
170
    }
171
172
    /**
173
     * Are multiple selections allowed?
174
     *
175
     * @return bool
176
     */
177
    public function isMultiple(): bool
178
    {
179
        return $this->_multiple;
180
    }
181
182
    /**
183
     * Get the size
184
     *
185
     * @return int
186
     */
187
    public function getSize(): int
188
    {
189
        return $this->_size;
190
    }
191
192
    /**
193
     * Get an array of pre-selected values
194
     *
195
     * @param bool $encode To sanitizer the text?
196
     * @return array
197
     */
198
    public function getValue($encode = false): array
199
    {
200
        if (!$encode) {
201
            return $this->_value;
202
        }
203
        $value = [];
204
        foreach ($this->_value as $val) {
205
            $value[] = $val ? \htmlspecialchars($val, \ENT_QUOTES) : $val;
206
        }
207
208
        return $value;
209
    }
210
211
    /**
212
     * Set pre-selected values
213
     *
214
     * @param mixed $value
215
     */
216
    public function setValue($value): void
217
    {
218
        if (\is_array($value)) {
219
            foreach ($value as $v) {
220
                $this->_value[] = (int)$v;
221
            }
222
//            $this->_value[] = array_values($value);
223
        } elseif (isset($value)) {
224
            $this->_value[] = $value;
225
        }
226
    }
227
228
    /**
229
     * Add an option
230
     *
231
     * @param string $value "value" attribute
232
     * @param string $name  "name" attribute
233
     */
234
    public function addOption($value, $name = ''): void
235
    {
236
        if ('' != $name) {
237
            $this->_options[$value] = $name;
238
        } else {
239
            $this->_options[$value] = $value;
240
        }
241
    }
242
243
    /**
244
     * Add multiple options
245
     *
246
     * @param array $options Associative array of value->name pairs
247
     */
248
    public function addOptionArray($options): void
249
    {
250
        if (\is_array($options)) {
0 ignored issues
show
introduced by
The condition is_array($options) is always true.
Loading history...
251
            foreach ($options as $k => $v) {
252
                $this->addOption($k, $v);
253
            }
254
        }
255
    }
256
257
    /**
258
     * Get an array with all the options
259
     *
260
     * Note: both name and value should be sanitized. However for backward compatibility, only value is sanitized for now.
261
     *
262
     * @param bool|int $encode To sanitizer the text? potential values: 0 - skip; 1 - only for value; 2 - for both value and name
263
     * @return array Associative array of value->name pairs
264
     */
265
    public function getOptions($encode = false): array
266
    {
267
        if (!$encode) {
268
            return $this->_options;
269
        }
270
        $value = [];
271
        foreach ($this->_options as $val => $name) {
272
            $value[$encode ? \htmlspecialchars($val, \ENT_QUOTES) : $val] = ($encode > 1) ? \htmlspecialchars($name, \ENT_QUOTES) : $name;
273
        }
274
275
        return $value;
276
    }
277
278
    /**
279
     * Prepare HTML for output
280
     *
281
     * @return string HTML
282
     */
283
    public function render(): string
284
    {
285
        $ele_name    = $this->getName();
286
        $ele_title   = $this->getTitle();
287
        $ele_value   = $this->getValue();
288
        $ele_options = $this->getOptions();
289
        $ret         = '<select size="' . $this->getSize() . '"' . $this->getExtra();
290
        if ($this->isMultiple()) {
291
            $ret .= ' name="' . $ele_name . '[]" id="' . $ele_name . '" title="' . $ele_title . '" multiple="multiple">';
292
        } else {
293
            $ret .= ' name="' . $ele_name . '" id="' . $ele_name . '" title="' . $ele_title . '">';
294
        }
295
        foreach ($ele_options as $value => $name) {
296
            $ret .= '<option value="' . \htmlspecialchars((string)$value, \ENT_QUOTES) . '"';
297
            if (\count($ele_value) > 0 && \in_array($value, $ele_value, true)) {
298
                $ret .= ' selected';
299
            }
300
            $ret .= '>' . $name . '</option>';
301
        }
302
        $ret .= '</select>';
303
304
        return $ret;
305
    }
306
307
    /**
308
     * Render custom javascript validation code
309
     *
310
     * @seealso XoopsForm::renderValidationJS
311
     */
312
    public function renderValidationJS()
313
    {
314
        // render custom validation code if any
315
        if (!empty($this->customValidationCode)) {
316
            return \implode("\n", $this->customValidationCode);
317
            // generate validation code if required
318
        }
319
320
        if ($this->isRequired()) {
321
            $eltname    = $this->getName();
322
            $eltcaption = $this->getCaption();
323
            $eltmsg     = empty($eltcaption) ? \sprintf(_FORM_ENTER, $eltname) : \sprintf(_FORM_ENTER, $eltcaption);
324
            $eltmsg     = \str_replace('"', '\"', \stripslashes($eltmsg));
325
326
            return "\nvar hasSelected = false; var selectBox = myform.{$eltname};"
327
                   . 'for (i = 0; i < selectBox.options.length; i++ ) { if (selectBox.options[i].selected === true) { hasSelected = true; break; } }'
328
                   . "if (!hasSelected) { window.alert(\"{$eltmsg}\"); selectBox.focus(); return false; }";
329
        }
330
331
        return '';
332
    }
333
}
334