Issues (340)

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/PostHandler.php (19 issues)

1
<?php declare(strict_types=1);
2
3
namespace XoopsModules\Newbb;
4
5
/*
6
 * You may not change or alter any portion of this comment or credits
7
 * of supporting developers from this source code or any supporting source code
8
 * which is considered copyrighted (c) material of the original comment or credit authors.
9
 *
10
 * This program is distributed in the hope that it will be useful,
11
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13
 */
14
//  ------------------------------------------------------------------------ //
15
//  Author: phppp (D.J., [email protected])                                  //
16
//  URL: https://xoops.org                                                    //
17
//  Project: Article Project                                                 //
18
//  ------------------------------------------------------------------------ //
19
20
\defined('NEWBB_FUNCTIONS_INI') || require $GLOBALS['xoops']->path('modules/newbb/include/functions.ini.php');
21
22
/** @var TopicHandler $topicHandler */
23
24
/**
25
 * Class PostHandler
26
 */
27
class PostHandler extends \XoopsPersistableObjectHandler
28
{
29
    /**
30
     * @param \XoopsDatabase|null $db
31
     */
32
    public function __construct(\XoopsDatabase $db = null)
33
    {
34
        parent::__construct($db, 'newbb_posts', Post::class, 'post_id', 'subject');
35
    }
36
37
    /**
38
     * @param mixed $id
39
     * @param array $fields fields to fetch
40
     * @return \XoopsObject|null
41
     */
42
    public function get($id = null,  $fields = null): ?\XoopsObject //get($id)
43
    {
44
        $id    = (int)$id;
45
        $post  = null;
46
        $sql   = 'SELECT p.*, t.* FROM ' . $this->db->prefix('newbb_posts') . ' p LEFT JOIN ' . $this->db->prefix('newbb_posts_text') . ' t ON p.post_id=t.post_id WHERE p.post_id=' . $id;
47
        $result = $this->db->query($sql);
48
        if ($this->db->isResultSet($result)) {
49
            $array = $this->db->fetchArray($result);
50
            if ($array) {
51
                $post = $this->create(false);
52
                $post->assignVars($array);
53
            }
54
        }
55
        return $post;
56
    }
57
58
    /**
59
     * @param int                   $limit    Max number of objects to fetch
60
     * @param int                   $start    Which record to start at
61
     * @param \CriteriaElement|null $criteria {@link \CriteriaElement} to match
62
     * @param null                  $fields   variables to fetch
0 ignored issues
show
Documentation Bug introduced by
Are you sure the doc-type for parameter $fields is correct as it would always require null to be passed?
Loading history...
63
     * @param bool                  $asObject flag indicating as object, otherwise as array
64
     * @param int                   $topic_id Max number of objects to fetch
65
     * @param int                   $approved Which record to start at
66
     * @return array           of objects     {@link XoopsObject}
67
     */
68
    //    public function getByLimit($topic_id, $limit, $approved = 1)
69
70
//    public function &getByLimit($limit = 0, $start = 0, CriteriaElement $criteria = null, $fields = null, $asObject = true)
71
    public function &getByLimit(
72
         $limit = 0,
73
         $start = 0,
74
        \CriteriaElement $criteria = null,
75
         $fields = null,
76
         $asObject = true,
77
        int $topic_id = 0,
78
        int $approved = 1
79
    ): array {
80
        $sql    = 'SELECT p.*, t.*, tp.topic_status FROM '
81
                  . $this->db->prefix('newbb_posts')
82
                  . ' p LEFT JOIN '
83
                  . $this->db->prefix('newbb_posts_text')
84
                  . ' t ON p.post_id=t.post_id LEFT JOIN '
85
                  . $this->db->prefix('newbb_topics')
86
                  . ' tp ON tp.topic_id=p.topic_id WHERE p.topic_id='
87
                  . $topic_id
88
                  . ' AND p.approved ='
89
                  . $approved
90
                  . ' ORDER BY p.post_time DESC';
91
        $result = $this->db->query($sql, $limit, 0);
92
        $ret    = [];
93
        if ($this->db->isResultSet($result)) {
94
            while (false !== ($myrow = $this->db->fetchArray($result))) {
95
                $post = $this->create(false);
96
                $post->assignVars($myrow);
97
98
                $ret[$myrow['post_id']] = $post;
99
                unset($post);
100
            }
101
        }
102
103
        return $ret;
104
    }
105
106
    /**
107
     * @param Post $post
108
     * @return array
109
     */
110
    public function getPostForPDF(Post $post): array
111
    {
112
        return $post->getPostBody();
113
    }
114
115
    /**
116
     * @param Post $post
117
     * @return array
118
     */
119
    public function getPostForPrint(Post $post): array
120
    {
121
        return $post->getPostBody();
122
    }
123
124
    /**
125
     * @param int|Post $post
126
     * @param bool     $force
127
     * @return bool
128
     */
129
    public function approve(&$post, bool $force = false): bool
130
    {
131
        if (empty($post)) {
132
            return false;
133
        }
134
        if (\is_numeric($post)) {
135
            $post = $this->get($post);
136
        }
137
138
        $wasApproved = $post->getVar('approved');
139
        // irmtfan approve post if the approved = 0 (pending) or -1 (deleted)
140
        if (empty($force) && $wasApproved > 0) {
141
            return true;
142
        }
143
        $post->setVar('approved', 1);
144
        $this->insert($post, true);
0 ignored issues
show
It seems like $post can also be of type null; however, parameter $object of XoopsModules\Newbb\PostHandler::insert() does only seem to accept XoopsObject, 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

144
        $this->insert(/** @scrutinizer ignore-type */ $post, true);
Loading history...
145
146
        /** @var TopicHandler $topicHandler */
147
        $topicHandler = Helper::getInstance()->getHandler('Topic');
148
        $topicObject  = $topicHandler->get($post->getVar('topic_id'));
149
        if ($topicObject->getVar('topic_last_post_id') < $post->getVar('post_id')) {
150
            $topicObject->setVar('topic_last_post_id', $post->getVar('post_id'));
151
        }
152
        if ($post->isTopic()) {
0 ignored issues
show
The method isTopic() does not exist on XoopsObject. It seems like you code against a sub-type of XoopsObject such as Post or XoopsModules\Newbb\Post. ( Ignorable by Annotation )

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

152
        if ($post->/** @scrutinizer ignore-call */ isTopic()) {
Loading history...
153
            $topicObject->setVar('approved', 1);
154
        } else {
155
            $topicObject->setVar('topic_replies', $topicObject->getVar('topic_replies') + 1);
156
        }
157
        $topicHandler->insert($topicObject, true);
0 ignored issues
show
It seems like $topicObject can also be of type null; however, parameter $object of XoopsModules\Newbb\TopicHandler::insert() does only seem to accept XoopsObject, 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

157
        $topicHandler->insert(/** @scrutinizer ignore-type */ $topicObject, true);
Loading history...
158
159
        /** @var ForumHandler $forumHandler */
160
        $forumHandler = Helper::getInstance()->getHandler('Forum');
161
        $forumObject  = $forumHandler->get($post->getVar('forum_id'));
162
        if ($forumObject->getVar('forum_last_post_id') < $post->getVar('post_id')) {
163
            $forumObject->setVar('forum_last_post_id', $post->getVar('post_id'));
164
        }
165
        $forumObject->setVar('forum_posts', $forumObject->getVar('forum_posts') + 1);
166
        if ($post->isTopic()) {
167
            $forumObject->setVar('forum_topics', $forumObject->getVar('forum_topics') + 1);
168
        }
169
        $forumHandler->insert($forumObject, true);
170
171
        // Update user stats
172
        if ($post->getVar('uid') > 0) {
173
            /** @var \XoopsMemberHandler $memberHandler */
174
            $memberHandler = \xoops_getHandler('member');
175
            $poster        = $memberHandler->getUser($post->getVar('uid'));
176
            if (\is_object($poster) && $post->getVar('uid') == $poster->getVar('uid')) {
177
                $poster->setVar('posts', $poster->getVar('posts') + 1);
178
                $res = $memberHandler->insertUser($poster, true);
0 ignored issues
show
The assignment to $res is dead and can be removed.
Loading history...
179
                unset($poster);
180
            }
181
        }
182
183
        // Update forum stats
184
        /** @var StatsHandler $statsHandler */
185
        $statsHandler = Helper::getInstance()->getHandler('Stats');
186
        $statsHandler->update($post->getVar('forum_id'), 'post');
0 ignored issues
show
It seems like $post->getVar('forum_id') can also be of type array and array; however, parameter $id of XoopsModules\Newbb\StatsHandler::update() does only seem to accept integer|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

186
        $statsHandler->update(/** @scrutinizer ignore-type */ $post->getVar('forum_id'), 'post');
Loading history...
187
        if ($post->isTopic()) {
188
            $statsHandler->update($post->getVar('forum_id'), 'topic');
189
        }
190
191
        return true;
192
    }
193
194
    /**
195
     * @param \XoopsObject $object Post Object
196
     * @param bool $force
197
     * @return bool|int
198
     */
199
    public function insert(\XoopsObject $object, $force = true) //insert(&$object, $force = true)
200
    {
201
        /** @var Post $post */
202
        $post        = $object;
203
        $topicObject = null;
204
        // Set the post time
205
        // The time should be "publish" time. To be adjusted later
206
        if (!$post->getVar('post_time')) {
207
            $post->setVar('post_time', \time());
208
        }
209
210
        $topicHandler = Helper::getInstance()->getHandler('Topic');
211
        // Verify the topic ID
212
        $topic_id = $post->getVar('topic_id');
213
        if ($topic_id) {
214
            $topicObject = $topicHandler->get($topic_id);
215
            // Invalid topic OR the topic is no approved and the post is not top post
216
            if (!$topicObject//    || (!$post->isTopic() && $topicObject->getVar("approved") < 1)
217
            ) {
218
                return false;
219
            }
220
        }
221
        if (empty($topic_id)) {
222
            $post->setVar('topic_id', 0);
223
            $post->setVar('pid', 0);
224
            $post->setNew();
225
            $topicObject = $topicHandler->create();
226
        }
227
        $textHandler    = Helper::getInstance()->getHandler('Text');
228
        $post_text_vars = ['post_text', 'post_edit', 'dohtml', 'doxcode', 'dosmiley', 'doimage', 'dobr'];
229
        if ($post->isNew()) {
230
            if (!$topic_id = $post->getVar('topic_id')) {
231
                $topicObject->setVar('topic_title', $post->getVar('subject', 'n'));
232
                $topicObject->setVar('topic_poster', $post->getVar('uid'));
233
                $topicObject->setVar('forum_id', $post->getVar('forum_id'));
234
                $topicObject->setVar('topic_time', $post->getVar('post_time'));
235
                $topicObject->setVar('poster_name', $post->getVar('poster_name'));
236
                $topicObject->setVar('approved', $post->getVar('approved'));
237
238
                if (!$topic_id = $topicHandler->insert($topicObject, $force)) {
0 ignored issues
show
It seems like $topicObject can also be of type null; however, parameter $object of XoopsModules\Newbb\TopicHandler::insert() does only seem to accept XoopsObject, 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

238
                if (!$topic_id = $topicHandler->insert(/** @scrutinizer ignore-type */ $topicObject, $force)) {
Loading history...
239
                    $post->deleteAttachment();
240
                    $post->setErrors('insert topic error');
241
242
                    //xoops_error($topicObject->getErrors());
243
                    return false;
244
                }
245
                $post->setVar('topic_id', $topic_id);
246
247
                $pid = 0;
0 ignored issues
show
The assignment to $pid is dead and can be removed.
Loading history...
248
                $post->setVar('pid', 0);
249
            } elseif (!$post->getVar('pid')) {
250
                $pid = $topicHandler->getTopPostId($topic_id);
251
                $post->setVar('pid', $pid);
252
            }
253
254
            $textObject = $textHandler->create();
255
            foreach ($post_text_vars as $key) {
256
                $textObject->vars[$key] = $post->vars[$key];
257
            }
258
            $post->destroyVars($post_text_vars);
259
260
            //            if (!$postId = parent::insert($post, $force)) {
261
            //                return false;
262
            //            }
263
264
            if (!$postId = parent::insert($post, $force)) {
265
                return false;
266
            }
267
            $post->unsetNew();
268
269
            $textObject->setVar('post_id', $postId);
270
            if (!$textHandler->insert($textObject, $force)) {
271
                $this->myDelete($post);
272
                $post->setErrors('post text insert error');
273
274
                //xoops_error($textObject->getErrors());
275
                return false;
276
            }
277
            if ($post->getVar('approved') > 0) {
278
                $this->approve($post, true);
279
            }
280
            $post->setVar('post_id', $postId);
281
        } else {
282
            if ($post->isTopic()) {
283
                if ($post->getVar('subject') !== $topicObject->getVar('topic_title')) {
284
                    $topicObject->setVar('topic_title', $post->getVar('subject', 'n'));
285
                }
286
                if ($post->getVar('approved') !== $topicObject->getVar('approved')) {
287
                    $topicObject->setVar('approved', $post->getVar('approved'));
288
                }
289
                $topicObject->setDirty();
290
                if (!$result = $topicHandler->insert($topicObject, $force)) {
0 ignored issues
show
The assignment to $result is dead and can be removed.
Loading history...
291
                    $post->setErrors('update topic error');
292
293
                    //xoops_error($topicObject->getErrors());
294
                    return false;
295
                }
296
            }
297
            $textObject = $textHandler->get($post->getVar('post_id'));
298
            $textObject->setDirty();
299
            foreach ($post_text_vars as $key) {
300
                $textObject->vars[$key] = $post->vars[$key];
301
            }
302
            $post->destroyVars($post_text_vars);
303
            if (!$postId = parent::insert($post, $force)) {
0 ignored issues
show
The assignment to $postId is dead and can be removed.
Loading history...
304
                //xoops_error($post->getErrors());
305
                return false;
306
            }
307
            $post->unsetNew();
308
309
            if (!$textHandler->insert($textObject, $force)) {
310
                $post->setErrors('update post text error');
311
312
                //xoops_error($textObject->getErrors());
313
                return false;
314
            }
315
        }
316
317
        return $post->getVar('post_id');
318
    }
319
320
    /**
321
     * @param Post $post Post Object
322
     * @param bool $isDeleteOne
323
     * @param bool $force
324
     * @return bool
325
     */
326
    public function myDelete(Post $post, bool $isDeleteOne = true, bool $force = false): bool
327
    {
328
        if (!\is_object($post) || 0 == $post->getVar('post_id')) {
329
            return false;
330
        }
331
332
        if ($isDeleteOne) {
333
            if ($post->isTopic()) {
334
                $criteria = new \CriteriaCompo(new \Criteria('topic_id', $post->getVar('topic_id')));
0 ignored issues
show
It seems like $post->getVar('topic_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

334
                $criteria = new \CriteriaCompo(new \Criteria('topic_id', /** @scrutinizer ignore-type */ $post->getVar('topic_id')));
Loading history...
335
                $criteria->add(new \Criteria('approved', 1));
336
                $criteria->add(new \Criteria('pid', '0', '>'));
337
                if ($this->getPostCount($criteria) > 0) {
338
                    return false;
339
                }
340
            }
341
342
            return $this->delete($post, $force);
343
        }
344
        require_once $GLOBALS['xoops']->path('class/xoopstree.php');
345
        $mytree = new Tree($this->db->prefix('newbb_posts'), 'post_id', 'pid');
346
        $arr    = $mytree->getAllChild($post->getVar('post_id'));
347
        // irmtfan - delete childs in a reverse order
348
        for ($i = (is_countable($arr) ? \count($arr) : 0) - 1; $i >= 0; $i--) {
0 ignored issues
show
It seems like $arr can also be of type mixed; 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

348
        for ($i = (is_countable($arr) ? \count(/** @scrutinizer ignore-type */ $arr) : 0) - 1; $i >= 0; $i--) {
Loading history...
349
            /** @var Post $childpost */
350
            $childpost = $this->create(false);
351
            $childpost->assignVars($arr[$i]);
352
            $this->delete($childpost, $force);
353
            unset($childpost);
354
        }
355
        $this->delete($post, $force);
356
357
        return true;
358
    }
359
360
    /**
361
     * @param \XoopsObject $object
362
     * @param bool         $force
363
     * @return bool
364
     */
365
    public function delete(\XoopsObject $object, $force = false): bool
366
    {
367
        global $xoopsModule;
368
369
        $post = $object;
370
371
        if (!\is_object($post) || 0 == $post->getVar('post_id')) {
372
            return false;
373
        }
374
375
        /* Set active post as deleted */
376
        if ($post->getVar('approved') > 0 && empty($force)) {
377
            $sql = 'UPDATE ' . $this->db->prefix('newbb_posts') . ' SET approved = -1 WHERE post_id = ' . $post->getVar('post_id');
378
            if (!$result = $this->db->queryF($sql)) {
0 ignored issues
show
The assignment to $result is dead and can be removed.
Loading history...
379
            }
380
            /* delete pending post directly */
381
        } else {
382
            $sql = \sprintf('DELETE FROM `%s` WHERE post_id = %u', $this->db->prefix('newbb_posts'), $post->getVar('post_id'));
0 ignored issues
show
It seems like $post->getVar('post_id') can also be of type array and array; however, parameter $values of sprintf() does only seem to accept double|integer|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

382
            $sql = \sprintf('DELETE FROM `%s` WHERE post_id = %u', $this->db->prefix('newbb_posts'), /** @scrutinizer ignore-type */ $post->getVar('post_id'));
Loading history...
383
            if (!$result = $this->db->queryF($sql)) {
384
                $post->setErrors('delete post error: ' . $sql);
385
386
                return false;
387
            }
388
            $post->deleteAttachment();
0 ignored issues
show
The method deleteAttachment() does not exist on XoopsObject. It seems like you code against a sub-type of XoopsObject such as Post or XoopsModules\Newbb\Post. ( Ignorable by Annotation )

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

388
            $post->/** @scrutinizer ignore-call */ 
389
                   deleteAttachment();
Loading history...
389
390
            $sql = \sprintf('DELETE FROM `%s` WHERE post_id = %u', $this->db->prefix('newbb_posts_text'), $post->getVar('post_id'));
391
            if (!$result = $this->db->queryF($sql)) {
392
                $post->setErrors('Could not remove post text: ' . $sql);
393
394
                return false;
395
            }
396
        }
397
398
        if ($post->isTopic()) {
399
            $topicHandler = Helper::getInstance()->getHandler('Topic');
400
            /** @var Topic $topicObject */
401
            $topicObject = $topicHandler->get($post->getVar('topic_id'));
402
            if (\is_object($topicObject) && $topicObject->getVar('approved') > 0 && empty($force)) {
403
                $topiccount_toupdate = 1;
0 ignored issues
show
The assignment to $topiccount_toupdate is dead and can be removed.
Loading history...
404
                $topicObject->setVar('approved', -1);
405
                $topicHandler->insert($topicObject);
406
                \xoops_notification_deletebyitem($xoopsModule->getVar('mid'), 'thread', $post->getVar('topic_id'));
407
            } else {
408
                if (\is_object($topicObject)) {
409
                    if ($topicObject->getVar('approved') > 0) {
410
                        \xoops_notification_deletebyitem($xoopsModule->getVar('mid'), 'thread', $post->getVar('topic_id'));
411
                    }
412
413
                    $poll_id = $topicObject->getVar('poll_id');
414
                    // START irmtfan poll_module
415
                    $topicObject->deletePoll($poll_id);
416
                    // END irmtfan poll_module
417
                }
418
419
                $sql = \sprintf('DELETE FROM `%s` WHERE topic_id = %u', $this->db->prefix('newbb_topics'), $post->getVar('topic_id'));
420
                if (!$result = $this->db->queryF($sql)) {
421
                    //xoops_error($this->db->error());
422
                }
423
                $sql = \sprintf('DELETE FROM `%s` WHERE topic_id = %u', $this->db->prefix('newbb_votedata'), $post->getVar('topic_id'));
424
                if (!$result = $this->db->queryF($sql)) {
425
                    //xoops_error($this->db->error());
426
                }
427
            }
428
        } else {
429
            $sql = 'UPDATE ' . $this->db->prefix('newbb_topics') . ' t
430
                            LEFT JOIN ' . $this->db->prefix('newbb_posts') . ' p ON p.topic_id = t.topic_id
431
                            SET t.topic_last_post_id = p.post_id
432
                            WHERE t.topic_last_post_id = ' . $post->getVar('post_id') . '
433
                                    AND p.post_id = (SELECT MAX(post_id) FROM ' . $this->db->prefix('newbb_posts') . ' WHERE topic_id=t.topic_id)';
434
            if (!$result = $this->db->queryF($sql)) {
435
            }
436
        }
437
438
        $postcount_toupdate = $post->getVar('approved');
439
440
        if ($postcount_toupdate > 0) {
441
            // Update user stats
442
            if ($post->getVar('uid') > 0) {
443
                /** @var \XoopsMemberHandler $memberHandler */
444
                $memberHandler = \xoops_getHandler('member');
445
                $poster        = $memberHandler->getUser($post->getVar('uid'));
446
                if (\is_object($poster) && $post->getVar('uid') == $poster->getVar('uid')) {
447
                    $poster->setVar('posts', $poster->getVar('posts') - 1);
448
                    $res = $memberHandler->insertUser($poster, true);
0 ignored issues
show
The assignment to $res is dead and can be removed.
Loading history...
449
                    unset($poster);
450
                }
451
            }
452
            // irmtfan - just update the pid for approved posts when the post is not topic (pid=0)
453
            if (!$post->isTopic()) {
454
                $sql = 'UPDATE ' . $this->db->prefix('newbb_posts') . ' SET pid = ' . $post->getVar('pid') . ' WHERE approved=1 AND pid=' . $post->getVar('post_id');
455
                if (!$result = $this->db->queryF($sql)) {
456
                    //xoops_error($this->db->error());
457
                }
458
            }
459
        }
460
461
        return true;
462
    }
463
464
    // START irmtfan enhance getPostCount when there is join (read_mode = 2)
465
    /**
466
     * @param \CriteriaElement|\CriteriaCompo|null $criteria
467
     * @param string|null                          $join
468
     * @return int|null
469
     */
470
    public function getPostCount(\CriteriaElement $criteria = null, string $join = null): ?int
471
    {
472
        // if not join get the count from XOOPS/class/model/stats as before
473
        if (empty($join)) {
474
            return $this->getCount($criteria);
475
        }
476
477
        $sql = 'SELECT COUNT(*) as count' . ' FROM ' . $this->db->prefix('newbb_posts') . ' AS p' . ' LEFT JOIN ' . $this->db->prefix('newbb_posts_text') . ' AS t ON t.post_id = p.post_id';
478
        // LEFT JOIN
479
        $sql .= $join;
480
        // WHERE
481
         if (\is_object($criteria) && \is_subclass_of($criteria, \CriteriaElement::class)) {
482
            $sql .= ' ' . $criteria->renderWhere();
0 ignored issues
show
The method renderWhere() does not exist on CriteriaElement. Did you maybe mean render()? ( Ignorable by Annotation )

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

482
            $sql .= ' ' . $criteria->/** @scrutinizer ignore-call */ renderWhere();

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
483
        }
484
        $result = $this->db->query($sql);
485
        if (!$this->db->isResultSet($result)) {
486
            //xoops_error($this->db->error().'<br>'.$sql);
487
            return null;
488
        }
489
        $myrow = $this->db->fetchArray($result);
490
        $count = (int)$myrow['count'];
491
492
        return $count;
493
    }
494
495
    // END irmtfan enhance getPostCount when there is join (read_mode = 2)
496
    /*
497
     * TODO: combining viewtopic.php
498
     */
499
    /**
500
     * @param \CriteriaElement|\CriteriaCompo|null $criteria
501
     * @param int                                  $limit
502
     * @param int                                  $start
503
     * @param string|null                          $join
504
     * @return array
505
     */
506
    public function getPostsByLimit(\CriteriaElement $criteria = null, int $limit = 1, int $start = 0, ?string $join = null): array
507
    {
508
        $ret = [];
509
        $sql = 'SELECT p.*, t.* ' . ' FROM ' . $this->db->prefix('newbb_posts') . ' AS p' . ' LEFT JOIN ' . $this->db->prefix('newbb_posts_text') . ' AS t ON t.post_id = p.post_id';
510
        if (!empty($join)) {
511
            $sql .= $join;
512
        }
513
         if (\is_object($criteria) && \is_subclass_of($criteria, \CriteriaElement::class)) {
514
            $sql .= ' ' . $criteria->renderWhere();
515
            if ('' !== $criteria->getSort()) {
516
                $sql .= ' ORDER BY ' . $criteria->getSort() . ' ' . $criteria->getOrder();
517
            }
518
        }
519
        $result = $this->db->query($sql, $limit, $start);
520
        if ($this->db->isResultSet($result)) {
521
            while (false !== ($myrow = $this->db->fetchArray($result))) {
522
                $post = $this->create(false);
523
                $post->assignVars($myrow);
524
                $ret[$myrow['post_id']] = $post;
525
                unset($post);
526
            }
527
        }
528
529
        return $ret;
530
    }
531
532
    /**
533
     * @return bool
534
     */
535
    public function synchronization(): bool
536
    {
537
        //$this->cleanOrphan();
538
        return true;
539
    }
540
541
    /**
542
     * clean orphan items from database
543
     *
544
     * @param string $table_link
545
     * @param string $field_link
546
     * @param string $field_object
547
     * @return bool   true on success
548
     */
549
    public function cleanOrphan($table_link = '', $field_link = '', $field_object = ''): bool //cleanOrphan()
550
    {
551
        $this->deleteAll(new \Criteria('post_time', '0'), true, true);
552
        parent::cleanOrphan($this->db->prefix('newbb_topics'), 'topic_id');
553
        parent::cleanOrphan($this->db->prefix('newbb_posts_text'), 'post_id');
554
555
        $sql = 'DELETE FROM ' . $this->db->prefix('newbb_posts_text') . ' WHERE (post_id NOT IN ( SELECT DISTINCT post_id FROM ' . $this->table . ') )';
556
        if (!$result = $this->db->queryF($sql)) {
0 ignored issues
show
The assignment to $result is dead and can be removed.
Loading history...
557
            //xoops_error($this->db->error());
558
            return false;
559
        }
560
561
        return true;
562
    }
563
564
    /**
565
     * clean expired objects from database
566
     *
567
     * @param int $expire time limit for expiration
568
     * @return bool true on success
569
     */
570
    public function cleanExpires(int $expire = 0): bool
571
    {
572
        // irmtfan if 0 no cleanup look include/plugin.php
573
        if (!\func_num_args()) {
574
            $newbbConfig = \newbbLoadConfig();
575
            $expire      = isset($newbbConfig['pending_expire']) ? (int)$newbbConfig['pending_expire'] : 7;
576
            $expire      *= 24 * 3600; // days to seconds
577
        }
578
        if (empty($expire)) {
579
            return false;
580
        }
581
        $crit_expire = new \CriteriaCompo(new \Criteria('approved', '0', '<='));
582
        //if (!empty($expire)) {
583
        $crit_expire->add(new \Criteria('post_time', \time() - (int)$expire, '<'));
584
585
        //}
586
        return $this->deleteAll($crit_expire, true/*, true*/);
587
    }
588
}
589