Passed
Pull Request — master (#2)
by Michael
07:08 queued 02:34
created

SonglistFormSelectCategory   B

Complexity

Total Complexity 46

Size/Duplication

Total Lines 256
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
eloc 95
dl 0
loc 256
rs 8.72
c 0
b 0
f 0
wmc 46

13 Methods

Rating   Name   Duplication   Size   Complexity  
A SonglistFormSelectCategory() 0 18 4
A addOptionArray() 0 5 3
A renderValidationJS() 0 14 4
A getOptions() 0 10 5
A setValue() 0 8 4
B populateList() 0 8 8
A render() 0 21 5
A getValue() 0 10 4
A TreeMenu() 0 16 4
A isMultiple() 0 3 1
A addOption() 0 6 2
A getSize() 0 3 1
A GetCategory() 0 9 1

How to fix   Complexity   

Complex Class

Complex classes like SonglistFormSelectCategory 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 SonglistFormSelectCategory, and based on these observations, apply Extract Interface, too.

1
<?php
2
3
/*
4
Module: Xcenter
5
6
Version: 2.01
7
8
Description: Multilingual Content Module with tags and lists with search functions
9
10
Author: Written by Simon Roberts aka. Wishcraft ([email protected])
11
12
Owner: Chronolabs
13
14
License: See /docs - GPL 2.0
15
*/
16
17
/*
18
 You may not change or alter any portion of this comment or credits
19
 of supporting developers from this source code or any supporting source code
20
 which is considered copyrighted (c) material of the original comment or credit authors.
21
22
 This program is distributed in the hope that it will be useful,
23
 but WITHOUT ANY WARRANTY; without even the implied warranty of
24
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
25
*/
26
27
/**
28
 *  Xoops Form Class Elements
29
 *
30
 * @copyright       The XOOPS Project http://sourceforge.net/projects/xoops/
31
 * @license         http://www.fsf.org/copyleft/gpl.html GNU public license
32
 * @package         class
33
 * @package         kernel
34
 * @subpackage      form
35
 * @author          Kazumi Ono <[email protected]>
36
 * @author          Taiwen Jiang <[email protected]>
37
 * @author          John Neill <[email protected]>
38
 * @version         $Id: formselect.php 3988 2009-12-05 15:46:47Z trabis $
39
 */
40
defined('XOOPS_ROOT_PATH') or die('Restricted access');
41
42
xoops_load('XoopsFormElement');
43
44
/**
45
 * A select field
46
 *
47
 * @author 		Kazumi Ono <[email protected]>
48
 * @author 		Taiwen Jiang <[email protected]>
49
 * @author 		John Neill <[email protected]>
50
 * @copyright   The XOOPS Project http://sourceforge.net/projects/xoops/
51
 * @package 	kernel
52
 * @subpackage 	form
53
 * @access 		public
54
 */
55
class SonglistFormSelectCategory extends XoopsFormElement
56
{
57
    /**
58
     * Options
59
     *
60
     * @var array
61
     * @access private
62
     */
63
    var $_options = array();
64
65
    /**
66
     * Allow multiple selections?
67
     *
68
     * @var bool
69
     * @access private
70
     */
71
    var $_multiple = false;
72
73
    /**
74
     * Number of rows. "1" makes a dropdown list.
75
     *
76
     * @var int
77
     * @access private
78
     */
79
    var $_size;
80
81
    /**
82
     * Pre-selcted values
83
     *
84
     * @var array
85
     * @access private
86
     */
87
    var $_value = array();
88
89
    /**
90
     * Constructor
91
     *
92
     * @param string $caption Caption
93
     * @param string $name "name" attribute
94
     * @param mixed $value Pre-selected value (or array of them).
95
     * @param int $size Number or rows. "1" makes a drop-down-list
96
     * @param bool $multiple Allow multiple selections?
97
     */
98
    function SonglistFormSelectCategory($caption, $name, $value = null, $size = 1, $multiple = false, $ownid=0)
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
99
    {
100
    	global $_form_object_options;
101
    	xoops_loadLanguage('modinfo', 'songlist');
102
    	
103
        $this->setCaption($caption);
104
        $this->setName($name);
105
        $this->_multiple = $multiple;
106
        $this->_size = intval($size);
107
        if (isset($value)) {
108
            $this->setValue($value);
109
        }
110
		$this->addOption('0', _MI_SONGLIST_ALL);
111
		if (!isset($_form_object_options['category'])) {
112
			$_form_object_options['category'] = $this->GetCategory(0);
113
		}
114
		if (isset($_form_object_options['category'])) 
115
			$this->populateList($_form_object_options['category'], $ownid);
116
    }
117
118
    function populateList($vars, $ownid = 0) {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
119
    	foreach($vars as $previd => $cats) {
120
			if ($previd!=$ownid||$ownid==0) {
121
				foreach($cats as $catid => $title) {
122
					if ($catid!=$ownid||$ownid==0) {
123
						$this->addOption($catid, $title['item']);
124
						if (isset($title['sub'])) {
125
							$this->populateList($title['sub'], $ownid);
126
						}
127
					}		
128
				}
129
			} 
130
		}
131
    }
132
	function GetCategory($ownid){
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
133
	
134
		$category_handler =& xoops_getmodulehandler('category', 'songlist');
135
		$criteria = new Criteria('pid', '0');
136
		$criteria->setSort('`name`');
137
		$criteria->setOrder('ASC');
138
		$categories = $category_handler->getObjects($criteria, true);
0 ignored issues
show
Bug introduced by
The method getObjects() does not exist on XoopsObjectHandler. It seems like you code against a sub-type of said class. However, the method does not exist in XoopsRankHandler or XoUserHandler. Are you sure you never get one of those? ( Ignorable by Annotation )

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

138
		/** @scrutinizer ignore-call */ 
139
  $categories = $category_handler->getObjects($criteria, true);
Loading history...
139
		$langs_array = $this->TreeMenu(array(), $categories, -1, $ownid);
140
		return $langs_array;
141
	}
142
	
143
	function TreeMenu($langs_array, $categories, $level, $ownid, $previd=0) {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
144
		$level++;
145
		$category_handler =& xoops_getmodulehandler('category', 'songlist');
146
		foreach($categories as $catid => $category) {
147
			if ($catid!=$ownid) {
148
				$langs_array[$previd][$catid]['item'] = str_repeat('--', $level).$category->getVar('name');
149
				$criteria = new Criteria('pid', $catid);
150
				$criteria->setSort('`name`');
151
				$criteria->setOrder('ASC');
152
				if ($categoriesb = $category_handler->getObjects($criteria, true)){
153
					$langs_array[$previd][$catid]['sub'] = $this->TreeMenu($langs_array, $categoriesb, $level, $ownid, $catid);
154
				}
155
			}
156
		}
157
		$level--;
158
		return ($langs_array);
159
	}
160
161
    /**
162
     * Are multiple selections allowed?
163
     *
164
     * @return bool
165
     */
166
    function isMultiple()
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
167
    {
168
        return $this->_multiple;
169
    }
170
171
    /**
172
     * Get the size
173
     *
174
     * @return int
175
     */
176
    function getSize()
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
177
    {
178
        return $this->_size;
179
    }
180
181
    /**
182
     * Get an array of pre-selected values
183
     *
184
     * @param bool $encode To sanitizer the text?
185
     * @return array
186
     */
187
    function getValue($encode = false)
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
188
    {
189
        if (! $encode) {
190
            return $this->_value;
191
        }
192
        $value = array();
193
        foreach($this->_value as $val) {
194
            $value[] = $val ? htmlspecialchars($val, ENT_QUOTES) : $val;
195
        }
196
        return $value;
197
    }
198
199
    /**
200
     * Set pre-selected values
201
     *
202
     * @param  $value mixed
203
     */
204
    function setValue($value)
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
205
    {
206
        if (is_array($value)) {
207
            foreach($value as $v) {
208
                $this->_value[] = $v;
209
            }
210
        } elseif (isset($value)) {
211
            $this->_value[] = $value;
212
        }
213
    }
214
215
    /**
216
     * Add an option
217
     *
218
     * @param string $value "value" attribute
219
     * @param string $name "name" attribute
220
     */
221
    function addOption($value, $name = '')
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
222
    {
223
        if ($name != '') {
224
            $this->_options[$value] = $name;
225
        } else {
226
            $this->_options[$value] = $value;
227
        }
228
    }
229
230
    /**
231
     * Add multiple options
232
     *
233
     * @param array $options Associative array of value->name pairs
234
     */
235
    function addOptionArray($options)
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
236
    {
237
        if (is_array($options)) {
0 ignored issues
show
introduced by
The condition is_array($options) is always true.
Loading history...
238
            foreach($options as $k => $v) {
239
                $this->addOption($k, $v);
240
            }
241
        }
242
    }
243
244
    /**
245
     * Get an array with all the options
246
     *
247
     * Note: both name and value should be sanitized. However for backward compatibility, only value is sanitized for now.
248
     *
249
     * @param int $encode To sanitizer the text? potential values: 0 - skip; 1 - only for value; 2 - for both value and name
250
     * @return array Associative array of value->name pairs
251
     */
252
    function getOptions($encode = false)
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
253
    {
254
        if (! $encode) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $encode of type false|integer is loosely compared to false; this is ambiguous if the integer can be 0. You might want to explicitly use === false instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For integer values, zero is a special case, in particular the following results might be unexpected:

0   == false // true
0   == null  // true
123 == false // false
123 == null  // false

// It is often better to use strict comparison
0 === false // false
0 === null  // false
Loading history...
255
            return $this->_options;
256
        }
257
        $value = array();
258
        foreach($this->_options as $val => $name) {
259
            $value[$encode ? htmlspecialchars($val, ENT_QUOTES) : $val] = ($encode > 1) ? htmlspecialchars($name, ENT_QUOTES) : $name;
260
        }
261
        return $value;
262
    }
263
264
    /**
265
     * Prepare HTML for output
266
     *
267
     * @return string HTML
268
     */
269
    function render()
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
270
    {
271
        $ele_name = $this->getName();
272
		$ele_title = $this->getTitle();
273
        $ele_value = $this->getValue();
274
        $ele_options = $this->getOptions();
275
        $ret = '<select size="'.$this->getSize().'"'.$this->getExtra();
276
        if ($this->isMultiple() != false) {
0 ignored issues
show
Coding Style Best Practice introduced by
It seems like you are loosely comparing two booleans. Considering using the strict comparison !== instead.

When comparing two booleans, it is generally considered safer to use the strict comparison operator.

Loading history...
277
            $ret .= ' name="'.$ele_name.'[]" id="'.$ele_name.'" title="'. $ele_title. '" multiple="multiple">' ;
278
        } else {
279
            $ret .= ' name="'.$ele_name.'" id="'.$ele_name.'" title="'. $ele_title. '">' ;
280
        }
281
        foreach($ele_options as $value => $name) {
282
            $ret .= '<option value="'.htmlspecialchars($value, ENT_QUOTES).'"';
283
            if (count($ele_value) > 0 && in_array($value, $ele_value)) {
284
                $ret .= ' selected="selected"';
285
            }
286
            $ret .= '>'.$name.'</option>' ;
287
        }
288
        $ret .= '</select>';
289
        return $ret;
290
    }
291
292
    /**
293
     * Render custom javascript validation code
294
     *
295
     * @seealso XoopsForm::renderValidationJS
296
     */
297
    function renderValidationJS()
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
298
    {
299
        // render custom validation code if any
300
        if (! empty($this->customValidationCode)) {
301
            return implode("\n", $this->customValidationCode);
302
            // generate validation code if required
303
        } elseif ($this->isRequired()) {
304
            $eltname = $this->getName();
305
            $eltcaption = $this->getCaption();
306
            $eltmsg = empty($eltcaption) ? sprintf(_FORM_ENTER, $eltname) : sprintf(_FORM_ENTER, $eltcaption);
307
            $eltmsg = str_replace('"', '\"', stripslashes($eltmsg));
308
            return "\nvar hasSelected = false; var selectBox = myform.{$eltname};"."for (i = 0; i < selectBox.options.length; i++ ) { if (selectBox.options[i].selected == true) { hasSelected = true; break; } }"."if (!hasSelected) { window.alert(\"{$eltmsg}\"); selectBox.focus(); return false; }";
309
        }
310
        return '';
311
    }
312
}
313
314
?>
0 ignored issues
show
Best Practice introduced by
It is not recommended to use PHP's closing tag ?> in files other than templates.

Using a closing tag in PHP files that only contain PHP code is not recommended as you might accidentally add whitespace after the closing tag which would then be output by PHP. This can cause severe problems, for example headers cannot be sent anymore.

A simple precaution is to leave off the closing tag as it is not required, and it also has no negative effects whatsoever.

Loading history...