Post   F
last analyzed

Complexity

Total Complexity 122

Size/Duplication

Total Lines 692
Duplicated Lines 0 %

Importance

Changes 5
Bugs 0 Features 0
Metric Value
eloc 436
c 5
b 0
f 0
dl 0
loc 692
rs 2
wmc 122

14 Methods

Rating   Name   Duplication   Size   Complexity  
B setPostEdit() 0 35 10
A isTopic() 0 3 1
A getAttachment() 0 13 3
C getPostBody() 0 44 15
B displayPostEdit() 0 38 11
A incrementDownload() 0 8 2
A setAttachment() 0 24 5
B deleteAttachment() 0 32 9
A saveAttachment() 0 14 4
A checkIdentity() 0 14 5
A checkTimelimit() 0 8 2
A __construct() 0 27 1
F showPost() 0 234 41
C displayAttachment() 0 84 13

How to fix   Complexity   

Complex Class

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

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
use Xmf\Highlighter;
21
use Xmf\IPAddress;
22
use Xmf\Request;
23
use XoopsModules\Newbb;
24
25
\defined('NEWBB_FUNCTIONS_INI') || require $GLOBALS['xoops']->path('modules/newbb/include/functions.ini.php');
26
27
/**
28
 * Class Post
29
 */
30
class Post extends \XoopsObject
31
{
32
    public int $post_id;
33
    public int $topic_id;
34
    public int $forum_id;
35
    public int $post_time;
36
    //        public $poster_ip ;
37
    public string $poster_ip;
38
    public string $poster_name;
39
    public string $subject;
40
    public int    $pid;
41
    public int    $dohtml;
42
    public int    $dosmiley;
43
    public int    $doxcode;
44
    public int    $doimage;
45
    public int    $dobr;
46
    public int    $uid;
47
    public string $icon;
48
    public int    $attachsig;
49
    public int    $approved;
50
    public int    $post_karma;
51
    public int    $require_reply;
52
    public string $attachment;
53
    public string $post_text;
54
    public string $post_edit;
55
    //class Post extends \XoopsObject {
56
    private array $attachmentArray = [];
57
58
    public function __construct()
59
    {
60
        parent::__construct();
61
62
        $this->initVar('post_id', \XOBJ_DTYPE_INT);
63
        $this->initVar('topic_id', \XOBJ_DTYPE_INT, 0, true);
64
        $this->initVar('forum_id', \XOBJ_DTYPE_INT, 0, true);
65
        $this->initVar('post_time', \XOBJ_DTYPE_INT, 0, true);
66
        //        $this->initVar('poster_ip', XOBJ_DTYPE_INT, 0);
67
        $this->initVar('poster_ip', \XOBJ_DTYPE_TXTBOX, '');
68
        $this->initVar('poster_name', \XOBJ_DTYPE_TXTBOX, '');
69
        $this->initVar('subject', \XOBJ_DTYPE_TXTBOX, '', true);
70
        $this->initVar('pid', \XOBJ_DTYPE_INT, 0);
71
        $this->initVar('dohtml', \XOBJ_DTYPE_INT, 0);
72
        $this->initVar('dosmiley', \XOBJ_DTYPE_INT, 1);
73
        $this->initVar('doxcode', \XOBJ_DTYPE_INT, 1);
74
        $this->initVar('doimage', \XOBJ_DTYPE_INT, 1);
75
        $this->initVar('dobr', \XOBJ_DTYPE_INT, 1);
76
        $this->initVar('uid', \XOBJ_DTYPE_INT, 1);
77
        $this->initVar('icon', \XOBJ_DTYPE_TXTBOX, '');
78
        $this->initVar('attachsig', \XOBJ_DTYPE_INT, 0);
79
        $this->initVar('approved', \XOBJ_DTYPE_INT, 1);
80
        $this->initVar('post_karma', \XOBJ_DTYPE_INT, 0);
81
        $this->initVar('require_reply', \XOBJ_DTYPE_INT, 0);
82
        $this->initVar('attachment', \XOBJ_DTYPE_TXTAREA, '');
83
        $this->initVar('post_text', \XOBJ_DTYPE_TXTAREA, '');
84
        $this->initVar('post_edit', \XOBJ_DTYPE_TXTAREA, '');
85
    }
86
87
    // ////////////////////////////////////////////////////////////////////////////////////
88
    // attachment functions    TODO: there should be a file/attachment management class
89
90
    /**
91
     * @return array|mixed|null
92
     */
93
    public function getAttachment()
94
    {
95
        if (\count($this->attachmentArray)) {
96
            return $this->attachmentArray;
97
        }
98
        $attachment = $this->getVar('attachment');
99
        if (empty($attachment)) {
100
            $this->attachmentArray = [];
101
        } else {
102
            $this->attachmentArray = @\unserialize(\base64_decode((string) $attachment, true));
103
        }
104
105
        return $this->attachmentArray;
106
    }
107
108
    /**
109
     * @param string $attachKey
110
     * @return bool
111
     */
112
    public function incrementDownload(string $attachKey): bool
113
    {
114
        if (!$attachKey) {
115
            return false;
116
        }
117
        $this->attachmentArray[(string)$attachKey]['numDownload']++;
118
119
        return $this->attachmentArray[(string)$attachKey]['numDownload'];
120
    }
121
122
    /**
123
     * @return bool
124
     */
125
    public function saveAttachment(): bool
126
    {
127
        $attachmentSave = '';
128
        if ($this->attachmentArray && \is_array($this->attachmentArray)) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $this->attachmentArray of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
129
            $attachmentSave = \base64_encode(\serialize($this->attachmentArray));
130
        }
131
        $this->setVar('attachment', $attachmentSave);
132
        $sql = 'UPDATE ' . $GLOBALS['xoopsDB']->prefix('newbb_posts') . ' SET attachment=' . $GLOBALS['xoopsDB']->quoteString($attachmentSave) . ' WHERE post_id = ' . $this->getVar('post_id');
133
        if (!$result = $GLOBALS['xoopsDB']->queryF($sql)) {
0 ignored issues
show
Unused Code introduced by
The assignment to $result is dead and can be removed.
Loading history...
134
            //xoops_error($GLOBALS['xoopsDB']->error());
135
            return false;
136
        }
137
138
        return true;
139
    }
140
141
    /**
142
     * @param array|null $attachArray
143
     * @return bool
144
     */
145
    public function deleteAttachment(array $attachArray = null): bool
146
    {
147
        $attachOld = $this->getAttachment();
148
        if (!\is_array($attachOld) || \count($attachOld) < 1) {
0 ignored issues
show
introduced by
The condition is_array($attachOld) is always true.
Loading history...
149
            return true;
150
        }
151
        $this->attachmentArray = [];
152
153
        if (null === $attachArray) {
154
            $attachArray = \array_keys($attachOld);
155
        } // to delete all!
156
        if (!\is_array($attachArray)) {
0 ignored issues
show
introduced by
The condition is_array($attachArray) is always true.
Loading history...
157
            $attachArray = [$attachArray];
158
        }
159
160
        foreach ($attachOld as $key => $attach) {
161
            if (\in_array($key, $attachArray, true)) {
162
                $file = $GLOBALS['xoops']->path($GLOBALS['xoopsModuleConfig']['dir_attachments'] . '/' . $attach['name_saved']);
163
                @\unlink($file);
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition for unlink(). This can introduce security issues, and is generally not recommended. ( Ignorable by Annotation )

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

163
                /** @scrutinizer ignore-unhandled */ @\unlink($file);

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
164
                $file = $GLOBALS['xoops']->path($GLOBALS['xoopsModuleConfig']['dir_attachments'] . '/thumbs/' . $attach['name_saved']); // delete thumbnails
165
                @\unlink($file);
166
                continue;
167
            }
168
            $this->attachmentArray[$key] = $attach;
169
        }
170
        $attachmentSave = '';
171
        if ($this->attachmentArray && \is_array($this->attachmentArray)) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $this->attachmentArray of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
172
            $attachmentSave = \base64_encode(\serialize($this->attachmentArray));
173
        }
174
        $this->setVar('attachment', $attachmentSave);
175
176
        return true;
177
    }
178
179
    /**
180
     * @param string $name_saved
181
     * @param string $nameDisplay
182
     * @param string $mimetype
183
     * @param int    $numDownload
184
     * @return bool
185
     */
186
    public function setAttachment(string $name_saved = '', string $nameDisplay = '', string $mimetype = '', int $numDownload = 0): bool
187
    {
188
        static $counter = 0;
189
        $this->attachmentArray = $this->getAttachment();
190
        if ($name_saved) {
191
            $key                         = (string)(\time() + $counter++);
192
            $this->attachmentArray[$key] = [
193
                'name_saved'  => $name_saved,
194
                // BigKev73 >  without this change the nameDisplay will always get set to the $name_Saved, so in the forum it will show the on-disk filename instead of the name of the orginal file
195
                //'nameDisplay' => empty($nameDisplay) ? $nameDisplay : $name_saved,
196
                'nameDisplay' => !empty($nameDisplay) ? $nameDisplay : $name_saved,
197
                'mimetype'    => $mimetype,
198
                // BigKev73 >  without this change the numDownload will always be set to 0
199
                //'numDownload' => empty($numDownload) ? (int)$numDownload : 0,
200
                'numDownload' => !empty($numDownload) ? (int)$numDownload : 0,
201
            ];
202
        }
203
        $attachmentSave = null;
204
        if (\is_array($this->attachmentArray)) {
0 ignored issues
show
introduced by
The condition is_array($this->attachmentArray) is always true.
Loading history...
205
            $attachmentSave = \base64_encode(\serialize($this->attachmentArray));
206
        }
207
        $this->setVar('attachment', $attachmentSave);
208
209
        return true;
210
    }
211
212
    /**
213
     * TODO: refactor
214
     * @param bool $asSource
215
     * @return string
216
     */
217
    public function displayAttachment(bool $asSource = false): string
0 ignored issues
show
Unused Code introduced by
The parameter $asSource is not used and could be removed. ( Ignorable by Annotation )

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

217
    public function displayAttachment(/** @scrutinizer ignore-unused */ bool $asSource = false): string

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
218
    {
219
        global $xoopsModule;
220
221
        $post_attachment = '';
222
        $attachments     = $this->getAttachment();
223
        if ($attachments && \is_array($attachments)) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $attachments of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
224
            $iconHandler = \newbbGetIconHandler();
225
            $mime_path   = $iconHandler->getPath('mime');
226
            require_once \dirname(__DIR__) . '/include/functions.image.php';
227
            $image_extensions = ['jpg', 'jpeg', 'gif', 'png', 'bmp']; // need improve !!!
228
            $post_attachment  .= '<br><strong>' . \_MD_NEWBB_ATTACHMENT . '</strong>:';
229
            $post_attachment  .= '<br><hr size="1" noshade="noshade" ><br>';
230
            foreach ($attachments as $key => $att) {
231
                $file_extension = \ltrim(mb_strrchr((string) $att['name_saved'], '.'), '.');
232
                $filetype       = $file_extension;
233
                if (\file_exists($GLOBALS['xoops']->path($mime_path . '/' . $filetype . '.gif'))) {
234
                    $icon_filetype = XOOPS_URL . '/' . $mime_path . '/' . $filetype . '.gif';
235
                } else {
236
                    $icon_filetype = XOOPS_URL . '/' . $mime_path . '/unknown.gif';
237
                }
238
                $file_size = @\filesize($GLOBALS['xoops']->path($GLOBALS['xoopsModuleConfig']['dir_attachments'] . '/' . $att['name_saved']));
239
                $file_size = \number_format($file_size / 1024, 2) . ' KB';
240
                $att['nameDisplay'] ??= '';
241
                if ($GLOBALS['xoopsModuleConfig']['media_allowed']
242
                    && \in_array(mb_strtolower($file_extension), $image_extensions, true)) {
243
                    $post_attachment .= '<br><img src="' . $icon_filetype . '" alt="' . $filetype . '" ><strong>&nbsp; ' . $att['nameDisplay'] . '</strong> <small>(' . $file_size . ')</small>';
244
                    $post_attachment .= '<br>' . \newbbAttachmentImage($att['name_saved']);
245
                    $isDisplayed     = true;
0 ignored issues
show
Unused Code introduced by
The assignment to $isDisplayed is dead and can be removed.
Loading history...
246
                } elseif (empty($GLOBALS['xoopsModuleConfig']['show_userattach'])) {
247
                    $post_attachment .= '<a href="'
248
                                        . XOOPS_URL
249
                                        . '/modules/'
250
                                        . $xoopsModule->getVar('dirname', 'n')
251
                                        . '/dl_attachment.php?attachid='
252
                                        . $key
253
                                        . '&amp;post_id='
254
                                        . $this->getVar('post_id')
255
                                        . '"> <img src="'
256
                                        . $icon_filetype
257
                                        . '" alt="'
258
                                        . $filetype
259
                                        . '" > '
260
                                        . $att['nameDisplay']
261
                                        . '</a> '
262
                                        . \_MD_NEWBB_FILESIZE
263
                                        . ': '
264
                                        . $file_size
265
                                        . '; '
266
                                        . \_MD_NEWBB_HITS
267
                                        . ': '
268
                                        . (isset($att['numDownload']) ? $att['numDownload'] : '');
269
                } elseif ($GLOBALS['xoopsUser'] && $GLOBALS['xoopsUser']->uid() > 0
270
                          && $GLOBALS['xoopsUser']->isactive()) {
271
                    $post_attachment .= '<a href="'
272
                                        . XOOPS_URL
273
                                        . '/modules/'
274
                                        . $xoopsModule->getVar('dirname', 'n')
275
                                        . '/dl_attachment.php?attachid='
276
                                        . $key
277
                                        . '&amp;post_id='
278
                                        . $this->getVar('post_id')
279
                                        . '"> <img src="'
280
                                        . $icon_filetype
281
                                        . '" alt="'
282
                                        . $filetype
283
                                        . '" > '
284
                                        . $att['nameDisplay']
285
                                        . '</a> '
286
                                        . \_MD_NEWBB_FILESIZE
287
                                        . ': '
288
                                        . $file_size
289
                                        . '; '
290
                                        . \_MD_NEWBB_HITS
291
                                        . ': '
292
                                        . (isset($att['numDownload']) ? $att['numDownload'] : '');
293
                } else {
294
                    $post_attachment .= \_MD_NEWBB_SEENOTGUEST;
295
                }
296
                $post_attachment .= '<br>';
297
            }
298
        }
299
300
        return $post_attachment;
301
    }
302
303
    // attachment functions
304
    // ////////////////////////////////////////////////////////////////////////////////////
305
306
    /**
307
     * @param string $poster_name
308
     * @param string $post_editmsg
309
     * @return bool
310
     */
311
    public function setPostEdit(string $poster_name = '', string $post_editmsg = ''): bool
0 ignored issues
show
Unused Code introduced by
The parameter $poster_name is not used and could be removed. ( Ignorable by Annotation )

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

311
    public function setPostEdit(/** @scrutinizer ignore-unused */ string $poster_name = '', string $post_editmsg = ''): bool

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
312
    {
313
        $edit_user = '';
314
        if (empty($GLOBALS['xoopsModuleConfig']['recordedit_timelimit'])
315
            || $this->getVar('approved') < 1
316
            || (\time() - $this->getVar('post_time')) < $GLOBALS['xoopsModuleConfig']['recordedit_timelimit'] * 60
317
        ) {
318
            return true;
319
        }
320
        if (\is_object($GLOBALS['xoopsUser']) && $GLOBALS['xoopsUser']->isActive()) {
321
            if ($GLOBALS['xoopsModuleConfig']['show_realname'] && $GLOBALS['xoopsUser']->getVar('name')) {
322
                $edit_user = $GLOBALS['xoopsUser']->getVar('name');
323
            } else {
324
                $edit_user = $GLOBALS['xoopsUser']->getVar('uname');
325
            }
326
        }
327
        $post_edit              = [];
328
        $post_edit['edit_user'] = $edit_user; // (?) The proper way is to store uid instead of name.
329
        // However, to save queries when displaying, the current way is ok.
330
        $post_edit['edit_time'] = \time();
331
        $post_edit['edit_msg']  = $post_editmsg;
332
333
        $post_edits = $this->getVar('post_edit');
334
        if (!empty($post_edits)) {
335
            $post_edits = \unserialize(\base64_decode((string) $post_edits, true));
336
        }
337
        if (!\is_array($post_edits)) {
338
            $post_edits = [];
339
        }
340
        $post_edits[] = $post_edit;
341
        $post_edit    = \base64_encode(\serialize($post_edits));
342
        unset($post_edits);
343
        $this->setVar('post_edit', $post_edit);
344
345
        return true;
346
    }
347
348
    /**
349
     * @return bool|string
350
     */
351
    public function displayPostEdit()
352
    {
353
        global $myts;
354
355
        if (empty($GLOBALS['xoopsModuleConfig']['recordedit_timelimit'])) {
356
            return false;
357
        }
358
359
        $post_edit  = '';
360
        $post_edits = $this->getVar('post_edit');
361
        if (!empty($post_edits)) {
362
            $post_edits = \unserialize(\base64_decode((string) $post_edits, true));
363
        }
364
        if (!isset($post_edits) || !\is_array($post_edits)) {
365
            $post_edits = [];
366
        }
367
        if ($post_edits && \is_array($post_edits)) {
368
            foreach ($post_edits as $postedit) {
369
                $edit_time = (int)$postedit['edit_time'];
370
                $edit_user = $postedit['edit_user'];
371
                $edit_msg  = !empty($postedit['edit_msg']) ? $postedit['edit_msg'] : '';
372
                // Start irmtfan add option to do only the latest edit when do_latestedit=0 (Alfred)
373
                if (empty($GLOBALS['xoopsModuleConfig']['do_latestedit'])) {
374
                    $post_edit = '';
375
                }
376
                // End irmtfan add option to do only the latest edit when do_latestedit=0 (Alfred)
377
                // START hacked by irmtfan
378
                // display/save all edit records.
379
                $post_edit .= \_MD_NEWBB_EDITEDBY . ' ' . $edit_user . ' ' . \_MD_NEWBB_ON . ' ' . \formatTimestamp($edit_time) . '<br>';
380
                // if reason is not empty
381
                if ('' !== $edit_msg) {
382
                    $post_edit .= \_MD_NEWBB_EDITEDMSG . ' ' . $edit_msg . '<br>';
383
                }
384
                // START hacked by irmtfan
385
            }
386
        }
387
388
        return $post_edit;
389
    }
390
391
    /**
392
     * @return array
393
     */
394
    public function &getPostBody(): array
395
    {
396
        global $viewtopic_users;
397
        $newbbConfig = \newbbLoadConfig();
398
        require_once \dirname(__DIR__) . '/include/functions.user.php';
399
        require_once \dirname(__DIR__) . '/include/functions.render.php';
400
401
        $uid = \is_object($GLOBALS['xoopsUser']) ? $GLOBALS['xoopsUser']->getVar('uid') : 0;
402
        /** @var KarmaHandler $karmaHandler */
403
        $karmaHandler = Helper::getInstance()->getHandler('Karma');
404
        $user_karma   = $karmaHandler->getUserKarma();
405
406
        $post               = [];
407
        $post['attachment'] = false;
408
        $post_text          = \newbbDisplayTarea($this->vars['post_text']['value'], $this->getVar('dohtml'), $this->getVar('dosmiley'), $this->getVar('doxcode'), $this->getVar('doimage'), $this->getVar('dobr'));
409
        if ($this->checkIdentity() || \newbbIsAdmin($this->getVar('forum_id'))) {
410
            $post['text'] = $post_text . '<br>' . $this->displayAttachment();
411
        } elseif ($newbbConfig['enable_karma'] && $this->getVar('post_karma') > $user_karma) {
412
            $post['text'] = \sprintf(\_MD_NEWBB_KARMA_REQUIREMENT, $user_karma, $this->getVar('post_karma'));
0 ignored issues
show
Bug introduced by
It seems like $this->getVar('post_karma') 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

412
            $post['text'] = \sprintf(\_MD_NEWBB_KARMA_REQUIREMENT, $user_karma, /** @scrutinizer ignore-type */ $this->getVar('post_karma'));
Loading history...
413
        } elseif ($newbbConfig['allow_require_reply'] && $this->getVar('require_reply')
414
                  && (!$uid || !isset($viewtopic_users[$uid]))) {
415
            $post['text'] = \_MD_NEWBB_REPLY_REQUIREMENT;
416
        } else {
417
            $post['text'] = $post_text . '<br>' . $this->displayAttachment();
418
        }
419
        /** @var \XoopsMemberHandler $memberHandler */
420
        $memberHandler = \xoops_getHandler('member');
421
        $eachposter    = $memberHandler->getUser($this->getVar('uid'));
422
        if (\is_object($eachposter) && $eachposter->isActive()) {
423
            if ($newbbConfig['show_realname'] && $eachposter->getVar('name')) {
424
                $post['author'] = $eachposter->getVar('name');
425
            } else {
426
                $post['author'] = $eachposter->getVar('uname');
427
            }
428
            unset($eachposter);
429
        } else {
430
            $post['author'] = $this->getVar('poster_name') ?: $GLOBALS['xoopsConfig']['anonymous'];
431
        }
432
433
        $post['subject'] = \newbbhtmlspecialchars($this->vars['subject']['value']);
434
435
        $post['date'] = $this->getVar('post_time');
436
437
        return $post;
438
    }
439
440
    /**
441
     * @return bool
442
     */
443
    public function isTopic(): bool
444
    {
445
        return !$this->getVar('pid');
446
    }
447
448
    /**
449
     * @param string $action_tag
450
     * @return bool
451
     */
452
    public function checkTimelimit(string $action_tag = 'edit_timelimit'): bool
453
    {
454
        $newbbConfig = \newbbLoadConfig();
455
        if (empty($newbbConfig['edit_timelimit'])) {
456
            return true;
457
        }
458
459
        return ($this->getVar('post_time') > \time() - $newbbConfig[$action_tag] * 60);
460
    }
461
462
    /**
463
     * @param int $uid
464
     * @return bool
465
     */
466
    public function checkIdentity(int $uid = -1): bool
467
    {
468
        $uid = ($uid > -1) ? $uid : (\is_object($GLOBALS['xoopsUser']) ? $GLOBALS['xoopsUser']->getVar('uid') : 0);
469
        if ($this->getVar('uid') > 0) {
470
            $user_ok = ($uid == $this->getVar('uid'));
471
        } else {
472
            static $user_ip;
473
            if (!isset($user_ip)) {
474
                $user_ip = IPAddress::fromRequest()->asReadable();
475
            }
476
            $user_ok = ($user_ip == $this->getVar('poster_ip'));
477
        }
478
479
        return $user_ok;
480
    }
481
482
    // TODO: cleaning up and merge with post hanldings in viewpost.php
483
484
    /**
485
     * @param bool $isAdmin
486
     * @return array
487
     */
488
    public function showPost(bool $isAdmin): array
489
    {
490
        global $xoopsModule, $myts;
491
        global $forumUrl, $forumImage, $forumObject, $online, $viewmode;
492
        global $viewtopic_users, $viewtopic_posters, $topicObject, $user_karma;
493
        global $order, $start, $total_posts, $topic_status;
494
        static $post_NO = 0;
495
        static $name_anonymous;
496
        /** @var TopicHandler $topicHandler */
497
        $topicHandler = Helper::getInstance()->getHandler('Topic');
498
        if (null === $name_anonymous) {
499
            $name_anonymous = \htmlspecialchars((string)$GLOBALS['xoopsConfig']['anonymous'], \ENT_QUOTES | \ENT_HTML5);
500
        }
501
502
        require_once \dirname(__DIR__) . '/include/functions.time.php';
503
        require_once \dirname(__DIR__) . '/include/functions.render.php';
504
505
        $post_id  = $this->getVar('post_id');
506
        $topic_id = $this->getVar('topic_id');
507
        $forum_id = $this->getVar('forum_id');
508
509
        $query_vars              = ['status', 'order', 'start', 'mode', 'viewmode'];
510
        $query_array             = [];
511
        $query_array['topic_id'] = "topic_id={$topic_id}";
512
        foreach ($query_vars as $var) {
513
            if (Request::getString($var, '', 'GET')) {
514
                $query_array[$var] = "{$var}=" . Request::getString($var, '', 'GET');
515
            }
516
        }
517
        $page_query = \htmlspecialchars(\implode('&', \array_values($query_array)), \ENT_QUOTES | \ENT_HTML5);
518
519
        $uid = \is_object($GLOBALS['xoopsUser']) ? $GLOBALS['xoopsUser']->getVar('uid') : 0;
520
521
        ++$post_NO;
522
        if ('desc' === \mb_strtolower((string) $order)) {
523
            $post_no = $total_posts - ($start + $post_NO) + 1;
524
        } else {
525
            $post_no = $start + $post_NO;
526
        }
527
528
        if ($isAdmin || $this->checkIdentity()) {
529
            $post_text       = $this->getVar('post_text');
530
            $post_attachment = $this->displayAttachment();
531
        } elseif ($GLOBALS['xoopsModuleConfig']['enable_karma'] && $this->getVar('post_karma') > $user_karma) {
532
            $post_text       = "<div class='karma'>" . \sprintf(\_MD_NEWBB_KARMA_REQUIREMENT, $user_karma, $this->getVar('post_karma')) . '</div>';
0 ignored issues
show
Bug introduced by
It seems like $this->getVar('post_karma') 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

532
            $post_text       = "<div class='karma'>" . \sprintf(\_MD_NEWBB_KARMA_REQUIREMENT, $user_karma, /** @scrutinizer ignore-type */ $this->getVar('post_karma')) . '</div>';
Loading history...
533
            $post_attachment = '';
534
        } elseif ($GLOBALS['xoopsModuleConfig']['allow_require_reply'] && $this->getVar('require_reply')
535
                  && (!$uid || !\in_array($uid, $viewtopic_posters, true))) {
536
            $post_text       = "<div class='karma'>" . \_MD_NEWBB_REPLY_REQUIREMENT . '</div>';
537
            $post_attachment = '';
538
        } else {
539
            $post_text       = $this->getVar('post_text');
540
            $post_attachment = $this->displayAttachment();
541
        }
542
543
        // Hightlight search words
544
        $post_title = $this->getVar('subject');
545
        $keywords   = Request::getString('keywords', '', 'GET');
546
        if ($keywords) {
547
            //$keywords   = htmlspecialchars(trim(urldecode(Request::getString('keywords', '', 'GET'))));
548
            $post_text  = Highlighter::apply($keywords, $post_text, '<mark>', '</mark>');
549
            $post_title = Highlighter::apply($keywords, $post_title, '<mark>', '</mark>');
0 ignored issues
show
Bug introduced by
It seems like $post_title can also be of type array and array; however, parameter $body of Xmf\Highlighter::apply() 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

549
            $post_title = Highlighter::apply($keywords, /** @scrutinizer ignore-type */ $post_title, '<mark>', '</mark>');
Loading history...
550
        }
551
552
        if (isset($viewtopic_users[$this->getVar('uid')])) {
553
            $poster = $viewtopic_users[$this->getVar('uid')];
554
        } else {
555
            $name   = ($post_name = $this->getVar('poster_name')) ? $post_name : $name_anonymous;
556
            $poster = [
557
                'poster_uid' => 0,
558
                'name'       => $name,
559
                'link'       => $name,
560
            ];
561
        }
562
563
        $posticon = $this->getVar('icon');
564
        if ($posticon) {
565
            $post_image = '<a name="' . $post_id . '"><img src="' . XOOPS_URL . '/images/subject/' . $posticon . '" alt="" ></a>';
566
        } else {
567
            $post_image = '<a name="' . $post_id . '"><img src="' . XOOPS_URL . '/images/icons/posticon.gif" alt="" ></a>';
568
        }
569
570
        $thread_buttons = [];
571
        $mod_buttons    = [];
572
573
        if ($isAdmin && $this->getVar('uid') > 0 && ($GLOBALS['xoopsUser'] && $GLOBALS['xoopsUser']->getVar('uid') !== $this->getVar('uid'))) {
574
            $mod_buttons['bann']['image']    = \newbbDisplayImage('p_bann', \_MD_NEWBB_SUSPEND_MANAGEMENT);
575
            $mod_buttons['bann']['link']     = XOOPS_URL . '/modules/' . $xoopsModule->getVar('dirname') . '/moderate.php?forum=' . $forum_id . '&amp;uid=' . $this->getVar('uid');
576
            $mod_buttons['bann']['name']     = \_MD_NEWBB_SUSPEND_MANAGEMENT;
577
            $thread_buttons['bann']['image'] = \newbbDisplayImage('p_bann', \_MD_NEWBB_SUSPEND_MANAGEMENT);
578
            $thread_buttons['bann']['link']  = XOOPS_URL . '/modules/' . $xoopsModule->getVar('dirname') . '/moderate.php?forum=' . $forum_id . '&amp;uid=' . $this->getVar('uid');
579
            $thread_buttons['bann']['name']  = \_MD_NEWBB_SUSPEND_MANAGEMENT;
580
        }
581
582
        if ($GLOBALS['xoopsModuleConfig']['enable_permcheck']) {
583
            // /** @var TopicHandler $topicHandler */
584
            //            $topicHandler =  Newbb\Helper::getInstance()->getHandler('Topic');
585
            $topic_status = $topicObject->getVar('topic_status');
586
            if ($topicHandler->getPermission($forum_id, $topic_status, 'edit')) {
587
                $edit_ok = ($isAdmin || ($this->checkIdentity() && $this->checkTimelimit('edit_timelimit')));
588
589
                if ($edit_ok) {
590
                    $thread_buttons['edit']['image'] = \newbbDisplayImage('p_edit', _EDIT);
591
                    $thread_buttons['edit']['link']  = XOOPS_URL . '/modules/' . $xoopsModule->getVar('dirname') . "/edit.php?{$page_query}";
592
                    $thread_buttons['edit']['name']  = _EDIT;
593
                    $mod_buttons['edit']['image']    = \newbbDisplayImage('p_edit', _EDIT);
594
                    $mod_buttons['edit']['link']     = XOOPS_URL . '/modules/' . $xoopsModule->getVar('dirname') . "/edit.php?{$page_query}";
595
                    $mod_buttons['edit']['name']     = _EDIT;
596
                }
597
            }
598
599
            if ($topicHandler->getPermission($forum_id, $topic_status, 'delete')) {
600
                $delete_ok = ($isAdmin || ($this->checkIdentity() && $this->checkTimelimit('delete_timelimit')));
601
602
                if ($delete_ok) {
603
                    $thread_buttons['delete']['image'] = \newbbDisplayImage('p_delete', _DELETE);
604
                    $thread_buttons['delete']['link']  = XOOPS_URL . '/modules/' . $xoopsModule->getVar('dirname') . "/delete.php?{$page_query}";
605
                    $thread_buttons['delete']['name']  = _DELETE;
606
                    $mod_buttons['delete']['image']    = \newbbDisplayImage('p_delete', _DELETE);
607
                    $mod_buttons['delete']['link']     = XOOPS_URL . '/modules/' . $xoopsModule->getVar('dirname') . "/delete.php?{$page_query}";
608
                    $mod_buttons['delete']['name']     = _DELETE;
609
                }
610
            }
611
            if ($topicHandler->getPermission($forum_id, $topic_status, 'reply')) {
612
                $thread_buttons['reply']['image'] = \newbbDisplayImage('p_reply', \_MD_NEWBB_REPLY);
613
                $thread_buttons['reply']['link']  = XOOPS_URL . '/modules/' . $xoopsModule->getVar('dirname') . "/reply.php?{$page_query}";
614
                $thread_buttons['reply']['name']  = \_MD_NEWBB_REPLY;
615
616
                $thread_buttons['quote']['image'] = \newbbDisplayImage('p_quote', \_MD_NEWBB_QUOTE);
617
                $thread_buttons['quote']['link']  = XOOPS_URL . '/modules/' . $xoopsModule->getVar('dirname') . "/reply.php?{$page_query}&amp;quotedac=1";
618
                $thread_buttons['quote']['name']  = \_MD_NEWBB_QUOTE;
619
            }
620
        } else {
621
            $mod_buttons['edit']['image'] = \newbbDisplayImage('p_edit', _EDIT);
622
            $mod_buttons['edit']['link']  = XOOPS_URL . '/modules/' . $xoopsModule->getVar('dirname') . "/edit.php?{$page_query}";
623
            $mod_buttons['edit']['name']  = _EDIT;
624
625
            $mod_buttons['delete']['image'] = \newbbDisplayImage('p_delete', _DELETE);
626
            $mod_buttons['delete']['link']  = XOOPS_URL . '/modules/' . $xoopsModule->getVar('dirname') . "/delete.php?{$page_query}";
627
            $mod_buttons['delete']['name']  = _DELETE;
628
629
            $thread_buttons['reply']['image'] = \newbbDisplayImage('p_reply', \_MD_NEWBB_REPLY);
630
            $thread_buttons['reply']['link']  = XOOPS_URL . '/modules/' . $xoopsModule->getVar('dirname') . "/reply.php?{$page_query}";
631
            $thread_buttons['reply']['name']  = \_MD_NEWBB_REPLY;
632
        }
633
634
        if (!$isAdmin && $GLOBALS['xoopsModuleConfig']['reportmod_enabled']) {
635
            $thread_buttons['report']['image'] = \newbbDisplayImage('p_report', \_MD_NEWBB_REPORT);
636
            $thread_buttons['report']['link']  = XOOPS_URL . '/modules/' . $xoopsModule->getVar('dirname') . "/report.php?{$page_query}";
637
            $thread_buttons['report']['name']  = \_MD_NEWBB_REPORT;
638
        }
639
640
        $thread_action = [];
641
        // irmtfan add pdf permission
642
        if (\file_exists(XOOPS_ROOT_PATH . '/class/libraries/vendor/tecnickcom/tcpdf/tcpdf.php')
643
            && $topicHandler->getPermission($forum_id, $topic_status, 'pdf')) {
644
            $thread_action['pdf']['image']  = \newbbDisplayImage('pdf', \_MD_NEWBB_PDF);
645
            $thread_action['pdf']['link']   = XOOPS_URL . '/modules/newbb/makepdf.php?type=post&amp;pageid=0';
646
            $thread_action['pdf']['name']   = \_MD_NEWBB_PDF;
647
            $thread_action['pdf']['target'] = '_blank';
648
        }
649
        // irmtfan add print permission
650
        if ($topicHandler->getPermission($forum_id, $topic_status, 'print')) {
651
            $thread_action['print']['image']  = \newbbDisplayImage('printer', \_MD_NEWBB_PRINT);
652
            $thread_action['print']['link']   = XOOPS_URL . '/modules/newbb/print.php?form=2&amp;forum=' . $forum_id . '&amp;topic_id=' . $topic_id;
653
            $thread_action['print']['name']   = \_MD_NEWBB_PRINT;
654
            $thread_action['print']['target'] = '_blank';
655
        }
656
657
        if ($GLOBALS['xoopsModuleConfig']['show_sociallinks']) {
658
            $full_title  = $this->getVar('subject');
659
            $clean_title = \preg_replace('/[^A-Za-z0-9-]+/', '+', (string) $this->getVar('subject'));
660
            // BigKev73 - added to make page scroll to the last post
661
            $full_link = XOOPS_URL . '/modules/newbb/viewtopic.php?post_id=' . $post_id . '#forumpost=' . $post_id;
662
            //$full_link   = XOOPS_URL . '/modules/newbb/viewtopic.php?post_id=' . $post_id;
663
664
            $thread_action['social_twitter']['image']  = \newbbDisplayImage('twitter', \_MD_NEWBB_SHARE_TWITTER);
665
            $thread_action['social_twitter']['link']   = 'https://twitter.com/share?text=' . $clean_title . '&amp;url=' . $full_link;
666
            $thread_action['social_twitter']['name']   = \_MD_NEWBB_SHARE_TWITTER;
667
            $thread_action['social_twitter']['target'] = '_blank';
668
669
            $thread_action['social_facebook']['image']  = \newbbDisplayImage('facebook', \_MD_NEWBB_SHARE_FACEBOOK);
670
            $thread_action['social_facebook']['link']   = 'https://www.facebook.com/sharer.php?u=' . $full_link;
671
            $thread_action['social_facebook']['name']   = \_MD_NEWBB_SHARE_FACEBOOK;
672
            $thread_action['social_facebook']['target'] = '_blank';
673
674
            $thread_action['social_gplus']['link']   = 'https://plusone.google.com/_/+1/confirm?hl=en&url=' . $full_link;
675
            $thread_action['social_gplus']['name']   = \_MD_NEWBB_SHARE_GOOGLEPLUS;
676
            $thread_action['social_gplus']['target'] = '_blank';
677
678
            $thread_action['social_linkedin']['image']  = \newbbDisplayImage('linkedin', \_MD_NEWBB_SHARE_LINKEDIN);
679
            $thread_action['social_linkedin']['link']   = 'https://www.linkedin.com/shareArticle?mini=true&amp;title=' . $full_title . '&amp;url=' . $full_link;
680
            $thread_action['social_linkedin']['name']   = \_MD_NEWBB_SHARE_LINKEDIN;
681
            $thread_action['social_linkedin']['target'] = '_blank';
682
683
            $thread_action['social_delicious']['image']  = \newbbDisplayImage('delicious', \_MD_NEWBB_SHARE_DELICIOUS);
684
            $thread_action['social_delicious']['link']   = 'https://del.icio.us/post?title=' . $full_title . '&amp;url=' . $full_link;
685
            $thread_action['social_delicious']['name']   = \_MD_NEWBB_SHARE_DELICIOUS;
686
            $thread_action['social_delicious']['target'] = '_blank';
687
688
            $thread_action['social_reddit']['image']  = \newbbDisplayImage('reddit', \_MD_NEWBB_SHARE_REDDIT);
689
            $thread_action['social_reddit']['link']   = 'https://reddit.com/submit?title=' . $full_title . '&amp;url=' . $full_link;
690
            $thread_action['social_reddit']['name']   = \_MD_NEWBB_SHARE_REDDIT;
691
            $thread_action['social_reddit']['target'] = '_blank';
692
        }
693
694
        $post = [
695
            'post_id'         => $post_id,
696
            'post_parent_id'  => $this->getVar('pid'),
697
            'post_date'       => \newbbFormatTimestamp($this->getVar('post_time')),
698
            'post_image'      => $post_image,
699
            'post_title'      => $post_title,
700
            // irmtfan $post_title to add highlight keywords
701
            'post_text'       => $post_text,
702
            'post_attachment' => $post_attachment,
703
            'post_edit'       => $this->displayPostEdit(),
704
            'post_no'         => $post_no,
705
            'post_signature'  => $this->getVar('attachsig') ? @$poster['signature'] : '',
706
            //            'poster_ip'       => ($isAdmin && $GLOBALS['xoopsModuleConfig']['show_ip']) ? long2ip($this->getVar('poster_ip')) : '',
707
            'poster_ip'       => ($isAdmin
708
                                  && $GLOBALS['xoopsModuleConfig']['show_ip']) ? $this->getVar('poster_ip') : '',
709
            'thread_action'   => $thread_action,
710
            'thread_buttons'  => $thread_buttons,
711
            'mod_buttons'     => $mod_buttons,
712
            'poster'          => $poster,
713
            //Modified by BigKev73
714
            'post_permalink'  => '<a href="' . XOOPS_URL . '/modules/' . $xoopsModule->getVar('dirname') . '/viewtopic.php?topic_id=' . $topic_id . '&amp;post_id=' . $post_id . '#forumpost=' . $post_id . '"></a>',
715
716
            //'post_permalink'  => '<a href="' . XOOPS_URL . '/modules/' . $xoopsModule->getVar('dirname') . '/viewtopic.php?post_id=' . $post_id . '"></a>',
717
        ];
718
719
        unset($thread_buttons, $mod_buttons);
720
721
        return $post;
722
    }
723
}
724