SongsHandler   F
last analyzed

Complexity

Total Complexity 97

Size/Duplication

Total Lines 396
Duplicated Lines 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 211
c 1
b 0
f 0
dl 0
loc 396
rs 2
wmc 97

10 Methods

Rating   Name   Duplication   Size   Complexity  
A getObjects() 0 26 1
A filterFields() 0 3 1
A getFilterForm() 0 8 2
A getSearchURL() 0 8 2
A get() 0 12 5
F insert() 0 188 67
A getTop() 0 13 2
A getURL() 0 39 5
A __construct() 0 8 1
B getFilterCriteria() 0 24 11

How to fix   Complexity   

Complex Class

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

1
<?php declare(strict_types=1);
2
3
namespace XoopsModules\Songlist;
4
5
require_once \dirname(__DIR__) . '/include/songlist.object.php';
6
// require_once \dirname(__DIR__) . '/include/songlist.form.php';
7
use  XoopsModules\Songlist\Form\FormController;
8
9
/**
10
 * Class SongsHandler
11
 */
12
class SongsHandler extends \XoopsPersistableObjectHandler
13
{
14
    /**
15
     * SongsHandler constructor.
16
     * @param \XoopsDatabase $db
17
     */
18
    public function __construct(\XoopsDatabase $db)
19
    {
20
        $moduleHandler                   = \xoops_getHandler('module');
21
        $configHandler                   = \xoops_getHandler('config');
22
        $GLOBALS['songlistModule']       = $moduleHandler->getByDirname('songlist');
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

22
        /** @scrutinizer ignore-call */ 
23
        $GLOBALS['songlistModule']       = $moduleHandler->getByDirname('songlist');
Loading history...
23
        $GLOBALS['songlistModuleConfig'] = $configHandler->getConfigList($GLOBALS['songlistModule']->getVar('mid'));
0 ignored issues
show
Bug introduced by
The method getConfigList() does not exist on XoopsObjectHandler. It seems like you code against a sub-type of XoopsObjectHandler such as XoopsPersistableObjectHandler. ( Ignorable by Annotation )

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

23
        /** @scrutinizer ignore-call */ 
24
        $GLOBALS['songlistModuleConfig'] = $configHandler->getConfigList($GLOBALS['songlistModule']->getVar('mid'));
Loading history...
24
25
        parent::__construct($db, 'songlist_songs', Songs::class, 'sid', 'title');
26
    }
27
28
    /**
29
     * @return array
30
     */
31
    public function filterFields(): array
32
    {
33
        return ['sid', 'cid', 'mp3', 'gid', 'vcid', 'aids', 'abid', 'songid', 'title', 'lyrics', 'hits', 'rank', 'votes', 'tags', 'created', 'updated'];
34
    }
35
36
    /**
37
     * @param $filter
38
     * @return \CriteriaCompo
39
     */
40
    public function getFilterCriteria($filter): \CriteriaCompo
41
    {
42
        $parts    = \explode('|', $filter);
43
        $criteria = new \CriteriaCompo();
44
        foreach ($parts as $part) {
45
            $var = \explode(',', $part);
46
            if (!empty($var[1]) && !\is_numeric($var[0])) {
47
                $object = $this->create();
48
                if (\XOBJ_DTYPE_TXTBOX == $object->vars[$var[0]]['data_type']
49
                    || \XOBJ_DTYPE_TXTAREA == $object->vars[$var[0]]['data_type']) {
50
                    $criteria->add(new \Criteria('`' . $var[0] . '`', '%' . $var[1] . '%', ($var[2] ?? 'LIKE')));
51
                } elseif (in_array($object->vars[$var[0]]['data_type'], [XOBJ_DTYPE_INT, XOBJ_DTYPE_DECIMAL, XOBJ_DTYPE_FLOAT])) {
52
                    $criteria->add(new \Criteria('`' . $var[0] . '`', $var[1], ($var[2] ?? '=')));
53
                } elseif (\XOBJ_DTYPE_ENUM == $object->vars[$var[0]]['data_type']) {
54
                    $criteria->add(new \Criteria('`' . $var[0] . '`', $var[1], ($var[2] ?? '=')));
55
                } elseif (\XOBJ_DTYPE_ARRAY == $object->vars[$var[0]]['data_type']) {
56
                    $criteria->add(new \Criteria('`' . $var[0] . '`', '%"' . $var[1] . '";%', ($var[2] ?? 'LIKE')));
57
                }
58
            } elseif (!empty($var[1]) && \is_numeric($var[0])) {
59
                $criteria->add(new \Criteria($var[0], $var[1]));
60
            }
61
        }
62
63
        return $criteria;
64
    }
65
66
    /**
67
     * @param        $filter
68
     * @param        $field
69
     * @param string $sort
70
     * @param string $op
71
     * @param string $fct
72
     * @return string
73
     */
74
    public function getFilterForm($filter, $field, $sort = 'created', $op = 'dashboard', $fct = 'list'): string
75
    {
76
        $ele = Utility::getFilterElement($filter, $field, $sort, $op, $fct);
77
        if (\is_object($ele)) {
78
            return $ele->render();
79
        }
80
81
        return '&nbsp;';
82
    }
83
84
    /**
85
     * @param bool $force
86
     * @param null $object
0 ignored issues
show
Documentation Bug introduced by
Are you sure the doc-type for parameter $object is correct as it would always require null to be passed?
Loading history...
87
     * @return bool|mixed
88
     */
89
    public function insert(\XoopsObject $obj, $force = true, $object = null)
90
    {
91
        if ($obj->isNew()) {
92
            $new = true;
93
            $old = $this->create();
94
            $obj->setVar('created', \time());
95
        } else {
96
            $new = false;
97
            $old = $this->get($obj->getVar('sid'));
98
            $obj->setVar('updated', \time());
99
        }
100
101
        $albumsHandler   = \XoopsModules\Songlist\Helper::getInstance()->getHandler('Albums');
102
        $artistsHandler  = \XoopsModules\Songlist\Helper::getInstance()->getHandler('Artists');
103
        $genreHandler    = \XoopsModules\Songlist\Helper::getInstance()->getHandler('Genre');
104
        $voiceHandler    = \XoopsModules\Songlist\Helper::getInstance()->getHandler('Voice');
105
        $categoryHandler = \XoopsModules\Songlist\Helper::getInstance()->getHandler('Category');
106
107
        if (true === ($obj->vars['gid']['changed']??false)) {
108
            if ($new || (0 != $obj->vars['gid']['value'])) {
109
                $genre = $genreHandler->get($obj->vars['gid']['value']);
110
                if (\is_object($genre)) {
111
                    $genre->setVar('songs', $genre->getVar('songs') + 1);
112
                    $genreHandler->insert($genre, true, $obj);
0 ignored issues
show
Unused Code introduced by
The call to XoopsModules\Songlist\GenreHandler::insert() has too many arguments starting with $obj. ( Ignorable by Annotation )

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

112
                    $genreHandler->/** @scrutinizer ignore-call */ 
113
                                   insert($genre, true, $obj);

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress. Please note the @ignore annotation hint above.

Loading history...
113
                }
114
            }
115
            if (!$old->isNew() && $old->getVar('gid') > 0) {
116
                $genre = $genreHandler->get($old->vars['gid']['value']);
117
                if (\is_object($genre)) {
118
                    $genre->setVar('songs', $genre->getVar('songs') - 1);
119
                    $genreHandler->insert($genre, true, null);
120
                }
121
            }
122
        }
123
124
        if (true === $obj->vars['vcid']['changed']) {
125
            if ($new || (0 != $obj->vars['vcid']['value'])) {
126
                $voice = $voiceHandler->get($obj->vars['vcid']['value']);
127
                if (\is_object($voice)) {
128
                    $voice->setVar('songs', $voice->getVar('songs') + 1);
129
                    $voiceHandler->insert($voice, true, $obj);
0 ignored issues
show
Unused Code introduced by
The call to XoopsModules\Songlist\VoiceHandler::insert() has too many arguments starting with $obj. ( Ignorable by Annotation )

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

129
                    $voiceHandler->/** @scrutinizer ignore-call */ 
130
                                   insert($voice, true, $obj);

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress. Please note the @ignore annotation hint above.

Loading history...
130
                }
131
            }
132
            if (!$old->isNew() && $old->getVar('vcid') > 0) {
133
                $voice = $voiceHandler->get($old->vars['vcid']['value']);
134
                if (\is_object($voice)) {
135
                    $voice->setVar('songs', $voice->getVar('songs') - 1);
136
                    $voiceHandler->insert($voice, true, null);
137
                }
138
            }
139
        }
140
141
        if (true === $obj->vars['cid']['changed']) {
142
            if (true === $new || (0 != $obj->vars['cid']['value'])) {
143
                $category = $categoryHandler->get($obj->vars['cid']['value']);
144
                if (\is_object($category)) {
145
                    $category->setVar('songs', $category->getVar('songs') + 1);
146
                    $categoryHandler->insert($category, true, $obj);
0 ignored issues
show
Unused Code introduced by
The call to XoopsModules\Songlist\CategoryHandler::insert() has too many arguments starting with $obj. ( Ignorable by Annotation )

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

146
                    $categoryHandler->/** @scrutinizer ignore-call */ 
147
                                      insert($category, true, $obj);

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress. Please note the @ignore annotation hint above.

Loading history...
147
                    foreach ($obj->getVar('aids') as $aid) {
148
                        $artists                   = $artistsHandler->get($aid);
149
                        $cids                      = $artists->getVar('cids');
150
                        $cids[$obj->getVar('cid')] = $obj->getVar('cid');
151
                        if (\is_object($artists)) {
152
                            $artists->setVar('cids', $cids);
153
                            $artistsHandler->insert($artists, true, null);
154
                        }
155
                    }
156
                }
157
            }
158
            if (!$old->isNew() && $old->getVar('cid') > 0) {
159
                $category = $categoryHandler->get($old->vars['cid']['value']);
160
                if (\is_object($category)) {
161
                    $category->setVar('songs', $category->getVar('songs') - 1);
162
                    $categoryHandler->insert($category, true, null);
163
                    foreach ($obj->getVar('aids') as $aid) {
164
                        $artists = $artistsHandler->get($aid);
165
                        $cids    = [];
166
                        foreach ($artists->getVar('cids') as $cid) {
167
                            if ($cid != $old->getVar('cid') || $cid == $obj->getVar('cid')) {
168
                                $cids[$cid] = $cid;
169
                            }
170
                        }
171
                        if (\is_object($artists)) {
172
                            $artists->setVar('cids', $cids);
173
                            $artistsHandler->insert($artists, true, null);
174
                        }
175
                    }
176
                }
177
            }
178
        }
179
180
        if (true === $obj->vars['aids']['changed'] && 0 != \count($obj->vars['aids']['value'])) {
181
            if (true === $new || 0 != \count($obj->vars['aids']['value'])) {
182
                foreach ($obj->vars['aids']['value'] as $aid) {
183
                    if (!\in_array($aid, $old->vars['aids']['value'], true)) {
184
                        $artists = $artistsHandler->get($aid);
185
                        if (\is_object($artists)) {
186
                            $artists->setVar('songs', $artists->getVar('songs') + 1);
187
                            $artistsHandler->insert($artists, true, $obj);
188
                            if (true === $new || (0 != $obj->vars['vcid']['value'])) {
189
                                $voice = $voiceHandler->get($obj->vars['vcid']['value']);
190
                                if (\is_object($voice)) {
191
                                    $voice->setVar('artists', $voice->getVar('artists') + 1);
192
                                    $voiceHandler->insert($voice, true, $obj);
193
                                }
194
                            }
195
                        }
196
                    }
197
                }
198
            }
199
            if (!$old->isNew() && 0 == \count($old->getVar('aids'))) {
0 ignored issues
show
Bug introduced by
It seems like $old->getVar('aids') can also be of type boolean and null and string; however, parameter $value of count() does only seem to accept Countable|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

199
            if (!$old->isNew() && 0 == \count(/** @scrutinizer ignore-type */ $old->getVar('aids'))) {
Loading history...
200
                foreach ($old->getVar('aids') as $aid) {
201
                    if (!\in_array($aid, $obj->vars['aids']['value'], true)) {
202
                        $artists = $artistsHandler->get($aid);
203
                        if (\is_object($artists)) {
204
                            $artists->setVar('songs', $artists->getVar('songs') - 1);
205
                            $artistsHandler->insert($artists, true, null);
206
                            if (!$old->isNew() && $old->getVar('vcid') > 0) {
207
                                $voice = $voiceHandler->get($old->vars['vcid']['value']);
208
                                if (\is_object($voice)) {
209
                                    $voice->setVar('artists', $voice->getVar('artists') - 1);
210
                                    $voiceHandler->insert($voice, true, null);
211
                                }
212
                            }
213
                        }
214
                    }
215
                }
216
            }
217
        }
218
219
        if (true === $obj->vars['abid']['changed']) {
220
            if (true === $new || (0 != $obj->vars['abid']['value'])) {
221
                $album = $albumsHandler->get($obj->vars['abid']['value']);
222
                if (\is_object($album)) {
223
                    $album->setVar('songs', $album->getVar('songs') + 1);
224
                    $albumsHandler->insert($album, true, $obj);
225
                    if (true === $new || (0 != $obj->vars['vcid']['value'])) {
226
                        $voice = $voiceHandler->get($obj->vars['vcid']['value']);
227
                        if (\is_object($voice)) {
228
                            $voice->setVar('albums', $voice->getVar('albums') + 1);
229
                            $voiceHandler->insert($voice, true, $obj);
230
                        }
231
                    }
232
                }
233
            }
234
            if (!$old->isNew() && $old->getVar('abid') > 0) {
235
                $album = $albumsHandler->get($obj->vars['abid']['value']);
236
                if (\is_object($album)) {
237
                    $album->setVar('songs', $album->getVar('songs') - 1);
238
                    $albumsHandler->insert($album, true, null);
239
                    if (!$old->isNew() && $old->getVar('vcid') > 0) {
240
                        $voice = $voiceHandler->get($old->vars['vcid']['value']);
241
                        if (\is_object($voice)) {
242
                            $voice->setVar('albums', $voice->getVar('albums') - 1);
243
                            $voiceHandler->insert($voice, true, null);
244
                        }
245
                    }
246
                }
247
            }
248
        }
249
250
        if ('' == $obj->getVar('title')) {
251
            return false;
252
        }
253
254
        $sid = parent::insert($obj, $force);
255
        if ($obj->vars['abid']['value'] > 0) {
256
            $album      = $albumsHandler->get($obj->vars['abid']['value']);
257
            $arry       = $album->getVar('sids');
258
            $arry[$sid] = $sid;
259
            if (\is_object($album)) {
260
                $album->setVar('sids', $arry);
261
                $albumsHandler->insert($album);
262
            }
263
        }
264
        if (\count($obj->getVar('aids')) > 0) {
265
            foreach ($obj->getVar('aids') as $aid) {
266
                $artist     = $artistsHandler->get($aid);
267
                $arry       = $artist->getVar('sids');
268
                $arry[$sid] = $sid;
269
                if (\is_object($artists)) {
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $artists does not seem to be defined for all execution paths leading up to this point.
Loading history...
270
                    $artist->setVar('sids', $arry);
271
                    $artistsHandler->insert($artist);
272
                }
273
            }
274
        }
275
276
        return $sid;
277
    }
278
279
    public $_objects = ['object' => [], 'array' => []];
280
281
    /**
282
     * @param null $id
0 ignored issues
show
Documentation Bug introduced by
Are you sure the doc-type for parameter $id is correct as it would always require null to be passed?
Loading history...
283
     * @param null $fields
0 ignored issues
show
Documentation Bug introduced by
Are you sure the doc-type for parameter $fields is correct as it would always require null to be passed?
Loading history...
284
     * @return \XoopsObject
285
     */
286
    public function get($id = null, $fields = null): \XoopsObject//get($id, $fields = '*')
287
    {
288
        $fields = $fields ?: '*';
0 ignored issues
show
introduced by
$fields is of type null, thus it always evaluated to false.
Loading history...
289
        if (!isset($this->_objects['object'][$id])) {
290
            $this->_objects['object'][$id] = parent::get($id, $fields);
0 ignored issues
show
Bug introduced by
$fields of type string is incompatible with the type array expected by parameter $fields of XoopsPersistableObjectHandler::get(). ( Ignorable by Annotation )

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

290
            $this->_objects['object'][$id] = parent::get($id, /** @scrutinizer ignore-type */ $fields);
Loading history...
291
            if (!isset($GLOBALS['songlistAdmin']) && \is_object($this->_objects['object'][$id])) {
292
                $sql = 'UPDATE `' . $this->table . '` set hits=hits+1 where `' . $this->keyName . '` = ' . $this->_objects['object'][$id]->getVar($this->keyName);
293
                $GLOBALS['xoopsDB']->queryF($sql);
294
            }
295
        }
296
297
        return $this->_objects['object'][$id];
298
    }
299
300
    /**
301
     * @param \CriteriaElement|\CriteriaCompo $criteria
302
     * @param bool $id_as_key
303
     * @param bool $as_object
304
     * @return array
305
     */
306
    public function &getObjects($criteria = null, $id_as_key = false, $as_object = true): array
307
    {
308
        $ret = parent::getObjects($criteria, $id_as_key, $as_object);
309
310
        /*if (!isset($GLOBALS['songlistAdmin'])) {
311
            foreach($ret as $data) {
312
                $id = [];
313
                if ($as_object==true) {
314
                    if (!in_array($data->getVar($this->keyName), array_keys($this->_objects['object']))) {
315
                        $this->_objects['object'][$data->getVar($this->keyName)] = $data;
316
                        $id[$data->getVar($this->keyName)] = $data->getVar($this->keyName);
317
                    }
318
                } else {
319
                    if (!in_array($data[$this->keyName], array_keys($this->_objects['array']))) {
320
                        $this->_objects['array'][$data[$this->keyName]] = $data;
321
                        $id[$data[$this->keyName]] = $data[$this->keyName];;
322
                    }
323
                }
324
            }
325
        }
326
        if (!isset($GLOBALS['songlistAdmin'])&&count($id)>0) {
327
            $sql = 'UPDATE `'.$this->table.'` set hits=hits+1 where `'.$this->keyName.'` IN ('.implode(',', $id).')';
328
            $GLOBALS['xoopsDB']->queryF($sql);
329
        }*/
330
331
        return $ret;
332
    }
333
334
    /**
335
     * @return string
336
     */
337
    public function getURL(): string
338
    {
339
        global $file, $op, $fct, $id, $value, $gid, $vid, $vcid, $cid, $start, $limit;
340
        if ($GLOBALS['songlistModuleConfig']['htaccess']) {
341
            if (0 != $cid) {
342
                $artistHandler = \XoopsModules\Songlist\Helper::getInstance()->getHandler('Artists');
343
                $artist        = $artistHandler->get($cid);
344
                if (\is_object($artist) && !$artist->isNew()) {
345
                    return XOOPS_URL
346
                           . '/'
347
                           . $GLOBALS['songlistModuleConfig']['baseofurl']
348
                           . '/'
349
                           . $file
350
                           . '/'
351
                           . \urlencode(\str_replace([' ', \chr(9)], '-', $artist->getVar('name')))
352
                           . '/'
353
                           . $start
354
                           . '-'
355
                           . $id
356
                           . '-'
357
                           . $op
358
                           . '-'
359
                           . $fct
360
                           . '-'
361
                           . $gid
362
                           . '-'
363
                           . $cid
364
                           . '/'
365
                           . \urlencode($value)
366
                           . $GLOBALS['songlistModuleConfig']['endofurl'];
367
                }
368
369
                return XOOPS_URL . '/' . $GLOBALS['songlistModuleConfig']['baseofurl'] . '/' . $file . '/' . $start . '-' . $id . '-' . $op . '-' . $fct . '-' . $gid . '-' . $cid . '/' . \urlencode($value) . $GLOBALS['songlistModuleConfig']['endofurl'];
370
            }
371
372
            return XOOPS_URL . '/' . $GLOBALS['songlistModuleConfig']['baseofurl'] . '/' . $file . '/' . $start . '-' . $id . '-' . $op . '-' . $fct . '-' . $gid . '-' . $cid . '/' . \urlencode($value) . $GLOBALS['songlistModuleConfig']['endofurl'];
373
        }
374
375
        return XOOPS_URL . '/modules/songlist/' . $file . '.php?op=' . $op . '&fct=' . $fct . '&id=' . $id . '&value=' . \urlencode($value ?? '') . '&gid=' . $gid . '&vid=' . $vid . '&cid=' . $cid . '&start=' . $start;
376
    }
377
378
    /**
379
     * @return string
380
     */
381
    public function getSearchURL(): string
382
    {
383
        global $file, $op, $fct, $id, $value, $gid, $vcid, $cid, $start, $limit;
384
        if ($GLOBALS['songlistModuleConfig']['htaccess']) {
385
            return XOOPS_URL . '/' . $GLOBALS['songlistModuleConfig']['baseofurl'] . '/' . $file . '/' . $start . '-' . $op . '-' . $fct . '-' . $gid . '-' . ($_GET['cid'] ?? $cid) . '-' . $vcid . '/' . \urlencode($value) . $GLOBALS['songlistModuleConfig']['endofurl'];
386
        }
387
388
        return XOOPS_URL . '/modules/songlist/' . $file . '.php?op=' . $op . '&fct=' . $fct . '&value=' . \urlencode($value ?? '') . '&cid=' . $cid . '&gid=' . $gid . '&vcid=' . $vcid . '&start=' . $start;
389
    }
390
391
    /**
392
     * @param int $limit
393
     * @return array
394
     */
395
    public function getTop($limit = 1): array
396
    {
397
        $sql     = 'SELECT * FROM `' . $this->table . '` WHERE `rank`>=0 ORDER BY (`rank`/`votes`) DESC LIMIT ' . $limit;
398
        $results = $GLOBALS['xoopsDB']->queryF($sql);
399
        $ret     = [];
400
        $i       = 0;
401
        while (false !== ($row = $GLOBALS['xoopsDB']->fetchArray($results))) {
402
            $ret[$i] = $this->create();
403
            $ret[$i]->assignVars($row);
404
            ++$i;
405
        }
406
407
        return $ret;
408
    }
409
}
410