Passed
Branch master (410c7b)
by Michael
03:30
created

Field   F

Complexity

Total Complexity 95

Size/Duplication

Total Lines 371
Duplicated Lines 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
wmc 95
eloc 232
dl 0
loc 371
rs 2
c 1
b 0
f 0

7 Methods

Rating   Name   Duplication   Size   Complexity  
F getOutputValue() 0 112 38
F getEditElement() 0 115 28
A getUserVars() 0 8 1
A getVar() 0 11 4
A setVar() 0 9 4
D getValueForSave() 0 34 19
A __construct() 0 19 1

How to fix   Complexity   

Complex Class

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

1
<?php
2
3
declare(strict_types=1);
4
5
namespace XoopsModules\Suico;
6
7
/**
8
 * Extended User Profile
9
 *
10
 * You may not change or alter any portion of this comment or credits
11
 * of supporting developers from this source code or any supporting source code
12
 * which is considered copyrighted (c) material of the original comment or credit authors.
13
 * This program is distributed in the hope that it will be useful,
14
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
16
 *
17
 * @copyright       (c) 2000-2016 XOOPS Project (www.xoops.org)
18
 * @license             GNU GPL 2 (http://www.gnu.org/licenses/gpl-2.0.html)
19
 * @package             profile
20
 * @since               2.3.0
21
 * @author              Jan Pedersen
22
 * @author              Taiwen Jiang <[email protected]>
23
 */
24
25
// defined('XOOPS_ROOT_PATH') || exit("XOOPS root path not defined");
26
27
/**
28
 * @package             kernel
29
 * @copyright       (c) 2000-2016 XOOPS Project (www.xoops.org)
30
 */
31
class Field extends \XoopsObject
32
{
33
    public function __construct()
34
    {
35
        $this->initVar('field_id', \XOBJ_DTYPE_INT, null);
36
        $this->initVar('cat_id', \XOBJ_DTYPE_INT, null, true);
37
        $this->initVar('field_type', \XOBJ_DTYPE_TXTBOX);
38
        $this->initVar('field_valuetype', \XOBJ_DTYPE_INT, null, true);
39
        $this->initVar('field_name', \XOBJ_DTYPE_TXTBOX, null, true);
40
        $this->initVar('field_title', \XOBJ_DTYPE_TXTBOX);
41
        $this->initVar('field_description', \XOBJ_DTYPE_TXTAREA);
42
        $this->initVar('field_required', \XOBJ_DTYPE_INT, 0); //0 = no, 1 = yes
43
        $this->initVar('field_maxlength', \XOBJ_DTYPE_INT, 0);
44
        $this->initVar('field_weight', \XOBJ_DTYPE_INT, 0);
45
        $this->initVar('field_default', \XOBJ_DTYPE_TXTAREA, '');
46
        $this->initVar('field_notnull', \XOBJ_DTYPE_INT, 1);
47
        $this->initVar('field_edit', \XOBJ_DTYPE_INT, 0);
48
        $this->initVar('field_show', \XOBJ_DTYPE_INT, 0);
49
        $this->initVar('field_config', \XOBJ_DTYPE_INT, 0);
50
        $this->initVar('field_options', \XOBJ_DTYPE_ARRAY, []);
51
        $this->initVar('step_id', \XOBJ_DTYPE_INT, 0);
52
    }
53
54
    /**
55
     * Extra treatment dealing with non latin encoding
56
     * Tricky solution
57
     * @param string $key
58
     * @param mixed  $value
59
     * @param bool   $not_gpc
60
     */
61
62
    public function setVar($key, $value, $not_gpc = false)
63
    {
64
        if ('field_options' === $key && \is_array($value)) {
65
            foreach (\array_keys($value) as $idx) {
66
                $value[$idx] = \base64_encode($value[$idx]);
67
            }
68
        }
69
70
        parent::setVar($key, $value, $not_gpc);
71
    }
72
73
    /**
74
     * @param string $key
75
     * @param string $format
76
     *
77
     * @return mixed
78
     */
79
80
    public function getVar($key, $format = 's')
81
    {
82
        $value = parent::getVar($key, $format);
83
84
        if ('field_options' === $key && !empty($value)) {
85
            foreach (\array_keys($value) as $idx) {
0 ignored issues
show
Bug introduced by
It seems like $value can also be of type boolean and string; however, parameter $input of array_keys() does only seem to accept array, maybe add an additional type check? ( Ignorable by Annotation )

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

85
            foreach (\array_keys(/** @scrutinizer ignore-type */ $value) as $idx) {
Loading history...
86
                $value[$idx] = \base64_decode($value[$idx]);
87
            }
88
        }
89
90
        return $value;
91
    }
92
93
    /**
94
     * Returns a {@link XoopsFormElement} for editing the value of this field
95
     *
96
     * @param \XoopsUser      $user    {@link \XoopsUser} object to edit the value of
97
     * @param Profile $profile {@link Profile} object to edit the value of
98
     *
99
     * @return \XoopsFormCheckBox|\XoopsFormDatetime|\XoopsFormDhtmlTextArea|\XoopsFormLabel|\XoopsFormRadio|\XoopsFormRadioYN|\XoopsFormSelect|\XoopsFormSelectGroup|\XoopsFormSelectLang|\XoopsFormSelectTheme|\XoopsFormSelectTimezone|\XoopsFormText|\XoopsFormTextArea|\XoopsFormTextDateSelect
100
     */
101
102
    public function getEditElement($user, $profile)
103
    {
104
        $value = \in_array($this->getVar('field_name'), $this->getUserVars()) ? $user->getVar($this->getVar('field_name'), 'e') : $profile->getVar($this->getVar('field_name'), 'e');
105
106
        $caption = $this->getVar('field_title');
107
108
        $caption = \defined($caption) ? \constant($caption) : $caption;
109
110
        $name = $this->getVar('field_name', 'e');
111
112
        $options = $this->getVar('field_options');
113
114
        if (\is_array($options)) {
115
            //asort($options);
116
117
            foreach (\array_keys($options) as $key) {
118
                $optval = \defined($options[$key]) ? \constant($options[$key]) : $options[$key];
119
120
                $optkey = \defined((string)$key) ? \constant($key) : $key;
121
122
                unset($options[$key]);
123
124
                $options[$optkey] = $optval;
125
            }
126
        }
127
128
        include_once $GLOBALS['xoops']->path('class/xoopsformloader.php');
129
130
        switch ($this->getVar('field_type')) {
131
            default:
132
            case 'autotext':
133
                //autotext is not for editing
134
                $element = new \XoopsFormLabel($caption, $this->getOutputValue($user, $profile));
0 ignored issues
show
Bug introduced by
It seems like $this->getOutputValue($user, $profile) can also be of type array and array and array; however, parameter $value of XoopsFormLabel::__construct() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

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

134
                $element = new \XoopsFormLabel($caption, /** @scrutinizer ignore-type */ $this->getOutputValue($user, $profile));
Loading history...
135
                break;
136
            case 'textbox':
137
                $element = new \XoopsFormText($caption, $name, 35, $this->getVar('field_maxlength'), $value);
0 ignored issues
show
Bug introduced by
It seems like $value can also be of type array and array; however, parameter $value of XoopsFormText::__construct() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

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

137
                $element = new \XoopsFormText($caption, $name, 35, $this->getVar('field_maxlength'), /** @scrutinizer ignore-type */ $value);
Loading history...
138
                break;
139
            case 'textarea':
140
                $element = new \XoopsFormTextArea($caption, $name, $value, 4, 30);
0 ignored issues
show
Bug introduced by
It seems like $value can also be of type array and array; however, parameter $value of XoopsFormTextArea::__construct() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

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

140
                $element = new \XoopsFormTextArea($caption, $name, /** @scrutinizer ignore-type */ $value, 4, 30);
Loading history...
141
                break;
142
            case 'dhtml':
143
                $element = new \XoopsFormDhtmlTextArea($caption, $name, $value, 10, 30);
0 ignored issues
show
Bug introduced by
It seems like $value can also be of type array and array; however, parameter $value of XoopsFormDhtmlTextArea::__construct() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

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

143
                $element = new \XoopsFormDhtmlTextArea($caption, $name, /** @scrutinizer ignore-type */ $value, 10, 30);
Loading history...
144
                break;
145
            case 'select':
146
                $element = new \XoopsFormSelect($caption, $name, $value);
147
                // If options do not include an empty element, then add a blank option to prevent any default selection
148
                //                if (!in_array('', array_keys($options))) {
149
                if (!\array_key_exists('', $options)) {
150
                    $element->addOption('', \_NONE);
151
152
                    $eltmsg = empty($caption) ? \sprintf(\_FORM_ENTER, $name) : \sprintf(\_FORM_ENTER, $caption);
153
154
                    $eltmsg = \str_replace('"', '\"', \stripslashes($eltmsg));
155
156
                    $element->customValidationCode[] = "\nvar hasSelected = false; var selectBox = myform.{$name};"
157
                                                       . "for (i = 0; i < selectBox.options.length; i++) { if (selectBox.options[i].selected == true && selectBox.options[i].value != '') { hasSelected = true; break; } }"
158
                                                       . "if (!hasSelected) { window.alert(\"{$eltmsg}\"); selectBox.focus(); return false; }";
159
                }
160
                $element->addOptionArray($options);
161
                break;
162
            case 'select_multi':
163
                $element = new \XoopsFormSelect($caption, $name, $value, 5, true);
164
                $element->addOptionArray($options);
165
                break;
166
            case 'radio':
167
                $element = new \XoopsFormRadio($caption, $name, $value);
0 ignored issues
show
Bug introduced by
It seems like $value can also be of type array and array; however, parameter $value of XoopsFormRadio::__construct() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

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

167
                $element = new \XoopsFormRadio($caption, $name, /** @scrutinizer ignore-type */ $value);
Loading history...
168
                $element->addOptionArray($options);
169
                break;
170
            case 'checkbox':
171
                $element = new \XoopsFormCheckBox($caption, $name, $value);
172
                $element->addOptionArray($options);
173
                break;
174
            case 'yesno':
175
                $element = new \XoopsFormRadioYN($caption, $name, $value);
0 ignored issues
show
Bug introduced by
It seems like $value can also be of type array and array; however, parameter $value of XoopsFormRadioYN::__construct() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

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

175
                $element = new \XoopsFormRadioYN($caption, $name, /** @scrutinizer ignore-type */ $value);
Loading history...
176
                break;
177
            case 'group':
178
                $element = new \XoopsFormSelectGroup($caption, $name, true, $value);
179
                break;
180
            case 'group_multi':
181
                $element = new \XoopsFormSelectGroup($caption, $name, true, $value, 5, true);
182
                break;
183
            case 'language':
184
                $element = new \XoopsFormSelectLang($caption, $name, $value);
185
                break;
186
            case 'date':
187
                $element = new \XoopsFormTextDateSelect($caption, $name, 15, $value);
188
                break;
189
            case 'longdate':
190
                $element = new \XoopsFormTextDateSelect($caption, $name, 15, \str_replace('-', '/', $value));
191
                break;
192
            case 'datetime':
193
                $element = new \XoopsFormDatetime($caption, $name, 15, $value);
194
                break;
195
            case 'timezone':
196
                $element = new \XoopsFormSelectTimezone($caption, $name, $value);
197
                $element->setExtra("style='width: 280px;'");
198
                break;
199
            case 'rank':
200
                $element = new \XoopsFormSelect($caption, $name, $value);
201
202
                include_once $GLOBALS['xoops']->path('class/xoopslists.php');
203
                $ranks = \XoopsLists::getUserRankList();
204
                $element->addOption(0, '--------------');
205
                $element->addOptionArray($ranks);
206
                break;
207
            case 'theme':
208
                $element = new \XoopsFormSelectTheme($caption, $name, $value, 1, true);
209
                break;
210
        }
211
212
        if ('' != $this->getVar('field_description')) {
213
            $element->setDescription($this->getVar('field_description'));
214
        }
215
216
        return $element;
217
    }
218
219
    /**
220
     * Returns a value for output of this field
221
     *
222
     * @param XoopsUser      $user    {@link XoopsUser} object to get the value of
0 ignored issues
show
Bug introduced by
The type XoopsModules\Suico\XoopsUser was not found. Did you mean XoopsUser? If so, make sure to prefix the type with \.
Loading history...
223
     * @param profileProfile $profile object to get the value of
0 ignored issues
show
Bug introduced by
The type XoopsModules\Suico\profileProfile was not found. Did you mean profileProfile? If so, make sure to prefix the type with \.
Loading history...
224
     *
225
     * @return mixed
226
     **/
227
228
    public function getOutputValue($user, $profile)
229
    {
230
        if (\file_exists($file = $GLOBALS['xoops']->path('modules/suico/language/' . $GLOBALS['xoopsConfig']['language'] . '/modinfo.php'))) {
231
            include_once $file;
232
        } else {
233
            include_once $GLOBALS['xoops']->path('modules/suico/language/english/modinfo.php');
234
        }
235
236
        $value = \in_array($this->getVar('field_name'), $this->getUserVars()) ? $user->getVar($this->getVar('field_name')) : $profile->getVar($this->getVar('field_name'));
237
238
        switch ($this->getVar('field_type')) {
239
            default:
240
            case 'textbox':
241
                $value = \is_array($value) ? $value[0] : $value;
242
                if ('url' === $this->getVar('field_name') && '' !== $value) {
243
                    return '<a href="' . \formatURL($value) . '" rel="external">' . $value . '</a>';
244
                }
245
246
                return $value;
247
                break;
0 ignored issues
show
Unused Code introduced by
break is not strictly necessary here and could be removed.

The break statement is not necessary if it is preceded for example by a return statement:

switch ($x) {
    case 1:
        return 'foo';
        break; // This break is not necessary and can be left off.
}

If you would like to keep this construct to be consistent with other case statements, you can safely mark this issue as a false-positive.

Loading history...
248
            case 'textarea':
249
            case 'dhtml':
250
            case 'theme':
251
            case 'language':
252
                return $value;
253
                break;
254
            case 'select':
255
            case 'radio':
256
                $value   = \is_array($value) ? $value[0] : $value;
257
                $options = $this->getVar('field_options');
258
                if (isset($options[$value])) {
259
                    $value = \htmlspecialchars(\defined($options[$value]) ? \constant($options[$value]) : $options[$value]);
260
                } else {
261
                    $value = '';
262
                }
263
264
                return $value;
265
                break;
266
            case 'select_multi':
267
            case 'checkbox':
268
                $options = $this->getVar('field_options');
269
                $ret     = [];
270
                if (\count($options) > 0) {
271
                    foreach (\array_keys($options) as $key) {
272
                        if (\in_array($key, $value)) {
273
                            $ret[$key] = \htmlspecialchars(\defined($options[$key]) ? \constant($options[$key]) : $options[$key]);
274
                        }
275
                    }
276
                }
277
278
                return $ret;
279
                break;
280
            case 'group':
281
                /* @var XoopsMemberHandler $memberHandler */ $memberHandler = \xoops_getHandler('member');
282
                $options                                                    = $memberHandler->getGroupList();
283
                $ret                                                        = $options[$value] ?? '';
284
285
                return $ret;
286
                break;
287
            case 'group_multi':
288
                /* @var XoopsMemberHandler $memberHandler */ $memberHandler = \xoops_getHandler('member');
289
                $options                                                    = $memberHandler->getGroupList();
290
                $ret                                                        = [];
291
                foreach (\array_keys($options) as $key) {
292
                    if (\in_array($key, $value)) {
293
                        $ret[$key] = \htmlspecialchars($options[$key]);
294
                    }
295
                }
296
297
                return $ret;
298
                break;
299
            case 'longdate':
300
                //return YYYY/MM/DD format - not optimal as it is not using local date format, but how do we do that
301
                //when we cannot convert it to a UNIX timestamp?
302
                return \str_replace('-', '/', $value);
303
            case 'date':
304
                return \formatTimestamp($value, 's');
305
                break;
306
            case 'datetime':
307
                if (!empty($value)) {
308
                    return \formatTimestamp($value, 'm');
309
                }
310
311
                return $value = _MI_SUICO_NEVER_LOGGED_IN;
0 ignored issues
show
Unused Code introduced by
The assignment to $value is dead and can be removed.
Loading history...
312
                break;
313
            case 'autotext':
314
                $value = $user->getVar($this->getVar('field_name'), 'n'); //autotext can have HTML in it
315
                $value = \str_replace('{X_UID}', $user->getVar('uid'), $value);
316
                $value = \str_replace('{X_URL}', XOOPS_URL, $value);
317
                $value = \str_replace('{X_UNAME}', $user->getVar('uname'), $value);
318
319
                return $value;
320
                break;
321
            case 'rank':
322
                $userrank       = $user->rank();
323
                $user_rankimage = '';
324
                if (isset($userrank['image']) && '' !== $userrank['image']) {
325
                    $user_rankimage = '<img src="' . \XOOPS_UPLOAD_URL . '/' . $userrank['image'] . '" alt="' . $userrank['title'] . '" /> ';
326
                }
327
328
                return $user_rankimage . $userrank['title'];
329
                break;
330
            case 'yesno':
331
                return $value ? \_YES : \_NO;
332
                break;
333
            case 'timezone':
334
                include_once $GLOBALS['xoops']->path('class/xoopslists.php');
335
                $timezones = \XoopsLists::getTimeZoneList();
336
                $value     = empty($value) ? '0' : (string)$value;
337
338
                return $timezones[\str_replace('.0', '', $value)];
339
                break;
340
        }
341
    }
342
343
    /**
344
     * Returns a value ready to be saved in the database
345
     *
346
     * @param mixed $value Value to format
347
     *
348
     * @return mixed
349
     */
350
351
    public function getValueForSave($value)
352
    {
353
        switch ($this->getVar('field_type')) {
354
            default:
355
            case 'textbox':
356
            case 'textarea':
357
            case 'dhtml':
358
            case 'yesno':
359
            case 'timezone':
360
            case 'theme':
361
            case 'language':
362
            case 'select':
363
            case 'radio':
364
            case 'select_multi':
365
            case 'group':
366
            case 'group_multi':
367
            case 'longdate':
368
                return $value;
369
            case 'checkbox':
370
                return (array)$value;
371
            case 'date':
372
                if ('' !== $value) {
373
                    return \strtotime($value);
374
                }
375
376
                return $value;
377
                break;
0 ignored issues
show
Unused Code introduced by
break is not strictly necessary here and could be removed.

The break statement is not necessary if it is preceded for example by a return statement:

switch ($x) {
    case 1:
        return 'foo';
        break; // This break is not necessary and can be left off.
}

If you would like to keep this construct to be consistent with other case statements, you can safely mark this issue as a false-positive.

Loading history...
378
            case 'datetime':
379
                if (!empty($value)) {
380
                    return \strtotime($value['date']) + (int)$value['time'];
381
                }
382
383
                return $value;
384
                break;
385
        }
386
    }
387
388
    /**
389
     * Get names of user variables
390
     *
391
     * @return array
392
     */
393
394
    public function getUserVars()
395
    {
396
        /* @var Suico\ProfileHandler $profileHandler */
397
398
        $helper = \XoopsModules\Suico\Helper::getInstance();
399
        $profileHandler = $helper->getHandler('Profile');
400
401
        return $profileHandler->getUserVars();
402
    }
403
}
404