FieldHandler   D
last analyzed

Complexity

Total Complexity 58

Size/Duplication

Total Lines 234
Duplicated Lines 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 144
c 1
b 0
f 0
dl 0
loc 234
rs 4.5599
wmc 58

5 Methods

Rating   Name   Duplication   Size   Complexity  
A delete() 0 26 6
A __construct() 0 3 1
A getPostVars() 0 18 1
F insert() 0 130 45
A loadFields() 0 16 5

How to fix   Complexity   

Complex Class

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

1
<?php declare(strict_types=1);
2
3
namespace XoopsModules\Songlist;
4
5
/**
6
 * @copyright copyright &copy; 2000 XOOPS.org
7
 */
8
class FieldHandler extends \XoopsPersistableObjectHandler
9
{
10
    /**
11
     * FieldHandler constructor.
12
     * @param \XoopsDatabase $db
13
     */
14
    public function __construct(\XoopsDatabase $db)
15
    {
16
        parent::__construct($db, 'songlist_field', Field::class, 'field_id', 'field_title');
17
    }
18
19
    /**
20
     * Read field information from cached storage
21
     *
22
     * @param bool $force_update read fields from database and not cached storage
23
     *
24
     * @return array|false
25
     */
26
    public function loadFields($force_update = false)
27
    {
28
        static $fields = [];
29
        if (!empty($force_update) || 0 == \count($fields)) {
30
            $criteria = new \Criteria('field_id', 0, '!=');
31
            $criteria->setSort('field_weight');
32
            if (0 == $this->getCount($criteria)) {
33
                return false;
34
            }
35
            $field_objs = $this->getObjects($criteria);
36
            foreach (\array_keys($field_objs) as $i) {
37
                $fields[$field_objs[$i]->getVar('field_name')] = $field_objs[$i];
38
            }
39
        }
40
41
        return $fields;
42
    }
43
44
    /**
45
     * save a profile field in the database
46
     *
47
     * @param \XoopsObject $obj   reference to the object
48
     * @param bool         $force whether to force the query execution despite security settings
49
     * @return bool FALSE if failed, TRUE if already present and unchanged or successful
50
     * @internal param bool $checkObject check if the object is dirty and clean the attributes
51
     */
52
    public function insert(\XoopsObject $obj, $force = false)
53
    {
54
        $objectsHandler = \XoopsModules\Songlist\Helper::getInstance()->getHandler('Extras');
55
        $obj->setVar('field_name', \str_replace(' ', '_', $obj->getVar('field_name')));
56
        $obj->cleanVars();
57
        $defaultstring = '';
58
        switch ($obj->getVar('field_type')) {
59
            case 'datetime':
60
            case 'date':
61
                $obj->setVar('field_valuetype', \XOBJ_DTYPE_INT);
62
                $obj->setVar('field_maxlength', 10);
63
                break;
64
            case 'longdate':
65
                $obj->setVar('field_valuetype', \XOBJ_DTYPE_MTIME);
66
                break;
67
            case 'yesno':
68
                $obj->setVar('field_valuetype', \XOBJ_DTYPE_INT);
69
                $obj->setVar('field_maxlength', 1);
70
                break;
71
            case 'textbox':
72
                if (\XOBJ_DTYPE_INT != $obj->getVar('field_valuetype')) {
73
                    $obj->setVar('field_valuetype', \XOBJ_DTYPE_TXTBOX);
74
                }
75
                break;
76
            case 'autotext':
77
                if (\XOBJ_DTYPE_INT != $obj->getVar('field_valuetype')) {
78
                    $obj->setVar('field_valuetype', \XOBJ_DTYPE_TXTAREA);
79
                }
80
                break;
81
            case 'group_multi':
82
            case 'select_multi':
83
            case 'checkbox':
84
                $obj->setVar('field_valuetype', \XOBJ_DTYPE_ARRAY);
85
                break;
86
            case 'language':
87
            case 'timezone':
88
            case 'theme':
89
                $obj->setVar('field_valuetype', \XOBJ_DTYPE_TXTBOX);
90
                break;
91
            case 'dhtml':
92
            case 'textarea':
93
                $obj->setVar('field_valuetype', \XOBJ_DTYPE_TXTAREA);
94
                break;
95
        }
96
97
        if ('' == $obj->getVar('field_valuetype')) {
98
            $obj->setVar('field_valuetype', \XOBJ_DTYPE_TXTBOX);
99
        }
100
101
        if (!\in_array($obj->getVar('field_name'), $this->getPostVars(), true)) {
102
            if ($obj->isNew()) {
103
                //add column to table
104
                $changetype = 'ADD';
105
            } else {
106
                //update column information
107
                $changetype = 'CHANGE `' . $obj->getVar('field_name', 'n') . '`';
108
            }
109
            $maxlengthstring = $obj->getVar('field_maxlength') > 0 ? '(' . $obj->getVar('field_maxlength') . ')' : '';
110
            $notnullstring   = ' NOT NULL';
111
            //set type
112
            switch ($obj->getVar('field_valuetype')) {
113
                default:
114
                case \XOBJ_DTYPE_ARRAY:
115
                case \XOBJ_DTYPE_UNICODE_ARRAY:
116
                    $type = 'mediumtext';
117
                    break;
118
                case \XOBJ_DTYPE_UNICODE_EMAIL:
119
                case \XOBJ_DTYPE_UNICODE_TXTBOX:
120
                case \XOBJ_DTYPE_UNICODE_URL:
121
                case \XOBJ_DTYPE_EMAIL:
122
                case \XOBJ_DTYPE_TXTBOX:
123
                case \XOBJ_DTYPE_URL:
124
                    $type = 'varchar';
125
                    // varchars must have a maxlength
126
                    if (!$maxlengthstring) {
127
                        //so set it to max if maxlength is not set - or should it fail?
128
                        $maxlengthstring = '(255)';
129
                        $obj->setVar('field_maxlength', 255);
130
                    }
131
                    //if ( $obj->getVar('field_default')  ) {
132
                    $defaultstring = ' DEFAULT ' . $this->db->quote($obj->cleanVars['field_default']);
133
                    //}
134
                    break;
135
                case \XOBJ_DTYPE_INT:
136
                    $type = 'int';
137
                    if ($obj->getVar('field_default') || '' !== $obj->getVar('field_default')) {
138
                        $defaultstring = " DEFAULT '" . (int)$obj->cleanVars['field_default'] . "'";
139
                        $obj->setVar('field_default', (int)$obj->cleanVars['field_default']);
140
                    }
141
                    break;
142
                case \XOBJ_DTYPE_DECIMAL:
143
                    $type = 'decimal(14,6)';
144
                    if ($obj->getVar('field_default') || '' !== $obj->getVar('field_default')) {
145
                        $defaultstring = " DEFAULT '" . (float)$obj->cleanVars['field_default'] . "'";
146
                        $obj->setVar('field_default', (float)$obj->cleanVars['field_default']);
147
                    }
148
                    break;
149
                case XOBJ_DTYPE_FLOAT:
150
                    $type = 'float(15,9)';
151
                    if ($obj->getVar('field_default') || '' !== $obj->getVar('field_default')) {
152
                        $defaultstring = " DEFAULT '" . (float)$obj->cleanVars['field_default'] . "'";
153
                        $obj->setVar('field_default', (float)$obj->cleanVars['field_default']);
154
                    }
155
                    break;
156
                case \XOBJ_DTYPE_OTHER:
157
                case \XOBJ_DTYPE_UNICODE_TXTAREA:
158
                case \XOBJ_DTYPE_TXTAREA:
159
                    $type            = 'text';
160
                    $maxlengthstring = '';
161
                    $notnullstring   = '';
162
                    break;
163
                case \XOBJ_DTYPE_MTIME:
164
                    $type            = 'date';
165
                    $maxlengthstring = '';
166
                    break;
167
            }
168
169
            $sql = 'ALTER TABLE `' . $objectsHandler->table . '` ' . $changetype . ' `' . $obj->cleanVars['field_name'] . '` ' . $type . $maxlengthstring . $notnullstring . $defaultstring;
170
            if (!$this->db->query($sql)) {
171
                return false;
172
            }
173
        }
174
175
        //change this to also update the cached field information storage
176
        $obj->setDirty();
177
        if (!parent::insert($obj, $force)) {
178
            return false;
179
        }
180
181
        return $obj->getVar('field_id');
0 ignored issues
show
Bug Best Practice introduced by
The expression return $obj->getVar('field_id') also could return the type array|string which is incompatible with the documented return type boolean.
Loading history...
182
    }
183
184
    /**
185
     * delete a profile field from the database
186
     *
187
     * @param \XoopsObject $obj reference to the object to delete
188
     * @param bool         $force
189
     * @return bool FALSE if failed.
190
     **/
191
    public function delete(\XoopsObject $obj, $force = false): bool
192
    {
193
        $objectsHandler = \XoopsModules\Songlist\Helper::getInstance()->getHandler('Extras');
194
        // remove column from table
195
        $sql = 'ALTER TABLE ' . $objectsHandler->table . ' DROP `' . $obj->getVar('field_name', 'n') . '`';
196
        if ($this->db->query($sql)) {
197
            //change this to update the cached field information storage
198
            if (!parent::delete($obj, $force)) {
199
                return false;
200
            }
201
202
            if ($obj->getVar('field_show') || $obj->getVar('field_edit')) {
203
                $moduleHandler  = \xoops_getHandler('module');
204
                $objects_module = $moduleHandler->getByDirname('profile');
0 ignored issues
show
Bug introduced by
The method getByDirname() does not exist on XoopsObjectHandler. It seems like you code against a sub-type of XoopsObjectHandler such as XoopsModuleHandler or XoopsPersistableObjectHandler. ( Ignorable by Annotation )

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

204
                /** @scrutinizer ignore-call */ 
205
                $objects_module = $moduleHandler->getByDirname('profile');
Loading history...
205
                if (\is_object($objects_module)) {
206
                    // Remove group permissions
207
                    $grouppermHandler = \xoops_getHandler('groupperm');
208
                    $criteria         = new \CriteriaCompo(new \Criteria('gperm_modid', $objects_module->getVar('mid')));
209
                    $criteria->add(new \Criteria('gperm_itemid', $obj->getVar('field_id')));
0 ignored issues
show
Bug introduced by
It seems like $obj->getVar('field_id') can also be of type array and array; however, parameter $value of Criteria::__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

209
                    $criteria->add(new \Criteria('gperm_itemid', /** @scrutinizer ignore-type */ $obj->getVar('field_id')));
Loading history...
210
211
                    return $grouppermHandler->deleteAll($criteria);
0 ignored issues
show
Bug introduced by
The method deleteAll() does not exist on XoopsObjectHandler. Did you maybe mean delete()? ( Ignorable by Annotation )

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

211
                    return $grouppermHandler->/** @scrutinizer ignore-call */ deleteAll($criteria);

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
212
                }
213
            }
214
        }
215
216
        return false;
217
    }
218
219
    /**
220
     * Get array of standard variable names (song table)
221
     *
222
     * @return array
223
     */
224
    public function getPostVars(): array
225
    {
226
        return [
227
            'sid',
228
            'cid',
229
            'gid',
230
            'aids',
231
            'abid',
232
            'songid',
233
            'traxid',
234
            'title',
235
            'lyrics',
236
            'hits',
237
            'rank',
238
            'votes',
239
            'tags',
240
            'created',
241
            'updated',
242
        ];
243
    }
244
}
245