PluginHandler   F
last analyzed

Complexity

Total Complexity 62

Size/Duplication

Total Lines 312
Duplicated Lines 0 %

Importance

Changes 5
Bugs 0 Features 0
Metric Value
eloc 171
c 5
b 0
f 0
dl 0
loc 312
rs 3.44
wmc 62

12 Methods

Rating   Name   Duplication   Size   Complexity  
B getObjects2() 0 45 11
A getCount() 0 13 4
A create() 0 9 1
A forceDeactivate() 0 7 1
A getPluginFileList() 0 12 4
A __construct() 0 17 3
B checkPlugin() 0 33 8
C insert() 0 49 13
A getInstance() 0 8 2
A delete() 0 16 4
A get() 0 10 3
B modifyObjects() 0 26 8

How to fix   Complexity   

Complex Class

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

1
<?php
2
3
declare(strict_types=1);
4
5
namespace XoopsModules\Rssfit;
6
7
/*
8
 * You may not change or alter any portion of this comment or credits
9
 * of supporting developers from this source code or any supporting source code
10
 * which is considered copyrighted (c) material of the original comment or credit authors.
11
 *
12
 * This program is distributed in the hope that it will be useful,
13
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
15
 */
16
17
/**
18
 * @copyright    XOOPS Project (https://xoops.org)
19
 * @license      GNU GPL 2 or later (https://www.gnu.org/licenses/gpl-2.0.html)
20
 * @package      RSSFit - Extendable XML news feed generator
21
 * @author       NS Tai (aka tuff) <http://www.brandycoke.com>
22
 * @author       XOOPS Development Team
23
 */
24
25
if (!\defined('RSSFIT_ROOT_PATH')) {
26
    exit();
27
}
28
29
/**
30
 * Class PluginHandler
31
 * @package XoopsModules\Rssfit
32
 */
33
class PluginHandler extends \XoopsPersistableObjectHandler
34
{
35
    /**
36
     * @var \XoopsMySQLDatabase
37
     */
38
    public $db;
39
    public $dbTable;
40
    public $objClass = Plugin::class;
41
    public $objKey   = 'rssf_conf_id';
42
    public $sortby   = 'rssf_order';
43
    public $order    = 'ASC';
44
    /**
45
     * @var \XoopsModules\Rssfit\Helper
46
     */
47
    public $helper;
48
49
    public function __construct(?\XoopsDatabase $db = null, ?Helper $helper = null)
50
    {
51
        if (null === $helper) {
52
            $helper = \XoopsModules\Rssfit\Helper::getInstance();
53
        }
54
        $this->helper = $helper;
55
56
        if (null === $db) {
57
            $db = \XoopsDatabaseFactory::getDatabaseConnection();
58
        }
59
        $this->db = $db;
60
        //        $this->dbTable = $db->prefix($helper->getDirname() . '_plugins');
61
62
        $table         = $db->prefix($helper->getDirname() . '_plugins');
63
        $this->dbTable = $table;
64
65
        parent::__construct($db, $table, Plugin::class, 'rssf_conf_id', 'rssf_filename');
66
    }
67
68
    public function getInstance(?\XoopsDatabase $db = null): \XoopsPersistableObjectHandler
69
    {
70
        static $instance;
71
        if (null === $instance) {
72
            $instance = new static($db);
73
        }
74
75
        return $instance;
76
    }
77
78
    /**
79
     * @param bool $isNew
80
     */
81
    public function create($isNew = true): ?\XoopsObject
82
    {
83
        $object = parent::create($isNew);
84
        //        if ($isNew) {
85
        //            $object->setDefaultPermissions();
86
        //        }
87
        $object->helper = $this->helper;
88
89
        return $object;
90
    }
91
92
    //    public function get($id, $fields = '*')
93
94
    /**
95
     * @param null|int $id
96
     * @param null|array $fields
97
     */
98
    public function get($id = null, $fields = null): ?\XoopsObject
99
    {
100
        $ret      = null;
101
        $criteria = new \Criteria($this->objKey, (int)$id);
102
        $objs     = $this->getObjects2($criteria);
103
        if (\is_array($objs) && 1 === \count($objs)) {
104
            $ret = &$objs[0];
105
        }
106
107
        return $ret;
108
    }
109
110
    /**
111
     * @param bool $force flag to force the query execution despite security settings
112
     * @return array|bool|int|mixed|null
113
     */
114
    public function insert(\XoopsObject $object, $force = true)
115
    {
116
        if (mb_strtolower(\get_class($object)) != mb_strtolower($this->objClass)) {
117
            return false;
118
        }
119
        if (!$object->isDirty()) {
120
            return true;
121
        }
122
        if (!$object->cleanVars()) {
123
            return false;
124
        }
125
        foreach ($object->cleanVars as $k => $v) {
126
            if (\XOBJ_DTYPE_INT == $object->vars[$k]['data_type']) {
127
                $cleanvars[$k] = (int)$v;
128
            } else {
129
                $cleanvars[$k] = $this->db->quoteString($v);
130
            }
131
        }
132
        if (\count($object->getErrors()) > 0) {
133
            return false;
134
        }
135
        if (empty($cleanvars[$this->objKey]) || $object->isNew()) {
136
            $cleanvars[$this->objKey] = $this->db->genId($this->dbTable . '_' . $this->objKey . '_seq');
137
            $sql                      = 'INSERT INTO ' . $this->dbTable . ' (' . \implode(',', \array_keys($cleanvars)) . ') VALUES (' . \implode(',', $cleanvars) . ')';
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $cleanvars seems to be defined by a foreach iteration on line 125. Are you sure the iterator is never empty, otherwise this variable is not defined?
Loading history...
138
        } else {
139
            unset($cleanvars[$this->objKey]);
140
            $sql = 'UPDATE ' . $this->dbTable . ' SET';
141
            foreach ($cleanvars as $k => $v) {
142
                $sql .= ' ' . $k . '=' . $v . ',';
143
            }
144
            $sql = mb_substr($sql, 0, -1);
145
            $sql .= ' WHERE ' . $this->objKey . ' = ' . $object->getVar($this->objKey);
146
        }
147
        if ($force) {
148
            $result = $this->db->queryF($sql);
149
        } else {
150
            $result = $this->db->query($sql);
151
        }
152
        if (!$result) {
153
            $object->setErrors('Could not store data in the database.<br>' . $this->db->error() . ' (' . $this->db->errno() . ')<br>' . $sql);
154
155
            return false;
156
        }
157
        //        if (false === $object->getVar($this->objKey)) {
158
        if (0 === (int)$object->getVar($this->objKey)) {
159
            $object->assignVar($this->objKey, $this->db->getInsertId());
160
        }
161
162
        return $object->getVar($this->objKey);
163
    }
164
165
    /**
166
     * @param bool         $force
167
     */
168
    public function delete(\XoopsObject $object, $force = false): bool
169
    {
170
        if (mb_strtolower(\get_class($object)) != mb_strtolower($this->objClass)) {
171
            return false;
172
        }
173
        $sql = 'DELETE FROM ' . $this->dbTable . ' WHERE ' . $this->objKey . '=' . $object->getVar($this->objKey);
174
        if ($force) {
175
            $result = $this->db->queryF($sql);
176
        } else {
177
            $result = $this->db->query($sql);
178
        }
179
        if (!$result) {
180
            return false;
181
        }
182
183
        return true;
184
    }
185
186
    /**
187
     * @param null|\Criteria|\CriteriaCompo $criteria
188
     */
189
    public function getObjects2($criteria = null, string $fields = '*', string $key = ''): ?array
190
    {
191
        $ret   = null;
192
        $limit = $start = 0;
193
        switch ($fields) {
194
            case 'p_activated':
195
                $fields = 'rssf_conf_id, rssf_filename, rssf_grab, rssf_order';
196
                break;
197
            case 'p_inactive':
198
                $fields = 'rssf_conf_id, rssf_filename';
199
                break;
200
            case 'sublist':
201
                $fields = 'rssf_conf_id, rssf_filename, subfeed, sub_title';
202
                break;
203
        }
204
        $sql = 'SELECT ' . $fields . ' FROM ' . $this->dbTable;
205
        if (($criteria instanceof \CriteriaCompo) || ($criteria instanceof \Criteria)) {
206
            $sql .= ' ' . $criteria->renderWhere();
207
            if ('' != $criteria->getSort()) {
208
                $sql .= ' ORDER BY ' . $criteria->getSort() . ' ' . $criteria->getOrder();
209
            }
210
            $limit = $criteria->getLimit();
211
            $start = $criteria->getStart();
212
        }
213
        if (!\preg_match('/ORDER BY/', $sql)) {
214
            $sql .= ' ORDER BY ' . $this->sortby . ' ' . $this->order;
215
        }
216
        $result = $this->db->query($sql, $limit, $start);
217
        if ($result instanceof \mysqli_result) {
218
            $ret = [];
219
            while (false !== ($myrow = $this->db->fetchArray($result))) {
220
                $object = new $this->objClass();
221
                $object->assignVars($myrow);
222
                switch ($key) {
223
                    default:
224
                        $ret[] = &$object;
225
                        break;
226
                    case 'id':
227
                        $ret[$myrow[$this->objKey]] = &$object;
228
                        break;
229
                }
230
                unset($object);
231
            }
232
        }
233
        return $ret;
234
    }
235
236
    /**
237
     * @param null|\Criteria|\CriteriaCompo $criteria
238
     */
239
    public function modifyObjects($criteria = null, array $fields = [], bool $force = false): ?string
240
    {
241
        if (\count($fields) > 0) {
242
            $object = new $this->objClass();
243
            $sql    = '';
244
            foreach ($fields as $k => $v) {
245
                $sql .= $k . ' = ';
246
                $sql .= 3 == $object->vars[$k]['data_type'] ? (int)$v : $this->db->quoteString($v);
247
                $sql .= ', ';
248
            }
249
            $sql = mb_substr($sql, 0, -2);
250
            $sql = 'UPDATE ' . $this->dbTable . ' SET ' . $sql;
251
            if (($criteria instanceof \CriteriaCompo) || ($criteria instanceof \Criteria)) {
252
                $sql .= ' ' . $criteria->renderWhere();
253
            }
254
            if ($force) {
255
                $result = $this->db->queryF($sql);
256
            } else {
257
                $result = $this->db->query($sql);
258
            }
259
            if (!$result) {
260
                return 'Could not store data in the database.<br>' . $this->db->error() . ' (' . $this->db->errno() . ')<br>' . $sql;
261
            }
262
        }
263
264
        return null;
265
    }
266
267
    /**
268
     * count objects matching a condition
269
     * @param null|\Criteria|\CriteriaCompo $criteria
270
     */
271
    public function getCount($criteria = null): ?int
272
    {
273
        $sql = 'SELECT COUNT(*) FROM ' . $this->dbTable;
274
        if (($criteria instanceof \CriteriaCompo) || ($criteria instanceof \Criteria)) {
275
            $sql .= ' ' . $criteria->renderWhere();
276
        }
277
        $result = $this->db->query($sql);
278
        if (!$result instanceof \mysqli_result) {
279
            return null;
280
        }
281
        [$count] = $this->db->fetchRow($result);
282
283
        return $count;
284
    }
285
286
    public function forceDeactivate(\XoopsObject $object, string $type = 'rssf_activated'): bool
0 ignored issues
show
Unused Code introduced by
The parameter $type is not used and could be removed. ( Ignorable by Annotation )

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

286
    public function forceDeactivate(\XoopsObject $object, /** @scrutinizer ignore-unused */ string $type = 'rssf_activated'): bool

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
287
    {
288
        $criteria = new \Criteria($this->objKey, $object->getVar($this->objKey));
0 ignored issues
show
Bug introduced by
It seems like $object->getVar($this->objKey) 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

288
        $criteria = new \Criteria($this->objKey, /** @scrutinizer ignore-type */ $object->getVar($this->objKey));
Loading history...
289
        $fields   = ['rssf_activated' => 0, 'subfeed' => 0];
290
        $this->modifyObjects($criteria, $fields, true);
291
292
        return true;
293
    }
294
295
    public function &getPluginFileList(): ?array
296
    {
297
        $ret  = null;
298
        $objs = $this->getObjects2(null, 'rssf_filename');
299
        if (\is_array($objs) && !empty($objs)) {
300
            $ret = [];
301
            foreach ($objs as $o) {
302
                $ret[] = $o->getVar('rssf_filename');
303
            }
304
        }
305
306
        return $ret;
307
    }
308
309
    /**
310
     * @return null|mixed
311
     */
312
    public function checkPlugin(\XoopsObject $object)
313
    {
314
        $ret = null;
315
        $file = \RSSFIT_ROOT_PATH . 'class/Plugins/' . $object->getVar('rssf_filename');
0 ignored issues
show
Bug introduced by
The constant RSSFIT_ROOT_PATH was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
316
        if (\is_file($file)) {
317
            $ret = [];
318
            //mb            $require_once = require $file;
319
            $name  = \explode('.', $object->getVar('rssf_filename'));
320
            $class = __NAMESPACE__ . '\Plugins\\' . \ucfirst($name[0]);
321
            if (\class_exists($class)) {
322
                $plugin = new $class();
323
                if (!\method_exists($plugin, 'loadmodule') || !\method_exists($plugin, 'grabentries')) {
324
                    $object->setErrors(\_AM_RSSFIT_PLUGIN_FUNCNOTFOUND);
325
                } else {
326
                    $dirname = $plugin->dirname;
327
                    if (!empty($dirname) && \is_dir(XOOPS_ROOT_PATH . '/modules/' . $dirname)) {
328
                        if ($plugin->loadModule()) {
329
                            $ret = $plugin;
330
                        } else {
331
                            $object->setErrors(\_AM_RSSFIT_PLUGIN_MODNOTFOUND);
332
                        }
333
                    } else {
334
                        $object->setErrors(\_AM_RSSFIT_PLUGIN_MODNOTFOUND);
335
                    }
336
                }
337
            } else {
338
                $object->setErrors(\_AM_RSSFIT_PLUGIN_CLASSNOTFOUND . ' ' . $class);
339
            }
340
        } else {
341
            $object->setErrors(\_AM_RSSFIT_PLUGIN_FILENOTFOUND);
342
        }
343
344
        return $ret;
345
    }
346
}
347