Issues (380)

Security Analysis    not enabled

This project does not seem to handle request data directly as such no vulnerable execution paths were found.

  File Inclusion
File Inclusion enables an attacker to inject custom files into PHP's file loading mechanism, either explicitly passed to include, or for example via PHP's auto-loading mechanism.
  Regex Injection
Regex Injection enables an attacker to execute arbitrary code in your PHP process.
  SQL Injection
SQL Injection enables an attacker to execute arbitrary SQL code on your database server gaining access to user data, or manipulating user data.
  Response Splitting
Response Splitting can be used to send arbitrary responses.
  File Manipulation
File Manipulation enables an attacker to write custom data to files. This potentially leads to injection of arbitrary code on the server.
  Object Injection
Object Injection enables an attacker to inject an object into PHP code, and can lead to arbitrary code execution, file exposure, or file manipulation attacks.
  File Exposure
File Exposure allows an attacker to gain access to local files that he should not be able to access. These files can for example include database credentials, or other configuration files.
  XML Injection
XML Injection enables an attacker to read files on your local filesystem including configuration files, or can be abused to freeze your web-server process.
  Code Injection
Code Injection enables an attacker to execute arbitrary code on the server.
  Variable Injection
Variable Injection enables an attacker to overwrite program variables with custom data, and can lead to further vulnerabilities.
  XPath Injection
XPath Injection enables an attacker to modify the parts of XML document that are read. If that XML document is for example used for authentication, this can lead to further vulnerabilities similar to SQL Injection.
  Other Vulnerability
This category comprises other attack vectors such as manipulating the PHP runtime, loading custom extensions, freezing the runtime, or similar.
  Command Injection
Command Injection enables an attacker to inject a shell command that is execute with the privileges of the web-server. This can be used to expose sensitive data, or gain access of your server.
  LDAP Injection
LDAP Injection enables an attacker to inject LDAP statements potentially granting permission to run unauthorized queries, or modify content inside the LDAP tree.
  Cross-Site Scripting
Cross-Site Scripting enables an attacker to inject code into the response of a web-request that is viewed by other users. It can for example be used to bypass access controls, or even to take over other users' accounts.
  Header Injection
Unfortunately, the security analysis is currently not available for your project. If you are a non-commercial open-source project, please contact support to gain access.

class/ForumHandler.php (4 issues)

1
<?php
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 or later (https://www.gnu.org/licenses/gpl-2.0.html)
17
 * @package         newbb
18
 * @since           4.0
19
 * @author          Taiwen Jiang <[email protected]>
20
 */
21
22
use XoopsModules\Newbb;
23
24
 /**
25
 * Class ForumHandler
26
 */
27
class ForumHandler extends \XoopsPersistableObjectHandler
28
{
29
    /**
30
     * @param null|\XoopsDatabase $db
31
     */
32
    public function __construct(\XoopsDatabase $db = null)
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
    public function insert(\XoopsObject $object, $force = true) //insert($forum)
44
    {
45
        $forum = $object;
46
        if (!parent::insert($forum, true)) {
47
            return false;
48
        }
49
50
        if ($forum->isNew()) {
51
            $this->applyPermissionTemplate($forum);
52
        }
53
54
        return $forum->getVar('forum_id');
55
    }
56
57
    /**
58
     * @param \XoopsObject $forum
59
     * @param bool         $force
60
     * @return bool
61
     */
62
    public function delete(\XoopsObject $forum, $force = false) //delete(&$forum)
63
    {
64
        global $xoopsModule;
65
        // RMV-NOTIFY
66
        \xoops_notification_deletebyitem($xoopsModule->getVar('mid'), 'forum', $forum->getVar('forum_id'));
67
        // Get list of all topics in forum, to delete them too
68
        /** @var Newbb\TopicHandler $topicHandler */
69
        $topicHandler = \XoopsModules\Newbb\Helper::getInstance()->getHandler('Topic');
70
        $topicHandler->deleteAll(new \Criteria('forum_id', $forum->getVar('forum_id')), true, true);
71
        $this->updateAll('parent_forum', $forum->getVar('parent_forum'), new \Criteria('parent_forum', $forum->getVar('forum_id')));
72
        $this->deletePermission($forum);
73
74
        return parent::delete($forum);
75
    }
76
77
    /**
78
     * @param string $perm
79
     * @return mixed
80
     */
81
    public function getIdsByPermission($perm = 'access')
82
    {
83
        /** var Newbb\PermissionHandler $permHandler */
84
        $permHandler = \XoopsModules\Newbb\Helper::getInstance()->getHandler('Permission');
85
86
        return $permHandler->getForums($perm);
87
    }
88
89
    /**
90
     * @param int|array $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'));
104
        if (\is_numeric($cat) && $cat > 0) {
105
            $criteria->add(new \Criteria('cat_id', (int)$cat));
106
        } elseif ($cat && \is_array($cat)) {
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    = [];
132
        $array_forum  = [];
133
        if (!\is_array($forums)) {
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;
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);
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 ($forum && \is_array($forum)) {
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}";
197
        $criteria_extra   = '';
198
        $criteria_approve = ' AND t.approved = 1';
199
        $post_on          = ' p.post_id = t.topic_last_post_id';
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) {
203
            case 'digest':
204
                $criteria_extra = ' AND t.topic_digest = 1';
205
                break;
206
            case 'unreplied':
207
                $criteria_extra = ' AND t.topic_replies < 1';
208
                break;
209
            case 'unread':
210
                if (empty($GLOBALS['xoopsModuleConfig']['read_mode'])) {
211
                } elseif (2 == $GLOBALS['xoopsModuleConfig']['read_mode']) {
212
                    // START irmtfan use read_uid to find the unread posts when the user is logged in
213
                    $read_uid = \is_object($GLOBALS['xoopsUser']) ? $GLOBALS['xoopsUser']->getVar('uid') : 0;
214
                    if (!empty($read_uid)) {
215
                        $leftjoin      .= ' LEFT JOIN ' . $this->db->prefix('newbb_reads_topic') . ' r ON r.read_item = t.topic_id AND r.uid = ' . $read_uid . ' ';
216
                        $criteria_post .= ' AND (r.read_id IS NULL OR r.post_id < t.topic_last_post_id)';
217
                    }
218
                    // END irmtfan use read_uid to find the unread posts when the user is logged in
219
                } elseif (1 == $GLOBALS['xoopsModuleConfig']['read_mode']) {
220
                    // START irmtfan fix read_mode = 1 bugs - for all users (member and anon)
221
                    $time_criterion = \max($GLOBALS['last_visit'], $startdate);
222
                    if ($time_criterion) {
223
                        $criteria_post  = ' p.post_time > ' . $time_criterion; // for all users
224
                        $topics         = [];
225
                        $topic_lastread = \newbbGetCookie('LT', true);
226
                        if (\count($topic_lastread) > 0) {
227
                            foreach ($topic_lastread as $id => $time) {
228
                                if ($time > $time_criterion) {
229
                                    $topics[] = $id;
230
                                }
231
                            }
232
                        }
233
                        if (\count($topics) > 0) {
234
                            $criteria_extra = ' AND t.topic_id NOT IN (' . \implode(',', $topics) . ')';
235
                        }
236
                    }
237
                    // END irmtfan fix read_mode = 1 bugs - for all users (member and anon)
238
                }
239
                break;
240
            case 'pending':
241
                $post_on          = ' p.topic_id = t.topic_id';
242
                $criteria_post    .= ' AND p.pid = 0';
243
                $criteria_approve = ' AND t.approved = 0';
244
                break;
245
            case 'deleted':
246
                $criteria_approve = ' AND t.approved = -1';
247
                break;
248
            case 'all': // For viewall.php; do not display sticky topics at first
249
            case 'active': // same as "all"
250
                break;
251
            default:
252
                if ($startdate > 0) {
253
                    $criteria_post = ' (p.post_time > ' . $startdate . ' OR t.topic_sticky=1)';
254
                }
255
                $sort_array[] = 't.topic_sticky DESC';
256
                break;
257
        }
258
259
        $select = 't.*, ' . ' p.post_time as last_post_time, p.poster_name as last_poster_name, p.icon, p.post_id, p.uid';
260
        $from   = $this->db->prefix('newbb_topics') . ' t ' . $leftjoin;
261
        $where  = $criteria_post . $criteria_topic . $criteria_forum . $criteria_extra . $criteria_approve;
262
263
        if ($excerpt) {
264
            $select .= ', p.post_karma, p.require_reply, pt.post_text';
265
            $from   .= ' LEFT JOIN ' . $this->db->prefix('newbb_posts_text') . ' pt ON pt.post_id = t.topic_last_post_id';
266
        }
267
        if ('u.uname' === $sort) {
268
            $sort = 't.topic_poster';
269
        }
270
271
        $sort_array[] = \trim($sort . ' ' . $order);
272
        $sortby       = \implode(', ', \array_filter($sort_array));
273
        if (empty($sortby)) {
274
            $sortby = 't.topic_last_post_id DESC';
275
        }
276
277
        $sql = 'SELECT ' . $select . ' FROM ' . $from . ' WHERE ' . $where . ' ORDER BY ' . $sortby;
278
279
        if (!$result = $this->db->query($sql, $GLOBALS['xoopsModuleConfig']['topics_per_page'], $start)) {
280
            \redirect_header('index.php', 2, \_MD_NEWBB_ERROROCCURED);
281
        }
282
283
        $sticky  = 0;
284
        $topics  = [];
285
        $posters = [];
286
        $reads   = [];
287
        $types   = [];
288
289
        /** @var Newbb\TypeHandler $typeHandler */
290
        $typeHandler = \XoopsModules\Newbb\Helper::getInstance()->getHandler('Type');
291
        $typen       = $typeHandler->getByForum($forum->getVar('forum_id'));
292
        while (false !== ($myrow = $this->db->fetchArray($result))) {
293
            if ($myrow['topic_sticky']) {
294
                ++$sticky;
295
            }
296
297
            // ------------------------------------------------------
298
            // topic_icon: priority: sticky -> digest -> regular
299
300
            if ($myrow['topic_haspoll']) {
301
                if ($myrow['topic_sticky']) {
302
                    $topic_icon = \newbbDisplayImage('topic_sticky', \_MD_NEWBB_TOPICSTICKY) . '<br>' . \newbbDisplayImage('poll', \_MD_NEWBB_TOPICHASPOLL);
303
                } else {
304
                    $topic_icon = \newbbDisplayImage('poll', \_MD_NEWBB_TOPICHASPOLL);
305
                }
306
            } elseif ($myrow['topic_sticky']) {
307
                $topic_icon = \newbbDisplayImage('topic_sticky', \_MD_NEWBB_TOPICSTICKY);
308
            } elseif (!empty($myrow['icon'])) {
309
                $topic_icon = '<img src="' . XOOPS_URL . '/images/subject/' . \htmlspecialchars($myrow['icon'], \ENT_QUOTES | \ENT_HTML5) . '" alt="" >';
310
            } else {
311
                $topic_icon = '<img src="' . XOOPS_URL . '/images/icons/no_posticon.gif" alt="" >';
312
            }
313
314
            // ------------------------------------------------------
315
            // rating_img
316
            $rating = \number_format($myrow['rating'] / 2, 0);
317
            // irmtfan - add alt key for rating
318
            if ($rating < 1) {
319
                $rating_img = \newbbDisplayImage('blank');
320
            } else {
321
                $rating_img = \newbbDisplayImage('rate' . $rating, \constant('_MD_NEWBB_RATE' . $rating));
322
            }
323
            // ------------------------------------------------------
324
            // topic_page_jump
325
            $topic_page_jump      = '';
326
            $topic_page_jump_icon = '';
327
            $totalpages           = \ceil(($myrow['topic_replies'] + 1) / $GLOBALS['xoopsModuleConfig']['posts_per_page']);
328
            if ($totalpages > 1) {
329
                $topic_page_jump .= '&nbsp;&nbsp;';
330
                $append          = false;
331
                for ($i = 1; $i <= $totalpages; ++$i) {
332
                    if ($i > 3 && $i < $totalpages) {
333
                        if (!$append) {
334
                            $topic_page_jump .= '...';
335
                            $append          = true;
336
                        }
337
                    } else {
338
                        $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>]';
339
                        // irmtfan remove here and move
340
                        //$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>';
341
                    }
342
                }
343
            }
344
            // irmtfan - move here for both topics with and without pages
345
            $topic_page_jump_icon = "<a href='" . XOOPS_URL . '/modules/newbb/viewtopic.php?post_id=' . $myrow['post_id'] . "'>" . \newbbDisplayImage('lastposticon', _MD_NEWBB_GOTOLASTPOST) . '</a>';
346
347
            // ------------------------------------------------------
348
            // => topic array
349
            $forum_link = '';
350
            if (!empty($viewAllForums[$myrow['forum_id']])) {
351
                $forum_link = '<a href="' . XOOPS_URL . '/modules/newbb/viewforum.php?forum=' . $myrow['forum_id'] . '">' . $viewAllForums[$myrow['forum_id']]['forum_name'] . '</a>';
352
            }
353
354
            $topic_title = $myts->htmlSpecialChars($myrow['topic_title']);
355
            // irmtfan remove here and move to for loop
356
            //if ($myrow['type_id'] > 0) {
357
            //$topic_title = '<span style="color:'.$typen[$myrow["type_id"]]["type_color"].'">['.$typen[$myrow["type_id"]]["type_name"].']</span> '.$topic_title.'';
358
            //}
359
            if ($myrow['topic_digest']) {
360
                $topic_title = "<span class='digest'>" . $topic_title . '</span>';
361
            }
362
363
            if (0 == $excerpt) {
364
                $topic_excerpt = '';
365
            } elseif (($myrow['post_karma'] > 0 || $myrow['require_reply'] > 0) && !\newbbIsAdmin($forum)) {
366
                $topic_excerpt = '';
367
            } else {
368
                $topic_excerpt = \xoops_substr(\newbbHtml2text($myts->displayTarea($myrow['post_text'])), 0, $excerpt);
369
                $topic_excerpt = \str_replace('[', '&#91;', $myts->htmlSpecialChars($topic_excerpt));
370
            }
371
            // START irmtfan move here
372
            $topics[$myrow['topic_id']] = [
373
                'topic_id'             => $myrow['topic_id'],
374
                'topic_icon'           => $topic_icon,
375
                'type_id'              => $myrow['type_id'],
376
                //'type_text'                 => $topic_prefix,/*irmtfan remove here and move to for loop*/
377
                'topic_title'          => $topic_title,
378
                //'topic_link'                => XOOPS_URL . '/modules/newbb/viewtopic.php?topic_id=' . $myrow['topic_id'],
379
                'topic_link'           => 'viewtopic.php?topic_id=' . $myrow['topic_id'],
380
                'rating_img'           => $rating_img,
381
                'topic_page_jump'      => $topic_page_jump,
382
                'topic_page_jump_icon' => $topic_page_jump_icon,
383
                'topic_replies'        => $myrow['topic_replies'],
384
385
                'topic_digest' => $myrow['topic_digest'],
386
                //mb
387
388
                'topic_poster_uid'       => $myrow['topic_poster'],
389
                'topic_poster_name'      => $myts->htmlSpecialChars($myrow['poster_name'] ?: $GLOBALS['xoopsConfig']['anonymous']),
390
                'topic_views'            => $myrow['topic_views'],
391
                'topic_time'             => \newbbFormatTimestamp($myrow['topic_time']),
392
                'topic_last_posttime'    => \newbbFormatTimestamp($myrow['last_post_time']),
393
                'topic_last_poster_uid'  => $myrow['uid'],
394
                'topic_last_poster_name' => $myts->htmlSpecialChars($myrow['last_poster_name'] ?: $GLOBALS['xoopsConfig']['anonymous']),
395
                'topic_forum_link'       => $forum_link,
396
                'topic_excerpt'          => $topic_excerpt,
397
                'stick'                  => empty($myrow['topic_sticky']),
398
                'stats'                  => [
399
                    $myrow['topic_status'],
400
                    $myrow['topic_digest'],
401
                    $myrow['topic_replies'],
402
                ],
403
                /* irmtfan uncomment use ib the for loop*/
404
                //"topic_poster"              => $topic_poster,/*irmtfan remove here and move to for loop*/
405
                //"topic_last_poster"         => $topic_last_poster,/*irmtfan remove here and move to for loop*/
406
                //"topic_folder"              => newbbDisplayImage($topic_folder,$topic_folder_text),/*irmtfan remove here and move to for loop*/
407
            ];
408
            // END irmtfan move here
409
            /* users */
410
            $posters[$myrow['topic_poster']] = 1;
411
            $posters[$myrow['uid']]          = 1;
412
            // reads
413
            if (!empty($GLOBALS['xoopsModuleConfig']['read_mode'])) {
414
                $reads[$myrow['topic_id']] = (1 == $GLOBALS['xoopsModuleConfig']['read_mode']) ? $myrow['last_post_time'] : $myrow['topic_last_post_id'];
415
            }
416
        }// irmtfan while end
417
        // START irmtfan move to a for loop
418
        $posters_name = \newbbGetUnameFromIds(\array_keys($posters), $GLOBALS['xoopsModuleConfig']['show_realname'], true);
419
        //$topic_poster = newbbGetUnameFromId($myrow['topic_poster'], $GLOBALS['xoopsModuleConfig']['show_realname'], true);
420
        //$topic_last_poster = newbbGetUnameFromId($myrow['uid'], $GLOBALS['xoopsModuleConfig']['show_realname'], true);
421
        $topic_isRead = \newbbIsRead('topic', $reads);
422
        foreach (\array_keys($topics) as $id) {
423
            $topics[$id]['topic_read'] = empty($topic_isRead[$id]) ? 0 : 1; // add topic-read/topic-new smarty variable
424
            if (!empty($topics[$id]['type_id']) && isset($typen[$topics[$id]['type_id']])) {
425
                $topics[$id]['topic_title'] = \getTopicTitle($topics[$id]['topic_title'], $typen[$topics[$id]['type_id']]['type_name'], $typen[$topics[$id]['type_id']]['type_color']);
426
            }
427
            //$topic_prefix =  (!empty($typen[$myrow['type_id']])) ? getTopicTitle("", $typen[$myrow['type_id']]["type_name"], $typen[$myrow['type_id']]["type_color"]) : "";
428
            $topics[$id]['topic_poster']      = !empty($posters_name[$topics[$id]['topic_poster_uid']]) ? $posters_name[$topics[$id]['topic_poster_uid']] : $topics[$id]['topic_poster_name'];
429
            $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'];
430
431
            // ------------------------------------------------------
432
            // topic_folder: priority: newhot -> hot/new -> regular
433
            [$topic_status, $topic_digest, $topic_replies] = $topics[$id]['stats'];
434
            if (1 == $topic_status) {
435
                $topic_folder      = 'topic_locked';
436
                $topic_folder_text = \_MD_NEWBB_TOPICLOCKED;
437
            } else {
438
                if ($topic_digest) {
439
                    $topic_folder      = 'topic_digest';
440
                    $topic_folder_text = \_MD_NEWBB_TOPICDIGEST;
441
                } elseif ($topic_replies >= $hot_threshold) {
442
                    $topic_folder      = empty($topic_isRead[$id]) ? 'topic_hot_new' : 'topic_hot';
443
                    $topic_folder_text = empty($topic_isRead[$id]) ? \_MD_NEWBB_MORETHAN : \_MD_NEWBB_MORETHAN2;
444
                } else {
445
                    $topic_folder      = empty($topic_isRead[$id]) ? 'topic_new' : 'topic';
446
                    $topic_folder_text = empty($topic_isRead[$id]) ? \_MD_NEWBB_NEWPOSTS : \_MD_NEWBB_NONEWPOSTS;
447
                }
448
            }
449
            $topics[$id]['topic_folder'] = \newbbDisplayImage($topic_folder, $topic_folder_text);
450
            unset($topics[$id]['topic_poster_name'], $topics[$id]['topic_last_poster_name'], $topics[$id]['stats']);
451
        } // irmtfan end for loop
452
        // END irmtfan move to a for loop
453
        if (\count($topics) > 0) {
454
            $sql    = ' SELECT DISTINCT topic_id FROM ' . $this->db->prefix('newbb_posts') . " WHERE attachment != ''" . ' AND topic_id IN (' . \implode(',', \array_keys($topics)) . ')';
455
            $result = $this->db->query($sql);
456
            if ($result) {
457
                while (list($topic_id) = $this->db->fetchRow($result)) {
458
                    $topics[$topic_id]['attachment'] = '&nbsp;' . \newbbDisplayImage('attachment', \_MD_NEWBB_TOPICSHASATT);
459
                }
460
            }
461
        }
462
463
        return [$topics, $sticky];
464
    }
465
466
    /**
467
     * @param $forum
468
     * @param $startdate
469
     * @param $type
470
     * @return null|int
471
     */
472
    public function getTopicCount($forum, $startdate, $type)
473
    {
474
        require_once $GLOBALS['xoops']->path('modules/newbb/include/functions.session.php');
475
476
        $criteria_extra   = '';
477
        $criteria_approve = ' AND t.approved = 1'; // any others?
478
        $leftjoin         = ' LEFT JOIN ' . $this->db->prefix('newbb_posts') . ' p ON p.post_id = t.topic_last_post_id';
479
        $criteria_post    = ' p.post_time > ' . $startdate;
480
        switch ($type) {
481
            case 'digest':
482
                $criteria_extra = ' AND topic_digest = 1';
483
                break;
484
            case 'unreplied':
485
                $criteria_extra = ' AND topic_replies < 1';
486
                break;
487
            case 'unread':
488
                if (empty($GLOBALS['xoopsModuleConfig']['read_mode'])) {
489
                } elseif (2 == $GLOBALS['xoopsModuleConfig']['read_mode']) {
490
                    // START irmtfan use read_uid to find the unread posts when the user is logged in
491
492
                    $read_uid = \is_object($GLOBALS['xoopsUser']) ? $GLOBALS['xoopsUser']->getVar('uid') : 0;
493
                    if (!empty($read_uid)) {
494
                        $leftjoin      .= ' LEFT JOIN ' . $this->db->prefix('newbb_reads_topic') . ' r ON r.read_item = t.topic_id AND r.uid = ' . $read_uid . ' ';
495
                        $criteria_post .= ' AND (r.read_id IS NULL OR r.post_id < t.topic_last_post_id)';
496
                    }
497
                    // END irmtfan use read_uid to find the unread posts when the user is logged in
498
                } elseif (1 == $GLOBALS['xoopsModuleConfig']['read_mode']) {
499
                    // START irmtfan fix read_mode = 1 bugs - for all users (member and anon)
500
                    $time_criterion = \max($GLOBALS['last_visit'], $startdate);
501
                    if ($time_criterion) {
502
                        $criteria_post  = ' p.post_time > ' . $time_criterion; // for all users
503
                        $topics         = [];
504
                        $topic_lastread = \newbbGetCookie('LT', true);
505
                        if (\count($topic_lastread) > 0) {
506
                            foreach ($topic_lastread as $id => $time) {
507
                                if ($time > $time_criterion) {
508
                                    $topics[] = $id;
509
                                }
510
                            }
511
                        }
512
                        if (\count($topics) > 0) {
513
                            $criteria_extra = ' AND t.topic_id NOT IN (' . \implode(',', $topics) . ')';
514
                        }
515
                    }
516
                    // END irmtfan fix read_mode = 1 bugs - for all users (member and anon)
517
                }
518
                break;
519
            case 'pending':
520
                $criteria_approve = ' AND t.approved = 0';
521
                break;
522
            case 'deleted':
523
                $criteria_approve = ' AND t.approved = -1';
524
                break;
525
            case 'all':
526
                break;
527
            default:
528
                $criteria_post = ' (p.post_time > ' . $startdate . ' OR t.topic_sticky=1)';
529
                break;
530
        }
531
        $criteria_forum = '';
532
        if (\is_object($forum)) {
533
            $criteria_forum = ' AND t.forum_id = ' . $forum->getVar('forum_id');
534
        } else {
535
            if ($forum && \is_array($forum)) {
536
                $criteria_forum = ' AND t.forum_id IN (' . \implode(',', \array_keys($forum)) . ')';
537
            } elseif (!empty($forum)) {
538
                $criteria_forum = ' AND t.forum_id =' . (int)$forum;
539
            }
540
        }
541
542
        $sql = 'SELECT COUNT(*) AS count FROM ' . $this->db->prefix('newbb_topics') . ' t ' . $leftjoin;
543
        $sql .= ' WHERE ' . $criteria_post . $criteria_forum . $criteria_extra . $criteria_approve;
544
        if (!$result = $this->db->query($sql)) {
545
            //xoops_error($this->db->error().'<br>'.$sql);
546
            return null;
547
        }
548
        $myrow = $this->db->fetchArray($result);
549
        $count = $myrow['count'];
550
551
        return $count;
552
    }
553
554
    // get permission
555
556
    /**
557
     * @param         $forum
558
     * @param string  $type
559
     * @param bool    $checkCategory
560
     * @return bool
561
     */
562
    public function getPermission($forum, $type = 'access', $checkCategory = true)
563
    {
564
        global $xoopsModule;
565
        static $_cachedPerms;
566
567
        if ('all' === $type) {
568
            return true;
569
        }
570
571
        require_once \dirname(__DIR__) . '/include/functions.user.php';
572
        if (\newbbIsAdmin($forum)) {
573
            return true;
574
        }
575
        //if ($GLOBALS["xoopsUserIsAdmin"] && $xoopsModule->getVar("dirname") === "newbb") {
576
        //return true;
577
        //}
578
579
        if (!\is_object($forum)) {
580
            $forum = $this->get($forum);
581
        }
582
583
        if (!empty($checkCategory)) {
584
            /** @var Newbb\CategoryHandler $categoryHandler */
585
            $categoryHandler = \XoopsModules\Newbb\Helper::getInstance()->getHandler('Category');
586
            $categoryPerm    = $categoryHandler->getPermission($forum->getVar('cat_id'));
587
            if (!$categoryPerm) {
588
                return false;
589
            }
590
        }
591
592
        $type = mb_strtolower($type);
593
        // START irmtfan commented and removed
594
        //if ('moderate' === $type) {
595
        //require_once $GLOBALS['xoops']->path('modules/newbb/include/functions.user.php');
596
        //$permission = newbbIsModerator($forum);
597
        //} else {
598
        $forum_id = $forum->getVar('forum_id');
599
        /** var Newbb\PermissionHandler $permHandler */
600
        $permHandler = \XoopsModules\Newbb\Helper::getInstance()->getHandler('Permission');
601
        $permission  = $permHandler->getPermission('forum', $type, $forum_id);
602
        //}
603
        // END irmtfan commented and removed
604
        return $permission;
605
    }
606
607
    /**
608
     * @param $forum
609
     * @return mixed
610
     */
611
    public function deletePermission($forum)
612
    {
613
        /** var Newbb\PermissionHandler $permHandler */
614
        $permHandler = \XoopsModules\Newbb\Helper::getInstance()->getHandler('Permission');
615
616
        return $permHandler->deleteByForum($forum->getVar('forum_id'));
617
    }
618
619
    /**
620
     * @param $forum
621
     * @return mixed
622
     */
623
    public function applyPermissionTemplate($forum)
624
    {
625
        /** var Newbb\PermissionHandler $permHandler */
626
        $permHandler = \XoopsModules\Newbb\Helper::getInstance()->getHandler('Permission');
627
628
        return $permHandler->applyTemplate($forum->getVar('forum_id'));
629
    }
630
631
    /*
632
    function isForum($forum)
633
    {
634
        $count = false;
635
        $sql = 'SELECT COUNT(*) as count FROM ' . $this->db->prefix("newbb_forums");
636
        $sql .= ' WHERE forum_id=' . $forum ;
637
        if ($result = $this->db->query($sql)) {
638
            $myrow = $this->db->fetchArray($result);
639
            $count = $myrow['count'];
640
        }
641
642
        return $count;
643
    }
644
    */
645
646
    /**
647
     * clean orphan forums from database
648
     * @param string $table_link
649
     * @param string $field_link
650
     * @param string $field_object
651
     * @param array  $forum_ids forum IDs
652
     * @return bool   true on success
653
     */
654
    // START irmtfan rewrite forum cleanOrphan function. add parent_forum and cat_id orphan check
655
    //    public function cleanOrphan(array $forum_ids = [])
656
    public function cleanOrphan($table_link = '', $field_link = '', $field_object = '', $forum_ids = [])
657
    {
658
        // check parent_forum orphan forums
659
        if (empty($forum_ids)) {
660
            $forum_ids = $this->getIds();
661
        }
662
        if (empty($forum_ids)) {
663
            return false;
664
        }
665
        /*
666
            $sql =    "    UPDATE ".$GLOBALS['xoopsDB']->prefix("newbb_forums").
667
                    "    SET parent_forum = 0".
668
                    "    WHERE (parent_forum NOT IN ( ".$forum_ids."))".
669
                    "        OR parent_forum = forum_id";
670
        */
671
        $criteria = new \CriteriaCompo();
672
        $criteria->add(new \Criteria('parent_forum', '(' . \implode(', ', $forum_ids) . ')', 'NOT IN'), 'AND');
673
        $criteria->add(new \Criteria('parent_forum', '`forum_id`', '='), 'OR');
674
        $b1 = $this->updateAll('parent_forum', 0, $criteria, true);
675
        // check cat_id orphan forums
676
        $categoryHandler = \XoopsModules\Newbb\Helper::getInstance()->getHandler('Category');
677
        $cat_ids         = $categoryHandler->getIds();
678
        if (empty($cat_ids)) {
679
            return false;
680
        }
681
        $criteria = new \CriteriaCompo();
682
        $criteria->add(new \Criteria('cat_id', '(' . \implode(', ', $cat_ids) . ')', 'NOT IN'), 'AND');
683
        $b2 = $this->updateAll('cat_id', $cat_ids[0], $criteria, true);
684
685
        return ($b1 && $b2);
686
    }
687
688
    // END irmtfan rewrite forum cleanOrphan function. add parent_forum and cat_id orphan check
689
690
    /**
691
     * forum data synchronization
692
     *
693
     * @param mixed $object null for all forums; integer for forum_id; object for forum object
694
     * @return bool
695
     * @internal param int $mode 1 for stats only; 2 for forum index data only; 0 for both
696
     */
697
    public function synchronization($object = null)
698
    {
699
        if (empty($object)) {
700
            $forums = $this->getIds();
701
            $this->cleanOrphan('', '', '', $forums); // irmtfan - move cleanOrphan to synchronization function
702
            foreach ($forums as $id) {
703
                $this->synchronization($id);
704
            }
705
706
            return true;
707
        }
708
709
        if (!\is_object($object)) {
710
            $object = $this->get((int)$object);
711
        }
712
713
        if (!$object->getVar('forum_id')) {
714
            return false;
715
        }
716
        $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');
717
718
        $result = $this->db->query($sql);
719
        if ($result) {
720
            $last_post = 0;
721
            $posts     = 0;
722
            $row       = $this->db->fetchArray($result);
723
            if ($row) {
724
                $last_post = (int)$row['last_post'];
725
                $posts     = (int)$row['total'];
726
            }
727
            if ($object->getVar('forum_last_post_id') !== $last_post) {
728
                $object->setVar('forum_last_post_id', $last_post);
729
            }
730
            if ($object->getVar('forum_posts') !== $posts) {
731
                $object->setVar('forum_posts', $posts);
732
            }
733
        }
734
735
        $sql    = 'SELECT COUNT(*) AS total FROM ' . $this->db->prefix('newbb_topics') . ' WHERE approved=1 AND forum_id = ' . $object->getVar('forum_id');
736
        $result = $this->db->query($sql);
737
        if ($result) {
738
            $row = $this->db->fetchArray($result);
739
            if ($row) {
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) {
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;
812
813
        $posts       = [];
814
        $postsObject = [];
815
        foreach (\array_keys($forums) as $id) {
816
            $posts[] = $forums[$id]['forum_last_post_id'];
817
        }
818
        if (!empty($posts)) {
819
            $postHandler = \XoopsModules\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 = [];
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
            $moderators[$id] = $forum['forum_moderator'];
851
            if ($moderators[$id]) {
852
                $users = \array_merge($users, $moderators[$id]);
853
            }
854
855
            // reads
856
            if (!empty($GLOBALS['xoopsModuleConfig']['read_mode'])) {
857
                $reads[$id] = (1 == $GLOBALS['xoopsModuleConfig']['read_mode']) ? $post['post_time'] : $post['post_id'];
858
            }
859
        }
860
861
        require_once $GLOBALS['xoops']->path('modules/newbb/include/functions.user.php');
862
        require_once $GLOBALS['xoops']->path('modules/newbb/include/functions.time.php');
863
        require_once $GLOBALS['xoops']->path('modules/newbb/include/functions.render.php');
864
        require_once $GLOBALS['xoops']->path('modules/newbb/include/functions.read.php');
865
        $forum_isread = \newbbIsRead('forum', $reads);
866
        $users_linked = \newbbGetUnameFromIds(\array_unique($users), !empty($GLOBALS['xoopsModuleConfig']['show_realname']), true);
867
868
        $forums_array   = [];
869
        $name_anonymous = $myts->htmlSpecialChars($GLOBALS['xoopsConfig']['anonymous']);
870
871
        foreach (\array_keys($forums) as $id) {
872
            $forum = &$forums[$id];
873
874
            $_forum_data                 = [];
875
            $_forum_data['forum_order']  = $forum['forum_order'];
876
            $_forum_data['forum_id']     = $id;
877
            $_forum_data['forum_cid']    = $forum['cat_id'];
878
            $_forum_data['forum_name']   = $forum['forum_name'];
879
            $forumDescLength             = $GLOBALS['xoopsModuleConfig']['forum_desc_length'];
880
            $_forum_data['forum_desc']   = mb_strimwidth($forum['forum_desc'], 0, $forumDescLength, '...');
881
            $_forum_data['forum_topics'] = $forum['forum_topics'] + @$stats_forum[$id]['topics'];
882
            $_forum_data['forum_posts']  = $forum['forum_posts'] + @$stats_forum[$id]['posts'];
883
            //$_forum_data["forum_type"]= $forum['forum_type'];
884
885
            $forum_moderators = [];
886
            if (!empty($moderators[$id])) {
887
                foreach (@$moderators[$id] as $moderator) {
888
                    $forum_moderators[] = @$users_linked[$moderator];
889
                }
890
            }
891
            $_forum_data['forum_moderators'] = \implode(', ', $forum_moderators);
892
893
            // irmtfan change if/endif to if{} method
894
            $post_id = $forum['forum_last_post_id'];
895
            if ($post_id) {
896
                $post                               = &$posts[$post_id];
897
                $_forum_data['forum_lastpost_id']   = $post_id;
898
                $_forum_data['forum_lastpost_time'] = \newbbFormatTimestamp($post['post_time']);
899
                if (!empty($users_linked[$post['uid']])) {
900
                    $_forum_data['forum_lastpost_user'] = $users_linked[$post['uid']];
901
                } elseif ($poster_name = $post['poster_name']) {
902
                    $_forum_data['forum_lastpost_user'] = $poster_name;
903
                } else {
904
                    $_forum_data['forum_lastpost_user'] = $name_anonymous;
905
                }
906
                if (!empty($length_title_index)) {
907
                    $subject = $post['subject'];
908
                    if ($length_title_index < 255) {
909
                        $subject = \xoops_substr($subject, 0, $length_title_index);
910
                    }
911
                    $_forum_data['forum_lastpost_subject'] = $subject;
912
                }
913
                // irmtfan - remove icon_path and use newbbDisplayImage
914
                $_forum_data['forum_lastpost_icon'] = \newbbDisplayImage('lastposticon', _MD_NEWBB_GOTOLASTPOST);
915
                // START irmtfan change the method to add read smarty
916
                if (empty($forum_isread[$id])) {
917
                    $_forum_data['forum_folder'] = \newbbDisplayImage('forum_new', \_MD_NEWBB_NEWPOSTS);
918
                    $_forum_data['forum_read']   = 0; // irmtfan add forum-read/forum-new smarty variable
919
                } else {
920
                    $_forum_data['forum_folder'] = \newbbDisplayImage('forum', \_MD_NEWBB_NONEWPOSTS);
921
                    $_forum_data['forum_read']   = 1; // irmtfan add forum-read/forum-new smarty variable
922
                }
923
                // END irmtfan change the method to add read smarty
924
            }
925
            $forums_array[$forum['parent_forum']][] = $_forum_data;
926
        }
927
928
        return $forums_array;
929
    }
930
931
    /**
932
     * get a hierarchical tree of forums
933
     *
934
     * {@link newbbTree}
935
     *
936
     * @param int               $cat_id     category ID
937
     * @param int               $pid        Top forum ID
938
     * @param string            $permission permission type
939
     * @param string            $prefix     prefix for display
940
     * @param string|array|null $tags       variables to fetch
941
     * @return array  associative array of category IDs and sanitized titles
942
     */
943
    public function &getTree($cat_id = 0, $pid = 0, $permission = 'access', $prefix = '--', $tags = null)
944
    {
945
        $pid         = (int)$pid;
946
        $perm_string = $permission;
947
        if (!\is_array($tags) || 0 === \count($tags)) {
948
            $tags = ['forum_id', 'parent_forum', 'forum_name', 'forum_order', 'cat_id'];
949
        }
950
        $forumsObject = $this->getByPermission($cat_id, $perm_string, $tags);
951
952
        //        require_once __DIR__ . '/Tree.php';
953
        $forums_structured = [];
954
        foreach (\array_keys($forumsObject) as $key) {
955
            $forums_structured[$forumsObject[$key]->getVar('cat_id')][$key] = $forumsObject[$key];
956
        }
957
958
        foreach (\array_keys($forums_structured) as $cid) {
959
            $tree              = new ObjectTree($forums_structured[$cid]);
960
            $forum_array[$cid] = $tree->makeTree($prefix, $pid, $tags);
961
            unset($tree);
962
        }
963
964
        return $forum_array;
965
    }
966
967
    /**
968
     * get a hierarchical array tree of forums
969
     *
970
     * {@link newbbTree}
971
     *
972
     * @param int               $cat_id     category ID
973
     * @param int               $pid        Top forum ID
974
     * @param string            $permission permission type
975
     * @param string|array|null $tags       variables to fetch
976
     * @param int               $depth      level of subcategories
977
     * @return array   associative array of category IDs and sanitized titles
978
     */
979
    public function &getArrayTree($cat_id = 0, $pid = 0, $permission = 'access', $tags = null, $depth = 0)
980
    {
981
        $pid         = (int)$pid;
982
        $perm_string = $permission;
983
        if (!\is_array($tags) || 0 === \count($tags)) {
984
            $tags = ['forum_id', 'parent_forum', 'forum_name', 'forum_order', 'cat_id'];
985
        }
986
        $forumsObject = $this->getByPermission($cat_id, $perm_string, $tags);
987
988
        //        require_once __DIR__ . '/Tree.php';
989
        $forums_structured = [];
990
        foreach (\array_keys($forumsObject) as $key) {
991
            $forumObject                                             = &$forumsObject[$key];
992
            $forums_structured[$forumObject->getVar('cat_id')][$key] = $forumsObject[$key];
993
        }
994
        foreach (\array_keys($forums_structured) as $cid) {
995
            $tree              = new ObjectTree($forums_structured[$cid]);
996
            $forum_array[$cid] = $tree->makeArrayTree($pid, $tags, $depth);
997
            unset($tree);
998
        }
999
1000
        return $forum_array;
1001
    }
1002
1003
    /**
1004
     * @param $object
1005
     * @return array|null
1006
     */
1007
    public function &getParents($object)
1008
    {
1009
        $ret = null;
1010
        if (!$object->getVar('forum_id')) {
1011
            return $ret;
1012
        }
1013
1014
        require_once $GLOBALS['xoops']->path('modules/newbb/include/functions.forum.php');
1015
        if (!$parents = \newbbGetParentForum($object->getVar('forum_id'))) {
1016
            return $ret;
1017
        }
1018
        $parents_list = $this->getList(new \Criteria('forum_id', '(' . \implode(', ', $parents) . ')', 'IN'));
1019
        foreach ($parents as $key => $id) {
1020
            $ret[] = ['forum_id' => $id, 'forum_name' => $parents_list[$id]];
1021
        }
1022
        unset($parents, $parents_list);
1023
1024
        return $ret;
1025
    }
1026
1027
    // START irmtfan - get forum Ids by values. parse positive values to forum IDs and negative values to category IDs. value=0 => all valid forums
1028
1029
    /**
1030
     * function for get forum Ids by positive and negative values
1031
     *
1032
     * @param int|text|array $values : positive values = forums | negative values = cats | $values=0 = all valid forums, $permission , true/false $parse_cats
1033
     * @param string         $permission
1034
     * @param bool           $parse_cats
1035
     * @return array|mixed $validForums
1036
     */
1037
    public function getIdsByValues($values = 0, $permission = 'access', $parse_cats = true)
1038
    {
1039
        // Get all valid forums with this permission
1040
        $validForums = $this->getIdsByPermission($permission);
1041
        // if no value or value=0 return all valid forums
1042
        if (empty($values)) {
1043
            return $validForums;
1044
        }
1045
        $values = \is_numeric($values) ? [$values] : $values;
1046
        //parse negative values to category IDs
1047
        $forums = [];
1048
        $cats   = [];
1049
        foreach ($values as $val) {
1050
            if (0 == $val) {
1051
                // value=0 => all valid forums
1052
                return $validForums;
1053
            } elseif ($val > 0) {
1054
                $forums[] = $val;
1055
            } else {
1056
                $cats[] = \abs($val);
1057
            }
1058
        }
1059
        // if dont want to parse categories OR no cats return all forums
1060
        if (empty($parse_cats) || empty($cats)) {
1061
            return \array_intersect($validForums, $forums);
1062
        }
1063
        // Get all forums by category IDs
1064
        $forumObjs = $this->getForumsByCategory($cats, $permission, true);
1065
        $forums    = \array_merge($forums, \array_keys($forumObjs));
1066
1067
        return \array_intersect($validForums, $forums);
1068
    }
1069
1070
    // END irmtfan - get forum Ids by values. parse positive values to forum IDs and negative values to category IDs. value=0 => all valid forums
1071
}
1072