ForumHandler   F
last analyzed

Complexity

Total Complexity 194

Size/Duplication

Total Lines 1096
Duplicated Lines 0 %

Importance

Changes 7
Bugs 1 Features 0
Metric Value
eloc 576
dl 0
loc 1096
rs 2
c 7
b 1
f 0
wmc 194

19 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 3 1
A getIdsByPermission() 0 9 1
C synchronization() 0 51 12
F display() 0 121 20
B getForumsByCategory() 0 35 7
B getSubforumStats() 0 58 11
A getParents() 0 18 4
A delete() 0 14 1
A getByPermission() 0 18 6
A cleanOrphan() 0 30 5
A insert() 0 14 3
F getAllTopics() 0 332 74
A getTree() 0 23 5
A applyPermissionTemplate() 0 6 1
A getPermission() 0 43 6
A getArrayTree() 0 23 5
F getTopicCount() 0 80 23
A deletePermission() 0 6 1
B getIdsByValues() 0 35 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 declare(strict_types=1);
2
3
namespace XoopsModules\Newbb;
4
5
/**
6
 * Newbb module
7
 *
8
 * You may not change or alter any portion of this comment or credits
9
 * of supporting developers from this source code or any supporting source code
10
 * which is considered copyrighted (c) material of the original comment or credit authors.
11
 * This program is distributed in the hope that it will be useful,
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
14
 *
15
 * @copyright       XOOPS Project (https://xoops.org)
16
 * @license         GNU GPL 2.0 or later (https://www.gnu.org/licenses/gpl-2.0.html)
17
 * @since           4.0
18
 * @author          Taiwen Jiang <[email protected]>
19
 */
20
21
use XoopsModules\Newbb;
22
23
/**
24
 * Class ForumHandler
25
 */
26
class ForumHandler extends \XoopsPersistableObjectHandler
27
{
28
    /**
29
     * @param null|\XoopsDatabase $db
30
     */
31
    public function __construct(\XoopsDatabase $db = null)
32
    {
33
        parent::__construct($db, 'newbb_forums', Forum::class, 'forum_id', 'forum_name');
34
    }
35
36
    /**
37
     * @param \XoopsObject $object Forum
38
     * @param bool $force
39
     * @return bool|int
40
     */
41
    public function insert(\XoopsObject $object, $force = true) //insert($object)
42
    {
43
44
        $forum = $object;
45
        if (!parent::insert($forum, true)) {
46
            return false;
47
        }
48
49
        if ($forum->isNew()) {
50
//          $this->applyPermissionTemplate($forum);
51
            $this->applyPermissionTemplate($forum->getVar('forum_id'));
52
        }
53
54
        return $forum->getVar('forum_id');
0 ignored issues
show
Bug Best Practice introduced by
The expression return $forum->getVar('forum_id') also could return the type array|string which is incompatible with the documented return type boolean|integer.
Loading history...
55
    }
56
57
    /**
58
     * @param \XoopsObject $object Forum
59
     * @param bool $force
60
     * @return bool
61
     */
62
    public function delete(\XoopsObject $object, $force = false): bool //delete(&$object)
63
    {
64
        global $xoopsModule;
65
        $forum = $object;
66
        // RMV-NOTIFY
67
        \xoops_notification_deletebyitem($xoopsModule->getVar('mid'), 'forum', $forum->getVar('forum_id'));
68
        // Get list of all topics in forum, to delete them too
69
        /** @var TopicHandler $topicHandler */
70
        $topicHandler = Helper::getInstance()->getHandler('Topic');
71
        $topicHandler->deleteAll(new \Criteria('forum_id', $forum->getVar('forum_id')), true, true);
0 ignored issues
show
Bug introduced by
It seems like $forum->getVar('forum_id') can also be of type array and array; however, parameter $value of Criteria::__construct() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

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

71
        $topicHandler->deleteAll(new \Criteria('forum_id', /** @scrutinizer ignore-type */ $forum->getVar('forum_id')), true, true);
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|null $perm
80
     * @return array
81
     */
82
    public function getIdsByPermission(?string $perm = null): array
83
    {
84
        $perm ??= 'access';
85
86
        /** var PermissionHandler $permHandler */
87
        $permHandler = Helper::getInstance()
88
                             ->getHandler('Permission');
89
90
        return $permHandler->getForums($perm);
91
    }
92
93
    /**
94
     * @param int|mixed[] $cat
95
     * @param string     $permission
96
     * @param array|null $tags
97
     * @param bool       $asObject
98
     * @return array
99
     */
100
    public function &getByPermission($cat = 0, string $permission = 'access', array $tags = null, bool $asObject = true): array
101
    {
102
        $_cachedForums = [];
103
        if (!$valid_ids = $this->getIdsByPermission($permission)) {
104
            return $_cachedForums;
105
        }
106
107
        $criteria = new \CriteriaCompo(new \Criteria('forum_id', '(' . \implode(', ', $valid_ids) . ')', 'IN'));
108
        if (\is_numeric($cat) && $cat > 0) {
109
            $criteria->add(new \Criteria('cat_id', (int)$cat));
110
        } elseif ($cat && \is_array($cat)) {
111
            $criteria->add(new \Criteria('cat_id', '(' . \implode(', ', $cat) . ')', 'IN'));
112
        }
113
        $criteria->setSort('forum_order');
114
        $criteria->setOrder('ASC');
115
        $_cachedForums = $this->getAll($criteria, $tags, $asObject);
116
117
        return $_cachedForums;
118
    }
119
120
    /**
121
     * @param int|mixed[] $categoryid
122
     * @param string     $permission
123
     * @param bool       $asObject
124
     * @param array|null $tags
125
     * @return array
126
     */
127
    public function getForumsByCategory($categoryid = 0, string $permission = '', bool $asObject = true, array $tags = null): array
128
    {
129
        $forums = $this->getByPermission($categoryid, $permission, $tags);
130
        if ($asObject) {
131
            return $forums;
132
        }
133
134
        $forums_array = [];
135
        $array_cat    = [];
0 ignored issues
show
Unused Code introduced by
The assignment to $array_cat is dead and can be removed.
Loading history...
136
        $array_forum  = [];
137
        if (!\is_array($forums)) {
0 ignored issues
show
introduced by
The condition is_array($forums) is always true.
Loading history...
138
            return [];
139
        }
140
        foreach (\array_keys($forums) as $forumid) {
141
            $forum                                                  = $forums[$forumid];
142
            $forums_array[$forum->getVar('parent_forum')][$forumid] = [
143
                'cid'   => $forum->getVar('cat_id'),
144
                'title' => $forum->getVar('forum_name'),
145
            ];
146
        }
147
        if (!isset($forums_array[0])) {
148
            $ret = [];
149
150
            return $ret;
151
        }
152
        foreach ($forums_array[0] as $key => $forum) {
153
            if (isset($forums_array[$key])) {
154
                $forum['sub'] = $forums_array[$key];
155
            }
156
            $array_forum[$forum['cid']][$key] = $forum;
157
        }
158
        \ksort($array_forum);
159
        unset($forums, $forums_array);
160
161
        return $array_forum;
162
    }
163
164
    /**
165
     * @param \XoopsModules\Newbb\Forum|mixed[]|int $forum
166
     * @param array|null   $criteria
167
     * @return array
168
     */
169
    public function getAllTopics($forum, array $criteria = null): array
170
    {
171
        global $myts, $viewAllForums, $xoopsUser;
172
        $startdate = 0;
173
        $type      = '';
174
        $status    = '';
175
        $excerpt   = 0;
176
        $sort      = '';
177
        $order     = '';
178
        $start     = 0;
179
180
        require_once $GLOBALS['xoops']->path('modules/newbb/include/functions.render.php');
181
        require_once $GLOBALS['xoops']->path('modules/newbb/include/functions.session.php');
182
        require_once $GLOBALS['xoops']->path('modules/newbb/include/functions.time.php');
183
        require_once $GLOBALS['xoops']->path('modules/newbb/include/functions.read.php');
184
        require_once $GLOBALS['xoops']->path('modules/newbb/include/functions.topic.php');
185
186
        //BigKev73 > Added this to suport the call into the Topic Handler
187
        $topicHandler = Helper::getInstance()->getHandler('Topic');
188
189
        $criteria_vars = ['startdate', 'start', 'sort', 'order', 'type', 'status', 'excerpt'];
190
        foreach ($criteria_vars as $var) {
191
            ${$var} = $criteria[$var];
192
        }
193
194
        $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...
195
        $criteria_forum = '';
196
        if (\is_object($forum)) {
197
            $criteria_forum = ' AND t.forum_id = ' . $forum->getVar('forum_id');
198
            $hot_threshold  = $forum->getVar('hot_threshold');
199
        } else {
200
            $hot_threshold = 10;
201
            if ($forum && \is_array($forum)) {
202
                $criteria_forum = ' AND t.forum_id IN (' . \implode(',', \array_keys($forum)) . ')';
203
            } elseif (!empty($forum)) {
204
                $criteria_forum = ' AND t.forum_id =' . (int)$forum;
205
            }
206
        }
207
208
        $criteria_post    = $startdate ? ' p.post_time > ' . $startdate : ' 1 = 1 ';
209
        $criteria_topic   = empty($type) ? '' : " AND t.type_id={$type}";
0 ignored issues
show
introduced by
The condition empty($type) is always true.
Loading history...
210
        $criteria_extra   = '';
211
        $criteria_approve = ' AND t.approved = 1';
212
        $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...
213
        $leftjoin         = ' LEFT JOIN ' . $this->db->prefix('newbb_posts') . ' p ON p.post_id = t.topic_last_post_id';
214
        $sort_array       = [];
215
        switch ($status) {
216
            case 'digest':
217
                $criteria_extra = ' AND t.topic_digest = 1';
218
                break;
219
            case 'unreplied':
220
                $criteria_extra = ' AND t.topic_replies < 1';
221
                break;
222
            case 'unread':
223
                if (empty($GLOBALS['xoopsModuleConfig']['read_mode'])) {
224
                } elseif (2 == $GLOBALS['xoopsModuleConfig']['read_mode']) {
225
                    // START irmtfan use read_uid to find the unread posts when the user is logged in
226
                    $read_uid = \is_object($GLOBALS['xoopsUser']) ? $GLOBALS['xoopsUser']->getVar('uid') : 0;
227
                    if (!empty($read_uid)) {
228
                        $leftjoin      .= ' LEFT JOIN ' . $this->db->prefix('newbb_reads_topic') . ' r ON r.read_item = t.topic_id AND r.uid = ' . $read_uid . ' ';
229
                        $criteria_post .= ' AND (r.read_id IS NULL OR r.post_id < t.topic_last_post_id)';
230
                    }
231
                    // END irmtfan use read_uid to find the unread posts when the user is logged in
232
                } elseif (1 == $GLOBALS['xoopsModuleConfig']['read_mode']) {
233
                    // START irmtfan fix read_mode = 1 bugs - for all users (member and anon)
234
                    $time_criterion = \max($GLOBALS['last_visit'], $startdate);
235
                    if ($time_criterion) {
236
                        $criteria_post  = ' p.post_time > ' . $time_criterion; // for all users
237
                        $topics         = [];
238
                        $topic_lastread = \newbbGetCookie('LT', true);
239
                        if ((is_countable($topic_lastread) ? \count($topic_lastread) : 0) > 0) {
240
                            foreach ($topic_lastread as $id => $time) {
241
                                if ($time > $time_criterion) {
242
                                    $topics[] = $id;
243
                                }
244
                            }
245
                        }
246
                        if (\count($topics) > 0) {
247
                            $criteria_extra = ' AND t.topic_id NOT IN (' . \implode(',', $topics) . ')';
248
                        }
249
                    }
250
                    // END irmtfan fix read_mode = 1 bugs - for all users (member and anon)
251
                }
252
                break;
253
            case 'pending':
254
                $post_on          = ' p.topic_id = t.topic_id';
255
                $criteria_post    .= ' AND p.pid = 0';
256
                $criteria_approve = ' AND t.approved = 0';
257
                break;
258
            case 'deleted':
259
                $criteria_approve = ' AND t.approved = -1';
260
                break;
261
            case 'all': // For viewall.php; do not display sticky topics at first
262
            case 'active': // same as "all"
263
                break;
264
            default:
265
                if ($startdate > 0) {
266
                    $criteria_post = ' (p.post_time > ' . $startdate . ' OR t.topic_sticky=1)';
267
                }
268
                $sort_array[] = 't.topic_sticky DESC';
269
                break;
270
        }
271
272
        $select = 't.*, ' . ' p.post_time as last_post_time, p.poster_name as last_poster_name, p.icon, p.post_id, p.uid';
273
        $from   = $this->db->prefix('newbb_topics') . ' t ' . $leftjoin;
274
        $where  = $criteria_post . $criteria_topic . $criteria_forum . $criteria_extra . $criteria_approve;
275
276
        if ($excerpt) {
277
            $select .= ', p.post_karma, p.require_reply, pt.post_text';
278
            $from   .= ' LEFT JOIN ' . $this->db->prefix('newbb_posts_text') . ' pt ON pt.post_id = t.topic_last_post_id';
279
        }
280
        if ('u.uname' === $sort) {
0 ignored issues
show
introduced by
The condition 'u.uname' === $sort is always false.
Loading history...
281
            $sort = 't.topic_poster';
282
        }
283
284
        $sort_array[] = \trim($sort . ' ' . $order);
285
        $sortby       = \implode(', ', \array_filter($sort_array));
286
        if (empty($sortby)) {
287
            $sortby = 't.topic_last_post_id DESC';
288
        }
289
290
        $sql = 'SELECT ' . $select . ' FROM ' . $from . ' WHERE ' . $where . ' ORDER BY ' . $sortby;
291
        $result = $this->db->query($sql, $GLOBALS['xoopsModuleConfig']['topics_per_page'], $start);
292
        if (!$this->db->isResultSet($result)) {
293
            \redirect_header('index.php', 2, \_MD_NEWBB_ERROROCCURED);
294
        }
295
296
        $sticky  = 0;
297
        $topics  = [];
298
        $posters = [];
299
        $reads   = [];
300
        $types   = [];
0 ignored issues
show
Unused Code introduced by
The assignment to $types is dead and can be removed.
Loading history...
301
302
        /** @var TypeHandler $typeHandler */
303
        $typeHandler = Helper::getInstance()->getHandler('Type');
304
        $typen       = $typeHandler->getByForum($forum->getVar('forum_id'));
305
        while (false !== ($myrow = $this->db->fetchArray($result))) {
306
            if ($myrow['topic_sticky']) {
307
                ++$sticky;
308
            }
309
310
            // ------------------------------------------------------
311
            // topic_icon: priority: sticky -> digest -> regular
312
313
            if ($myrow['topic_haspoll']) {
314
                if ($myrow['topic_sticky']) {
315
                    $topic_icon = \newbbDisplayImage('topic_sticky', \_MD_NEWBB_TOPICSTICKY) . '<br>' . \newbbDisplayImage('poll', \_MD_NEWBB_TOPICHASPOLL);
316
                } else {
317
                    $topic_icon = \newbbDisplayImage('poll', \_MD_NEWBB_TOPICHASPOLL);
318
                }
319
            } elseif ($myrow['topic_sticky']) {
320
                $topic_icon = \newbbDisplayImage('topic_sticky', \_MD_NEWBB_TOPICSTICKY);
321
            } elseif (!empty($myrow['icon'])) {
322
                $topic_icon = '<img src="' . XOOPS_URL . '/images/subject/' . \htmlspecialchars((string)$myrow['icon'], \ENT_QUOTES | \ENT_HTML5) . '" alt="" >';
323
            } else {
324
                $topic_icon = '<img src="' . XOOPS_URL . '/images/icons/no_posticon.gif" alt="" >';
325
            }
326
327
            // ------------------------------------------------------
328
            // rating_img
329
            $rating = \number_format($myrow['rating'] / 2, 0);
330
            // irmtfan - add alt key for rating
331
            if ($rating < 1) {
332
                $rating_img = \newbbDisplayImage('blank');
333
            } else {
334
                $rating_img = \newbbDisplayImage('rate' . $rating, \constant('_MD_NEWBB_RATE' . $rating));
335
            }
336
            // ------------------------------------------------------
337
            // topic_page_jump
338
            $topic_page_jump      = '';
339
            $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...
340
            $totalpages           = \ceil(($myrow['topic_replies'] + 1) / $GLOBALS['xoopsModuleConfig']['posts_per_page']);
341
            if ($totalpages > 1) {
342
                $topic_page_jump .= '&nbsp;&nbsp;';
343
                $append          = false;
344
                for ($i = 1; $i <= $totalpages; ++$i) {
345
                    if ($i > 3 && $i < $totalpages) {
346
                        if (!$append) {
347
                            $topic_page_jump .= '...';
348
                            $append          = true;
349
                        }
350
                    } else {
351
                        //BigKev73 - Made change so link scroll directly to that post
352
                        $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']) . '#forumpost' . $myrow['post_id'] . '">' . $i . '</a>]';
353
                        // $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>]';
354
                        // irmtfan remove here and move
355
                        //$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>';
356
                    }
357
                }
358
            }
359
            // irmtfan - move here for both topics with and without pages
360
            $topic_page_jump_icon = "<a href='" . XOOPS_URL . '/modules/newbb/viewtopic.php?topic_id=' . $myrow['topic_id'] . '&amp;post_id=' . $myrow['post_id'] . '#forumpost' . $myrow['post_id'] . "'>" . \newbbDisplayImage('lastposticon', \_MD_NEWBB_GOTOLASTPOST) . '</a>';
361
362
            // ------------------------------------------------------
363
            // => topic array
364
            $forum_link = '';
365
            if (!empty($viewAllForums[$myrow['forum_id']])) {
366
                $forum_link = '<a href="' . XOOPS_URL . '/modules/newbb/viewforum.php?forum=' . $myrow['forum_id'] . '">' . $viewAllForums[$myrow['forum_id']]['forum_name'] . '</a>';
367
            }
368
369
            $topic_title = \htmlspecialchars((string)$myrow['topic_title'], \ENT_QUOTES | \ENT_HTML5);
370
            // irmtfan remove here and move to for loop
371
            //if ($myrow['type_id'] > 0) {
372
            //$topic_title = '<span style="color:'.$typen[$myrow["type_id"]]["type_color"].'">['.$typen[$myrow["type_id"]]["type_name"].']</span> '.$topic_title.'';
373
            //}
374
            if ($myrow['topic_digest']) {
375
                $topic_title = "<span class='digest'>" . $topic_title . '</span>';
376
            }
377
378
            if (0 == $excerpt) {
379
                $topic_excerpt = '';
380
            } elseif (($myrow['post_karma'] > 0 || $myrow['require_reply'] > 0) && !\newbbIsAdmin($forum)) {
0 ignored issues
show
Bug introduced by
It seems like $forum can also be of type array<mixed,mixed>; however, parameter $forum of newbbIsAdmin() does only seem to accept XoopsModules\Newbb\Forum|integer, 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

380
            } elseif (($myrow['post_karma'] > 0 || $myrow['require_reply'] > 0) && !\newbbIsAdmin(/** @scrutinizer ignore-type */ $forum)) {
Loading history...
381
                $topic_excerpt = '';
382
            } else {
383
                $topic_excerpt = \xoops_substr(\newbbHtml2text($myts->displayTarea($myrow['post_text'])), 0, $excerpt);
384
                $topic_excerpt = \str_replace('[', '&#91;', \htmlspecialchars((string) $topic_excerpt, \ENT_QUOTES | \ENT_HTML5));
385
            }
386
            // START irmtfan move here
387
388
            //BigKev73 > Adding this code to support jumping directly to the last read post if that value exists for a user, block also would need to change to support same functionality
389
            $topicLink = 'viewtopic.php?topic_id=' . $myrow['topic_id'];
390
391
            if ($xoopsUser) {
392
                $lastRead = \newbbGetRead('topic', (int)$myrow['topic_id']);
393
                if (isset($lastRead)) {
394
                    if (!empty($lastRead)) {
395
                        if ($lastRead < $myrow['topic_last_post_id']) {
396
                            $topicLink = 'viewtopic.php?topic_id=' . $myrow['topic_id'] . '&amp;post_id=' . $lastRead . '#forumpost' . $lastRead;
397
398
                            //BigKev73 > Adding this code to support jumping to the next post after the LastReadPost, otherwise we could end up on the prior page
399
                            // if the lastread post is not on the last page and the next new post. Added getNextPostId to topichandler to support this
400
                            $nextPostID = $topicHandler->getNextPostId((int)$myrow['topic_id'], $lastRead);
0 ignored issues
show
Bug introduced by
It seems like $lastRead can also be of type boolean; however, parameter $lastreadpost_id of XoopsModules\Newbb\TopicHandler::getNextPostId() does only seem to accept integer, 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

400
                            $nextPostID = $topicHandler->getNextPostId((int)$myrow['topic_id'], /** @scrutinizer ignore-type */ $lastRead);
Loading history...
401
                            if (!empty($nextPostID)) {
402
                                $topicLink = 'viewtopic.php?topic_id=' . $myrow['topic_id'] . '&amp;post_id=' . $nextPostID . '#forumpost' . $nextPostID;
403
                                print('LastRead=' . $lastRead . ', NextPostID= ' . $nextPostID);
404
                            }
405
                        }
406
                    }
407
                }
408
            }
409
410
            $topics[$myrow['topic_id']] = [
411
                'topic_id'             => $myrow['topic_id'],
412
                'topic_icon'           => $topic_icon,
413
                'type_id'              => $myrow['type_id'],
414
                //'type_text'                 => $topic_prefix,/*irmtfan remove here and move to for loop*/
415
                'topic_title'          => $topic_title,
416
                //'topic_link'                => XOOPS_URL . '/modules/newbb/viewtopic.php?topic_id=' . $myrow['topic_id'],
417
                //'topic_link'           => 'viewtopic.php?topic_id=' . $myrow['topic_id'],
418
                'topic_link'           => $topicLink,
419
                'rating_img'           => $rating_img,
420
                'topic_page_jump'      => $topic_page_jump,
421
                'topic_page_jump_icon' => $topic_page_jump_icon,
422
                'topic_replies'        => $myrow['topic_replies'],
423
424
                'topic_digest' => $myrow['topic_digest'],
425
                //mb
426
427
                'topic_poster_uid'       => $myrow['topic_poster'],
428
                'topic_poster_name'      => \htmlspecialchars((string) ((string)$myrow['poster_name'] ?: $GLOBALS['xoopsConfig']['anonymous']), \ENT_QUOTES | \ENT_HTML5),
429
                'topic_views'            => $myrow['topic_views'],
430
                'topic_time'             => \newbbFormatTimestamp((int)$myrow['topic_time']),
431
                'topic_last_posttime'    => \newbbFormatTimestamp((int)$myrow['last_post_time']),
432
                'topic_last_poster_uid'  => $myrow['uid'],
433
                'topic_last_poster_name' => \htmlspecialchars((string) ((string)$myrow['last_poster_name'] ?: $GLOBALS['xoopsConfig']['anonymous']), \ENT_QUOTES | \ENT_HTML5),
434
                'topic_forum_link'       => $forum_link,
435
                'topic_excerpt'          => $topic_excerpt,
436
                'stick'                  => empty($myrow['topic_sticky']),
437
                'stats'                  => [
438
                    $myrow['topic_status'],
439
                    $myrow['topic_digest'],
440
                    $myrow['topic_replies'],
441
                ],
442
                /* irmtfan uncomment use ib the for loop*/
443
                //"topic_poster"              => $topic_poster,/*irmtfan remove here and move to for loop*/
444
                //"topic_last_poster"         => $topic_last_poster,/*irmtfan remove here and move to for loop*/
445
                //"topic_folder"              => newbbDisplayImage($topic_folder,$topic_folder_text),/*irmtfan remove here and move to for loop*/
446
            ];
447
            // END irmtfan move here
448
            /* users */
449
            $posters[$myrow['topic_poster']] = 1;
450
            $posters[$myrow['uid']]          = 1;
451
            // reads
452
            if (!empty($GLOBALS['xoopsModuleConfig']['read_mode'])) {
453
                $reads[$myrow['topic_id']] = (1 == $GLOBALS['xoopsModuleConfig']['read_mode']) ? $myrow['last_post_time'] : $myrow['topic_last_post_id'];
454
            }
455
        }// irmtfan while end
456
        // START irmtfan move to a for loop
457
        $posters_name = \newbbGetUnameFromIds(\array_keys($posters), (bool)$GLOBALS['xoopsModuleConfig']['show_realname'], true);
458
        //$topic_poster = newbbGetUnameFromId($myrow['topic_poster'], $GLOBALS['xoopsModuleConfig']['show_realname'], true);
459
        //$topic_last_poster = newbbGetUnameFromId($myrow['uid'], $GLOBALS['xoopsModuleConfig']['show_realname'], true);
460
        $topic_isRead = \newbbIsRead('topic', $reads);
461
        foreach (\array_keys($topics) as $id) {
462
            $topics[$id]['topic_read'] = empty($topic_isRead[$id]) ? 0 : 1; // add topic-read/topic-new smarty variable
463
            if (!empty($topics[$id]['type_id']) && isset($typen[$topics[$id]['type_id']])) {
464
                $topics[$id]['topic_title'] = \getTopicTitle($topics[$id]['topic_title'], $typen[$topics[$id]['type_id']]['type_name'], $typen[$topics[$id]['type_id']]['type_color']);
465
            }
466
            //$topic_prefix =  (!empty($typen[$myrow['type_id']])) ? getTopicTitle("", $typen[$myrow['type_id']]["type_name"], $typen[$myrow['type_id']]["type_color"]) : "";
467
            $topics[$id]['topic_poster']      = !empty($posters_name[$topics[$id]['topic_poster_uid']]) ? $posters_name[$topics[$id]['topic_poster_uid']] : $topics[$id]['topic_poster_name'];
468
            $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'];
469
470
            // ------------------------------------------------------
471
            // topic_folder: priority: newhot -> hot/new -> regular
472
            [$topic_status, $topic_digest, $topic_replies] = $topics[$id]['stats'];
473
            if (1 == $topic_status) {
474
                $topic_folder      = 'topic_locked';
475
                $topic_folder_text = \_MD_NEWBB_TOPICLOCKED;
476
            } elseif ($topic_digest) {
477
                $topic_folder      = 'topic_digest';
478
                $topic_folder_text = \_MD_NEWBB_TOPICDIGEST;
479
            } elseif ($topic_replies >= $hot_threshold) {
480
                $topic_folder      = empty($topic_isRead[$id]) ? 'topic_hot_new' : 'topic_hot';
481
                $topic_folder_text = empty($topic_isRead[$id]) ? \_MD_NEWBB_MORETHAN : \_MD_NEWBB_MORETHAN2;
482
            } else {
483
                $topic_folder      = empty($topic_isRead[$id]) ? 'topic_new' : 'topic';
484
                $topic_folder_text = empty($topic_isRead[$id]) ? \_MD_NEWBB_NEWPOSTS : \_MD_NEWBB_NONEWPOSTS;
485
            }
486
            $topics[$id]['topic_folder'] = \newbbDisplayImage($topic_folder, $topic_folder_text);
487
            unset($topics[$id]['topic_poster_name'], $topics[$id]['topic_last_poster_name'], $topics[$id]['stats']);
488
        } // irmtfan end for loop
489
        // END irmtfan move to a for loop
490
        if (\count($topics) > 0) {
491
            $sql    = ' SELECT DISTINCT topic_id FROM ' . $this->db->prefix('newbb_posts') . " WHERE attachment != ''" . ' AND topic_id IN (' . \implode(',', \array_keys($topics)) . ')';
492
            $result = $this->db->query($sql);
493
            if ($this->db->isResultSet($result)) {
494
                while ([$topic_id] = $this->db->fetchRow($result)) {
495
                    $topics[$topic_id]['attachment'] = '&nbsp;' . \newbbDisplayImage('attachment', \_MD_NEWBB_TOPICSHASATT);
496
                }
497
            }
498
        }
499
500
        return [$topics, $sticky];
501
    }
502
503
    /**
504
     * @param Forum|string|mixed[]|int $forum
505
     * @param int $startdate
506
     * @param string $type
507
     * @return null|int
508
     */
509
    public function getTopicCount($forum, int $startdate, string $type): ?int
510
    {
511
        require_once $GLOBALS['xoops']->path('modules/newbb/include/functions.session.php');
512
513
        $criteria_extra   = '';
514
        $criteria_approve = ' AND t.approved = 1'; // any others?
515
        $leftjoin         = ' LEFT JOIN ' . $this->db->prefix('newbb_posts') . ' p ON p.post_id = t.topic_last_post_id';
516
        $criteria_post    = ' p.post_time > ' . $startdate;
517
        switch ($type) {
518
            case 'digest':
519
                $criteria_extra = ' AND topic_digest = 1';
520
                break;
521
            case 'unreplied':
522
                $criteria_extra = ' AND topic_replies < 1';
523
                break;
524
            case 'unread':
525
                if (empty($GLOBALS['xoopsModuleConfig']['read_mode'])) {
526
                } elseif (2 == $GLOBALS['xoopsModuleConfig']['read_mode']) {
527
                    // START irmtfan use read_uid to find the unread posts when the user is logged in
528
529
                    $read_uid = \is_object($GLOBALS['xoopsUser']) ? $GLOBALS['xoopsUser']->getVar('uid') : 0;
530
                    if (!empty($read_uid)) {
531
                        $leftjoin      .= ' LEFT JOIN ' . $this->db->prefix('newbb_reads_topic') . ' r ON r.read_item = t.topic_id AND r.uid = ' . $read_uid . ' ';
532
                        $criteria_post .= ' AND (r.read_id IS NULL OR r.post_id < t.topic_last_post_id)';
533
                    }
534
                    // END irmtfan use read_uid to find the unread posts when the user is logged in
535
                } elseif (1 == $GLOBALS['xoopsModuleConfig']['read_mode']) {
536
                    // START irmtfan fix read_mode = 1 bugs - for all users (member and anon)
537
                    $time_criterion = \max($GLOBALS['last_visit'], $startdate);
538
                    if ($time_criterion) {
539
                        $criteria_post  = ' p.post_time > ' . $time_criterion; // for all users
540
                        $topics         = [];
541
                        $topic_lastread = \newbbGetCookie('LT', true);
542
                        if ((is_countable($topic_lastread) ? \count($topic_lastread) : 0) > 0) {
0 ignored issues
show
Bug introduced by
It seems like $topic_lastread can also be of type string; however, parameter $value of count() does only seem to accept Countable|array, maybe add an additional type check? ( Ignorable by Annotation )

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

542
                        if ((is_countable($topic_lastread) ? \count(/** @scrutinizer ignore-type */ $topic_lastread) : 0) > 0) {
Loading history...
543
                            foreach ($topic_lastread as $id => $time) {
544
                                if ($time > $time_criterion) {
545
                                    $topics[] = $id;
546
                                }
547
                            }
548
                        }
549
                        if (\count($topics) > 0) {
550
                            $criteria_extra = ' AND t.topic_id NOT IN (' . \implode(',', $topics) . ')';
551
                        }
552
                    }
553
                    // END irmtfan fix read_mode = 1 bugs - for all users (member and anon)
554
                }
555
                break;
556
            case 'pending':
557
                $criteria_approve = ' AND t.approved = 0';
558
                break;
559
            case 'deleted':
560
                $criteria_approve = ' AND t.approved = -1';
561
                break;
562
            case 'all':
563
                break;
564
            default:
565
                $criteria_post = ' (p.post_time > ' . $startdate . ' OR t.topic_sticky=1)';
566
                break;
567
        }
568
        $criteria_forum = '';
569
        if (\is_object($forum)) {
570
            $criteria_forum = ' AND t.forum_id = ' . $forum->getVar('forum_id');
571
        } elseif ($forum && \is_array($forum)) {
572
            $criteria_forum = ' AND t.forum_id IN (' . \implode(',', \array_keys($forum)) . ')';
573
        } elseif (!empty($forum)) {
574
            $criteria_forum = ' AND t.forum_id =' . (int)$forum;
575
        }
576
577
        $sql = 'SELECT COUNT(*) AS count FROM ' . $this->db->prefix('newbb_topics') . ' t ' . $leftjoin;
578
        $sql .= ' WHERE ' . $criteria_post . $criteria_forum . $criteria_extra . $criteria_approve;
579
        $result = $this->db->query($sql);
580
        if (!$this->db->isResultSet($result)) {
581
            // \trigger_error("Query Failed! SQL: $sql Error: " . $this->db->error(), \E_USER_ERROR);
582
            return null;
583
        }
584
585
        $myrow = $this->db->fetchArray($result);
586
        $count = (int)$myrow['count'];
587
588
        return $count;
589
    }
590
591
    // get permission
592
593
    /**
594
     * @param Forum|int $forum
595
     * @param string    $type
596
     * @param bool      $checkCategory
597
     * @return bool
598
     */
599
    public function getPermission($forum, string $type = 'access', bool $checkCategory = true): bool
600
    {
601
        global $xoopsModule;
602
        static $_cachedPerms;
603
604
        if ('all' === $type) {
605
            return true;
606
        }
607
608
        require_once \dirname(__DIR__) . '/include/functions.user.php';
609
        if (\newbbIsAdmin($forum)) {
610
            return true;
611
        }
612
        //if ($GLOBALS["xoopsUserIsAdmin"] && $xoopsModule->getVar("dirname") === "newbb") {
613
        //return true;
614
        //}
615
616
        if (!\is_object($forum)) {
617
            $forum = $this->get($forum);
618
        }
619
620
        if (!empty($checkCategory)) {
621
            /** @var CategoryHandler $categoryHandler */
622
            $categoryHandler = Helper::getInstance()->getHandler('Category');
623
            $categoryPerm    = $categoryHandler->getPermission($forum->getVar('cat_id'));
624
            if (!$categoryPerm) {
625
                return false;
626
            }
627
        }
628
629
        $type = \mb_strtolower($type);
630
        // START irmtfan commented and removed
631
        //if ('moderate' === $type) {
632
        //require_once $GLOBALS['xoops']->path('modules/newbb/include/functions.user.php');
633
        //$permission = newbbIsModerator($forum);
634
        //} else {
635
        $forum_id = $forum->getVar('forum_id');
636
        /** var PermissionHandler $permHandler */
637
        $permHandler = Helper::getInstance()->getHandler('Permission');
638
        $permission  = $permHandler->getPermission('forum', $type, $forum_id);
639
        //}
640
        // END irmtfan commented and removed
641
        return $permission;
642
    }
643
644
    /**
645
     * @param Forum|string|int $forum
646
     * @return mixed
647
     */
648
    public function deletePermission($forum)
649
    {
650
        /** var PermissionHandler $permHandler */
651
        $permHandler = Helper::getInstance()->getHandler('Permission');
652
653
        return $permHandler->deleteByForum($forum->getVar('forum_id'));
654
    }
655
656
    /**
657
     * @param int $forum
658
     * @return bool
659
     */
660
    public function applyPermissionTemplate(int $forum): bool
661
    {
662
        /** var PermissionHandler $permHandler */
663
        $permHandler = Helper::getInstance()->getHandler('Permission');
664
665
        return $permHandler->applyTemplate($forum);
666
    }
667
668
    /*
669
    function isForum($forum)
670
    {
671
        $count = false;
672
        $sql = 'SELECT COUNT(*) as count FROM ' . $this->db->prefix("newbb_forums");
673
        $sql .= ' WHERE forum_id=' . $forum ;
674
        $result = $this->db->query($sql);
675
        if ($this->db->isResultSet($result)) {
676
            $myrow = $this->db->fetchArray($result);
677
            $count = $myrow['count'];
678
        }
679
680
        return $count;
681
    }
682
    */
683
684
    /**
685
     * clean orphan forums from database
686
     * @param string $table_link
687
     * @param string $field_link
688
     * @param string $field_object
689
     * @param array  $forum_ids forum IDs
690
     * @return bool   true on success
691
     */
692
    // START irmtfan rewrite forum cleanOrphan function. add parent_forum and cat_id orphan check
693
    //    public function cleanOrphan(array $forum_ids = [])
694
    public function cleanOrphan($table_link = '', $field_link = '', $field_object = '', array $forum_ids = []): bool
695
    {
696
        // check parent_forum orphan forums
697
        if (empty($forum_ids)) {
698
            $forum_ids = $this->getIds();
699
        }
700
        if (empty($forum_ids)) {
701
            return false;
702
        }
703
        /*
704
            $sql =    "    UPDATE ".$GLOBALS['xoopsDB']->prefix("newbb_forums").
705
                    "    SET parent_forum = 0".
706
                    "    WHERE (parent_forum NOT IN ( ".$forum_ids."))".
707
                    "        OR parent_forum = forum_id";
708
        */
709
        $criteria = new \CriteriaCompo();
710
        $criteria->add(new \Criteria('parent_forum', '(' . \implode(', ', $forum_ids) . ')', 'NOT IN'), 'AND');
711
        $criteria->add(new \Criteria('parent_forum', '`forum_id`', '='), 'OR');
712
        $b1 = $this->updateAll('parent_forum', 0, $criteria, true);
713
        // check cat_id orphan forums
714
        $categoryHandler = Helper::getInstance()->getHandler('Category');
715
        $cat_ids         = $categoryHandler->getIds();
716
        if (empty($cat_ids)) {
717
            return false;
718
        }
719
        $criteria = new \CriteriaCompo();
720
        $criteria->add(new \Criteria('cat_id', '(' . \implode(', ', $cat_ids) . ')', 'NOT IN'), 'AND');
721
        $b2 = $this->updateAll('cat_id', $cat_ids[0], $criteria, true);
722
723
        return ($b1 && $b2);
724
    }
725
726
    // END irmtfan rewrite forum cleanOrphan function. add parent_forum and cat_id orphan check
727
    /**
728
     * forum data synchronization
729
     *
730
     * @param mixed $object null for all forums; integer for forum_id; object for forum object
731
     * @return bool|int
732
     * @internal param int $mode 1 for stats only; 2 for forum index data only; 0 for both
733
     */
734
    public function synchronization($object = null)
735
    {
736
        if (empty($object)) {
737
            $forums = $this->getIds();
738
            $this->cleanOrphan('', '', '', $forums); // irmtfan - move cleanOrphan to synchronization function
739
            foreach ($forums as $id) {
740
                $this->synchronization($id);
741
            }
742
743
            return true;
744
        }
745
746
        if (!\is_object($object)) {
747
            $object = $this->get((int)$object);
748
        }
749
750
        if (!$object->getVar('forum_id')) {
751
            return false;
752
        }
753
        $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');
754
755
        $result = $this->db->query($sql);
756
        if ($this->db->isResultSet($result)) {
757
            $last_post = 0;
758
            $posts     = 0;
759
            $row       = $this->db->fetchArray($result);
760
            if ($row) {
761
                $last_post = (int)$row['last_post'];
762
                $posts     = (int)$row['total'];
763
            }
764
            if ($object->getVar('forum_last_post_id') !== $last_post) {
765
                $object->setVar('forum_last_post_id', $last_post);
766
            }
767
            if ($object->getVar('forum_posts') !== $posts) {
768
                $object->setVar('forum_posts', $posts);
769
            }
770
        }
771
772
        $sql    = 'SELECT COUNT(*) AS total FROM ' . $this->db->prefix('newbb_topics') . ' WHERE approved=1 AND forum_id = ' . $object->getVar('forum_id');
773
        $result = $this->db->query($sql);
774
        if ($this->db->isResultSet($result)) {
775
            $row = $this->db->fetchArray($result);
776
            if ($row) {
777
                if ($object->getVar('forum_topics') !== $row['total']) {
778
                    $object->setVar('forum_topics', $row['total']);
779
                }
780
            }
781
        }
782
        $object->setDirty();
783
784
        return $this->insert($object, true);
785
    }
786
787
    /**
788
     * @param array|null $passedSubForums
789
     * @return array
790
     */
791
    public function getSubforumStats(array $passedSubForums = null): array
792
    {
793
        $stats = [];
794
795
        require_once $GLOBALS['xoops']->path('modules/newbb/include/functions.forum.php');
796
797
        $subForumTree = \newbbGetSubForum();
798
        if (empty($passedSubForums)) {
799
            $sub_forums = $subForumTree;
800
        } else {
801
            foreach ($passedSubForums as $id) {
802
                $sub_forums[$id] = $subForumTree[$id] ?? null;
803
            }
804
        }
805
806
        //        $forums_id = [];
807
        //        foreach (\array_keys($sub_forums) as $id) {
808
        //            if (empty($sub_forums[$id])) {
809
        //                continue;
810
        //            }
811
        //            $forums_id = \array_merge($forums_id, $sub_forums[$id]);
812
        //        }
813
814
        $forums_id = [];
815
        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...
816
            if (empty($sub_forums[$id])) {
817
                continue;
818
            }
819
            $forums_id[] = $sub_forums[$id]; // <- yes, we'll use a little bit more memory
820
        }
821
        $forums_id = \array_merge([], ...$forums_id); // the empty array covers cases when no loops were made
822
823
        if (empty($forums_id)) {
824
            return $stats;
825
        }
826
        $sql = '    SELECT forum_posts AS posts, forum_topics AS topics, forum_id AS id' . '    FROM ' . $this->table . '    WHERE forum_id IN (' . \implode(', ', $forums_id) . ')';
827
        $result = $this->db->query($sql);
828
        if (!$this->db->isResultSet($result)) {
829
            return $stats;
830
        }
831
832
        $forum_stats = [];
833
        while (false !== ($row = $this->db->fetchArray($result))) {
834
            $forum_stats[$row['id']] = ['topics' => $row['topics'], 'posts' => $row['posts']];
835
        }
836
837
        foreach (\array_keys($sub_forums) as $id) {
838
            if (empty($sub_forums[$id])) {
839
                continue;
840
            }
841
            $stats[$id] = ['topics' => 0, 'posts' => 0];
842
            foreach ($sub_forums[$id] as $fid) {
843
                $stats[$id]['topics'] += $forum_stats[$fid]['topics'];
844
                $stats[$id]['posts']  += $forum_stats[$fid]['posts'];
845
            }
846
        }
847
848
        return $stats;
849
    }
850
851
    /**
852
     * @param array $forums
853
     * @param int   $length_title_index
854
     * @param int   $count_subforum
855
     * @return array
856
     */
857
    public function &display(array $forums, int $length_title_index = 30, int $count_subforum = 1): array
858
    {
859
        global $myts;
860
861
        $posts       = [];
862
        $postsObject = [];
0 ignored issues
show
Unused Code introduced by
The assignment to $postsObject is dead and can be removed.
Loading history...
863
        foreach (\array_keys($forums) as $id) {
864
            $posts[] = $forums[$id]['forum_last_post_id'];
865
        }
866
        if (!empty($posts)) {
867
            $postHandler = Helper::getInstance()->getHandler('Post');
868
            $tags_post   = ['uid', 'topic_id', 'post_time', 'poster_name', 'icon'];
869
            if (!empty($length_title_index)) {
870
                $tags_post[] = 'subject';
871
            }
872
            $posts = $postHandler->getAll(new \Criteria('post_id', '(' . \implode(', ', $posts) . ')', 'IN'), $tags_post, false);
873
        }
874
875
        // Get topic/post stats per forum
876
        $stats_forum = [];
877
878
        if (!empty($count_subforum)) {
879
            $stats_forum = $this->getSubforumStats(\array_keys($forums)); // irmtfan uncomment to count sub forum posts/topics
880
        }
881
882
        $users  = [];
883
        $reads  = [];
884
        $topics = [];
0 ignored issues
show
Unused Code introduced by
The assignment to $topics is dead and can be removed.
Loading history...
885
886
        foreach (\array_keys($forums) as $id) {
887
            $forum = &$forums[$id];
888
889
            if (!$forum['forum_last_post_id']) {
890
                continue;
891
            }
892
            if (!$post = @$posts[$forum['forum_last_post_id']]) {
893
                $forum['forum_last_post_id'] = 0;
894
                continue;
895
            }
896
897
            $users[]         = $post['uid'];
898
            $moderators[$id] = $forum['forum_moderator'];
899
            if ($moderators[$id]) {
900
                $users = \array_merge($users, $moderators[$id]);
901
            }
902
903
            // reads
904
            if (!empty($GLOBALS['xoopsModuleConfig']['read_mode'])) {
905
                $reads[$id] = (1 == $GLOBALS['xoopsModuleConfig']['read_mode']) ? $post['post_time'] : $post['post_id'];
906
            }
907
        }
908
909
        require_once $GLOBALS['xoops']->path('modules/newbb/include/functions.user.php');
910
        require_once $GLOBALS['xoops']->path('modules/newbb/include/functions.time.php');
911
        require_once $GLOBALS['xoops']->path('modules/newbb/include/functions.render.php');
912
        require_once $GLOBALS['xoops']->path('modules/newbb/include/functions.read.php');
913
        $forum_isread = \newbbIsRead('forum', $reads);
914
        $users_linked = \newbbGetUnameFromIds(\array_unique($users), !empty($GLOBALS['xoopsModuleConfig']['show_realname']), true);
915
916
        $forums_array   = [];
917
        $name_anonymous = \htmlspecialchars((string)$GLOBALS['xoopsConfig']['anonymous'], \ENT_QUOTES | \ENT_HTML5);
918
919
        foreach (\array_keys($forums) as $id) {
920
            $forum = &$forums[$id];
921
922
            $_forum_data                 = [];
923
            $_forum_data['forum_order']  = $forum['forum_order'];
924
            $_forum_data['forum_id']     = $id;
925
            $_forum_data['forum_cid']    = $forum['cat_id'];
926
            $_forum_data['forum_name']   = $forum['forum_name'];
927
            $forumDescLength             = $GLOBALS['xoopsModuleConfig']['forum_desc_length'];
928
            $_forum_data['forum_desc']   = mb_strimwidth((string) $forum['forum_desc'], 0, $forumDescLength, '...');
929
            $_forum_data['forum_topics'] = $forum['forum_topics'] + @$stats_forum[$id]['topics'];
930
            $_forum_data['forum_posts']  = $forum['forum_posts'] + @$stats_forum[$id]['posts'];
931
            //$_forum_data["forum_type"]= $forum['forum_type'];
932
933
            $forum_moderators = [];
934
            if (!empty($moderators[$id])) {
935
                foreach (@$moderators[$id] as $moderator) {
936
                    $forum_moderators[] = @$users_linked[$moderator];
937
                }
938
            }
939
            $_forum_data['forum_moderators'] = \implode(', ', $forum_moderators);
940
941
            // irmtfan change if/endif to if{} method
942
            $post_id = $forum['forum_last_post_id'];
943
            if ($post_id) {
944
                $post                                  = &$posts[$post_id];
945
                $_forum_data['forum_lastpost_id']      = $post_id;
946
                $_forum_data['forum_lastpost_topicid'] = $post['topic_id'];
947
                $_forum_data['forum_lastpost_time']    = \newbbFormatTimestamp($post['post_time']);
948
                if (!empty($users_linked[$post['uid']])) {
949
                    $_forum_data['forum_lastpost_user'] = $users_linked[$post['uid']];
950
                } elseif ($poster_name = $post['poster_name']) {
951
                    $_forum_data['forum_lastpost_user'] = $poster_name;
952
                } else {
953
                    $_forum_data['forum_lastpost_user'] = $name_anonymous;
954
                }
955
                if (!empty($length_title_index)) {
956
                    $subject = $post['subject'];
957
                    if ($length_title_index < 255) {
958
                        $subject = \xoops_substr($subject, 0, $length_title_index);
959
                    }
960
                    $_forum_data['forum_lastpost_subject'] = $subject;
961
                }
962
                // irmtfan - remove icon_path and use newbbDisplayImage
963
                $_forum_data['forum_lastpost_icon'] = \newbbDisplayImage('lastposticon', \_MD_NEWBB_GOTOLASTPOST);
964
                // START irmtfan change the method to add read smarty
965
                if (empty($forum_isread[$id])) {
966
                    $_forum_data['forum_folder'] = \newbbDisplayImage('forum_new', \_MD_NEWBB_NEWPOSTS);
967
                    $_forum_data['forum_read']   = 0; // irmtfan add forum-read/forum-new smarty variable
968
                } else {
969
                    $_forum_data['forum_folder'] = \newbbDisplayImage('forum', \_MD_NEWBB_NONEWPOSTS);
970
                    $_forum_data['forum_read']   = 1; // irmtfan add forum-read/forum-new smarty variable
971
                }
972
                // END irmtfan change the method to add read smarty
973
            }
974
            $forums_array[$forum['parent_forum']][] = $_forum_data;
975
        }
976
977
        return $forums_array;
978
    }
979
980
    /**
981
     * get a hierarchical tree of forums
982
     *
983
     * {@link newbbTree}
984
     *
985
     * @param int|array         $cat_id     category ID
986
     * @param int               $pid        Top forum ID
987
     * @param string            $permission permission type
988
     * @param string            $prefix     prefix for display
989
     * @param string|array|null $tags       variables to fetch
990
     * @return array  associative array of category IDs and sanitized titles
991
     */
992
    public function &getTree($cat_id = 0, int $pid = 0, string $permission = 'access', string $prefix = '--', $tags = null): array
993
    {
994
        $forum_array = [];
995
        $pid         = (int)$pid;
996
        $perm_string = $permission;
997
        if (!\is_array($tags) || 0 === \count($tags)) {
998
            $tags = ['forum_id', 'parent_forum', 'forum_name', 'forum_order', 'cat_id'];
999
        }
1000
        $forumsObject = $this->getByPermission($cat_id, $perm_string, $tags);
1001
1002
        //        require_once __DIR__ . '/Tree.php';
1003
        $forums_structured = [];
1004
        foreach (\array_keys($forumsObject) as $key) {
1005
            $forums_structured[$forumsObject[$key]->getVar('cat_id')][$key] = $forumsObject[$key];
1006
        }
1007
1008
        foreach (\array_keys($forums_structured) as $cid) {
1009
            $tree              = new ObjectTree($forums_structured[$cid]);
1010
            $forum_array[$cid] = $tree->makeTree($prefix, $pid, $tags);
1011
            unset($tree);
1012
        }
1013
1014
        return $forum_array;
1015
    }
1016
1017
    /**
1018
     * get a hierarchical array tree of forums
1019
     *
1020
     * {@link newbbTree}
1021
     *
1022
     * @param int               $cat_id     category ID
1023
     * @param int               $pid        Top forum ID
1024
     * @param string            $permission permission type
1025
     * @param string|array|null $tags       variables to fetch
1026
     * @param int               $depth      level of subcategories
1027
     * @return array   associative array of category IDs and sanitized titles
1028
     */
1029
    public function &getArrayTree(int $cat_id = 0, int $pid = 0, string $permission = 'access', $tags = null, int $depth = 0): array
1030
    {
1031
        $forum_array = [];
1032
        $pid         = (int)$pid;
1033
        $perm_string = $permission;
1034
        if (!\is_array($tags) || 0 === \count($tags)) {
1035
            $tags = ['forum_id', 'parent_forum', 'forum_name', 'forum_order', 'cat_id'];
1036
        }
1037
        $forumsObject = $this->getByPermission($cat_id, $perm_string, $tags);
1038
1039
        //        require_once __DIR__ . '/Tree.php';
1040
        $forums_structured = [];
1041
        foreach (\array_keys($forumsObject) as $key) {
1042
            $forumObject                                             = &$forumsObject[$key];
1043
            $forums_structured[$forumObject->getVar('cat_id')][$key] = $forumsObject[$key];
1044
        }
1045
        foreach (\array_keys($forums_structured) as $cid) {
1046
            $tree              = new ObjectTree($forums_structured[$cid]);
1047
            $forum_array[$cid] = $tree->makeArrayTree($pid, $tags, $depth);
1048
            unset($tree);
1049
        }
1050
1051
        return $forum_array;
1052
    }
1053
1054
    /**
1055
     * @param Forum $object
1056
     * @return array|null
1057
     */
1058
    public function &getParents(Forum $object): ?array
1059
    {
1060
        $ret = null;
1061
        if (!$object->getVar('forum_id')) {
1062
            return $ret;
1063
        }
1064
1065
        require_once $GLOBALS['xoops']->path('modules/newbb/include/functions.forum.php');
1066
        if (!$parents = \newbbGetParentForum($object->getVar('forum_id'))) {
1067
            return $ret;
1068
        }
1069
        $parents_list = $this->getList(new \Criteria('forum_id', '(' . \implode(', ', $parents) . ')', 'IN'));
1070
        foreach ($parents as $key => $id) {
1071
            $ret[] = ['forum_id' => $id, 'forum_name' => $parents_list[$id]];
1072
        }
1073
        unset($parents, $parents_list);
1074
1075
        return $ret;
1076
    }
1077
1078
    // START irmtfan - get forum Ids by values. parse positive values to forum IDs and negative values to category IDs. value=0 => all valid forums
1079
    /**
1080
     * function for get forum Ids by positive and negative values
1081
     *
1082
     * @param int|text|array $values : positive values = forums | negative values = cats | $values=0 = all valid forums, $permission , true/false $parse_cats
1083
     * @param string|null    $permission
1084
     * @param bool           $parse_cats
1085
     * @return array
1086
     */
1087
    public function getIdsByValues($values = 0, ?string $permission = null, bool $parse_cats = true): array
1088
    {
1089
        $permission ??= 'access';
1090
        // Get all valid forums with this permission
1091
        $validForums = $this->getIdsByPermission($permission);
1092
        // if no value or value=0 return all valid forums
1093
        if (empty($values)) {
1094
            return $validForums;
1095
        }
1096
        $values = \is_numeric($values) ? [$values] : $values;
1097
        //parse negative values to category IDs
1098
        $forums = [];
1099
        /** @var array $cats */
1100
        $cats = [];
1101
        foreach ($values as $val) {
1102
            if (0 == $val) {
1103
                // value=0 => all valid forums
1104
                return $validForums;
1105
            }
1106
1107
            if ($val > 0) {
1108
                $forums[] = $val;
1109
            } else {
1110
                $cats[] = \abs($val);
1111
            }
1112
        }
1113
        // if dont want to parse categories OR no cats return all forums
1114
        if (empty($parse_cats) || empty($cats)) {
1115
            return \array_intersect($validForums, $forums);
1116
        }
1117
        // Get all forums by category IDs
1118
        $forumObjs = $this->getForumsByCategory($cats, $permission, true);
0 ignored issues
show
Unused Code introduced by
The assignment to $forumObjs is dead and can be removed.
Loading history...
1119
        return \array_intersect($validForums, $forums); //$forums    = [...$forums, ...array_keys($forumObjs)];
1120
1121
        return \array_intersect($validForums, $forums);
0 ignored issues
show
Unused Code introduced by
return array_intersect($validForums, $forums) is not reachable.

This check looks for unreachable code. It uses sophisticated control flow analysis techniques to find statements which will never be executed.

Unreachable code is most often the result of return, die or exit statements that have been added for debug purposes.

function fx() {
    try {
        doSomething();
        return true;
    }
    catch (\Exception $e) {
        return false;
    }

    return false;
}

In the above example, the last return false will never be executed, because a return statement has already been met in every possible execution path.

Loading history...
1122
    }
1123
    // END irmtfan - get forum Ids by values. parse positive values to forum IDs and negative values to category IDs. value=0 => all valid forums
1124
}
1125