PermissionHandler   F
last analyzed

Complexity

Total Complexity 65

Size/Duplication

Total Lines 416
Duplicated Lines 0 %

Importance

Changes 2
Bugs 0 Features 0
Metric Value
eloc 157
dl 0
loc 416
rs 3.2
c 2
b 0
f 0
wmc 65

20 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 10 2
A loadHandler() 0 9 2
A deleteByForum() 0 7 1
A getCategories() 0 5 1
C createPermData() 0 50 14
A getPermissionTable() 0 7 1
A validateRight() 0 20 5
B deleteRight() 0 30 7
A getForums() 0 5 1
A setTemplate() 0 6 1
B getAllowedItems() 0 27 9
A getTemplate() 0 7 1
A myCheckRight() 0 23 5
A getGroups() 0 7 2
A applyTemplate() 0 7 1
A deleteByCategory() 0 7 1
B getPermission() 0 21 7
A setCategoryPermission() 0 7 1
A loadPermData() 0 7 2
A getValidForumPerms() 0 6 1

How to fix   Complexity   

Complex Class

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

1
<?php declare(strict_types=1);
2
3
namespace XoopsModules\Newbb;
4
5
/**
6
 * NewBB,  the forum module for XOOPS project
7
 *
8
 * @copyright      XOOPS Project (https://xoops.org)
9
 * @license        GNU GPL 2.0 or later (https://www.gnu.org/licenses/gpl-2.0.html)
10
 * @author         Taiwen Jiang (phppp or D.J.) <[email protected]>
11
 * @since          4.00
12
 */
13
14
use Xmf\Module\Helper\Cache;
15
16
/** @var Cache $cacheHelper */
17
18
\defined('NEWBB_FUNCTIONS_INI') || require $GLOBALS['xoops']->path('modules/newbb/include/functions.ini.php');
19
\define('NEWBB_HANDLER_PERMISSION', 1);
20
21
// Initializing XoopsGroupPermHandler if not loaded yet
22
if (!\class_exists('XoopsGroupPermHandler')) {
23
    require_once $GLOBALS['xoops']->path('kernel/groupperm.php');
24
}
25
26
/**
27
 * Class PermissionHandler
28
 */
29
class PermissionHandler extends \XoopsGroupPermHandler
30
{
31
    protected Cache $cacheHelper;
32
    /** @var array|null */
33
    private array $_handler;
34
    
35
    /** @var Helper|null $helper
36
     * @readonly */
37
    private ?Helper $helper;
38
39
    /**
40
     * @param \XoopsDatabase|null $db
41
     * @param Helper|null         $helper
42
     */
43
    public function __construct(\XoopsDatabase $db = null, Helper $helper = null)
44
    {
45
        $this->cacheHelper = new Cache('newbb');
46
        if (null === $helper) {
47
            $helper = Helper::getInstance();
48
        }
49
        $this->helper = $helper;
50
51
        $this->db = $db;
52
        parent::__construct($db);
0 ignored issues
show
Bug introduced by
It seems like $db can also be of type null; however, parameter $db of XoopsGroupPermHandler::__construct() does only seem to accept XoopsDatabase, 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

52
        parent::__construct(/** @scrutinizer ignore-type */ $db);
Loading history...
53
    }
54
55
    /**
56
     * @param string $name
57
     * @return mixed
58
     */
59
    public function loadHandler(string $name)
60
    {
61
        if (!isset($this->_handler[$name])) {
62
            //            $className             = '\\XoopsModules\\Newbb\\Permission' . \ucfirst($name) . 'Handler';
63
            //            $this->_handler[$name] = new $className($this->db);
64
            $this->_handler[$name] = $this->helper->getHandler('Permission' . \ucfirst($name));
0 ignored issues
show
Bug introduced by
The method getHandler() does not exist on null. ( Ignorable by Annotation )

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

64
            /** @scrutinizer ignore-call */ 
65
            $this->_handler[$name] = $this->helper->getHandler('Permission' . \ucfirst($name));

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...
65
        }
66
67
        return $this->_handler[$name];
68
    }
69
70
    /**
71
     * @param bool $fullname
72
     * @return array
73
     */
74
    public function getValidForumPerms(bool $fullname = false): array
75
    {
76
        /** @var PermissionForumHandler $handler */
77
        $handler = $this->loadHandler('Forum');
78
79
        return $handler->getValidPerms($fullname);
80
    }
81
82
    /**
83
     * @param int|Forum  $forum
84
     * @param bool $topic_locked
85
     * @param bool $isAdmin
86
     * @return array
87
     */
88
    public function getPermissionTable($forum = 0, bool $topic_locked = false, bool $isAdmin = false): array
89
    {
90
        /** @var PermissionForumHandler $handler */
91
        $handler = $this->loadHandler('Forum');
92
        $perm    = $handler->getPermissionTable($forum, $topic_locked, $isAdmin);
93
94
        return $perm;
95
    }
96
97
    /**
98
     * @param int $forum_id
99
     * @return bool
100
     */
101
    public function deleteByForum(int $forum_id): bool
102
    {
103
        $this->cacheHelper->delete('permission_forum');
104
        /** @var PermissionForumHandler $handler */
105
        $handler = $this->loadHandler('Forum');
106
107
        return $handler->deleteByForum($forum_id);
108
    }
109
110
    /**
111
     * @param int $cat_id
112
     * @return bool
113
     */
114
    public function deleteByCategory(int $cat_id):bool
115
    {
116
        $this->cacheHelper->delete('permission_category');
117
        /** @var PermissionCategoryHandler $handler */
118
        $handler = $this->loadHandler('Category');
119
120
        return $handler->deleteByCategory($cat_id);
121
    }
122
123
    /**
124
     * @param int $category
125
     * @param array  $groups
126
     * @return bool
127
     */
128
    public function setCategoryPermission(int $category, array $groups = []): bool
129
    {
130
        $this->cacheHelper->delete('permission_category');
131
        /** @var PermissionCategoryHandler $handler */
132
        $handler = $this->loadHandler('Category');
133
134
        return $handler->setCategoryPermission($category, $groups);
135
    }
136
137
    /**
138
     * @param string $type
139
     * @param string $gperm_name
140
     * @param int    $id
141
     * @return bool
142
     */
143
    public function getPermission(string $type, string $gperm_name = 'access', int $id = 0): bool
144
    {
145
        global $xoopsModule;
146
        $ret = false;
147
        if ($GLOBALS['xoopsUserIsAdmin'] && 'newbb' === $xoopsModule->getVar('dirname')) {
148
            $ret = true;
149
        }
150
151
        $groups = \is_object($GLOBALS['xoopsUser']) ? $GLOBALS['xoopsUser']->getGroups() : [XOOPS_GROUP_ANONYMOUS];
152
        if (!$groups) {
153
            $ret = false;
154
        }
155
        if (!$allowed_groups = $this->getGroups("{$type}_{$gperm_name}", $id)) {
156
            $ret = false;
157
        }
158
159
        if (\count(\array_intersect($allowed_groups, $groups)) > 0) {
160
            $ret = true;
161
        }
162
163
        return $ret;
164
    }
165
166
    /**
167
     * @param string $permName
168
     * @return array
169
     */
170
    public function &getCategories(string $permName = 'access'): array
171
    {
172
        $ret = $this->getAllowedItems('category', "category_{$permName}");
173
174
        return $ret;
175
    }
176
177
    /**
178
     * @param string $permName
179
     * @return array
180
     */
181
    public function getForums(string $permName = 'access'): array
182
    {
183
        $ret = $this->getAllowedItems('forum', "forum_{$permName}");
184
185
        return $ret;
186
    }
187
188
    /**
189
     * @param string $type
190
     * @param string $permName
191
     * @return array
192
     */
193
    public function getAllowedItems(string $type, string $permName): array
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

193
    public function getAllowedItems(/** @scrutinizer ignore-unused */ string $type, string $permName): array

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...
194
    {
195
        $ret = [];
196
197
        $groups = \is_object($GLOBALS['xoopsUser']) ? $GLOBALS['xoopsUser']->getGroups() : [XOOPS_GROUP_ANONYMOUS];
198
        if ((is_countable($groups) ? \count($groups) : 0) < 1) {
199
            return $ret;
200
        }
201
202
        if (!$_cachedPerms = $this->loadPermData($permName)) {
203
            return $ret;
204
        }
205
206
        $allowed_items = [];
207
        foreach ($_cachedPerms as $id => $allowed_groups) {
208
            if (0 == $id || empty($allowed_groups)) {
209
                continue;
210
            }
211
212
            if (\array_intersect($groups, $allowed_groups)) {
213
                $allowed_items[$id] = 1;
214
            }
215
        }
216
        unset($_cachedPerms);
217
        $ret = \array_keys($allowed_items);
218
219
        return $ret;
220
    }
221
222
    /**
223
     * @param string $gperm_name
224
     * @param int    $id
225
     * @return array
226
     */
227
    public function getGroups(string $gperm_name, int $id = 0): array
228
    {
229
        $_cachedPerms = $this->loadPermData($gperm_name);
230
        $groups       = empty($_cachedPerms[$id]) ? [] : \array_unique($_cachedPerms[$id]);
231
        unset($_cachedPerms);
232
233
        return $groups;
234
    }
235
236
    /**
237
     * @param string $permName
238
     * @return array
239
     */
240
    public function createPermData(string $permName = 'forum_all'): array
241
    {
242
        global $xoopsModule;
243
        /** @var \XoopsModuleHandler $moduleHandler */
244
        $perms = [];
245
246
        if (\is_object($xoopsModule) && 'newbb' === $xoopsModule->getVar('dirname')) {
247
            $modid = $xoopsModule->getVar('mid');
248
        } else {
249
            /** @var \XoopsModuleHandler $moduleHandler */
250
            $moduleHandler = \xoops_getHandler('module');
251
            $module        = $moduleHandler->getByDirname('newbb');
252
            $modid         = $module->getVar('mid');
253
            unset($module);
254
        }
255
256
        if (\in_array($permName, ['forum_all', 'category_all'], true)) {
257
            /** @var \XoopsMemberHandler $memberHandler */
258
            $memberHandler = \xoops_getHandler('member');
259
            $groups        = \array_keys($memberHandler->getGroupList());
260
261
            $type = ('category_all' === $permName) ? 'Category' : 'Forum';
262
            /** @var \XoopsPersistableObjectHandler $objectHandler */
263
            $objectHandler = Helper::getInstance()->getHandler($type);
264
            $object_ids    = $objectHandler->getIds();
265
            foreach ($object_ids as $item_id) {
266
                $perms[$permName][$item_id] = $groups;
267
            }
268
        } else {
269
            $grouppermHandler = \xoops_getHandler('groupperm');
0 ignored issues
show
Unused Code introduced by
The assignment to $grouppermHandler is dead and can be removed.
Loading history...
270
            $criteria         = new \CriteriaCompo(new \Criteria('gperm_modid', $modid));
271
            if (!empty($permName) && 'forum_all' !== $permName && 'category_all' !== $permName) {
272
                $criteria->add(new \Criteria('gperm_name', $permName));
273
            }
274
            $permissions = $this->getObjects($criteria);
275
276
            foreach ($permissions as $gperm) {
277
                $item_id                                         = $gperm->getVar('gperm_itemid');
278
                $group_id                                        = (int)$gperm->getVar('gperm_groupid');
279
                $perms[$gperm->getVar('gperm_name')][$item_id][] = $group_id;
280
            }
281
        }
282
        if (\count($perms) > 0) {
283
            foreach (\array_keys($perms) as $perm) {
284
                $this->cacheHelper->write("permission_{$perm}", $perms[$perm]);
285
            }
286
        }
287
        $ret = (!empty($permName) && !empty($perms)) ? @$perms[$permName] : $perms;
288
289
        return $ret;
290
    }
291
292
    /**
293
     * @param string $permName
294
     * @return array
295
     */
296
    public function &loadPermData(string $permName = 'forum_access'): array
297
    {
298
        if (!$perms = $this->cacheHelper->read("permission_{$permName}")) {
299
            $perms = $this->createPermData($permName);
300
        }
301
302
        return $perms;
303
    }
304
305
    /**
306
     * @param string   $perm
307
     * @param int      $itemid
308
     * @param int      $groupid
309
     * @param int|null $mid
310
     * @return bool
311
     */
312
    public function validateRight(string $perm, int $itemid, int $groupid, ?int $mid = null): bool
313
    {
314
        if (empty($mid)) {
315
            if (\is_object($GLOBALS['xoopsModule']) && 'newbb' === $GLOBALS['xoopsModule']->getVar('dirname')) {
316
                $mid = $GLOBALS['xoopsModule']->getVar('mid');
317
            } else {
318
                /** @var \XoopsModuleHandler $moduleHandler */
319
                $moduleHandler = \xoops_getHandler('module');
320
                $mod           = $moduleHandler->getByDirname('newbb');
321
                $mid           = $mod->getVar('mid');
322
                unset($mod);
323
            }
324
        }
325
        if ($this->myCheckRight($perm, $itemid, $groupid, $mid)) {
326
            return true;
327
        }
328
        $this->cacheHelper->delete('permission');
329
        $this->addRight($perm, $itemid, $groupid, $mid);
330
331
        return true;
332
    }
333
334
    /**
335
     * Check permission (directly)
336
     *
337
     * @param string    $gperm_name    Name of permission
338
     * @param int       $gperm_itemid  ID of an item
339
     * @param int|array $gperm_groupid A group ID or an array of group IDs
340
     * @param int       $gperm_modid   ID of a module
341
     *
342
     * @return bool TRUE if permission is enabled
343
     */
344
    public function myCheckRight(string $gperm_name, int $gperm_itemid, $gperm_groupid, int $gperm_modid = 1): bool
345
    {
346
        $ret      = false;
347
        $criteria = new \CriteriaCompo(new \Criteria('gperm_modid', $gperm_modid));
348
        $criteria->add(new \Criteria('gperm_name', $gperm_name));
349
        $gperm_itemid = (int)$gperm_itemid;
350
        if ($gperm_itemid > 0) {
351
            $criteria->add(new \Criteria('gperm_itemid', $gperm_itemid));
352
        }
353
        if (\is_array($gperm_groupid)) {
354
            $criteria2 = new \CriteriaCompo();
355
            foreach ($gperm_groupid as $gid) {
356
                $criteria2->add(new \Criteria('gperm_groupid', $gid), 'OR');
357
            }
358
            $criteria->add($criteria2);
359
        } else {
360
            $criteria->add(new \Criteria('gperm_groupid', $gperm_groupid));
361
        }
362
        if ($this->getCount($criteria) > 0) {
363
            $ret = true;
364
        }
365
366
        return $ret;
367
    }
368
369
    /**
370
     * @param string   $perm
371
     * @param int      $itemid
372
     * @param int      $groupid
373
     * @param int|null $mid
374
     * @return bool
375
     */
376
    public function deleteRight(string $perm, int $itemid, int $groupid, ?int $mid = null): bool
377
    {
378
        $this->cacheHelper->delete('permission');
379
        if (null === $mid) {
380
            if (\is_object($GLOBALS['xoopsModule']) && 'newbb' === $GLOBALS['xoopsModule']->getVar('dirname')) {
381
                $mid = $GLOBALS['xoopsModule']->getVar('mid');
382
            } else {
383
                /** @var \XoopsModuleHandler $moduleHandler */
384
                $moduleHandler = \xoops_getHandler('module');
385
                $mod           = $moduleHandler->getByDirname('newbb');
386
                $mid           = $mod->getVar('mid');
387
                unset($mod);
388
            }
389
        }
390
        if (\is_callable('parent::deleteRight')) {
391
            return self::deleteRight($perm, $itemid, $groupid, $mid);
0 ignored issues
show
Bug Best Practice introduced by
The method XoopsModules\Newbb\Permi...nHandler::deleteRight() is not static, but was called statically. ( Ignorable by Annotation )

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

391
            return self::/** @scrutinizer ignore-call */ deleteRight($perm, $itemid, $groupid, $mid);
Loading history...
392
        }
393
        $criteria = new \CriteriaCompo(new \Criteria('gperm_name', $perm));
394
        $criteria->add(new \Criteria('gperm_groupid', $groupid));
395
        $criteria->add(new \Criteria('gperm_itemid', $itemid));
396
        $criteria->add(new \Criteria('gperm_modid', $mid));
397
        $permsObject = $this->getObjects($criteria);
398
        if (!empty($permsObject)) {
399
            foreach ($permsObject as $permObject) {
400
                $this->delete($permObject);
401
            }
402
        }
403
        unset($criteria, $permsObject);
404
405
        return true;
406
    }
407
408
    /**
409
     * @param int $forum
410
     * @param int $mid
411
     * @return bool
412
     */
413
    public function applyTemplate(int $forum, int $mid = 0): bool
414
    {
415
        $this->cacheHelper->delete('permission_forum');
416
        /** @var PermissionForumHandler $handler */
417
        $handler = $this->loadHandler('Forum');
418
419
        return $handler->applyTemplate($forum, $mid);
420
    }
421
422
    /**
423
     * @return array
424
     */
425
    public function getTemplate(): array
426
    {
427
        /** @var PermissionForumHandler $handler */
428
        $handler  = $this->loadHandler('Forum');
429
        $template = $handler->getTemplate();
430
431
        return $template;
432
    }
433
434
    /**
435
     * @param array $perms
436
     * @param int   $groupid
437
     * @return bool|int
438
     */
439
    public function setTemplate(array $perms, int $groupid = 0)
440
    {
441
        /** @var PermissionForumHandler $handler */
442
        $handler = $this->loadHandler('Forum');
443
444
        return $handler->setTemplate($perms, $groupid);
445
    }
446
}
447