Passed
Push — master ( d3e687...4990f6 )
by Michael
02:43
created

ForumHandler   F

Complexity

Total Complexity 188

Size/Duplication

Total Lines 1039
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
dl 0
loc 1039
rs 1.0168
c 0
b 0
f 0
wmc 188

19 Methods

Rating   Name   Duplication   Size   Complexity  
A getIdsByPermission() 0 5 1
C synchronization() 0 47 12
F display() 0 118 20
C getForumsByCategory() 0 35 7
C getSubforumStats() 0 47 12
A getParents() 0 18 4
A delete() 0 13 1
B getByPermission() 0 18 6
B cleanOrphan() 0 30 5
A insert() 0 12 3
F getAllTopics() 0 303 68
B getTree() 0 22 5
A applyPermissionTemplate() 0 6 1
B getPermission() 0 43 6
B getArrayTree() 0 22 5
D getTopicCount() 0 80 22
A deletePermission() 0 6 1
A __construct() 0 3 1
C getIdsByValues() 0 31 8

How to fix   Complexity   

Complex Class

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

1
<?php namespace XoopsModules\Newbb;
2
3
/**
4
 * Newbb module
5
 *
6
 * You may not change or alter any portion of this comment or credits
7
 * of supporting developers from this source code or any supporting source code
8
 * which is considered copyrighted (c) material of the original comment or credit authors.
9
 * This program is distributed in the hope that it will be useful,
10
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12
 *
13
 * @copyright       XOOPS Project (https://xoops.org)
14
 * @license         GNU GPL 2 or later (http://www.gnu.org/licenses/gpl-2.0.html)
15
 * @package         newbb
16
 * @since           4.0
17
 * @author          Taiwen Jiang <[email protected]>
18
 */
19
20
use XoopsModules\Newbb;
21
22
// defined('XOOPS_ROOT_PATH') || die('Restricted access');
0 ignored issues
show
Unused Code Comprehensibility introduced by
70% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
23
24
/**
25
 * Class ForumHandler
26
 */
27
class ForumHandler extends \XoopsPersistableObjectHandler
0 ignored issues
show
Bug introduced by
The type XoopsPersistableObjectHandler was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
28
{
29
    /**
30
     * @param null|\XoopsDatabase $db
31
     */
32
    public function __construct(\XoopsDatabase $db)
0 ignored issues
show
Bug introduced by
The type XoopsDatabase was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
33
    {
34
        parent::__construct($db, 'newbb_forums', Forum::class, 'forum_id', 'forum_name');
35
    }
36
37
    /**
38
     * @param \XoopsObject $object
39
     * @param  bool        $force
40
     * @return bool
41
     * @internal param \XoopsObject $forum
42
     */
43
44
    public function insert(\XoopsObject $object, $force = true) //insert($forum)
0 ignored issues
show
Bug introduced by
The type XoopsObject was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
45
    {
46
        $forum = $object;
47
        if (!parent::insert($forum, true)) {
48
            return false;
49
        }
50
51
        if ($forum->isNew()) {
52
            $this->applyPermissionTemplate($forum);
53
        }
54
55
        return $forum->getVar('forum_id');
56
    }
57
58
    /**
59
     * @param \XoopsObject $forum
60
     * @param  bool        $force
61
     * @return bool
62
     */
63
    public function delete(\XoopsObject $forum, $force = false) //delete(&$forum)
64
    {
65
        global $xoopsModule;
0 ignored issues
show
Compatibility Best Practice introduced by
Use of global functionality is not recommended; it makes your code harder to test, and less reusable.

Instead of relying on global state, we recommend one of these alternatives:

1. Pass all data via parameters

function myFunction($a, $b) {
    // Do something
}

2. Create a class that maintains your state

class MyClass {
    private $a;
    private $b;

    public function __construct($a, $b) {
        $this->a = $a;
        $this->b = $b;
    }

    public function myFunction() {
        // Do something
    }
}
Loading history...
66
        // RMV-NOTIFY
67
        xoops_notification_deletebyitem($xoopsModule->getVar('mid'), 'forum', $forum->getVar('forum_id'));
0 ignored issues
show
Bug introduced by
The function xoops_notification_deletebyitem was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

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

67
        /** @scrutinizer ignore-call */ 
68
        xoops_notification_deletebyitem($xoopsModule->getVar('mid'), 'forum', $forum->getVar('forum_id'));
Loading history...
68
        // Get list of all topics in forum, to delete them too
69
        /** @var Newbb\TopicHandler $topicHandler */
70
        $topicHandler = Newbb\Helper::getInstance()->getHandler('Topic');
71
        $topicHandler->deleteAll(new \Criteria('forum_id', $forum->getVar('forum_id')), true, true);
0 ignored issues
show
Bug introduced by
The type Criteria was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
72
        $this->updateAll('parent_forum', $forum->getVar('parent_forum'), new \Criteria('parent_forum', $forum->getVar('forum_id')));
73
        $this->deletePermission($forum);
74
75
        return parent::delete($forum);
76
    }
77
78
    /**
79
     * @param  string $perm
80
     * @return mixed
81
     */
82
    public function getIdsByPermission($perm = 'access')
83
    {
84
        /** var Newbb\PermissionHandler $permHandler */
85
        $permHandler = Newbb\Helper::getInstance()->getHandler('Permission');
86
        return $permHandler->getForums($perm);
87
    }
88
89
    /**
90
     * @param  int    $cat
91
     * @param  string $permission
92
     * @param  null   $tags
0 ignored issues
show
Documentation Bug introduced by
Are you sure the doc-type for parameter $tags is correct as it would always require null to be passed?
Loading history...
93
     * @param  bool   $asObject
94
     * @return array
95
     */
96
    public function &getByPermission($cat = 0, $permission = 'access', $tags = null, $asObject = true)
97
    {
98
        $_cachedForums = [];
99
        if (!$valid_ids = $this->getIdsByPermission($permission)) {
100
            return $_cachedForums;
101
        }
102
103
        $criteria = new \CriteriaCompo(new \Criteria('forum_id', '(' . implode(', ', $valid_ids) . ')', 'IN'));
0 ignored issues
show
Bug introduced by
The type CriteriaCompo was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
104
        if (is_numeric($cat) && $cat > 0) {
105
            $criteria->add(new \Criteria('cat_id', (int)$cat));
106
        } elseif (is_array($cat) && count($cat) > 0) {
107
            $criteria->add(new \Criteria('cat_id', '(' . implode(', ', $cat) . ')', 'IN'));
108
        }
109
        $criteria->setSort('forum_order');
110
        $criteria->setOrder('ASC');
111
        $_cachedForums = $this->getAll($criteria, $tags, $asObject);
112
113
        return $_cachedForums;
114
    }
115
116
    /**
117
     * @param  int    $categoryid
118
     * @param  string $permission
119
     * @param  bool   $asObject
120
     * @param  null   $tags
0 ignored issues
show
Documentation Bug introduced by
Are you sure the doc-type for parameter $tags is correct as it would always require null to be passed?
Loading history...
121
     * @return array
122
     */
123
    public function &getForumsByCategory($categoryid = 0, $permission = '', $asObject = true, $tags = null)
124
    {
125
        $forums = $this->getByPermission($categoryid, $permission, $tags);
126
        if ($asObject) {
127
            return $forums;
128
        }
129
130
        $forums_array = [];
131
        $array_cat    = [];
0 ignored issues
show
Unused Code introduced by
The assignment to $array_cat is dead and can be removed.
Loading history...
132
        $array_forum  = [];
133
        if (!is_array($forums)) {
0 ignored issues
show
introduced by
The condition is_array($forums) is always true.
Loading history...
134
            return [];
135
        }
136
        foreach (array_keys($forums) as $forumid) {
137
            $forum                                                  = $forums[$forumid];
138
            $forums_array[$forum->getVar('parent_forum')][$forumid] = [
139
                'cid'   => $forum->getVar('cat_id'),
140
                'title' => $forum->getVar('forum_name')
141
            ];
142
        }
143
        if (!isset($forums_array[0])) {
144
            $ret = [];
145
146
            return $ret;
147
        }
148
        foreach ($forums_array[0] as $key => $forum) {
149
            if (isset($forums_array[$key])) {
150
                $forum['sub'] = $forums_array[$key];
151
            }
152
            $array_forum[$forum['cid']][$key] = $forum;
153
        }
154
        ksort($array_forum);
155
        unset($forums, $forums_array);
156
157
        return $array_forum;
158
    }
159
160
    /**
161
     * @param        $forum
162
     * @param  null  $criteria
0 ignored issues
show
Documentation Bug introduced by
Are you sure the doc-type for parameter $criteria is correct as it would always require null to be passed?
Loading history...
163
     * @return array
164
     */
165
    public function getAllTopics(&$forum, $criteria = null)
166
    {
167
        global $myts, $viewAllForums;
0 ignored issues
show
Compatibility Best Practice introduced by
Use of global functionality is not recommended; it makes your code harder to test, and less reusable.

Instead of relying on global state, we recommend one of these alternatives:

1. Pass all data via parameters

function myFunction($a, $b) {
    // Do something
}

2. Create a class that maintains your state

class MyClass {
    private $a;
    private $b;

    public function __construct($a, $b) {
        $this->a = $a;
        $this->b = $b;
    }

    public function myFunction() {
        // Do something
    }
}
Loading history...
168
        $startdate = '';
169
170
        require_once $GLOBALS['xoops']->path('modules/newbb/include/functions.render.php');
171
        require_once $GLOBALS['xoops']->path('modules/newbb/include/functions.session.php');
172
        require_once $GLOBALS['xoops']->path('modules/newbb/include/functions.time.php');
173
        require_once $GLOBALS['xoops']->path('modules/newbb/include/functions.read.php');
174
        require_once $GLOBALS['xoops']->path('modules/newbb/include/functions.topic.php');
175
176
        $criteria_vars = ['startdate', 'start', 'sort', 'order', 'type', 'status', 'excerpt'];
177
        foreach ($criteria_vars as $var) {
178
            ${$var} = $criteria[$var];
179
        }
180
181
        $topic_lastread = newbbGetCookie('LT', true);
0 ignored issues
show
Unused Code introduced by
The assignment to $topic_lastread is dead and can be removed.
Loading history...
182
        $criteria_forum = '';
183
        if (is_object($forum)) {
184
            $criteria_forum = ' AND t.forum_id = ' . $forum->getVar('forum_id');
185
            $hot_threshold  = $forum->getVar('hot_threshold');
186
        } else {
187
            $hot_threshold = 10;
188
            if (is_array($forum) && count($forum) > 0) {
189
                $criteria_forum = ' AND t.forum_id IN (' . implode(',', array_keys($forum)) . ')';
190
            } elseif (!empty($forum)) {
191
                $criteria_forum = ' AND t.forum_id =' . (int)$forum;
192
            }
193
        }
194
195
        $criteria_post    = $startdate ? ' p.post_time > ' . $startdate : ' 1 = 1 ';
196
        $criteria_topic   = empty($type) ? '' : " AND t.type_id={$type}";
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $type does not exist. Did you maybe mean $typen?
Loading history...
197
        $criteria_extra   = '';
198
        $criteria_approve = ' AND t.approved = 1';
199
        $post_on          = ' p.post_id = t.topic_last_post_id';
0 ignored issues
show
Unused Code introduced by
The assignment to $post_on is dead and can be removed.
Loading history...
200
        $leftjoin         = ' LEFT JOIN ' . $this->db->prefix('newbb_posts') . ' p ON p.post_id = t.topic_last_post_id';
201
        $sort_array       = [];
202
        switch ($status) {
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $status does not exist. Did you maybe mean $topic_status?
Loading history...
203
            case 'digest':
204
                $criteria_extra = ' AND t.topic_digest = 1';
205
                break;
206
207
            case 'unreplied':
208
                $criteria_extra = ' AND t.topic_replies < 1';
209
                break;
210
211
            case 'unread':
212
                if (empty($GLOBALS['xoopsModuleConfig']['read_mode'])) {
0 ignored issues
show
Unused Code introduced by
This if statement is empty and can be removed.

This check looks for the bodies of if statements that have no statements or where all statements have been commented out. This may be the result of changes for debugging or the code may simply be obsolete.

These if bodies can be removed. If you have an empty if but statements in the else branch, consider inverting the condition.

if (rand(1, 6) > 3) {
//print "Check failed";
} else {
    print "Check succeeded";
}

could be turned into

if (rand(1, 6) <= 3) {
    print "Check succeeded";
}

This is much more concise to read.

Loading history...
213
                } elseif (2 == $GLOBALS['xoopsModuleConfig']['read_mode']) {
214
                    // START irmtfan use read_uid to find the unread posts when the user is logged in
215
                    $read_uid = is_object($GLOBALS['xoopsUser']) ? $GLOBALS['xoopsUser']->getVar('uid') : 0;
216
                    if (!empty($read_uid)) {
217
                        $leftjoin      .= ' LEFT JOIN ' . $this->db->prefix('newbb_reads_topic') . ' r ON r.read_item = t.topic_id AND r.uid = ' . $read_uid . ' ';
218
                        $criteria_post .= ' AND (r.read_id IS NULL OR r.post_id < t.topic_last_post_id)';
219
                    } else {
0 ignored issues
show
Unused Code introduced by
This else statement is empty and can be removed.

This check looks for the else branches of if statements that have no statements or where all statements have been commented out. This may be the result of changes for debugging or the code may simply be obsolete.

These else branches can be removed.

if (rand(1, 6) > 3) {
print "Check failed";
} else {
    //print "Check succeeded";
}

could be turned into

if (rand(1, 6) > 3) {
    print "Check failed";
}

This is much more concise to read.

Loading history...
220
                    }
221
                    // END irmtfan use read_uid to find the unread posts when the user is logged in
222
                } elseif (1 == $GLOBALS['xoopsModuleConfig']['read_mode']) {
223
                    // START irmtfan fix read_mode = 1 bugs - for all users (member and anon)
224
                    if ($time_criterion = max($GLOBALS['last_visit'], $startdate)) {
225
                        $criteria_post  = ' p.post_time > ' . $time_criterion; // for all users
226
                        $topics         = [];
227
                        $topic_lastread = newbbGetCookie('LT', true);
228
                        if (count($topic_lastread) > 0) {
229
                            foreach ($topic_lastread as $id => $time) {
230
                                if ($time > $time_criterion) {
231
                                    $topics[] = $id;
232
                                }
233
                            }
234
                        }
235
                        if (count($topics) > 0) {
236
                            $criteria_extra = ' AND t.topic_id NOT IN (' . implode(',', $topics) . ')';
237
                        }
238
                    }
239
                    // END irmtfan fix read_mode = 1 bugs - for all users (member and anon)
240
                }
241
                break;
242
            case 'pending':
243
                $post_on          = ' p.topic_id = t.topic_id';
244
                $criteria_post    .= ' AND p.pid = 0';
245
                $criteria_approve = ' AND t.approved = 0';
246
                break;
247
248
            case 'deleted':
249
                $criteria_approve = ' AND t.approved = -1';
250
                break;
251
252
            case 'all': // For viewall.php; do not display sticky topics at first
253
            case 'active': // same as "all"
254
                break;
255
256
            default:
257
                if ($startdate > 0) {
258
                    $criteria_post = ' (p.post_time > ' . $startdate . ' OR t.topic_sticky=1)';
259
                }
260
                $sort_array[] = 't.topic_sticky DESC';
261
                break;
262
        }
263
264
        $select = 't.*, ' . ' p.post_time as last_post_time, p.poster_name as last_poster_name, p.icon, p.post_id, p.uid';
265
        $from   = $this->db->prefix('newbb_topics') . ' t ' . $leftjoin;
266
        $where  = $criteria_post . $criteria_topic . $criteria_forum . $criteria_extra . $criteria_approve;
267
268
        if ($excerpt) {
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $excerpt does not exist. Did you maybe mean $topic_excerpt?
Loading history...
269
            $select .= ', p.post_karma, p.require_reply, pt.post_text';
270
            $from   .= ' LEFT JOIN ' . $this->db->prefix('newbb_posts_text') . ' pt ON pt.post_id = t.topic_last_post_id';
271
        }
272
        if ('u.uname' === $sort) {
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $sort seems to be never defined.
Loading history...
273
            $sort = 't.topic_poster';
274
        }
275
276
        $sort_array[] = trim($sort . ' ' . $order);
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $order seems to be never defined.
Loading history...
Comprehensibility Best Practice introduced by
The variable $sort does not seem to be defined for all execution paths leading up to this point.
Loading history...
277
        $sortby       = implode(', ', array_filter($sort_array));
278
        if (empty($sortby)) {
279
            $sortby = 't.topic_last_post_id DESC';
280
        }
281
282
        $sql = 'SELECT ' . $select . ' FROM ' . $from . ' WHERE ' . $where . ' ORDER BY ' . $sortby;
283
284
        if (!$result = $this->db->query($sql, $GLOBALS['xoopsModuleConfig']['topics_per_page'], $start)) {
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $start does not exist. Did you maybe mean $startdate?
Loading history...
285
            redirect_header('index.php', 2, _MD_NEWBB_ERROROCCURED);
0 ignored issues
show
Bug introduced by
The function redirect_header was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

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

285
            /** @scrutinizer ignore-call */ 
286
            redirect_header('index.php', 2, _MD_NEWBB_ERROROCCURED);
Loading history...
286
        }
287
288
        $sticky  = 0;
289
        $topics  = [];
290
        $posters = [];
291
        $reads   = [];
292
        $types   = [];
0 ignored issues
show
Unused Code introduced by
The assignment to $types is dead and can be removed.
Loading history...
293
294
        /** @var Newbb\TypeHandler $typeHandler */
295
        $typeHandler = Newbb\Helper::getInstance()->getHandler('Type');
296
        $typen       = $typeHandler->getByForum($forum->getVar('forum_id'));
297
       while (false !== ($myrow = $this->db->fetchArray($result))) {
298
            if ($myrow['topic_sticky']) {
299
                ++$sticky;
300
            }
301
302
            // ------------------------------------------------------
303
            // topic_icon: priority: sticky -> digest -> regular
304
305
            if ($myrow['topic_haspoll']) {
306
                if ($myrow['topic_sticky']) {
307
                    $topic_icon = newbbDisplayImage('topic_sticky', _MD_NEWBB_TOPICSTICKY) . '<br>' . newbbDisplayImage('poll', _MD_NEWBB_TOPICHASPOLL);
308
                } else {
309
                    $topic_icon = newbbDisplayImage('poll', _MD_NEWBB_TOPICHASPOLL);
310
                }
311
            } elseif ($myrow['topic_sticky']) {
312
                $topic_icon = newbbDisplayImage('topic_sticky', _MD_NEWBB_TOPICSTICKY);
313
            } elseif (!empty($myrow['icon'])) {
314
                $topic_icon = '<img src="' . XOOPS_URL . '/images/subject/' . htmlspecialchars($myrow['icon']) . '" alt="" />';
0 ignored issues
show
Bug introduced by
The constant XoopsModules\Newbb\XOOPS_URL was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
315
            } else {
316
                $topic_icon = '<img src="' . XOOPS_URL . '/images/icons/no_posticon.gif" alt="" />';
317
            }
318
319
            // ------------------------------------------------------
320
            // rating_img
321
            $rating = number_format($myrow['rating'] / 2, 0);
322
            // irmtfan - add alt key for rating
323
            if ($rating < 1) {
324
                $rating_img = newbbDisplayImage('blank');
325
            } else {
326
                $rating_img = newbbDisplayImage('rate' . $rating, constant('_MD_NEWBB_RATE' . $rating));
327
            }
328
            // ------------------------------------------------------
329
            // topic_page_jump
330
            $topic_page_jump      = '';
331
            $topic_page_jump_icon = '';
0 ignored issues
show
Unused Code introduced by
The assignment to $topic_page_jump_icon is dead and can be removed.
Loading history...
332
            $totalpages           = ceil(($myrow['topic_replies'] + 1) / $GLOBALS['xoopsModuleConfig']['posts_per_page']);
333
            if ($totalpages > 1) {
334
                $topic_page_jump .= '&nbsp;&nbsp;';
335
                $append          = false;
336
                for ($i = 1; $i <= $totalpages; ++$i) {
337
                    if ($i > 3 && $i < $totalpages) {
338
                        if (!$append) {
339
                            $topic_page_jump .= '...';
340
                            $append          = true;
341
                        }
342
                    } else {
343
                        $topic_page_jump .= '[<a href="' . XOOPS_URL . '/modules/newbb/viewtopic.php?topic_id=' . $myrow['topic_id'] . '&amp;start=' . (($i - 1) * $GLOBALS['xoopsModuleConfig']['posts_per_page']) . '">' . $i . '</a>]';
344
                        // irmtfan remove here and move
345
                        //$topic_page_jump_icon = "<a href='" . XOOPS_URL . "/modules/newbb/viewtopic.php?post_id=" . $myrow['post_id'] . "&amp;start=" . (($i - 1) * $GLOBALS['xoopsModuleConfig']['posts_per_page']) . "'>" . newbbDisplayImage('lastposticon',_MD_NEWBB_GOTOLASTPOST) . '</a>';
0 ignored issues
show
Unused Code Comprehensibility introduced by
44% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
346
                    }
347
                }
348
            }
349
            // irmtfan - move here for both topics with and without pages
350
            $topic_page_jump_icon = "<a href='" . XOOPS_URL . '/modules/newbb/viewtopic.php?post_id=' . $myrow['post_id'] . "'>" . newbbDisplayImage('lastposticon', _MD_NEWBB_GOTOLASTPOST) . '</a>';
351
352
            // ------------------------------------------------------
353
            // => topic array
354
            $forum_link = '';
355
            if (!empty($viewAllForums[$myrow['forum_id']])) {
356
                $forum_link = '<a href="' . XOOPS_URL . '/modules/newbb/viewforum.php?forum=' . $myrow['forum_id'] . '">' . $viewAllForums[$myrow['forum_id']]['forum_name'] . '</a>';
357
            }
358
359
            $topic_title = $myts->htmlSpecialChars($myrow['topic_title']);
360
            // irmtfan remove here and move to for loop
361
            //if ($myrow['type_id'] > 0) {
0 ignored issues
show
Unused Code Comprehensibility introduced by
65% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
362
            //$topic_title = '<span style="color:'.$typen[$myrow["type_id"]]["type_color"].'">['.$typen[$myrow["type_id"]]["type_name"].']</span> '.$topic_title.'';
0 ignored issues
show
Unused Code Comprehensibility introduced by
75% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
363
            //}
364
            if ($myrow['topic_digest']) {
365
                $topic_title = "<span class='digest'>" . $topic_title . '</span>';
366
            }
367
368
            if (0 == $excerpt) {
369
                $topic_excerpt = '';
370
            } elseif (($myrow['post_karma'] > 0 || $myrow['require_reply'] > 0) && !newbbIsAdmin($forum)) {
371
                $topic_excerpt = '';
372
            } else {
373
                $topic_excerpt = xoops_substr(newbbHtml2text($myts->displayTarea($myrow['post_text'])), 0, $excerpt);
0 ignored issues
show
Bug introduced by
The function xoops_substr was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

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

373
                $topic_excerpt = /** @scrutinizer ignore-call */ xoops_substr(newbbHtml2text($myts->displayTarea($myrow['post_text'])), 0, $excerpt);
Loading history...
374
                $topic_excerpt = str_replace('[', '&#91;', $myts->htmlSpecialChars($topic_excerpt));
375
            }
376
            // START irmtfan move here
377
            $topics[$myrow['topic_id']] = [
378
                'topic_id'             => $myrow['topic_id'],
379
                'topic_icon'           => $topic_icon,
380
                'type_id'              => $myrow['type_id'],
381
                //'type_text'                 => $topic_prefix,/*irmtfan remove here and move to for loop*/
382
                'topic_title'          => $topic_title,
383
                //'topic_link'                => XOOPS_URL . '/modules/newbb/viewtopic.php?topic_id=' . $myrow['topic_id'],
0 ignored issues
show
Unused Code Comprehensibility introduced by
48% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
384
                'topic_link'           => 'viewtopic.php?topic_id=' . $myrow['topic_id'],
385
                'rating_img'           => $rating_img,
386
                'topic_page_jump'      => $topic_page_jump,
387
                'topic_page_jump_icon' => $topic_page_jump_icon,
388
                'topic_replies'        => $myrow['topic_replies'],
389
390
                'topic_digest' => $myrow['topic_digest'],
391
                //mb
392
393
                'topic_poster_uid'       => $myrow['topic_poster'],
394
                'topic_poster_name'      => $myts->htmlSpecialChars($myrow['poster_name'] ?: $GLOBALS['xoopsConfig']['anonymous']),
395
                'topic_views'            => $myrow['topic_views'],
396
                'topic_time'             => newbbFormatTimestamp($myrow['topic_time']),
397
                'topic_last_posttime'    => newbbFormatTimestamp($myrow['last_post_time']),
398
                'topic_last_poster_uid'  => $myrow['uid'],
399
                'topic_last_poster_name' => $myts->htmlSpecialChars($myrow['last_poster_name'] ?: $GLOBALS['xoopsConfig']['anonymous']),
400
                'topic_forum_link'       => $forum_link,
401
                'topic_excerpt'          => $topic_excerpt,
402
                'stick'                  => empty($myrow['topic_sticky']),
403
                'stats'                  => [
404
                    $myrow['topic_status'],
405
                    $myrow['topic_digest'],
406
                    $myrow['topic_replies']
407
                ],
408
                /* irmtfan uncomment use ib the for loop*/
409
                //"topic_poster"              => $topic_poster,/*irmtfan remove here and move to for loop*/
410
                //"topic_last_poster"         => $topic_last_poster,/*irmtfan remove here and move to for loop*/
411
                //"topic_folder"              => newbbDisplayImage($topic_folder,$topic_folder_text),/*irmtfan remove here and move to for loop*/
0 ignored issues
show
Unused Code Comprehensibility introduced by
36% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
412
            ];
413
            // END irmtfan move here
414
            /* users */
415
            $posters[$myrow['topic_poster']] = 1;
416
            $posters[$myrow['uid']]          = 1;
417
            // reads
418
            if (!empty($GLOBALS['xoopsModuleConfig']['read_mode'])) {
419
                $reads[$myrow['topic_id']] = (1 == $GLOBALS['xoopsModuleConfig']['read_mode']) ? $myrow['last_post_time'] : $myrow['topic_last_post_id'];
420
            }
421
        }// irmtfan while end
422
        // START irmtfan move to a for loop
423
        $posters_name = newbbGetUnameFromIds(array_keys($posters), $GLOBALS['xoopsModuleConfig']['show_realname'], true);
424
        //$topic_poster = newbbGetUnameFromId($myrow['topic_poster'], $GLOBALS['xoopsModuleConfig']['show_realname'], true);
0 ignored issues
show
Unused Code Comprehensibility introduced by
75% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
425
        //$topic_last_poster = newbbGetUnameFromId($myrow['uid'], $GLOBALS['xoopsModuleConfig']['show_realname'], true);
0 ignored issues
show
Unused Code Comprehensibility introduced by
75% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
426
        $topic_isRead = newbbIsRead('topic', $reads);
427
        foreach (array_keys($topics) as $id) {
428
            $topics[$id]['topic_read'] = empty($topic_isRead[$id]) ? 0 : 1; // add topic-read/topic-new smarty variable
429
            if (!empty($topics[$id]['type_id']) && isset($typen[$topics[$id]['type_id']])) {
430
                $topics[$id]['topic_title'] = getTopicTitle($topics[$id]['topic_title'], $typen[$topics[$id]['type_id']]['type_name'], $typen[$topics[$id]['type_id']]['type_color']);
431
            }
432
            //$topic_prefix =  (!empty($typen[$myrow['type_id']])) ? getTopicTitle("", $typen[$myrow['type_id']]["type_name"], $typen[$myrow['type_id']]["type_color"]) : "";
0 ignored issues
show
Unused Code Comprehensibility introduced by
82% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
433
            $topics[$id]['topic_poster']      = !empty($posters_name[$topics[$id]['topic_poster_uid']]) ? $posters_name[$topics[$id]['topic_poster_uid']] : $topics[$id]['topic_poster_name'];
434
            $topics[$id]['topic_last_poster'] = !empty($posters_name[$topics[$id]['topic_last_poster_uid']]) ? $posters_name[$topics[$id]['topic_last_poster_uid']] : $topics[$id]['topic_last_poster_name'];
435
436
            // ------------------------------------------------------
437
            // topic_folder: priority: newhot -> hot/new -> regular
438
            list($topic_status, $topic_digest, $topic_replies) = $topics[$id]['stats'];
439
            if (1 == $topic_status) {
440
                $topic_folder      = 'topic_locked';
441
                $topic_folder_text = _MD_NEWBB_TOPICLOCKED;
442
            } else {
443
                if ($topic_digest) {
444
                    $topic_folder      = 'topic_digest';
445
                    $topic_folder_text = _MD_NEWBB_TOPICDIGEST;
446
                } elseif ($topic_replies >= $hot_threshold) {
447
                    $topic_folder      = empty($topic_isRead[$id]) ? 'topic_hot_new' : 'topic_hot';
448
                    $topic_folder_text = empty($topic_isRead[$id]) ? _MD_NEWBB_MORETHAN : _MD_NEWBB_MORETHAN2;
449
                } else {
450
                    $topic_folder      = empty($topic_isRead[$id]) ? 'topic_new' : 'topic';
451
                    $topic_folder_text = empty($topic_isRead[$id]) ? _MD_NEWBB_NEWPOSTS : _MD_NEWBB_NONEWPOSTS;
452
                }
453
            }
454
            $topics[$id]['topic_folder'] = newbbDisplayImage($topic_folder, $topic_folder_text);
455
            unset($topics[$id]['topic_poster_name'], $topics[$id]['topic_last_poster_name'], $topics[$id]['stats']);
456
        } // irmtfan end for loop
457
        // END irmtfan move to a for loop
458
        if (count($topics) > 0) {
459
            $sql = ' SELECT DISTINCT topic_id FROM ' . $this->db->prefix('newbb_posts') . " WHERE attachment != ''" . ' AND topic_id IN (' . implode(',', array_keys($topics)) . ')';
460
            if ($result = $this->db->query($sql)) {
461
                while (list($topic_id) = $this->db->fetchRow($result)) {
462
                    $topics[$topic_id]['attachment'] = '&nbsp;' . newbbDisplayImage('attachment', _MD_NEWBB_TOPICSHASATT);
463
                }
464
            }
465
        }
466
467
        return [$topics, $sticky];
468
    }
469
470
    /**
471
     * @param $forum
472
     * @param $startdate
473
     * @param $type
474
     * @return null|int
475
     */
476
    public function getTopicCount(&$forum, $startdate, $type)
477
    {
478
        require_once $GLOBALS['xoops']->path('modules/newbb/include/functions.session.php');
479
480
        $criteria_extra   = '';
481
        $criteria_approve = ' AND t.approved = 1'; // any others?
482
        $leftjoin         = ' LEFT JOIN ' . $this->db->prefix('newbb_posts') . ' p ON p.post_id = t.topic_last_post_id';
483
        $criteria_post    = ' p.post_time > ' . $startdate;
484
        switch ($type) {
485
            case 'digest':
486
                $criteria_extra = ' AND topic_digest = 1';
487
                break;
488
            case 'unreplied':
489
                $criteria_extra = ' AND topic_replies < 1';
490
                break;
491
            case 'unread':
492
                if (empty($GLOBALS['xoopsModuleConfig']['read_mode'])) {
0 ignored issues
show
Unused Code introduced by
This if statement is empty and can be removed.

This check looks for the bodies of if statements that have no statements or where all statements have been commented out. This may be the result of changes for debugging or the code may simply be obsolete.

These if bodies can be removed. If you have an empty if but statements in the else branch, consider inverting the condition.

if (rand(1, 6) > 3) {
//print "Check failed";
} else {
    print "Check succeeded";
}

could be turned into

if (rand(1, 6) <= 3) {
    print "Check succeeded";
}

This is much more concise to read.

Loading history...
493
                } elseif (2 == $GLOBALS['xoopsModuleConfig']['read_mode']) {
494
                    // START irmtfan use read_uid to find the unread posts when the user is logged in
495
496
                    $read_uid = is_object($GLOBALS['xoopsUser']) ? $GLOBALS['xoopsUser']->getVar('uid') : 0;
497
                    if (!empty($read_uid)) {
498
                        $leftjoin      .= ' LEFT JOIN ' . $this->db->prefix('newbb_reads_topic') . ' r ON r.read_item = t.topic_id AND r.uid = ' . $read_uid . ' ';
499
                        $criteria_post .= ' AND (r.read_id IS NULL OR r.post_id < t.topic_last_post_id)';
500
                    } else {
0 ignored issues
show
Unused Code introduced by
This else statement is empty and can be removed.

This check looks for the else branches of if statements that have no statements or where all statements have been commented out. This may be the result of changes for debugging or the code may simply be obsolete.

These else branches can be removed.

if (rand(1, 6) > 3) {
print "Check failed";
} else {
    //print "Check succeeded";
}

could be turned into

if (rand(1, 6) > 3) {
    print "Check failed";
}

This is much more concise to read.

Loading history...
501
                    }
502
                    // END irmtfan use read_uid to find the unread posts when the user is logged in
503
                } elseif (1 == $GLOBALS['xoopsModuleConfig']['read_mode']) {
504
                    // START irmtfan fix read_mode = 1 bugs - for all users (member and anon)
505
                    if ($time_criterion = max($GLOBALS['last_visit'], $startdate)) {
506
                        $criteria_post  = ' p.post_time > ' . $time_criterion; // for all users
507
                        $topics         = [];
508
                        $topic_lastread = newbbGetCookie('LT', true);
509
                        if (count($topic_lastread) > 0) {
510
                            foreach ($topic_lastread as $id => $time) {
511
                                if ($time > $time_criterion) {
512
                                    $topics[] = $id;
513
                                }
514
                            }
515
                        }
516
                        if (count($topics) > 0) {
517
                            $criteria_extra = ' AND t.topic_id NOT IN (' . implode(',', $topics) . ')';
518
                        }
519
                    }
520
                    // END irmtfan fix read_mode = 1 bugs - for all users (member and anon)
521
                }
522
                break;
523
            case 'pending':
524
                $criteria_approve = ' AND t.approved = 0';
525
                break;
526
            case 'deleted':
527
                $criteria_approve = ' AND t.approved = -1';
528
                break;
529
            case 'all':
530
                break;
531
            default:
532
                $criteria_post = ' (p.post_time > ' . $startdate . ' OR t.topic_sticky=1)';
533
                break;
534
        }
535
        $criteria_forum = '';
536
        if (is_object($forum)) {
537
            $criteria_forum = ' AND t.forum_id = ' . $forum->getVar('forum_id');
538
        } else {
539
            if (is_array($forum) && count($forum) > 0) {
540
                $criteria_forum = ' AND t.forum_id IN (' . implode(',', array_keys($forum)) . ')';
541
            } elseif (!empty($forum)) {
542
                $criteria_forum = ' AND t.forum_id =' . (int)$forum;
543
            }
544
        }
545
546
        $sql = 'SELECT COUNT(*) AS count FROM ' . $this->db->prefix('newbb_topics') . ' t ' . $leftjoin;
547
        $sql .= ' WHERE ' . $criteria_post . $criteria_forum . $criteria_extra . $criteria_approve;
548
        if (!$result = $this->db->query($sql)) {
549
            //xoops_error($this->db->error().'<br>'.$sql);
0 ignored issues
show
Unused Code Comprehensibility introduced by
67% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
550
            return null;
551
        }
552
        $myrow = $this->db->fetchArray($result);
553
        $count = $myrow['count'];
554
555
        return $count;
556
    }
557
558
    // get permission
559
560
    /**
561
     * @param         $forum
562
     * @param  string $type
563
     * @param  bool   $checkCategory
564
     * @return bool
565
     */
566
    public function getPermission($forum, $type = 'access', $checkCategory = true)
567
    {
568
        global $xoopsModule;
0 ignored issues
show
Compatibility Best Practice introduced by
Use of global functionality is not recommended; it makes your code harder to test, and less reusable.

Instead of relying on global state, we recommend one of these alternatives:

1. Pass all data via parameters

function myFunction($a, $b) {
    // Do something
}

2. Create a class that maintains your state

class MyClass {
    private $a;
    private $b;

    public function __construct($a, $b) {
        $this->a = $a;
        $this->b = $b;
    }

    public function myFunction() {
        // Do something
    }
}
Loading history...
569
        static $_cachedPerms;
570
571
        if ('all' === $type) {
572
            return true;
573
        }
574
575
        include_once __DIR__ . '/../include/functions.user.php';
576
        if (newbbIsAdmin($forum)) {
577
            return true;
578
        }
579
        //if ($GLOBALS["xoopsUserIsAdmin"] && $xoopsModule->getVar("dirname") === "newbb") {
0 ignored issues
show
Unused Code Comprehensibility introduced by
66% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
580
        //return true;
581
        //}
582
583
        if (!is_object($forum)) {
584
            $forum = $this->get($forum);
585
        }
586
587
        if (!empty($checkCategory)) {
588
            /** @var Newbb\CategoryHandler $categoryHandler */
589
            $categoryHandler = Newbb\Helper::getInstance()->getHandler('Category');
590
            $categoryPerm    = $categoryHandler->getPermission($forum->getVar('cat_id'));
591
            if (!$categoryPerm) {
592
                return false;
593
            }
594
        }
595
596
        $type = strtolower($type);
597
        // START irmtfan commented and removed
598
        //if ('moderate' === $type) {
0 ignored issues
show
Unused Code Comprehensibility introduced by
55% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
599
        //require_once $GLOBALS['xoops']->path('modules/newbb/include/functions.user.php');
0 ignored issues
show
Unused Code Comprehensibility introduced by
84% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
600
        //$permission = newbbIsModerator($forum);
0 ignored issues
show
Unused Code Comprehensibility introduced by
56% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
601
        //} else {
602
        $forum_id = $forum->getVar('forum_id');
603
        /** var Newbb\PermissionHandler $permHandler */
604
        $permHandler = Newbb\Helper::getInstance()->getHandler('Permission');
605
        $permission  = $permHandler->getPermission('forum', $type, $forum_id);
606
        //}
607
        // END irmtfan commented and removed
608
        return $permission;
609
    }
610
611
    /**
612
     * @param $forum
613
     * @return mixed
614
     */
615
    public function deletePermission(&$forum)
616
    {
617
        /** var Newbb\PermissionHandler $permHandler */
618
        $permHandler = Newbb\Helper::getInstance()->getHandler('Permission');
619
620
        return $permHandler->deleteByForum($forum->getVar('forum_id'));
621
    }
622
623
    /**
624
     * @param $forum
625
     * @return mixed
626
     */
627
    public function applyPermissionTemplate(&$forum)
628
    {
629
        /** var Newbb\PermissionHandler $permHandler */
630
        $permHandler = Newbb\Helper::getInstance()->getHandler('Permission');
631
632
        return $permHandler->applyTemplate($forum->getVar('forum_id'));
633
    }
634
635
    /*
0 ignored issues
show
Unused Code Comprehensibility introduced by
51% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
636
    function isForum($forum)
637
    {
638
        $count = false;
639
        $sql = 'SELECT COUNT(*) as count FROM ' . $this->db->prefix("newbb_forums");
640
        $sql .= ' WHERE forum_id=' . $forum ;
641
        if ($result = $this->db->query($sql)) {
642
            $myrow = $this->db->fetchArray($result);
643
            $count = $myrow['count'];
644
        }
645
646
        return $count;
647
    }
648
    */
649
650
    /**
651
     * clean orphan forums from database
652
     * @param  string $table_link
653
     * @param  string $field_link
654
     * @param  string $field_object
655
     * @param  array  $forum_ids forum IDs
656
     * @return bool   true on success
657
     */
658
    // START irmtfan rewrite forum cleanOrphan function. add parent_forum and cat_id orphan check
659
    //    public function cleanOrphan(array $forum_ids = array())
0 ignored issues
show
Unused Code Comprehensibility introduced by
53% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
660
    public function cleanOrphan($table_link = '', $field_link = '', $field_object = '', $forum_ids = [])
661
    {
662
        // check parent_forum orphan forums
663
        if (empty($forum_ids)) {
664
            $forum_ids = $this->getIds();
665
        }
666
        if (empty($forum_ids)) {
667
            return false;
668
        }
669
        /*
0 ignored issues
show
Unused Code Comprehensibility introduced by
54% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
670
            $sql =    "    UPDATE ".$GLOBALS['xoopsDB']->prefix("newbb_forums").
671
                    "    SET parent_forum = 0".
672
                    "    WHERE (parent_forum NOT IN ( ".$forum_ids."))".
673
                    "        OR parent_forum = forum_id";
674
        */
675
        $criteria = new \CriteriaCompo();
676
        $criteria->add(new \Criteria('parent_forum', '(' . implode(', ', $forum_ids) . ')', 'NOT IN'), 'AND');
677
        $criteria->add(new \Criteria('parent_forum', '`forum_id`', '='), 'OR');
678
        $b1 = $this->updateAll('parent_forum', 0, $criteria, true);
679
        // check cat_id orphan forums
680
        $categoryHandler = Newbb\Helper::getInstance()->getHandler('Category');
681
        $cat_ids         = $categoryHandler->getIds();
682
        if (empty($cat_ids)) {
683
            return false;
684
        }
685
        $criteria = new \CriteriaCompo();
686
        $criteria->add(new \Criteria('cat_id', '(' . implode(', ', $cat_ids) . ')', 'NOT IN'), 'AND');
687
        $b2 = $this->updateAll('cat_id', $cat_ids[0], $criteria, true);
688
689
        return ($b1 && $b2);
690
    }
691
    // END irmtfan rewrite forum cleanOrphan function. add parent_forum and cat_id orphan check
692
693
    /**
694
     * forum data synchronization
695
     *
696
     * @param  mixed $object null for all forums; integer for forum_id; object for forum object
697
     * @return bool
698
     * @internal param int $mode 1 for stats only; 2 for forum index data only; 0 for both
699
     *
700
     */
701
    public function synchronization($object = null)
702
    {
703
        if (empty($object)) {
704
            $forums = $this->getIds();
705
            $this->cleanOrphan('', '', '', $forums); // irmtfan - move cleanOrphan to synchronization function
706
            foreach ($forums as $id) {
707
                $this->synchronization($id);
708
            }
709
710
            return true;
711
        }
712
713
        if (!is_object($object)) {
714
            $object = $this->get((int)$object);
715
        }
716
717
        if (!$object->getVar('forum_id')) {
718
            return false;
719
        }
720
        $sql = 'SELECT MAX(post_id) AS last_post, COUNT(*) AS total FROM ' . $this->db->prefix('newbb_posts') . ' AS p LEFT JOIN  ' . $this->db->prefix('newbb_topics') . ' AS t ON p.topic_id=t.topic_id WHERE p.approved=1 AND t.approved=1 AND p.forum_id = ' . $object->getVar('forum_id');
721
722
        if ($result = $this->db->query($sql)) {
723
            $last_post = 0;
724
            $posts     = 0;
725
            if ($row = $this->db->fetchArray($result)) {
726
                $last_post = (int)$row['last_post'];
727
                $posts     = (int)$row['total'];
728
            }
729
            if ($object->getVar('forum_last_post_id') !== $last_post) {
730
                $object->setVar('forum_last_post_id', $last_post);
731
            }
732
            if ($object->getVar('forum_posts') !== $posts) {
733
                $object->setVar('forum_posts', $posts);
734
            }
735
        }
736
737
        $sql = 'SELECT COUNT(*) AS total FROM ' . $this->db->prefix('newbb_topics') . ' WHERE approved=1 AND forum_id = ' . $object->getVar('forum_id');
738
        if ($result = $this->db->query($sql)) {
739
            if ($row = $this->db->fetchArray($result)) {
740
                if ($object->getVar('forum_topics') !== $row['total']) {
741
                    $object->setVar('forum_topics', $row['total']);
742
                }
743
            }
744
        }
745
        $object->setDirty();
746
747
        return $this->insert($object, true);
748
    }
749
750
    /**
751
     * @param  null $passedSubForums
0 ignored issues
show
Documentation Bug introduced by
Are you sure the doc-type for parameter $passedSubForums is correct as it would always require null to be passed?
Loading history...
752
     * @return array
753
     */
754
    public function getSubforumStats($passedSubForums = null)
755
    {
756
        $stats = [];
757
758
        require_once $GLOBALS['xoops']->path('modules/newbb/include/functions.forum.php');
759
760
        $subForumTree = newbbGetSubForum();
761
        if (empty($passedSubForums)) {
762
            $sub_forums = $subForumTree;
763
        } else {
764
            foreach ($passedSubForums as $id) {
765
                $sub_forums[$id] = isset($subForumTree[$id]) ? $subForumTree[$id] : null;
766
            }
767
        }
768
769
        $forums_id = [];
770
        foreach (array_keys($sub_forums) as $id) {
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $sub_forums does not seem to be defined for all execution paths leading up to this point.
Loading history...
771
            if (empty($sub_forums[$id])) {
772
                continue;
773
            }
774
            $forums_id = array_merge($forums_id, $sub_forums[$id]);
775
        }
776
        if (!$forums_id) {
777
            return $stats;
778
        }
779
        $sql = '    SELECT forum_posts AS posts, forum_topics AS topics, forum_id AS id' . '    FROM ' . $this->table . '    WHERE forum_id IN (' . implode(', ', $forums_id) . ')';
780
        if (!$result = $this->db->query($sql)) {
781
            return $stats;
782
        }
783
784
        $forum_stats = [];
785
        while (false !== ($row = $this->db->fetchArray($result))) {
786
            $forum_stats[$row['id']] = ['topics' => $row['topics'], 'posts' => $row['posts']];
787
        }
788
789
        foreach (array_keys($sub_forums) as $id) {
790
            if (empty($sub_forums[$id])) {
791
                continue;
792
            }
793
            $stats[$id] = ['topics' => 0, 'posts' => 0];
794
            foreach ($sub_forums[$id] as $fid) {
795
                $stats[$id]['topics'] += $forum_stats[$fid]['topics'];
796
                $stats[$id]['posts']  += $forum_stats[$fid]['posts'];
797
            }
798
        }
799
800
        return $stats;
801
    }
802
803
    /**
804
     * @param        $forums
805
     * @param  int   $length_title_index
806
     * @param  int   $count_subforum
807
     * @return array
808
     */
809
    public function &display($forums, $length_title_index = 30, $count_subforum = 1)
810
    {
811
        global $myts;
0 ignored issues
show
Compatibility Best Practice introduced by
Use of global functionality is not recommended; it makes your code harder to test, and less reusable.

Instead of relying on global state, we recommend one of these alternatives:

1. Pass all data via parameters

function myFunction($a, $b) {
    // Do something
}

2. Create a class that maintains your state

class MyClass {
    private $a;
    private $b;

    public function __construct($a, $b) {
        $this->a = $a;
        $this->b = $b;
    }

    public function myFunction() {
        // Do something
    }
}
Loading history...
812
813
        $posts       = [];
814
        $postsObject = [];
0 ignored issues
show
Unused Code introduced by
The assignment to $postsObject is dead and can be removed.
Loading history...
815
        foreach (array_keys($forums) as $id) {
816
            $posts[] = $forums[$id]['forum_last_post_id'];
817
        }
818
        if (!empty($posts)) {
819
            $postHandler = Newbb\Helper::getInstance()->getHandler('Post');
820
            $tags_post   = ['uid', 'topic_id', 'post_time', 'poster_name', 'icon'];
821
            if (!empty($length_title_index)) {
822
                $tags_post[] = 'subject';
823
            }
824
            $posts = $postHandler->getAll(new \Criteria('post_id', '(' . implode(', ', $posts) . ')', 'IN'), $tags_post, false);
825
        }
826
827
        // Get topic/post stats per forum
828
        $stats_forum = [];
829
830
        if (!empty($count_subforum)) {
831
            $stats_forum = $this->getSubforumStats(array_keys($forums)); // irmtfan uncomment to count sub forum posts/topics
832
        }
833
834
        $users  = [];
835
        $reads  = [];
836
        $topics = [];
0 ignored issues
show
Unused Code introduced by
The assignment to $topics is dead and can be removed.
Loading history...
837
838
        foreach (array_keys($forums) as $id) {
839
            $forum =& $forums[$id];
840
841
            if (!$forum['forum_last_post_id']) {
842
                continue;
843
            }
844
            if (!$post = @$posts[$forum['forum_last_post_id']]) {
845
                $forum['forum_last_post_id'] = 0;
846
                continue;
847
            }
848
849
            $users[] = $post['uid'];
850
            if ($moderators[$id] = $forum['forum_moderator']) {
851
                $users = array_merge($users, $moderators[$id]);
852
            }
853
854
            // reads
855
            if (!empty($GLOBALS['xoopsModuleConfig']['read_mode'])) {
856
                $reads[$id] = (1 == $GLOBALS['xoopsModuleConfig']['read_mode']) ? $post['post_time'] : $post['post_id'];
857
            }
858
        }
859
860
        require_once $GLOBALS['xoops']->path('modules/newbb/include/functions.user.php');
861
        require_once $GLOBALS['xoops']->path('modules/newbb/include/functions.time.php');
862
        require_once $GLOBALS['xoops']->path('modules/newbb/include/functions.render.php');
863
        require_once $GLOBALS['xoops']->path('modules/newbb/include/functions.read.php');
864
        $forum_isread = newbbIsRead('forum', $reads);
865
        $users_linked = newbbGetUnameFromIds(array_unique($users), !empty($GLOBALS['xoopsModuleConfig']['show_realname']), true);
0 ignored issues
show
Bug introduced by
! empty($GLOBALS['xoopsM...fig']['show_realname']) of type boolean is incompatible with the type integer expected by parameter $usereal of newbbGetUnameFromIds(). ( Ignorable by Annotation )

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

865
        $users_linked = newbbGetUnameFromIds(array_unique($users), /** @scrutinizer ignore-type */ !empty($GLOBALS['xoopsModuleConfig']['show_realname']), true);
Loading history...
866
867
        $forums_array   = [];
868
        $name_anonymous = $myts->htmlSpecialChars($GLOBALS['xoopsConfig']['anonymous']);
869
870
        foreach (array_keys($forums) as $id) {
871
            $forum =& $forums[$id];
872
873
            $_forum_data                 = [];
874
            $_forum_data['forum_order']  = $forum['forum_order'];
875
            $_forum_data['forum_id']     = $id;
876
            $_forum_data['forum_cid']    = $forum['cat_id'];
877
            $_forum_data['forum_name']   = $forum['forum_name'];
878
            $forumDescLength             = $GLOBALS['xoopsModuleConfig']['forum_desc_length'];
879
            $_forum_data['forum_desc']   = mb_strimwidth($forum['forum_desc'], 0, $forumDescLength, '...');
880
            $_forum_data['forum_topics'] = $forum['forum_topics'] + @$stats_forum[$id]['topics'];
881
            $_forum_data['forum_posts']  = $forum['forum_posts'] + @$stats_forum[$id]['posts'];
882
            //$_forum_data["forum_type"]= $forum['forum_type'];
0 ignored issues
show
Unused Code Comprehensibility introduced by
82% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
883
884
            $forum_moderators = [];
885
            if (!empty($moderators[$id])) {
886
                foreach (@$moderators[$id] as $moderator) {
887
                    $forum_moderators[] = @$users_linked[$moderator];
888
                }
889
            }
890
            $_forum_data['forum_moderators'] = implode(', ', $forum_moderators);
891
892
            // irmtfan change if/endif to if{} method
893
            if ($post_id = $forum['forum_last_post_id']) {
894
                $post                               =& $posts[$post_id];
895
                $_forum_data['forum_lastpost_id']   = $post_id;
896
                $_forum_data['forum_lastpost_time'] = newbbFormatTimestamp($post['post_time']);
897
                if (!empty($users_linked[$post['uid']])) {
898
                    $_forum_data['forum_lastpost_user'] = $users_linked[$post['uid']];
899
                } elseif ($poster_name = $post['poster_name']) {
900
                    $_forum_data['forum_lastpost_user'] = $poster_name;
901
                } else {
902
                    $_forum_data['forum_lastpost_user'] = $name_anonymous;
903
                }
904
                if (!empty($length_title_index)) {
905
                    $subject = $post['subject'];
906
                    if ($length_title_index < 255) {
907
                        $subject = xoops_substr($subject, 0, $length_title_index);
0 ignored issues
show
Bug introduced by
The function xoops_substr was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

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

907
                        $subject = /** @scrutinizer ignore-call */ xoops_substr($subject, 0, $length_title_index);
Loading history...
908
                    }
909
                    $_forum_data['forum_lastpost_subject'] = $subject;
910
                }
911
                // irmtfan - remove icon_path and use newbbDisplayImage
912
                $_forum_data['forum_lastpost_icon'] = newbbDisplayImage('lastposticon', _MD_NEWBB_GOTOLASTPOST);
913
                // START irmtfan change the method to add read smarty
914
                if (empty($forum_isread[$id])) {
915
                    $_forum_data['forum_folder'] = newbbDisplayImage('forum_new', _MD_NEWBB_NEWPOSTS);
916
                    $_forum_data['forum_read']   = 0; // irmtfan add forum-read/forum-new smarty variable
917
                } else {
918
                    $_forum_data['forum_folder'] = newbbDisplayImage('forum', _MD_NEWBB_NONEWPOSTS);
919
                    $_forum_data['forum_read']   = 1; // irmtfan add forum-read/forum-new smarty variable
920
                }
921
                // END irmtfan change the method to add read smarty
922
            }
923
            $forums_array[$forum['parent_forum']][] = $_forum_data;
924
        }
925
926
        return $forums_array;
927
    }
928
929
    /**
930
     * get a hierarchical tree of forums
931
     *
932
     * {@link newbbTree}
933
     *
934
     * @param  int    $cat_id     category ID
935
     * @param  int    $pid        Top forum ID
936
     * @param  string $permission permission type
937
     * @param  string $prefix     prefix for display
938
     * @param  string $tags       variables to fetch
939
     * @return array  associative array of category IDs and sanitized titles
940
     */
941
    public function &getTree($cat_id = 0, $pid = 0, $permission = 'access', $prefix = '--', $tags = null)
942
    {
943
        $pid         = (int)$pid;
944
        $perm_string = $permission;
945
        if (!is_array($tags) || 0 === count($tags)) {
0 ignored issues
show
introduced by
The condition is_array($tags) is always false.
Loading history...
946
            $tags = ['forum_id', 'parent_forum', 'forum_name', 'forum_order', 'cat_id'];
947
        }
948
        $forumsObject = $this->getByPermission($cat_id, $perm_string, $tags);
949
950
        require_once __DIR__ . '/tree.php';
951
        $forums_structured = [];
952
        foreach (array_keys($forumsObject) as $key) {
953
            $forums_structured[$forumsObject[$key]->getVar('cat_id')][$key] = $forumsObject[$key];
954
        }
955
956
        foreach (array_keys($forums_structured) as $cid) {
957
            $tree              = new ObjectTree($forums_structured[$cid]);
958
            $forum_array[$cid] = $tree->makeTree($prefix, $pid, $tags);
959
            unset($tree);
960
        }
961
962
        return $forum_array;
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $forum_array seems to be defined by a foreach iteration on line 956. Are you sure the iterator is never empty, otherwise this variable is not defined?
Loading history...
963
    }
964
965
    /**
966
     * get a hierarchical array tree of forums
967
     *
968
     * {@link newbbTree}
969
     *
970
     * @param  int     $cat_id     category ID
971
     * @param  int     $pid        Top forum ID
972
     * @param  string  $permission permission type
973
     * @param  string  $tags       variables to fetch
974
     * @param  integer $depth      level of subcategories
975
     * @return array   associative array of category IDs and sanitized titles
976
     */
977
    public function &getArrayTree($cat_id = 0, $pid = 0, $permission = 'access', $tags = null, $depth = 0)
978
    {
979
        $pid         = (int)$pid;
980
        $perm_string = $permission;
981
        if (!is_array($tags) || 0 === count($tags)) {
0 ignored issues
show
introduced by
The condition is_array($tags) is always false.
Loading history...
982
            $tags = ['forum_id', 'parent_forum', 'forum_name', 'forum_order', 'cat_id'];
983
        }
984
        $forumsObject = $this->getByPermission($cat_id, $perm_string, $tags);
985
986
        require_once __DIR__ . '/tree.php';
987
        $forums_structured = [];
988
        foreach (array_keys($forumsObject) as $key) {
989
            $forumObject                                             =& $forumsObject[$key];
990
            $forums_structured[$forumObject->getVar('cat_id')][$key] = $forumsObject[$key];
991
        }
992
        foreach (array_keys($forums_structured) as $cid) {
993
            $tree              = new ObjectTree($forums_structured[$cid]);
994
            $forum_array[$cid] = $tree->makeArrayTree($pid, $tags, $depth);
995
            unset($tree);
996
        }
997
998
        return $forum_array;
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $forum_array seems to be defined by a foreach iteration on line 992. Are you sure the iterator is never empty, otherwise this variable is not defined?
Loading history...
999
    }
1000
1001
    /**
1002
     * @param $object
1003
     * @return array|null
1004
     */
1005
    public function &getParents($object)
1006
    {
1007
        $ret = null;
1008
        if (!$object->getVar('forum_id')) {
1009
            return $ret;
1010
        }
1011
1012
        require_once $GLOBALS['xoops']->path('modules/newbb/include/functions.forum.php');
1013
        if (!$parents = newbbGetParentForum($object->getVar('forum_id'))) {
1014
            return $ret;
1015
        }
1016
        $parents_list = $this->getList(new \Criteria('forum_id', '(' . implode(', ', $parents) . ')', 'IN'));
1017
        foreach ($parents as $key => $id) {
1018
            $ret[] = ['forum_id' => $id, 'forum_name' => $parents_list[$id]];
1019
        }
1020
        unset($parents, $parents_list);
1021
1022
        return $ret;
1023
    }
1024
1025
    // START irmtfan - get forum Ids by values. parse positive values to forum IDs and negative values to category IDs. value=0 => all valid forums
1026
1027
    /**
1028
     * function for get forum Ids by positive and negative values
1029
     *
1030
     * @param  int|text $values : positive values = forums | negative values = cats | $values=0 = all valid forums, $permission , true/false $parse_cats
1031
     * @param  string   $permission
1032
     * @param  bool     $parse_cats
1033
     * @return array|mixed $validForums
1034
     */
1035
    public function getIdsByValues($values = 0, $permission = 'access', $parse_cats = true)
1036
    {
1037
        // Get all valid forums with this permission
1038
        $validForums = $this->getIdsByPermission($permission);
1039
        // if no value or value=0 return all valid forums
1040
        if (empty($values)) {
1041
            return $validForums;
1042
        }
1043
        $values = is_numeric($values) ? [$values] : $values;
1044
        //parse negative values to category IDs
1045
        $forums = [];
1046
        $cats   = [];
1047
        foreach ($values as $val) {
1048
            if (0 == $val) {
1049
                // value=0 => all valid forums
1050
                return $validForums;
1051
            } elseif ($val > 0) {
1052
                $forums[] = $val;
1053
            } else {
1054
                $cats[] = abs($val);
1055
            }
1056
        }
1057
        // if dont want to parse categories OR no cats return all forums
1058
        if (empty($parse_cats) || empty($cats)) {
1059
            return array_intersect($validForums, $forums);
1060
        }
1061
        // Get all forums by category IDs
1062
        $forumObjs = $this->getForumsByCategory($cats, $permission, true);
0 ignored issues
show
Bug introduced by
$cats of type array<mixed,integer|double>|array is incompatible with the type integer expected by parameter $categoryid of XoopsModules\Newbb\Forum...::getForumsByCategory(). ( Ignorable by Annotation )

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

1062
        $forumObjs = $this->getForumsByCategory(/** @scrutinizer ignore-type */ $cats, $permission, true);
Loading history...
1063
        $forums    = array_merge($forums, array_keys($forumObjs));
1064
1065
        return array_intersect($validForums, $forums);
1066
    }
1067
    // END irmtfan - get forum Ids by values. parse positive values to forum IDs and negative values to category IDs. value=0 => all valid forums
1068
}
1069