Completed
Push — master ( 95fc9b...0d3dd3 )
by Michael
12:04
created

ProfileFieldHandler   C

Complexity

Total Complexity 55

Size/Duplication

Total Lines 253
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 5

Importance

Changes 4
Bugs 0 Features 0
Metric Value
wmc 55
c 4
b 0
f 0
lcom 1
cbo 5
dl 0
loc 253
rs 6.8

5 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 4 1
A loadFields() 0 15 4
F insert() 0 131 42
C delete() 0 30 7
B getUserVars() 0 35 1

How to fix   Complexity   

Complex Class

Complex classes like ProfileFieldHandler 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. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.

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 ProfileFieldHandler, and based on these observations, apply Extract Interface, too.

1
<?php
2
/**
3
 * Extended User Profile
4
 *
5
 * You may not change or alter any portion of this comment or credits
6
 * of supporting developers from this source code or any supporting source code
7
 * which is considered copyrighted (c) material of the original comment or credit authors.
8
 * This program is distributed in the hope that it will be useful,
9
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
11
 *
12
 * @copyright       (c) 2000-2016 XOOPS Project (www.xoops.org)
13
 * @license             GNU GPL 2 (http://www.gnu.org/licenses/gpl-2.0.html)
14
 * @package             profile
15
 * @since               2.3.0
16
 * @author              Jan Pedersen
17
 * @author              Taiwen Jiang <[email protected]>
18
 * @version             $Id: field.php 13090 2015-06-16 20:44:29Z beckmi $
19
 */
20
21
// defined('XOOPS_ROOT_PATH') || exit("XOOPS root path not defined");
22
23
/**
24
 * @package             kernel
25
 * @copyright       (c) 2000-2016 XOOPS Project (www.xoops.org)
26
 */
27
class ProfileField extends XoopsObject
28
{
29
    /**
30
     *
31
     */
32
    public function __construct()
33
    {
34
        $this->initVar('field_id', XOBJ_DTYPE_INT, null);
35
        $this->initVar('cat_id', XOBJ_DTYPE_INT, null, true);
36
        $this->initVar('field_type', XOBJ_DTYPE_TXTBOX);
37
        $this->initVar('field_valuetype', XOBJ_DTYPE_INT, null, true);
38
        $this->initVar('field_name', XOBJ_DTYPE_TXTBOX, null, true);
39
        $this->initVar('field_title', XOBJ_DTYPE_TXTBOX);
40
        $this->initVar('field_description', XOBJ_DTYPE_TXTAREA);
41
        $this->initVar('field_required', XOBJ_DTYPE_INT, 0); //0 = no, 1 = yes
42
        $this->initVar('field_maxlength', XOBJ_DTYPE_INT, 0);
43
        $this->initVar('field_weight', XOBJ_DTYPE_INT, 0);
44
        $this->initVar('field_default', XOBJ_DTYPE_TXTAREA, "");
45
        $this->initVar('field_notnull', XOBJ_DTYPE_INT, 1);
46
        $this->initVar('field_edit', XOBJ_DTYPE_INT, 0);
47
        $this->initVar('field_show', XOBJ_DTYPE_INT, 0);
48
        $this->initVar('field_config', XOBJ_DTYPE_INT, 0);
49
        $this->initVar('field_options', XOBJ_DTYPE_ARRAY, array());
50
        $this->initVar('step_id', XOBJ_DTYPE_INT, 0);
51
    }
52
53
    /**
54
     * Extra treatment dealing with non latin encoding
55
     * Tricky solution
56
     * @param string $key
57
     * @param mixed  $value
58
     * @param bool   $not_gpc
59
     */
60
    public function setVar($key, $value, $not_gpc = false)
61
    {
62 View Code Duplication
        if ($key === 'field_options' && is_array($value)) {
63
            foreach (array_keys($value) as $idx) {
64
                $value[$idx] = base64_encode($value[$idx]);
65
            }
66
        }
67
        parent::setVar($key, $value, $not_gpc);
68
    }
69
70
    /**
71
     * @param string $key
72
     * @param string $format
73
     *
74
     * @return mixed
75
     */
76
    public function getVar($key, $format = 's')
77
    {
78
        $value = parent::getVar($key, $format);
79 View Code Duplication
        if ($key === 'field_options' && !empty($value)) {
80
            foreach (array_keys($value) as $idx) {
81
                $value[$idx] = base64_decode($value[$idx]);
82
            }
83
        }
84
85
        return $value;
86
    }
87
88
    /**
89
     * Returns a {@link XoopsFormElement} for editing the value of this field
90
     *
91
     * @param XoopsUser      $user    {@link XoopsUser} object to edit the value of
92
     * @param ProfileProfile $profile {@link ProfileProfile} object to edit the value of
93
     *
94
     * @return XoopsFormElement
0 ignored issues
show
Documentation introduced by
Should the return type not be XoopsFormLabel|XoopsForm...ime|XoopsFormSelectList?

This check compares the return type specified in the @return annotation of a function or method doc comment with the types returned by the function and raises an issue if they mismatch.

Loading history...
95
     **/
96
    public function getEditElement($user, $profile)
97
    {
98
        $value = in_array($this->getVar('field_name'), $this->getUserVars()) ? $user->getVar($this->getVar('field_name'), 'e') : $profile->getVar($this->getVar('field_name'), 'e');
99
100
        $caption = $this->getVar('field_title');
101
        $caption = defined($caption) ? constant($caption) : $caption;
102
        $name    = $this->getVar('field_name', 'e');
103
        $options = $this->getVar('field_options');
104
        if (is_array($options)) {
105
            //asort($options);
106
107
            foreach (array_keys($options) as $key) {
108
                $optval = defined($options[$key]) ? constant($options[$key]) : $options[$key];
109
                $optkey = defined($key) ? constant($key) : $key;
110
                unset($options[$key]);
111
                $options[$optkey] = $optval;
112
            }
113
        }
114
        include_once $GLOBALS['xoops']->path('class/xoopsformloader.php');
115
        switch ($this->getVar('field_type')) {
116
            default:
117
            case "autotext":
118
                //autotext is not for editing
119
                $element = new XoopsFormLabel($caption, $this->getOutputValue($user, $profile));
120
                break;
121
122
            case "textbox":
123
                $element = new XoopsFormText($caption, $name, 35, $this->getVar('field_maxlength'), $value);
124
                break;
125
126
            case "textarea":
127
                $element = new XoopsFormTextArea($caption, $name, $value, 4, 30);
128
                break;
129
130
            case "dhtml":
131
                $element = new XoopsFormDhtmlTextArea($caption, $name, $value, 10, 30);
132
                break;
133
134
            case "select":
135
                $element = new XoopsFormSelect($caption, $name, $value);
136
                // If options do not include an empty element, then add a blank option to prevent any default selection
137
//                if (!in_array('', array_keys($options))) {
138
                if (!array_key_exists('', $options)) {
139
                    $element->addOption('', _NONE);
140
141
                    $eltmsg                          = empty($caption) ? sprintf(_FORM_ENTER, $name) : sprintf(_FORM_ENTER, $caption);
142
                    $eltmsg                          = str_replace('"', '\"', stripslashes($eltmsg));
143
                    $element->customValidationCode[] = "\nvar hasSelected = false; var selectBox = myform.{$name};" . "for (i = 0; i < selectBox.options.length; i++) { if (selectBox.options[i].selected == true && selectBox.options[i].value != '') { hasSelected = true; break; } }" . "if (!hasSelected) { window.alert(\"{$eltmsg}\"); selectBox.focus(); return false; }";
144
                }
145
                $element->addOptionArray($options);
146
                break;
147
148
            case "select_multi":
149
                $element = new XoopsFormSelect($caption, $name, $value, 5, true);
150
                $element->addOptionArray($options);
151
                break;
152
153
            case "radio":
154
                $element = new XoopsFormRadio($caption, $name, $value);
155
                $element->addOptionArray($options);
156
                break;
157
158
            case "checkbox":
159
                $element = new XoopsFormCheckBox($caption, $name, $value);
160
                $element->addOptionArray($options);
161
                break;
162
163
            case "yesno":
164
                $element = new XoopsFormRadioYN($caption, $name, $value);
165
                break;
166
167
            case "group":
168
                $element = new XoopsFormSelectGroup($caption, $name, true, $value);
169
                break;
170
171
            case "group_multi":
172
                $element = new XoopsFormSelectGroup($caption, $name, true, $value, 5, true);
173
                break;
174
175
            case "language":
176
                $element = new XoopsFormSelectLang($caption, $name, $value);
177
                break;
178
179
            case "date":
180
                $element = new XoopsFormTextDateSelect($caption, $name, 15, $value);
181
                break;
182
183
            case "longdate":
184
                $element = new XoopsFormTextDateSelect($caption, $name, 15, str_replace("-", "/", $value));
185
                break;
186
187
            case "datetime":
188
                $element = new XoopsFormDatetime($caption, $name, 15, $value);
189
                break;
190
191
            case "list":
192
                $element = new XoopsFormSelectList($caption, $name, $value, 1, $options[0]);
193
                break;
194
195
            case "timezone":
196
                $element = new XoopsFormSelectTimezone($caption, $name, $value);
197
                $element->setExtra("style='width: 280px;'");
198
                break;
199
200
            case "rank":
201
                $element = new XoopsFormSelect($caption, $name, $value);
202
203
                include_once $GLOBALS['xoops']->path('class/xoopslists.php');
204
                $ranks = XoopsLists::getUserRankList();
205
                $element->addOption(0, "--------------");
206
                $element->addOptionArray($ranks);
207
                break;
208
209
            case 'theme':
210
                $element = new XoopsFormSelect($caption, $name, $value);
211
                $element->addOption("0", _PROFILE_MA_SITEDEFAULT);
212
                $handle  = opendir(XOOPS_THEME_PATH . '/');
213
                $dirlist = array();
214
                while (false !== ($file = readdir($handle))) {
215
                    if (is_dir(XOOPS_THEME_PATH . '/' . $file) && !preg_match("/^[.]{1,2}$/", $file) && strtolower($file) !== 'cvs') {
216
                        if (file_exists(XOOPS_THEME_PATH . "/" . $file . "/theme.html") && in_array($file, $GLOBALS['xoopsConfig']['theme_set_allowed'])) {
217
                            $dirlist[$file] = $file;
218
                        }
219
                    }
220
                }
221
                closedir($handle);
222
                if (!empty($dirlist)) {
223
                    asort($dirlist);
224
                    $element->addOptionArray($dirlist);
225
                }
226
                break;
227
        }
228
        if ($this->getVar('field_description') != "") {
229
            $element->setDescription($this->getVar('field_description'));
230
        }
231
232
        return $element;
233
    }
234
235
    /**
236
     * Returns a value for output of this field
237
     *
238
     * @param XoopsUser      $user    {@link XoopsUser} object to get the value of
239
     * @param profileProfile $profile object to get the value of
240
     *
241
     * @return mixed
242
     **/
243
    public function getOutputValue(&$user, $profile)
244
    {
245 View Code Duplication
        if (file_exists($file = $GLOBALS['xoops']->path('modules/profile/language/' . $GLOBALS['xoopsConfig']['language'] . '/modinfo.php'))) {
246
            include_once $file;
247
        } else {
248
            include_once $GLOBALS['xoops']->path('modules/profile/language/english/modinfo.php');
249
        }
250
251
        $value = in_array($this->getVar('field_name'), $this->getUserVars()) ? $user->getVar($this->getVar('field_name')) : $profile->getVar($this->getVar('field_name'));
252
253
        switch ($this->getVar('field_type')) {
254
            default:
255
            case "textbox":
256
                if ($this->getVar('field_name') === 'url' && $value !== '') {
257
                    return '<a href="' . formatURL($value) . '" rel="external">' . $value . '</a>';
258
                } else {
259
                    return $value;
260
                }
261
                break;
0 ignored issues
show
Unused Code introduced by
break; does not seem to be reachable.

This check looks for unreachable code. It uses sophisticated control flow analysis techniques to find statements which will never be executed.

Unreachable code is most often the result of return, die or exit statements that have been added for debug purposes.

function fx() {
    try {
        doSomething();
        return true;
    }
    catch (\Exception $e) {
        return false;
    }

    return false;
}

In the above example, the last return false will never be executed, because a return statement has already been met in every possible execution path.

Loading history...
262
            case "textarea":
263
            case "dhtml":
264
            case 'theme':
265
            case "language":
266
            case "list":
267
                return $value;
268
                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...
269
270
            case "select":
271
            case "radio":
272
                $options = $this->getVar('field_options');
273 View Code Duplication
                if (isset($options[$value])) {
274
                    $value = htmlspecialchars(defined($options[$value]) ? constant($options[$value]) : $options[$value]);
275
                } else {
276
                    $value = "";
277
                }
278
279
                return $value;
280
                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...
281
282
            case "select_multi":
283
            case "checkbox":
284
                $options = $this->getVar('field_options');
285
                $ret     = array();
286
                if (count($options) > 0) {
287
                    foreach (array_keys($options) as $key) {
288 View Code Duplication
                        if (in_array($key, $value)) {
289
                            $ret[$key] = htmlspecialchars(defined($options[$key]) ? constant($options[$key]) : $options[$key]);
290
                        }
291
                    }
292
                }
293
294
                return $ret;
295
                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...
296
297
            case "group":
298
                $member_handler = xoops_getHandler('member');
299
                $options        = $member_handler->getGroupList();
300
                $ret            = isset($options[$value]) ? $options[$value] : '';
301
302
                return $ret;
303
                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...
304
305
            case "group_multi":
306
                $member_handler = xoops_getHandler('member');
307
                $options        = $member_handler->getGroupList();
308
                $ret            = array();
309
                foreach (array_keys($options) as $key) {
310
                    if (in_array($key, $value)) {
311
                        $ret[$key] = htmlspecialchars($options[$key]);
312
                    }
313
                }
314
315
                return $ret;
316
                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...
317
318
            case "longdate":
319
                //return YYYY/MM/DD format - not optimal as it is not using local date format, but how do we do that
320
                //when we cannot convert it to a UNIX timestamp?
321
                return str_replace("-", "/", $value);
322
323
            case "date":
324
                return formatTimestamp($value, 's');
325
                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...
326
327
            case "datetime":
328
                if (!empty($value)) {
329
                    return formatTimestamp($value, 'm');
330
                } else {
331
                    return $value = _PROFILE_MI_NEVER_LOGGED_IN;
0 ignored issues
show
Unused Code introduced by
$value is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
332
                }
333
                break;
0 ignored issues
show
Unused Code introduced by
break; does not seem to be reachable.

This check looks for unreachable code. It uses sophisticated control flow analysis techniques to find statements which will never be executed.

Unreachable code is most often the result of return, die or exit statements that have been added for debug purposes.

function fx() {
    try {
        doSomething();
        return true;
    }
    catch (\Exception $e) {
        return false;
    }

    return false;
}

In the above example, the last return false will never be executed, because a return statement has already been met in every possible execution path.

Loading history...
334
335
            case "autotext":
336
                $value = $user->getVar($this->getVar('field_name'), 'n'); //autotext can have HTML in it
337
                $value = str_replace("{X_UID}", $user->getVar("uid"), $value);
338
                $value = str_replace("{X_URL}", XOOPS_URL, $value);
339
                $value = str_replace("{X_UNAME}", $user->getVar("uname"), $value);
340
341
                return $value;
342
                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...
343
344
            case "rank":
345
                $userrank       = $user->rank();
346
                $user_rankimage = "";
347
                if (isset($userrank['image']) && $userrank['image'] !== "") {
348
                    $user_rankimage = '<img src="' . XOOPS_UPLOAD_URL . '/' . $userrank['image'] . '" alt="' . $userrank['title'] . '" /><br />';
349
                }
350
351
                return $user_rankimage . $userrank['title'];
352
                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...
353
354
            case "yesno":
355
                return $value ? _YES : _NO;
356
                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...
357
358
            case "timezone":
359
                include_once $GLOBALS['xoops']->path('class/xoopslists.php');
360
                $timezones = XoopsLists::getTimeZoneList();
361
                $value     = empty($value) ? "0" : (string)($value);
362
363
                return $timezones[str_replace('.0', '', $value)];
364
                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...
365
        }
366
    }
367
368
    /**
369
     * Returns a value ready to be saved in the database
370
     *
371
     * @param mixed $value Value to format
372
     *
373
     * @return mixed
374
     */
375
    public function getValueForSave($value)
376
    {
377
        switch ($this->getVar('field_type')) {
378
            default:
379
            case "textbox":
380
            case "textarea":
381
            case "dhtml":
382
            case "yesno":
383
            case "timezone":
384
            case 'theme':
385
            case "language":
386
            case "list":
387
            case "select":
388
            case "radio":
389
            case "select_multi":
390
            case "group":
391
            case "group_multi":
392
            case "longdate":
393
                return $value;
394
395
            case "checkbox":
396
                return (array)$value;
397
398
            case "date":
399
                if ($value !== "") {
400
                    return strtotime($value);
401
                }
402
403
                return $value;
404
                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...
405
406
            case "datetime":
407
                if (!empty($value)) {
408
                    return strtotime($value['date']) + (int)($value['time']);
409
                }
410
411
                return $value;
412
                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...
413
        }
414
    }
415
416
    /**
417
     * Get names of user variables
418
     *
419
     * @return array
420
     */
421
    public function getUserVars()
422
    {
423
        $profile_handler = xoops_getModuleHandler('profile', 'profile');
424
425
        return $profile_handler->getUserVars();
0 ignored issues
show
Bug introduced by
The method getUserVars cannot be called on $profile_handler (of type boolean).

Methods can only be called on objects. This check looks for methods being called on variables that have been inferred to never be objects.

Loading history...
426
    }
427
}
428
429
/**
430
 * @package             kernel
431
 * @copyright       (c) 2000-2016 XOOPS Project (www.xoops.org)
432
 */
433
class ProfileFieldHandler extends XoopsPersistableObjectHandler
0 ignored issues
show
Coding Style Compatibility introduced by
PSR1 recommends that each class should be in its own file to aid autoloaders.

Having each class in a dedicated file usually plays nice with PSR autoloaders and is therefore a well established practice. If you use other autoloaders, you might not want to follow this rule.

Loading history...
434
{
435
    /**
436
     * @param null|XoopsDatabase $db
437
     */
438
    public function __construct(XoopsDatabase $db)
439
    {
440
        parent::__construct($db, 'profile_field', "profilefield", "field_id", 'field_title');
441
    }
442
443
    /**
444
     * Read field information from cached storage
445
     *
446
     * @param bool $force_update read fields from database and not cached storage
447
     *
448
     * @return array
449
     */
450
    public function loadFields($force_update = false)
451
    {
452
        static $fields = array();
453
        if (!empty($force_update) || count($fields) == 0) {
454
            $this->table_link = $this->db->prefix('profile_category');
0 ignored issues
show
Bug introduced by
The property table_link does not exist. Did you maybe forget to declare it?

In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code:

class MyClass { }

$x = new MyClass();
$x->foo = true;

Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion:

class MyClass {
    public $foo;
}

$x = new MyClass();
$x->foo = true;
Loading history...
455
            $criteria         = new Criteria('o.field_id', 0, "!=");
456
            $criteria->setSort('l.cat_weight ASC, o.field_weight');
457
            $field_objs =& $this->getByLink($criteria, array('o.*'), true, 'cat_id', 'cat_id');
458
            foreach (array_keys($field_objs) as $i) {
459
                $fields[$field_objs[$i]->getVar('field_name')] = $field_objs[$i];
460
            }
461
        }
462
463
        return $fields;
464
    }
465
466
    /**
467
     * save a profile field in the database
468
     *
469
     * @param XoopsObject|ProfileField $obj   reference to the object
470
     * @param bool                     $force whether to force the query execution despite security settings
471
     *
472
     * @internal param bool $checkObject check if the object is dirty and clean the attributes
473
     * @return bool FALSE if failed, TRUE if already present and unchanged or successful
474
     */
475
    public function insert(XoopsObject $obj, $force = false)
476
    {
477
        if (!($obj instanceof $this->className)) {
478
            return false;
479
        }
480
        $profile_handler = xoops_getModuleHandler('profile', 'profile');
481
        $obj->setVar('field_name', str_replace(' ', '_', $obj->getVar('field_name')));
482
        $obj->cleanVars();
483
        $defaultstring = "";
0 ignored issues
show
Unused Code introduced by
$defaultstring is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
484
        switch ($obj->getVar('field_type')) {
485
            case "datetime":
486
            case "date":
487
                $obj->setVar('field_valuetype', XOBJ_DTYPE_INT);
488
                $obj->setVar('field_maxlength', 10);
489
                break;
490
491
            case "longdate":
492
                $obj->setVar('field_valuetype', XOBJ_DTYPE_MTIME);
493
                break;
494
495
            case "yesno":
496
                $obj->setVar('field_valuetype', XOBJ_DTYPE_INT);
497
                $obj->setVar('field_maxlength', 1);
498
                break;
499
500
            case "textbox":
501
                if ($obj->getVar('field_valuetype') != XOBJ_DTYPE_INT) {
502
                    $obj->setVar('field_valuetype', XOBJ_DTYPE_TXTBOX);
503
                }
504
                break;
505
506
            case "autotext":
507
                if ($obj->getVar('field_valuetype') != XOBJ_DTYPE_INT) {
508
                    $obj->setVar('field_valuetype', XOBJ_DTYPE_TXTAREA);
509
                }
510
                break;
511
512
            case "group_multi":
513
            case "select_multi":
514
            case "checkbox":
515
                $obj->setVar('field_valuetype', XOBJ_DTYPE_ARRAY);
516
                break;
517
518
            case "language":
519
            case "timezone":
520
            case "theme":
521
                $obj->setVar('field_valuetype', XOBJ_DTYPE_TXTBOX);
522
                break;
523
524
            case "dhtml":
525
            case "textarea":
526
                $obj->setVar('field_valuetype', XOBJ_DTYPE_TXTAREA);
527
                break;
528
        }
529
530
        if ($obj->getVar('field_valuetype') === "") {
531
            $obj->setVar('field_valuetype', XOBJ_DTYPE_TXTBOX);
532
        }
533
534
        if ((!in_array($obj->getVar('field_name'), $this->getUserVars())) && (isset($_REQUEST['field_required']))) {
535
            if ($obj->isNew()) {
536
                //add column to table
537
                $changetype = "ADD";
538
            } else {
539
                //update column information
540
                $changetype = "CHANGE `" . $obj->getVar('field_name', 'n') . "`";
541
            }
542
            $maxlengthstring = $obj->getVar('field_maxlength') > 0 ? "(" . $obj->getVar('field_maxlength') . ")" : "";
543
544
            //set type
545
            switch ($obj->getVar('field_valuetype')) {
546
                default:
547
                case XOBJ_DTYPE_ARRAY:
548
                case XOBJ_DTYPE_UNICODE_ARRAY:
549
                    $type = "mediumtext";
550
                    break;
551
                case XOBJ_DTYPE_UNICODE_EMAIL:
552
                case XOBJ_DTYPE_UNICODE_TXTBOX:
553
                case XOBJ_DTYPE_UNICODE_URL:
554
                case XOBJ_DTYPE_EMAIL:
555
                case XOBJ_DTYPE_TXTBOX:
556
                case XOBJ_DTYPE_URL:
557
                    $type = "varchar";
558
                    // varchars must have a maxlength
559
                    if (!$maxlengthstring) {
560
                        //so set it to max if maxlength is not set - or should it fail?
561
                        $maxlengthstring = "(255)";
562
                        $obj->setVar('field_maxlength', 255);
563
                    }
564
                    break;
565
566
                case XOBJ_DTYPE_INT:
567
                    $type = "int";
568
                    break;
569
570
                case XOBJ_DTYPE_DECIMAL:
571
                    $type = "decimal(14,6)";
572
                    break;
573
574
                case XOBJ_DTYPE_FLOAT:
575
                    $type = "float(15,9)";
576
                    break;
577
578
                case XOBJ_DTYPE_OTHER:
579
                case XOBJ_DTYPE_UNICODE_TXTAREA:
580
                case XOBJ_DTYPE_TXTAREA:
581
                    $type            = "text";
582
                    $maxlengthstring = "";
583
                    break;
584
585
                case XOBJ_DTYPE_MTIME:
586
                    $type            = "date";
587
                    $maxlengthstring = "";
588
                    break;
589
            }
590
591
            $sql = "ALTER TABLE `" . $profile_handler->table . "` " . $changetype . " `" . $obj->cleanVars['field_name'] . "` " . $type . $maxlengthstring . ' NULL';
592
            $result = $force ? $this->db->queryF($sql) : $this->db->query($sql);
593
            if (!$result) {
594
                return false;
595
            }
596
        }
597
598
        //change this to also update the cached field information storage
599
        $obj->setDirty();
600
        if (!parent::insert($obj, $force)) {
601
            return false;
602
        }
603
604
        return $obj->getVar('field_id');
605
    }
606
607
    /**
608
     * delete a profile field from the database
609
     *
610
     * @param XoopsObject|ProfileField $obj reference to the object to delete
611
     * @param bool   $force
612
     * @return bool FALSE if failed.
613
     **/
614
    public function delete(XoopsObject $obj, $force = false)
615
    {
616
        if (!($obj instanceof $this->className)) {
617
            return false;
618
        }
619
        $profile_handler = xoops_getModuleHandler('profile', 'profile');
620
        // remove column from table
621
        $sql = "ALTER TABLE " . $profile_handler->table . " DROP `" . $obj->getVar('field_name', 'n') . "`";
622
        if ($this->db->query($sql)) {
623
            //change this to update the cached field information storage
624
            if (!parent::delete($obj, $force)) {
625
                return false;
626
            }
627
628
            if ($obj->getVar('field_show') || $obj->getVar('field_edit')) {
629
                $module_handler = xoops_getHandler('module');
630
                $profile_module = $module_handler->getByDirname('profile');
631
                if (is_object($profile_module)) {
632
                    // Remove group permissions
633
                    $groupperm_handler = xoops_getHandler('groupperm');
634
                    $criteria          = new CriteriaCompo(new Criteria('gperm_modid', $profile_module->getVar('mid')));
635
                    $criteria->add(new Criteria('gperm_itemid', $obj->getVar('field_id')));
636
637
                    return $groupperm_handler->deleteAll($criteria);
638
                }
639
            }
640
        }
641
642
        return false;
643
    }
644
645
    /**
646
     * Get array of standard variable names (user table)
647
     *
648
     * @return array
649
     */
650
    public function getUserVars()
651
    {
652
        return array(
653
            'uid',
654
            'uname',
655
            'name',
656
            'email',
657
            'url',
658
            'user_avatar',
659
            'user_regdate',
660
            'user_icq',
661
            'user_from',
662
            'user_sig',
663
            'user_viewemail',
664
            'actkey',
665
            'user_aim',
666
            'user_yim',
667
            'user_msnm',
668
            'pass',
669
            'posts',
670
            'attachsig',
671
            'rank',
672
            'level',
673
            'theme',
674
            'timezone_offset',
675
            'last_login',
676
            'umode',
677
            'uorder',
678
            'notify_method',
679
            'notify_mode',
680
            'user_occ',
681
            'bio',
682
            'user_intrest',
683
            'user_mailok');
684
    }
685
}
686