Passed
Pull Request — master (#41)
by Michael
13:46
created

NewsStory::countPublishedByTopic()   B

Complexity

Conditions 8
Paths 22

Size

Total Lines 67
Code Lines 37

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 1 Features 0
Metric Value
cc 8
eloc 37
c 1
b 1
f 0
nc 22
nop 2
dl 0
loc 67
rs 8.0835

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php declare(strict_types=1);
2
3
namespace XoopsModules\News;
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
/**
16
 * @copyright      {@link https://xoops.org/ XOOPS Project}
17
 * @license        {@link https://www.gnu.org/licenses/gpl-2.0.html GNU GPL 2 or later}
18
 * @author         XOOPS Development Team
19
 */
20
21
use Xmf\Module\Admin;
22
23
//require_once XOOPS_ROOT_PATH . '/modules/news/class/xoopsstory.php';
24
require XOOPS_ROOT_PATH . '/include/comment_constants.php';
25
26
require_once \dirname(__DIR__) . '/preloads/autoloader.php';
27
28
/** @var Helper $helper */
29
$helper = Helper::getInstance();
30
$helper->loadLanguage('main');
31
32
/**
33
 * Class NewsStory
34
 */
35
class NewsStory extends XoopsStory
36
{
37
    public $newstopic; // XoopsTopic object
38
    public $rating; // News rating
39
    public $votes; // Number of votes
40
    public $description; // META, desciption
41
    public $keywords; // META, keywords
42
    public $picture;
43
    public $topic_imgurl;
44
    public $topic_title;
45
    public $topic_description;
46
    public $subtitle;
47
    public $pictureinfo;
48
49
    /**
50
     * Constructor
51
     * @param array|int  $storyid
52
     */
53
    public function __construct($storyid = -1)
54
    {
55
        /** @var \XoopsMySQLDatabase $this ->db */
56
        $this->db          = \XoopsDatabaseFactory::getDatabaseConnection();
0 ignored issues
show
Bug introduced by
The property db does not seem to exist on XoopsMySQLDatabase.
Loading history...
57
        $this->table       = $this->db->prefix('news_stories');
0 ignored issues
show
Bug introduced by
The property table does not seem to exist on XoopsMySQLDatabase.
Loading history...
58
        $this->topicstable = $this->db->prefix('news_topics');
0 ignored issues
show
Bug introduced by
The property topicstable does not seem to exist on XoopsMySQLDatabase.
Loading history...
59
        if (\is_array($storyid)) {
60
            $this->makeStory($storyid);
0 ignored issues
show
Bug introduced by
The method makeStory() does not exist on XoopsMySQLDatabase. ( Ignorable by Annotation )

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

60
            $this->/** @scrutinizer ignore-call */ 
61
                   makeStory($storyid);

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...
61
        } elseif (-1 != $storyid) {
62
            $this->getStory((int)$storyid);
0 ignored issues
show
Bug introduced by
The method getStory() does not exist on XoopsMySQLDatabase. ( Ignorable by Annotation )

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

62
            $this->/** @scrutinizer ignore-call */ 
63
                   getStory((int)$storyid);

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...
63
        }
64
    }
65
66
    /**
67
     * Returns the number of stories published before a date
68
     * @param int    $timestamp
69
     * @param int    $expired
70
     * @param string $topicslist
71
     * @return mixed
72
     */
73
    public function getCountStoriesPublishedBefore(int $timestamp, int $expired, string $topicslist = '')
74
    {
75
        $count = 0;
0 ignored issues
show
Unused Code introduced by
The assignment to $count is dead and can be removed.
Loading history...
76
        $sql = 'SELECT count(*) AS cpt FROM ' . $this->db->prefix('news_stories') . ' WHERE published <=' . $timestamp;
77
        if ($expired) {
78
            $sql .= ' AND (expired>0 AND expired<=' . \time() . ')';
79
        }
80
        if ('' !== \trim($topicslist)) {
81
            $sql .= ' AND topicid IN (' . $topicslist . ')';
82
        }
83
        $result = Utility::queryAndCheck($this->db, $sql);
84
        [$count] = $this->db->fetchRow($result);
85
86
        return $count;
87
    }
88
89
    /**
90
     * Load the specified story from the database
91
     * @param $storyid
92
     */
93
    public function getStory($storyid): void
94
    {
95
        $sql   = 'SELECT s.*, t.* FROM ' . $this->table . ' s, ' . $this->db->prefix('news_topics') . ' t WHERE (storyid=' . (int)$storyid . ') AND (s.topicid=t.topic_id)';
96
        $result = Utility::queryAndCheck($this->db, $sql);
97
        if (!$this->db->isResultSet($result)){
98
            \trigger_error("Query Failed! SQL: $sql Error: " . $this->db->error(), \E_USER_ERROR);
99
        }
100
        $array = $this->db->fetchArray($result);
101
        $this->makeStory($array);
0 ignored issues
show
Bug introduced by
It seems like $array can also be of type false; however, parameter $array of XoopsModules\News\XoopsStory::makeStory() does only seem to accept 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

101
        $this->makeStory(/** @scrutinizer ignore-type */ $array);
Loading history...
102
    }
103
104
    /**
105
     * Delete stories that were published before a given date
106
     * @param         $timestamp
107
     * @param         $expired
108
     * @param string  $topicslist
109
     * @return bool
110
     */
111
    public function deleteBeforeDate($timestamp, $expired, string $topicslist = ''): bool
112
    {
113
        global $xoopsModule;
114
        $mid          = $xoopsModule->getVar('mid');
115
        $prefix       = $this->db->prefix('news_stories');
116
        $vote_prefix  = $this->db->prefix('news_stories_votedata');
117
        $files_prefix = $this->db->prefix('news_stories_files');
118
        $sql          = 'SELECT storyid FROM  ' . $prefix . ' WHERE published <=' . $timestamp;
119
        if ($expired) {
120
            $sql .= ' (AND expired>0 AND expired<=' . \time() . ')';
121
        }
122
        if ('' !== \trim($topicslist)) {
123
            $sql .= ' AND topicid IN (' . $topicslist . ')';
124
        }
125
        $result = Utility::queryAndCheck($this->db, $sql);
126
        while (false !== ($myrow = $this->db->fetchArray($result))) {
127
            \xoops_comment_delete($mid, $myrow['storyid']); // Delete comments
128
            \xoops_notification_deletebyitem($mid, 'story', $myrow['storyid']); // Delete notifications
129
            $sql     = 'DELETE FROM ' . $vote_prefix . ' WHERE storyid=' . $myrow['storyid'];
130
            $result1 = $this->db->queryF($sql); // Delete votes
0 ignored issues
show
Unused Code introduced by
The assignment to $result1 is dead and can be removed.
Loading history...
131
            // Remove files and records related to the files
132
            $sql     = 'SELECT * FROM ' . $files_prefix . ' WHERE storyid=' . $myrow['storyid'];
133
            $result2 = Utility::queryAndCheck($this->db, $sql);
134
            while (false !== ($myrow2 = $this->db->fetchArray($result2))) {
135
                $name = XOOPS_ROOT_PATH . '/uploads/' . $myrow2['downloadname'];
136
                if (\is_file($name)) {
137
                    \unlink($name);
138
                }
139
                $sql     = 'DELETE FROM ' . $files_prefix . ' WHERE fileid=' . $myrow2['fileid'];
140
                $result3 = $this->db->query($sql);
0 ignored issues
show
Unused Code introduced by
The assignment to $result3 is dead and can be removed.
Loading history...
141
            }
142
            $sql     = 'DELETE FROM ' . $prefix . ' WHERE storyid=' . $myrow['storyid'];
143
            $result4 = $this->db->queryF($sql); // Delete the story
0 ignored issues
show
Unused Code introduced by
The assignment to $result4 is dead and can be removed.
Loading history...
144
        }
145
146
        return true;
147
    }
148
149
    /**
150
     * @param int|string $storyid
151
     * @param bool       $next
152
     * @param int       $checkRight
153
     *
154
     * @return array
155
     */
156
    public function _searchPreviousOrNextArticle($storyid, bool $next = true, int $checkRight = 0): ?array
157
    {
158
        $ret     = [];
159
        $storyid = (int)$storyid;
160
        if ($next) {
161
            $sql     = 'SELECT storyid, title FROM ' . $this->db->prefix('news_stories') . ' WHERE (published > 0 AND published <= ' . \time() . ') AND (expired = 0 OR expired > ' . \time() . ') AND storyid > ' . $storyid;
162
            $orderBy = ' ORDER BY storyid ASC';
163
        } else {
164
            $sql     = 'SELECT storyid, title FROM ' . $this->db->prefix('news_stories') . ' WHERE (published > 0 AND published <= ' . \time() . ') AND (expired = 0 OR expired > ' . \time() . ') AND storyid < ' . $storyid;
165
            $orderBy = ' ORDER BY storyid DESC';
166
        }
167
        if ($checkRight) {
168
            $topics = Utility::getMyItemIds('news_view');
169
            if (\count($topics) > 0) {
170
                $sql .= ' AND topicid IN (' . \implode(',', $topics) . ')';
171
            } else {
172
                return null;
173
            }
174
        }
175
        $sql .= $orderBy;
176
177
        $result = $this->db->query($sql, 1);
178
        if ($this->db->isResultSet($result)) {
179
            $myts = \MyTextSanitizer::getInstance();
0 ignored issues
show
Unused Code introduced by
The assignment to $myts is dead and can be removed.
Loading history...
180
            while (false !== ($row = $this->db->fetchArray($result))) {
181
                $ret = ['storyid' => $row['storyid'], 'title' => \htmlspecialchars($row['title'], \ENT_QUOTES | \ENT_HTML5)];
182
            }
183
        }
184
185
        return $ret;
186
    }
187
188
    /**
189
     * @param int  $storyid
190
     * @param int $checkRight
191
     *
192
     * @return null|array
193
     */
194
    public function getNextArticle(int $storyid, int $checkRight = 0): ?array
195
    {
196
        return $this->_searchPreviousOrNextArticle($storyid, true, $checkRight);
197
    }
198
199
    /**
200
     * @param      $storyid
201
     * @param int $checkRight
202
     *
203
     * @return array
204
     */
205
    public function getPreviousArticle($storyid, int $checkRight = 0): ?array
206
    {
207
        return $this->_searchPreviousOrNextArticle($storyid, false, $checkRight);
208
    }
209
210
    /**
211
     * Returns published stories according to some options
212
     * @param int       $limit
213
     * @param int       $start
214
     * @param int       $checkRight
215
     * @param array|int $topic
216
     * @param int       $ihome
217
     * @param bool      $asobject
218
     * @param string    $order
219
     * @param bool      $topic_frontpage
220
     * @return array|null
221
     */
222
    public static function getAllPublished(
223
        int    $limit = 0,
224
        int    $start = 0,
225
        int    $checkRight = 0,
226
        int    $topic = 0,
227
        int    $ihome = 0,
228
        bool   $asobject = true,
229
        string $order = 'published',
230
        bool   $topic_frontpage = false
231
    ): ?array {
232
        /** @var \XoopsMySQLDatabase $db */
233
        $db   = \XoopsDatabaseFactory::getDatabaseConnection();
234
        $myts = \MyTextSanitizer::getInstance();
0 ignored issues
show
Unused Code introduced by
The assignment to $myts is dead and can be removed.
Loading history...
235
        $ret  = [];
236
        $sql  = 'SELECT s.*, t.* FROM ' . $db->prefix('news_stories') . ' s, ' . $db->prefix('news_topics') . ' t WHERE (s.published > 0 AND s.published <= ' . \time() . ') AND (s.expired = 0 OR s.expired > ' . \time() . ') AND (s.topicid=t.topic_id) ';
237
        if (0 != $topic) {
238
            if (\is_array($topic)) {
0 ignored issues
show
introduced by
The condition is_array($topic) is always false.
Loading history...
239
                if ($checkRight) {
240
                    $topics = Utility::getMyItemIds('news_view');
241
                    $topic  = \array_intersect($topic, $topics);
242
                }
243
                if (\count($topic) > 0) {
244
                    $sql .= ' AND s.topicid IN (' . \implode(',', $topic) . ')';
245
                } else {
246
                    return null;
247
                }
248
            } elseif ($checkRight) {
249
                    $topics = Utility::getMyItemIds('news_view');
250
                    if (!\in_array($topic, $topics, true)) {
251
                        return null;
252
                    }
253
                    $sql .= ' AND s.topicid=' . (int)$topic . ' AND (s.ihome=1 OR s.ihome=0)';
254
                } else {
255
                    $sql .= ' AND s.topicid=' . (int)$topic . ' AND (s.ihome=1 OR s.ihome=0)';
256
            }
257
        } else {
258
            if ($checkRight) {
259
                $topics = Utility::getMyItemIds('news_view');
260
                if (\count($topics) > 0) {
261
                    $topics = \implode(',', $topics);
262
                    $sql    .= ' AND s.topicid IN (' . $topics . ')';
263
                } else {
264
                    return null;
265
                }
266
            }
267
            if (0 == (int)$ihome) {
268
                $sql .= ' AND s.ihome=0';
269
            }
270
        }
271
        if ($topic_frontpage) {
272
            $sql .= ' AND t.topic_frontpage=1';
273
        }
274
        $sql    .= " ORDER BY s.$order DESC";
275
        $result = $db->query($sql, (int)$limit, (int)$start);
276
277
        if (!$db->isResultSet($result)) {
278
//            \trigger_error("Query Failed! SQL: $sql- Error: " . $db->error(), E_USER_ERROR);
279
            $helper = Helper::getInstance();
280
            $helper->redirect('/index.php', 5, $db->error());
281
        }
282
283
        /** @var array $myrow */
284
        while (false !== ($myrow = $db->fetchArray($result))) {
0 ignored issues
show
Bug introduced by
It seems like $result can also be of type boolean; however, parameter $result of XoopsMySQLDatabase::fetchArray() does only seem to accept mysqli_result, 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

284
        while (false !== ($myrow = $db->fetchArray(/** @scrutinizer ignore-type */ $result))) {
Loading history...
285
                if ($asobject) {
286
                    $ret[] = new self($myrow);
287
                } else {
288
                    $ret[$myrow['storyid']] = \htmlspecialchars($myrow['title'], \ENT_QUOTES | \ENT_HTML5);
289
                }
290
            }
291
292
        return $ret;
293
    }
294
295
    /**
296
     * Returns the list of articles in the archives (for a given period)
297
     * @param int    $publish_start
298
     * @param int    $publish_end
299
     * @param int   $checkRight
300
     * @param bool   $asobject
301
     * @param string $order
302
     * @return array|null
303
     */
304
    public function getArchive(
305
        int $publish_start,
306
        int $publish_end,
307
        int $checkRight = 0,
308
        bool $asobject = true,
309
        string $order = 'published'
310
    ): ?array {
311
        $myts = \MyTextSanitizer::getInstance();
0 ignored issues
show
Unused Code introduced by
The assignment to $myts is dead and can be removed.
Loading history...
312
        $ret  = [];
313
        $sql  = 'SELECT s.*, t.* FROM ' . $this->db->prefix('news_stories') . ' s, ' . $this->db->prefix('news_topics') . ' t WHERE (s.topicid=t.topic_id) AND (s.published > ' . $publish_start . ' AND s.published <= ' . $publish_end . ') AND (expired = 0 OR expired > ' . \time() . ') ';
314
315
        if ($checkRight) {
316
            $topics = Utility::getMyItemIds('news_view');
317
            if (\count($topics) > 0) {
318
                $topics = \implode(',', $topics);
319
                $sql    .= ' AND topicid IN (' . $topics . ')';
320
            } else {
321
                return null;
322
            }
323
        }
324
        $sql    .= " ORDER BY $order DESC";
325
        $result = $this->db->query($sql);
326
        if ($this->db->isResultSet($result)) {
327
            while (false !== ($myrow = $this->db->fetchArray($result))) {
328
                if ($asobject) {
329
                    $ret[] = new self($myrow);
330
                } else {
331
                    $ret[$myrow['storyid']] = \htmlspecialchars($myrow['title'], \ENT_QUOTES | \ENT_HTML5);
332
                }
333
            }
334
        }
335
336
        return $ret;
337
    }
338
339
    /**
340
     * Get the today's most readed article
341
     *
342
     * @param int       $limit      records limit
343
     * @param int       $start      starting record
344
     * @param bool|int  $checkRight Do we need to check permissions (by topics) ?
345
     * @param array|int $topic      limit the job to one topic
346
     * @param int       $ihome      Limit to articles published in home page only ?
347
     * @param bool      $asobject   Do we have to return an array of objects or a simple array ?
348
     * @param string    $order      Fields to sort on
349
     *
350
     * @return array
351
     */
352
    public function getBigStory(
353
        int    $limit = 0,
354
        int    $start = 0,
355
        int    $checkRight = 0,
356
               $topic = 0,
357
        int    $ihome = 0,
358
        bool   $asobject = true,
359
        string $order = 'counter'
360
    ): ?array {
361
        $myts  = \MyTextSanitizer::getInstance();
0 ignored issues
show
Unused Code introduced by
The assignment to $myts is dead and can be removed.
Loading history...
362
        $ret   = [];
363
        $tdate = \mktime(0, 0, 0, (int)\date('n'), (int)\date('j'), (int)\date('Y'));
364
        $sql   = 'SELECT s.*, t.* FROM ' . $this->db->prefix('news_stories') . ' s, ' . $this->db->prefix('news_topics') . ' t WHERE (s.topicid=t.topic_id) AND (published > ' . $tdate . ' AND published < ' . \time() . ') AND (expired > ' . \time() . ' OR expired = 0) ';
365
366
        if (0 != (int)$topic) {
367
            if (!\is_array($topic)) {
368
                $sql .= ' AND topicid=' . (int)$topic . ' AND (ihome=1 OR ihome=0)';
369
            } elseif (\count($topic) > 0) {
370
                $sql .= ' AND topicid IN (' . \implode(',', $topic) . ')';
371
            } else {
372
                return null;
373
            }
374
        } else {
375
            if ($checkRight) {
376
                $topics = Utility::getMyItemIds('news_view');
377
                if (\count($topics) > 0) {
378
                    $topics = \implode(',', $topics);
379
                    $sql    .= ' AND topicid IN (' . $topics . ')';
380
                } else {
381
                    return null;
382
                }
383
            }
384
            if (0 == (int)$ihome) {
385
                $sql .= ' AND ihome=0';
386
            }
387
        }
388
        $sql    .= " ORDER BY $order DESC";
389
        $result = $this->db->query($sql, (int)$limit, (int)$start);
390
        if ($this->db->isResultSet($result)) {
391
            while (false !== ($myrow = $this->db->fetchArray($result))) {
392
                if ($asobject) {
393
                    $ret[] = new self($myrow);
394
                } else {
395
                    $ret[$myrow['storyid']] = \htmlspecialchars($myrow['title'], \ENT_QUOTES | \ENT_HTML5);
396
                }
397
            }
398
        }
399
400
        return $ret;
401
    }
402
403
    /**
404
     * Get all articles published by an author
405
     *
406
     * @param int  $uid        author's id
407
     * @param int $checkRight whether to check the user's rights to topics
408
     * @param bool $asobject
409
     *
410
     * @return array
411
     */
412
    public function getAllPublishedByAuthor(int $uid, int $checkRight = 0, bool $asobject = true): array
413
    {
414
        $myts      = \MyTextSanitizer::getInstance();
415
        $ret       = [];
416
        $tblstory  = $this->db->prefix('news_stories');
417
        $tbltopics = $this->db->prefix('news_topics');
418
419
        $sql = 'SELECT '
420
               . $tblstory
421
               . '.*, '
422
               . $tbltopics
423
               . '.topic_title, '
424
               . $tbltopics
425
               . '.topic_color FROM '
426
               . $tblstory
427
               . ','
428
               . $tbltopics
429
               . ' WHERE ('
430
               . $tblstory
431
               . '.topicid='
432
               . $tbltopics
433
               . '.topic_id) AND (published > 0 AND published <= '
434
               . \time()
435
               . ') AND (expired = 0 OR expired > '
436
               . \time()
437
               . ')';
438
        $sql .= ' AND uid=' . (int)$uid;
439
        if ($checkRight) {
440
            $topics = Utility::getMyItemIds('news_view');
441
            $topics = \implode(',', $topics);
442
            if ('' !== \xoops_trim($topics)) {
443
                $sql .= ' AND topicid IN (' . $topics . ')';
444
            }
445
        }
446
        $sql    .= ' ORDER BY ' . $tbltopics . '.topic_title ASC, ' . $tblstory . '.published DESC';
447
        $result = $this->db->query($sql);
448
        if ($this->db->isResultSet($result)) {
449
            while (false !== ($myrow = $this->db->fetchArray($result))) {
450
                if ($asobject) {
451
                    $ret[] = new self($myrow);
452
                } else {
453
                    if ($myrow['nohtml']) {
454
                        $html = 0;
455
                    } else {
456
                        $html = 1;
457
                    }
458
                    if ($myrow['nosmiley']) {
459
                        $smiley = 0;
460
                    } else {
461
                        $smiley = 1;
462
                    }
463
                    $ret[$myrow['storyid']] = [
464
                        'title'       => $myts->displayTarea($myrow['title'], $html, $smiley, 1),
465
                        'topicid'     => (int)$myrow['topicid'],
466
                        'storyid'     => (int)$myrow['storyid'],
467
                        'hometext'    => $myts->displayTarea($myrow['hometext'], $html, $smiley, 1),
468
                        'counter'     => (int)$myrow['counter'],
469
                        'created'     => (int)$myrow['created'],
470
                        'topic_title' => $myts->displayTarea($myrow['topic_title'], $html, $smiley, 1),
471
                        'topic_color' => $myts->displayTarea($myrow['topic_color']),
472
                        'published'   => (int)$myrow['published'],
473
                        'rating'      => (float)$myrow['rating'],
474
                        'votes'       => (int)$myrow['votes'],
475
                    ];
476
                }
477
            }
478
        }
479
480
        return $ret;
481
    }
482
483
    /**
484
     * Get all expired stories
485
     * @param int  $limit
486
     * @param int  $start
487
     * @param int  $topic
488
     * @param int  $ihome
489
     * @param bool $asobject
490
     * @return array
491
     */
492
    public static function getAllExpired(int $limit = 0, int $start = 0, int $topic = 0, int $ihome = 0, bool $asobject = true): array
493
    {
494
        /** @var \XoopsMySQLDatabase $db */
495
        $db   = \XoopsDatabaseFactory::getDatabaseConnection();
496
        $myts = \MyTextSanitizer::getInstance();
0 ignored issues
show
Unused Code introduced by
The assignment to $myts is dead and can be removed.
Loading history...
497
        $ret  = [];
498
        $sql  = 'SELECT * FROM ' . $db->prefix('news_stories') . ' WHERE expired <= ' . \time() . ' AND expired > 0';
499
        if (!empty($topic)) {
500
            $sql .= ' AND topicid=' . (int)$topic . ' AND (ihome=1 OR ihome=0)';
501
        } elseif (0 == (int)$ihome) {
502
            $sql .= ' AND ihome=0';
503
        }
504
505
        $sql    .= ' ORDER BY expired DESC';
506
        $result = $db->query($sql, (int)$limit, (int)$start);
507
        if ($db->isResultSet($result)) {
508
            while (false !== ($myrow = $db->fetchArray($result))) {
0 ignored issues
show
Bug introduced by
It seems like $result can also be of type boolean; however, parameter $result of XoopsMySQLDatabase::fetchArray() does only seem to accept mysqli_result, 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

508
            while (false !== ($myrow = $db->fetchArray(/** @scrutinizer ignore-type */ $result))) {
Loading history...
509
                if ($asobject) {
510
                    $ret[] = new self($myrow);
511
                } else {
512
                    $ret[$myrow['storyid']] = \htmlspecialchars($myrow['title'], \ENT_QUOTES | \ENT_HTML5);
513
                }
514
            }
515
        }
516
517
        return $ret;
518
    }
519
520
    /**
521
     * Returns an array of object containing all the news to be automatically published.
522
     * @param int  $limit
523
     * @param bool $asobject
524
     * @param int  $start
525
     * @return array
526
     */
527
    public static function getAllAutoStory(int $limit = 0, bool $asobject = true, int $start = 0): array
528
    {
529
        /** @var \XoopsMySQLDatabase $db */
530
        $db     = \XoopsDatabaseFactory::getDatabaseConnection();
531
        $myts   = \MyTextSanitizer::getInstance();
0 ignored issues
show
Unused Code introduced by
The assignment to $myts is dead and can be removed.
Loading history...
532
        $ret    = [];
533
        $sql    = 'SELECT * FROM ' . $db->prefix('news_stories') . ' WHERE published > ' . \time() . ' ORDER BY published ASC';
534
        $result = $db->query($sql, (int)$limit, (int)$start);
535
        if ($db->isResultSet($result)) {
536
            /** @var array $myrow */
537
            while (false !== ($myrow = $db->fetchArray($result))) {
0 ignored issues
show
Bug introduced by
It seems like $result can also be of type boolean; however, parameter $result of XoopsMySQLDatabase::fetchArray() does only seem to accept mysqli_result, 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

537
            while (false !== ($myrow = $db->fetchArray(/** @scrutinizer ignore-type */ $result))) {
Loading history...
538
                if ($asobject) {
539
                    $ret[] = new self($myrow);
540
                } else {
541
                    $ret[$myrow['storyid']] = \htmlspecialchars($myrow['title'], \ENT_QUOTES | \ENT_HTML5);
542
                }
543
            }
544
        }
545
546
        return $ret;
547
    }
548
549
    /**
550
     * Get all submitted stories awaiting approval
551
     *
552
     * @param int|null  $limit      Denotes where to start the query
553
     * @param bool $asobject   true will return the stories as an array of objects, false will return storyid => title
554
     * @param int|null $checkRight whether to check the user's rights to topics
555
     *
556
     * @param int  $start
557
     *
558
     * @return array
559
     */
560
    public static function getAllSubmitted(?int $limit = null, bool $asobject = true, ?int $checkRight = null, int $start = 0): array
561
    {
562
        $checkRight ??= false;
563
        $limit      ??= 0;
564
        /** @var \XoopsMySQLDatabase $db */
565
        $db       = \XoopsDatabaseFactory::getDatabaseConnection();
566
        $myts     = \MyTextSanitizer::getInstance();
0 ignored issues
show
Unused Code introduced by
The assignment to $myts is dead and can be removed.
Loading history...
567
        $ret      = [];
568
        $criteria = new \CriteriaCompo(new \Criteria('published', 0));
569
        if ($checkRight) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $checkRight of type false|integer is loosely compared to true; this is ambiguous if the integer can be 0. You might want to explicitly use !== false instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For integer values, zero is a special case, in particular the following results might be unexpected:

0   == false // true
0   == null  // true
123 == false // false
123 == null  // false

// It is often better to use strict comparison
0 === false // false
0 === null  // false
Loading history...
570
            global $xoopsUser;
571
            if (!\is_object($xoopsUser)) {
572
                return $ret;
573
            }
574
            $allowedtopics = Utility::getMyItemIds('news_approve');
575
            $criteria2     = new \CriteriaCompo();
576
            foreach ($allowedtopics as $key => $topicid) {
577
                $criteria2->add(new \Criteria('topicid', $topicid), 'OR');
578
            }
579
            $criteria->add($criteria2);
580
        }
581
        $sql    = 'SELECT s.*, t.* FROM ' . $db->prefix('news_stories') . ' s, ' . $db->prefix('news_topics') . ' t ';
582
        $sql    .= ' ' . $criteria->renderWhere() . ' AND (s.topicid=t.topic_id) ORDER BY created DESC';
583
        $result = $db->query($sql, (int)$limit, (int)$start);
584
        if ($db->isResultSet($result)) {
585
            /** @var array $myrow */
586
            while (false !== ($myrow = $db->fetchArray($result))) {
0 ignored issues
show
Bug introduced by
It seems like $result can also be of type boolean; however, parameter $result of XoopsMySQLDatabase::fetchArray() does only seem to accept mysqli_result, 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

586
            while (false !== ($myrow = $db->fetchArray(/** @scrutinizer ignore-type */ $result))) {
Loading history...
587
                if ($asobject) {
588
                    $ret[] = new self($myrow);
589
                } else {
590
                    $ret[$myrow['storyid']] = \htmlspecialchars($myrow['title'], \ENT_QUOTES | \ENT_HTML5);
591
                }
592
            }
593
        }
594
595
        return $ret;
596
    }
597
598
    /**
599
     * Used in the module's admin to know the number of expired, automated or pubilshed news
600
     *
601
     * @param int|null  $storytype  1=Expired, 2=Automated, 3=New submissions, 4=Last published stories
602
     * @param int $checkRight verify permissions or not ?
603
     *
604
     * @return int
605
     */
606
    public static function getAllStoriesCount(?int $storytype = null, int $checkRight = 0): int
607
    {
608
        $storytype ??= 1;
609
        /** @var \XoopsMySQLDatabase $db */
610
        $db  = \XoopsDatabaseFactory::getDatabaseConnection();
611
        $sql = 'SELECT count(*) AS cpt FROM ' . $db->prefix('news_stories') . ' WHERE ';
612
        switch ($storytype) {
613
            case 1: // Expired
614
                $sql .= '(expired <= ' . \time() . ' AND expired >0)';
615
                break;
616
            case 2: // Automated
617
                $sql .= '(published > ' . \time() . ')';
618
                break;
619
            case 3: // New submissions
620
                $sql .= '(published = 0)';
621
                break;
622
            case 4: // Last published stories
623
                $sql .= '(published > 0 AND published <= ' . \time() . ') AND (expired = 0 OR expired > ' . \time() . ')';
624
                break;
625
        }
626
        if ($checkRight) {
627
            $topics = Utility::getMyItemIds('news_view');
628
            if (\count($topics) > 0) {
629
                $topics = \implode(',', $topics);
630
                $sql    .= ' AND topicid IN (' . $topics . ')';
631
            } else {
632
                return 0;
633
            }
634
        }
635
        $result = $db->query($sql);
636
        if ($db->isResultSet($result)) {
637
            $myrow = $db->fetchArray($result);
0 ignored issues
show
Bug introduced by
It seems like $result can also be of type boolean; however, parameter $result of XoopsMySQLDatabase::fetchArray() does only seem to accept mysqli_result, 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

637
            $myrow = $db->fetchArray(/** @scrutinizer ignore-type */ $result);
Loading history...
638
            return (int)$myrow['cpt'];
639
        }
640
        return 0;
641
    }
642
643
    /**
644
     * Get a list of stories (as objects) related to a specific topic
645
     * @param int    $topicid
646
     * @param int    $limit
647
     * @return array
648
     */
649
    public static function getByTopic($topicid, int $limit = 0): array
650
    {
651
        $ret = [];
652
        /** @var \XoopsMySQLDatabase $db */
653
        $db     = \XoopsDatabaseFactory::getDatabaseConnection();
654
        $sql    = 'SELECT * FROM ' . $db->prefix('news_stories') . ' WHERE topicid=' . (int)$topicid . ' ORDER BY published DESC';
655
        $result = $db->query($sql, (int)$limit, 0);
656
        if ($db->isResultSet($result)) {
657
            while (false !== ($myrow = $db->fetchArray($result))) {
0 ignored issues
show
Bug introduced by
It seems like $result can also be of type boolean; however, parameter $result of XoopsMySQLDatabase::fetchArray() does only seem to accept mysqli_result, 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

657
            while (false !== ($myrow = $db->fetchArray(/** @scrutinizer ignore-type */ $result))) {
Loading history...
658
                $ret[] = new self($myrow);
659
            }
660
        }
661
662
        return $ret;
663
    }
664
665
    /**
666
     * Count the number of news published for a specific topic
667
     * @param int|null  $topicid
668
     * @param bool|int $checkRight
669
     * @return int|string
670
     */
671
    public static function countPublishedByTopic(?int $topicid = null, int $checkRight = 0): int
672
    {
673
        $topicid ??= 0;
674
        $count = 0;
675
676
        /** @var \XoopsMySQLDatabase $db */
677
        $db = \XoopsDatabaseFactory::getDatabaseConnection();
678
679
        // Base SQL query with placeholders for prepared statement
680
        $sql = 'SELECT COUNT(*) FROM ' . $db->prefix('news_stories') . ' WHERE published > 0 AND published <= ? AND (expired = 0 OR expired > ?)';
681
        $params = [\time(), \time()];
682
        $types = 'ii'; // integer, integer
683
684
        // Append topicid condition if provided
685
        if ($topicid > 0) {
686
            $sql .= ' AND topicid = ?';
687
            $params[] = $topicid;
688
            $types .= 'i'; // Add another integer type
689
        } else {
690
            $sql .= ' AND ihome = 0';
691
        }
692
693
        // Check user's rights if necessary
694
        if ($checkRight) {
695
            $topics = Utility::getMyItemIds('news_view');
696
            if (\count($topics) > 0) {
697
                $topicsList = \implode(',', \array_map('intval', $topics));
698
                $sql .= ' AND topicid IN (' . $topicsList . ')';
699
            } else {
700
                return $count;
701
            }
702
        }
703
704
        // Prepare the statement using the underlying mysqli connection
705
        $stmt = $db->conn->prepare($sql);
0 ignored issues
show
Bug introduced by
The method prepare() does not exist on XoopsDatabase. ( Ignorable by Annotation )

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

705
        /** @scrutinizer ignore-call */ 
706
        $stmt = $db->conn->prepare($sql);

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...
706
        if ($stmt === false) {
707
            \XoopsLogger::getInstance()->handleError(E_USER_ERROR, "Error preparing query in countPublishedByTopic: " . $db->error(), __FILE__, __LINE__);
708
            return $count;
709
        }
710
711
        // Bind parameters
712
        if (!$stmt->bind_param($types, ...$params)) {
713
            \XoopsLogger::getInstance()->handleError(E_USER_ERROR, "Error binding parameters in countPublishedByTopic: " . $stmt->error, __FILE__, __LINE__);
714
            $stmt->close();
715
            return $count;
716
        }
717
718
        // Execute the prepared statement
719
        if (!$stmt->execute()) {
720
            \XoopsLogger::getInstance()->handleError(E_USER_ERROR, "Error executing query in countPublishedByTopic: " . $stmt->error, __FILE__, __LINE__);
721
            $stmt->close();
722
            return $count;
723
        }
724
725
        // Bind the result
726
        $stmt->bind_result($count);
727
728
        // Fetch the result
729
        if (!$stmt->fetch()) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $stmt->fetch() of type null|true is loosely compared to false; this is ambiguous if the boolean can be false. You might want to explicitly use !== null instead.

If an expression can have both false, and null as possible values. It is generally a good practice to always use strict comparison to clearly distinguish between those two values.

$a = canBeFalseAndNull();

// Instead of
if ( ! $a) { }

// Better use one of the explicit versions:
if ($a !== null) { }
if ($a !== false) { }
if ($a !== null && $a !== false) { }
Loading history...
730
            \XoopsLogger::getInstance()->handleError(E_USER_ERROR, "Error fetching result in countPublishedByTopic: " . $stmt->error, __FILE__, __LINE__);
731
            $count = 0;
732
        }
733
734
        // Close the statement
735
        $stmt->close();
736
737
        return $count;
738
    }
739
740
741
    /**
742
     * Internal function
743
     */
744
    public function adminlink(): string
745
    {
746
        global $xoopsModule;
747
        $dirname = \basename(\dirname(__DIR__));
748
        /** @var \XoopsModuleHandler $moduleHandler */
749
        $moduleHandler = \xoops_getHandler('module');
750
        $module        = $moduleHandler->getByDirname($dirname);
0 ignored issues
show
Unused Code introduced by
The assignment to $module is dead and can be removed.
Loading history...
751
        $pathIcon16    = Admin::iconUrl('', '16');
752
753
        $ret = '&nbsp; <a href='
754
               . XOOPS_URL
755
               . '/modules/news/submit.php?op=edit&amp;storyid='
756
               . $this->storyid()
757
               . '><img src='
758
               . $pathIcon16
759
               . '/edit.png'
760
               . ' '
761
               . 'title='
762
               . \_NW_EDIT
763
               . '></a>'
764
               . '<a href='
765
               . XOOPS_URL
766
               . '/modules/news/admin/index.php?op=delete&amp;storyid='
767
               . $this->storyid()
768
               . '><img src='
769
               . $pathIcon16
770
               . '/delete.png'
771
               . ' '
772
               . 'title='
773
               . \_NW_DELETE
774
               . '></a> &nbsp;';
775
776
        return $ret;
777
    }
778
779
    /**
780
     * Get the topic image url
781
     * @param string $format
782
     * @return string
783
     */
784
    public function topic_imgurl(string $format = 'S'): string
785
    {
786
        if ('' === \trim($this->topic_imgurl)) {
787
            $this->topic_imgurl = 'blank.png';
788
        }
789
        $myts = \MyTextSanitizer::getInstance();
0 ignored issues
show
Unused Code introduced by
The assignment to $myts is dead and can be removed.
Loading history...
790
        switch ($format) {
791
            case 'S':
792
                $imgurl = \htmlspecialchars($this->topic_imgurl, \ENT_QUOTES | \ENT_HTML5);
793
                break;
794
            case 'E':
795
                $imgurl = \htmlspecialchars($this->topic_imgurl, \ENT_QUOTES | \ENT_HTML5);
796
                break;
797
            case 'P':
798
                $imgurl = \htmlspecialchars($this->topic_imgurl, \ENT_QUOTES | \ENT_HTML5);
799
                break;
800
            case 'F':
801
                $imgurl = \htmlspecialchars($this->topic_imgurl, \ENT_QUOTES | \ENT_HTML5);
802
                break;
803
        }
804
805
        return $imgurl;
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $imgurl does not seem to be defined for all execution paths leading up to this point.
Loading history...
806
    }
807
808
    /**
809
     * @param string $format
810
     *
811
     * @return string
812
     */
813
    public function topic_title(string $format = 'S'): string
814
    {
815
        $myts = \MyTextSanitizer::getInstance();
0 ignored issues
show
Unused Code introduced by
The assignment to $myts is dead and can be removed.
Loading history...
816
        switch ($format) {
817
            case 'S':
818
                $title = \htmlspecialchars($this->topic_title, \ENT_QUOTES | \ENT_HTML5);
819
                break;
820
            case 'E':
821
                $title = \htmlspecialchars($this->topic_title, \ENT_QUOTES | \ENT_HTML5);
822
                break;
823
            case 'P':
824
                $title = $this->topic_title;
825
                $title = \htmlspecialchars($title, \ENT_QUOTES | \ENT_HTML5);
826
                break;
827
            case 'F':
828
                $title = $this->topic_title;
829
                $title = \htmlspecialchars($title, \ENT_QUOTES | \ENT_HTML5);
830
                break;
831
        }
832
833
        return $title;
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $title does not seem to be defined for all execution paths leading up to this point.
Loading history...
834
    }
835
836
    /**
837
     * @return string
838
     */
839
    public function imglink(): string
840
    {
841
        $ret = '';
842
        if ('' !== $this->topic_imgurl()
843
            && \file_exists(XOOPS_ROOT_PATH . '/uploads/news/image/' . $this->topic_imgurl())) {
844
            $ret = '<a href="' . XOOPS_URL . '/modules/news/index.php?storytopic=' . $this->topicid() . '"><img src="' . XOOPS_URL . '/uploads/news/image/' . $this->topic_imgurl() . '" alt="' . $this->topic_title() . '" style="float: '. $this->topicalign() .'; margin: 10px; margin-top: 0px;" class="thumb_topic"></a>';
845
        }
846
847
        return $ret;
848
    }
849
850
    /**
851
     * @return string
852
     */
853
    public function textlink(): string
854
    {
855
        $ret = '<a title="' . $this->topic_title() . '" href="' . XOOPS_URL . '/modules/news/index.php?storytopic=' . $this->topicid() . '">' . $this->topic_title() . '</a>';
856
        return $ret;
857
    }
858
859
    /**
860
     * Function used to prepare an article to be showned
861
     * @param $filescount
862
     * @return array
863
     */
864
    public function prepare2show($filescount): array
865
    {
866
        global $xoopsUser, $xoopsConfig, $xoopsModule;
867
        /** @var Helper $helper */
868
        $helper = Helper::getInstance();
869
870
        $dirname = \basename(\dirname(__DIR__));
871
        /** @var \XoopsModuleHandler $moduleHandler */
872
        $moduleHandler = \xoops_getHandler('module');
873
        $module        = $moduleHandler->getByDirname($dirname);
0 ignored issues
show
Unused Code introduced by
The assignment to $module is dead and can be removed.
Loading history...
874
        $pathIcon16    = Admin::iconUrl('', '16');
875
876
        $myts                 = \MyTextSanitizer::getInstance();
877
        $infotips             = Utility::getModuleOption('infotips');
878
        $story                = [];
879
        $story['id']          = $this->storyid();
880
        $story['poster']      = $this->uname();
881
        $story['author_name'] = $this->uname();
882
        $story['author_uid']  = $this->uid();
883
        if (false !== $story['poster']) {
0 ignored issues
show
introduced by
The condition false !== $story['poster'] is always true.
Loading history...
884
            $story['poster'] = "<a href='" . XOOPS_URL . '/userinfo.php?uid=' . $this->uid() . "'>" . $story['poster'] . '</a>';
885
        } elseif (3 != $helper->getConfig('displayname')) {
886
            $story['poster'] = $xoopsConfig['anonymous'];
887
        }
888
        if ($helper->getConfig('ratenews')) {
889
            $story['rating'] = \number_format((float)$this->rating(), 2);
890
            if (1 == $this->votes) {
891
                $story['votes'] = \_NW_ONEVOTE;
892
            } else {
893
                $story['votes'] = \sprintf(\_NW_NUMVOTES, $this->votes);
894
            }
895
        }
896
        $story['posttimestamp']     = $this->published();
897
        $story['posttime']          = \formatTimestamp($story['posttimestamp'], Utility::getModuleOption('dateformat'));
898
        $story['topic_description'] = $myts->displayTarea($this->topic_description);
899
900
        $auto_summary = '';
0 ignored issues
show
Unused Code introduced by
The assignment to $auto_summary is dead and can be removed.
Loading history...
901
        $tmp          = '';
902
        $auto_summary = $this->auto_summary($this->bodytext(), $tmp);
903
904
        $story['text'] = $this->hometext();
905
        $story['text'] = \str_replace('[summary]', $auto_summary, $story['text']);
906
907
        //$story['picture'] = XOOPS_URL.'/uploads/news/image/'.$this->picture();
908
        if ('' !== $this->picture()) {
909
            $story['picture'] = XOOPS_URL . '/uploads/news/image/' . $this->picture();
910
        } else {
911
            $story['picture'] = '';
912
        }
913
        $story['pictureinfo'] = $this->pictureinfo();
914
915
        $introcount = \mb_strlen($story['text']);
916
        $fullcount  = \mb_strlen($this->bodytext());
917
        $totalcount = $introcount + $fullcount;
918
919
        $morelink = '';
920
        if ($fullcount > 1) {
921
            $morelink .= '<a href="' . XOOPS_URL . '/modules/news/article.php?storyid=' . $this->storyid();
922
            $morelink .= '">' . _NW_READMORE . '</a>';
923
            $morelink .= ' | ' . \sprintf(_NW_BYTESMORE, $totalcount);
924
            if (\XOOPS_COMMENT_APPROVENONE != $helper->getConfig('com_rule')) {
925
                $morelink .= ' | ';
926
            }
927
        }
928
        if (\XOOPS_COMMENT_APPROVENONE != $helper->getConfig('com_rule')) {
929
            $ccount    = $this->comments();
930
            $morelink  .= '<a href="' . XOOPS_URL . '/modules/news/article.php?storyid=' . $this->storyid();
931
            $morelink2 = '<a href="' . XOOPS_URL . '/modules/news/article.php?storyid=' . $this->storyid();
932
            if (0 == $ccount) {
933
                $morelink .= '">' . _NW_COMMENTS . '</a>';
934
            } elseif ($fullcount < 1) {
935
                if (1 == $ccount) {
936
                    $morelink .= '">' . _NW_READMORE . '</a> | ' . $morelink2 . '">' . _NW_ONECOMMENT . '</a>';
937
                } else {
938
                    $morelink .= '">' . _NW_READMORE . '</a> | ' . $morelink2 . '">';
939
                    $morelink .= \sprintf(_NW_NUMCOMMENTS, $ccount);
940
                    $morelink .= '</a>';
941
                }
942
            } elseif (1 == $ccount) {
943
                $morelink .= '">' . _NW_ONECOMMENT . '</a>';
944
            } else {
945
                $morelink .= '">';
946
                $morelink .= \sprintf(_NW_NUMCOMMENTS, $ccount);
947
                $morelink .= '</a>';
948
            }
949
        }
950
        $story['morelink']  = $morelink;
951
        $story['adminlink'] = '';
952
953
        $approveprivilege = 0;
954
        if (Utility::isAdminGroup()) {
955
            $approveprivilege = 1;
956
        }
957
958
        if (1 == $helper->getConfig('authoredit')
959
            && (\is_object($xoopsUser)
960
                && $xoopsUser->getVar('uid') == $this->uid())) {
961
            $approveprivilege = 1;
962
        }
963
        if ($approveprivilege) {
964
            $story['adminlink'] = $this->adminlink();
965
        }
966
        $story['mail_link'] = 'mailto:?subject=' . \sprintf(_NW_INTARTICLE, $xoopsConfig['sitename']) . '&amp;body=' . \sprintf(_NW_INTARTFOUND, $xoopsConfig['sitename']) . ':  ' . XOOPS_URL . '/modules/news/article.php?storyid=' . $this->storyid();
967
        $story['imglink']   = '';
968
        $story['align']     = '';
969
        if ($this->topicdisplay()) {
970
            $story['imglink'] = $this->imglink();
971
            $story['align']   = $this->topicalign();
972
        }
973
        if ($infotips > 0) {
974
            $story['infotips'] = ' title="' . Utility::makeInfotips($this->hometext()) . '"';
975
        } else {
976
            $story['infotips'] = 'title="' . $this->title() . '"';
977
        }
978
        $story['title'] = "<a href='" . XOOPS_URL . '/modules/news/article.php?storyid=' . $this->storyid() . "'" . $story['infotips'] . '>' . $this->title() . '</a>';
979
        //$story['subtitle'] = $this->subtitle();
980
981
        $story['hits'] = $this->counter();
982
        if ($filescount > 0) {
983
            $story['files_attached'] = true;
984
            $story['attached_link']  = "<a href='" . XOOPS_URL . '/modules/news/article.php?storyid=' . $this->storyid() . "' title='" . _NW_ATTACHEDLIB . "'><img src=" . $pathIcon16 . '/attach.png' . ' ' . 'title=' . _NW_ATTACHEDLIB . '></a>';
985
        } else {
986
            $story['files_attached'] = false;
987
            $story['attached_link']  = '';
988
        }
989
990
        return $story;
991
    }
992
993
    /**
994
     * Returns the user's name of the current story according to the module's option "displayname"
995
     * @param int $uid
996
     * @return string
997
     */
998
    public function uname(int $uid = 0): string
999
    {
1000
        global $xoopsConfig;
1001
        static $tblusers = [];
1002
        $option = -1;
0 ignored issues
show
Unused Code introduced by
The assignment to $option is dead and can be removed.
Loading history...
1003
        if (0 == $uid) {
1004
            $uid = $this->uid();
1005
        }
1006
1007
        if (\is_array($tblusers) && \array_key_exists($uid, $tblusers)) {
1008
            return $tblusers[$uid];
1009
        }
1010
1011
        /** @var Helper $helper */
1012
        $helper = Helper::getInstance();
1013
        $option = $helper->getConfig('displayname');
1014
        //        $option = Utility::getModuleOption('displayname');
1015
        if (!$option) {
1016
            $option = 1;
1017
        }
1018
1019
        switch ($option) {
1020
            case 1: // Username
1021
                $tblusers[$uid] = \XoopsUser::getUnameFromId($uid);
1022
1023
                return $tblusers[$uid];
1024
            case 2: // Display full name (if it is not empty)
1025
                /** @var \XoopsMemberHandler $memberHandler */
1026
                $memberHandler = xoops_getHandler('member');
1027
                $thisuser      = $memberHandler->getUser($uid);
1028
                if (\is_object($thisuser)) {
1029
                    $return = $thisuser->getVar('name');
1030
                    if ('' === $return) {
1031
                        $return = $thisuser->getVar('uname');
1032
                    }
1033
                } else {
1034
                    $return = $xoopsConfig['anonymous'];
1035
                }
1036
                $tblusers[$uid] = $return;
1037
                break;
1038
            case 3: // Nothing
1039
                $tblusers[$uid] = '';
1040
                break;
1041
            default:
1042
                $tblusers[$uid] = \XoopsUser::getUnameFromId($uid); // Default to username
1043
                break;
1044
        }
1045
1046
        return $tblusers[$uid] ?? ''; // Ensure we always return a string
1047
    }
1048
1049
1050
1051
    /**
1052
     * Function used to export news (in xml) and eventually the topics definitions
1053
     * Warning, permissions are not exported !
1054
     *
1055
     * @param int      $fromdate     Starting date
1056
     * @param int      $todate       Ending date
1057
     * @param string   $topicslist
1058
     * @param bool|int $usetopicsdef Should we also export topics definitions ?
1059
     * @param mixed    $tbltopics
1060
     * @param bool     $asobject     Return values as an object or not ?
1061
     *
1062
     * @param string   $order
1063
     *
1064
     * @return array
1065
     * @internal param string $topiclist If not empty, a list of topics to limit to
1066
     */
1067
    public function exportNews(
1068
        int    $fromdate,
1069
        int    $todate,
1070
        string $topicslist,
1071
               $usetopicsdef,
1072
               &$tbltopics,
1073
        bool   $asobject = true,
1074
        string $order = 'published'
1075
    ): array {
1076
        $ret = [];
1077
        $myts = \MyTextSanitizer::getInstance();
0 ignored issues
show
Unused Code introduced by
The assignment to $myts is dead and can be removed.
Loading history...
1078
        if ($usetopicsdef) { // We firt begin by exporting topics definitions
1079
            // Before all we must know wich topics to export
1080
            $sql = 'SELECT DISTINCT topicid FROM ' . $this->db->prefix('news_stories') . ' WHERE (published >=' . $fromdate . ' AND published <= ' . $todate . ')';
1081
            if ('' !== \trim($topicslist)) {
1082
                $sql .= ' AND topicid IN (' . $topicslist . ')';
1083
            }
1084
            $result = $this->db->query($sql);
1085
            if ($this->db->isResultSet($result)) {
1086
                while (false !== ($myrow = $this->db->fetchArray($result))) {
1087
                    $tbltopics[] = $myrow['topicid'];
1088
                }
1089
            }
1090
        }
1091
1092
        // Now we can search for the stories
1093
        $sql = 'SELECT s.*, t.* FROM ' . $this->table . ' s, ' . $this->db->prefix('news_topics') . ' t WHERE (s.topicid=t.topic_id) AND (s.published >=' . $fromdate . ' AND s.published <= ' . $todate . ')';
1094
        if ('' !== \trim($topicslist)) {
1095
            $sql .= ' AND topicid IN (' . $topicslist . ')';
1096
        }
1097
        $sql    .= " ORDER BY $order DESC";
1098
        $result = $this->db->query($sql);
1099
        if ($this->db->isResultSet($result)) {
1100
            while (false !== ($myrow = $this->db->fetchArray($result))) {
1101
                if ($asobject) {
1102
                    $ret[] = new self($myrow);
1103
                } else {
1104
                    $ret[$myrow['storyid']] = \htmlspecialchars($myrow['title'], \ENT_QUOTES | \ENT_HTML5);
1105
                }
1106
            }
1107
        }
1108
1109
        return $ret;
1110
    }
1111
1112
    /**
1113
     * Create or update an article
1114
     * @param bool $approved
1115
     * @return bool|int
1116
     */
1117
    public function store(bool $approved = false)
1118
    {
1119
        $myts        = \MyTextSanitizer::getInstance();
1120
        $counter     = $this->counter ?? 0;
1121
        $title       = $GLOBALS['xoopsDB']->escape($myts->executeExtension('censor', $this->title));
1122
        $subtitle    = $GLOBALS['xoopsDB']->escape($myts->executeExtension('censor', $this->subtitle));
1123
        $hostname    = $GLOBALS['xoopsDB']->escape($this->hostname);
1124
        $type        = $GLOBALS['xoopsDB']->escape($this->type);
1125
        $hometext    = $GLOBALS['xoopsDB']->escape($myts->executeExtension('censor', $this->hometext));
1126
        $bodytext    = $GLOBALS['xoopsDB']->escape($myts->executeExtension('censor', $this->bodytext));
1127
        $description = $GLOBALS['xoopsDB']->escape($myts->executeExtension('censor', $this->description));
1128
        $keywords    = $GLOBALS['xoopsDB']->escape($myts->executeExtension('censor', $this->keywords));
1129
        $picture     = $GLOBALS['xoopsDB']->escape($this->picture);
1130
        $pictureinfo = $GLOBALS['xoopsDB']->escape($myts->executeExtension('censor', $this->pictureinfo));
1131
        $votes       = (int)$this->votes;
1132
        $rating      = (float)$this->rating;
1133
        if (!isset($this->nohtml) || 1 != $this->nohtml) {
1134
            $this->nohtml = 0;
1135
        }
1136
        if (!isset($this->nosmiley) || 1 != $this->nosmiley) {
1137
            $this->nosmiley = 0;
1138
        }
1139
        if (!isset($this->notifypub) || 1 != $this->notifypub) {
1140
            $this->notifypub = 0;
1141
        }
1142
        if (!isset($this->topicdisplay) || 0 != $this->topicdisplay) {
1143
            $this->topicdisplay = 1;
1144
        }
1145
        $expired = !empty($this->expired) ? $this->expired : 0;
1146
        if (isset($this->storyid)) {
1147
            $sql        = \sprintf(
1148
                "UPDATE `%s` SET title='%s', published=%u, expired=%u, nohtml=%u, nosmiley=%u, hometext='%s', bodytext='%s', topicid=%u, ihome=%u, topicdisplay=%u, topicalign='%s', comments=%u, rating=%u, votes=%u, uid=%u, description='%s', keywords='%s', picture='%s' , pictureinfo='%s' , subtitle='%s' WHERE storyid = %u",
1149
                $this->table,
1150
                $title,
1151
                (int)$this->published(),
1152
                $expired,
1153
                $this->nohtml(),
1154
                $this->nosmiley(),
1155
                $hometext,
1156
                $bodytext,
1157
                (int)$this->topicid(),
1158
                $this->ihome(),
1159
                (int)$this->topicdisplay(),
1160
                $this->topicalign,
1161
                (int)$this->comments(),
1162
                $rating,
1163
                $votes,
1164
                (int)$this->uid(),
1165
                $description,
1166
                $keywords,
1167
                $picture,
1168
                $pictureinfo,
1169
                $subtitle,
1170
                (int)$this->storyid()
1171
            );
1172
            $newstoryid = (int)$this->storyid();
1173
        } else {
1174
            //$newpost = 1;
1175
            $newstoryid = $this->db->genId($this->table . '_storyid_seq');
1176
            $created    = \time();
1177
            $published  = $this->approved ? (int)$this->published : 0;
1178
            $sql        = \sprintf(
1179
                "INSERT INTO `%s` (storyid, uid, title, created, published, expired, hostname, nohtml, nosmiley, hometext, bodytext, counter, topicid, ihome, notifypub, story_type, topicdisplay, topicalign, comments, rating, votes, description, keywords, picture, pictureinfo, subtitle) VALUES (%u, %u, '%s', %u, %u, %u, '%s', %u, %u, '%s', '%s', %u, %u, %u, %u, '%s', %u, '%s', %u, %u, %u, '%s', '%s', '%s', '%s', '%s')",
1180
                $this->table,
1181
                $newstoryid,
1182
                (int)$this->uid(),
1183
                $title,
1184
                $created,
1185
                $published,
1186
                $expired,
1187
                $hostname,
1188
                $this->nohtml(),
1189
                $this->nosmiley(),
1190
                $hometext,
1191
                $bodytext,
1192
                $counter,
1193
                (int)$this->topicid(),
1194
                $this->ihome(),
1195
                $this->notifypub(),
1196
                $type,
1197
                (int)$this->topicdisplay(),
1198
                $this->topicalign,
1199
                (int)$this->comments(),
1200
                $rating,
1201
                $votes,
1202
                $description,
1203
                $keywords,
1204
                $picture,
1205
                $pictureinfo,
1206
                $subtitle
1207
            );
1208
        }
1209
        if (!$this->db->queryF($sql)) {
1210
            return false;
1211
        }
1212
        if (empty($newstoryid)) {
1213
            $newstoryid    = $this->db->getInsertId();
1214
            $this->storyid = $newstoryid;
1215
        }
1216
1217
        return $newstoryid;
1218
    }
1219
1220
    /**
1221
     * @return mixed
1222
     */
1223
    public function picture()
1224
    {
1225
        return $this->picture;
1226
    }
1227
1228
    /**
1229
     * @return mixed
1230
     */
1231
    public function pictureinfo()
1232
    {
1233
        return $this->pictureinfo;
1234
    }
1235
1236
    /**
1237
     * @return mixed
1238
     */
1239
    public function subtitle()
1240
    {
1241
        return $this->subtitle;
1242
    }
1243
1244
    /**
1245
     * @return mixed
1246
     */
1247
    public function rating()
1248
    {
1249
        return $this->rating;
1250
    }
1251
1252
    /**
1253
     * @return mixed
1254
     */
1255
    public function votes()
1256
    {
1257
        return $this->votes;
1258
    }
1259
1260
    /**
1261
     * @param $data
1262
     */
1263
    public function setPicture($data): void
1264
    {
1265
        $this->picture = $data;
1266
    }
1267
1268
    /**
1269
     * @param $data
1270
     */
1271
    public function setPictureinfo($data): void
1272
    {
1273
        $this->pictureinfo = $data;
1274
    }
1275
1276
    /**
1277
     * @param $data
1278
     */
1279
    public function setSubtitle($data): void
1280
    {
1281
        $this->subtitle = $data;
1282
    }
1283
1284
    /**
1285
     * @param $data
1286
     */
1287
    public function setDescription($data): void
1288
    {
1289
        $this->description = $data;
1290
    }
1291
1292
    /**
1293
     * @param $data
1294
     */
1295
    public function setKeywords($data): void
1296
    {
1297
        $this->keywords = $data;
1298
    }
1299
1300
    /**
1301
     * @param string $format
1302
     *
1303
     * @return string
1304
     */
1305
    public function description(string $format = 'S'): string
1306
    {
1307
        $myts = \MyTextSanitizer::getInstance();
0 ignored issues
show
Unused Code introduced by
The assignment to $myts is dead and can be removed.
Loading history...
1308
        switch (mb_strtoupper($format)) {
1309
            case 'S':
1310
                $description = \htmlspecialchars($this->description, \ENT_QUOTES | \ENT_HTML5);
1311
                break;
1312
            case 'P':
1313
            case 'F':
1314
                $description = \htmlspecialchars($this->description, \ENT_QUOTES | \ENT_HTML5);
1315
                break;
1316
            case 'E':
1317
                $description = \htmlspecialchars($this->description, \ENT_QUOTES | \ENT_HTML5);
1318
                break;
1319
        }
1320
1321
        return $description;
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $description does not seem to be defined for all execution paths leading up to this point.
Loading history...
1322
    }
1323
1324
    /**
1325
     * @param string $format
1326
     *
1327
     * @return string
1328
     */
1329
    public function keywords(string $format = 'S'): string
1330
    {
1331
        $myts = \MyTextSanitizer::getInstance();
0 ignored issues
show
Unused Code introduced by
The assignment to $myts is dead and can be removed.
Loading history...
1332
        switch (mb_strtoupper($format)) {
1333
            case 'S':
1334
                $keywords = \htmlspecialchars($this->keywords, \ENT_QUOTES | \ENT_HTML5);
1335
                break;
1336
            case 'P':
1337
            case 'F':
1338
                $keywords = \htmlspecialchars($this->keywords, \ENT_QUOTES | \ENT_HTML5);
1339
                break;
1340
            case 'E':
1341
                $keywords = \htmlspecialchars($this->keywords, \ENT_QUOTES | \ENT_HTML5);
1342
                break;
1343
        }
1344
1345
        return $keywords;
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $keywords does not seem to be defined for all execution paths leading up to this point.
Loading history...
1346
    }
1347
1348
    /**
1349
     * Returns a random number of news
1350
     * @param int       $limit
1351
     * @param int|null       $start
1352
     * @param int|null      $checkRight
1353
     * @param array|int $topic
1354
     * @param int|null       $ihome
1355
     * @param string|null    $order
1356
     * @param bool      $topic_frontpage
1357
     * @return array
1358
     */
1359
    public function getRandomNews(
1360
        int     $limit = 0,
1361
        ?int    $start = null,
1362
        ?int    $checkRight = 0,
1363
                $topic = 0,
1364
        ?int    $ihome = null,
1365
        ?string $order = null,
1366
        bool    $topic_frontpage = false
1367
    ): ?array {
1368
        $order      ??= 'published';
1369
        $checkRight ??= 0;
1370
        $ihome      ??= 0;
1371
        $start      ??= 0;
1372
        $ret        = [];
1373
        $rand_keys  = [];
0 ignored issues
show
Unused Code introduced by
The assignment to $rand_keys is dead and can be removed.
Loading history...
1374
        $ret3       = [];
1375
        $sql        = 'SELECT storyid FROM ' . $this->db->prefix('news_stories') . ' WHERE (published > 0 AND published <= ' . \time() . ') AND (expired = 0 OR expired > ' . \time() . ')';
1376
        if (0 != $topic) {
1377
            if (!\is_array($topic)) {
1378
                if ($checkRight) {
1379
                    $topics = Utility::getMyItemIds('news_view');
1380
                    if (!\in_array($topic, $topics, true)) {
1381
                        return null;
1382
                    }
1383
                    $sql .= ' AND topicid=' . (int)$topic . ' AND (ihome=1 OR ihome=0)';
1384
                } else {
1385
                    $sql .= ' AND topicid=' . (int)$topic . ' AND (ihome=1 OR ihome=0)';
1386
                }
1387
            } elseif (\count($topic) > 0) {
1388
                $sql .= ' AND topicid IN (' . \implode(',', $topic) . ')';
1389
            } else {
1390
                return null;
1391
            }
1392
        } else {
1393
            if ($checkRight) {
1394
                $topics = Utility::getMyItemIds('news_view');
1395
                if (\count($topics) > 0) {
1396
                    $topics = \implode(',', $topics);
1397
                    $sql    .= ' AND topicid IN (' . $topics . ')';
1398
                } else {
1399
                    return null;
1400
                }
1401
            }
1402
            if (0 == (int)$ihome) {
1403
                $sql .= ' AND ihome=0';
1404
            }
1405
        }
1406
        if ($topic_frontpage) {
1407
            $sql .= ' AND t.topic_frontpage=1';
1408
        }
1409
        $sql    .= " ORDER BY $order DESC";
1410
        $result = $this->db->query($sql);
1411
        if ($this->db->isResultSet($result)) {
1412
            while (false !== ($myrow = $this->db->fetchArray($result))) {
1413
                $ret[] = $myrow['storyid'];
1414
            }
1415
        }
1416
        $cnt = \count($ret);
1417
        if ($cnt) {
1418
            if ($limit > $cnt) {
1419
                $limit = $cnt;
1420
            }
1421
            $rand_keys = \array_rand($ret, $limit);
1422
            if ($limit > 1) {
1423
                for ($i = 0; $i < $limit; ++$i) {
1424
                    $onestory = $ret[$rand_keys[$i]];
1425
                    $ret3[]   = new self($onestory);
1426
                }
1427
            } else {
1428
                $ret3[] = new self($ret[$rand_keys]);
1429
            }
1430
        }
1431
1432
        return $ret3;
1433
    }
1434
1435
    /**
1436
     * Returns statistics about the stories and topics
1437
     * @param $limit
1438
     * @return array
1439
     */
1440
    public function getStats($limit): array
1441
    {
1442
        $ret = [];
1443
        $tbls = $this->db->prefix('news_stories');
1444
        $tblt = $this->db->prefix('news_topics');
1445
        $tblf = $this->db->prefix('news_stories_files');
1446
        // Number of stories per topic, including expired and non published stories
1447
        $ret2   = [];
1448
        $sql    = "SELECT count(s.storyid) as cpt, s.topicid, t.topic_title FROM $tbls s, $tblt t WHERE s.topicid=t.topic_id GROUP BY s.topicid ORDER BY t.topic_title";
1449
        $result = $this->db->query($sql);
1450
        if ($this->db->isResultSet($result)) {
1451
            while (false !== ($myrow = $this->db->fetchArray($result))) {
1452
                $ret2[$myrow['topicid']] = $myrow;
1453
            }
1454
        }
1455
        $ret['storiespertopic'] = $ret2;
1456
        unset($ret2);
1457
1458
        // Total of reads per topic
1459
        $ret2   = [];
1460
        $sql    = "SELECT Sum(counter) as cpt, topicid FROM $tbls GROUP BY topicid ORDER BY topicid";
1461
        $result = $this->db->query($sql);
1462
        if ($this->db->isResultSet($result)) {
1463
            while (false !== ($myrow = $this->db->fetchArray($result))) {
1464
                $ret2[$myrow['topicid']] = $myrow['cpt'];
1465
            }
1466
        }
1467
        $ret['readspertopic'] = $ret2;
1468
        unset($ret2);
1469
1470
        // Attached files per topic
1471
        $ret2   = [];
1472
        $sql    = "SELECT Count(*) as cpt, s.topicid FROM $tblf f, $tbls s WHERE f.storyid=s.storyid GROUP BY s.topicid ORDER BY s.topicid";
1473
        $result = $this->db->query($sql);
1474
        if ($this->db->isResultSet($result)) {
1475
            while (false !== ($myrow = $this->db->fetchArray($result))) {
1476
                $ret2[$myrow['topicid']] = $myrow['cpt'];
1477
            }
1478
        }
1479
        $ret['filespertopic'] = $ret2;
1480
        unset($ret2);
1481
1482
        // Expired articles per topic
1483
        $ret2   = [];
1484
        $sql    = "SELECT Count(storyid) as cpt, topicid FROM $tbls WHERE expired>0 AND expired<=" . \time() . ' GROUP BY topicid ORDER BY topicid';
1485
        $result = $this->db->query($sql);
1486
        if ($this->db->isResultSet($result)) {
1487
            while (false !== ($myrow = $this->db->fetchArray($result))) {
1488
                $ret2[$myrow['topicid']] = $myrow['cpt'];
1489
            }
1490
        }
1491
        $ret['expiredpertopic'] = $ret2;
1492
        unset($ret2);
1493
1494
        // Number of unique authors per topic
1495
        $ret2   = [];
1496
        $sql    = "SELECT Count(Distinct(uid)) as cpt, topicid FROM $tbls GROUP BY topicid ORDER BY topicid";
1497
        $result = $this->db->query($sql);
1498
        if ($this->db->isResultSet($result)) {
1499
            while (false !== ($myrow = $this->db->fetchArray($result))) {
1500
                $ret2[$myrow['topicid']] = $myrow['cpt'];
1501
            }
1502
        }
1503
        $ret['authorspertopic'] = $ret2;
1504
        unset($ret2);
1505
1506
        // Most readed articles
1507
        $ret2   = [];
1508
        $sql    = "SELECT s.storyid, s.uid, s.title, s.counter, s.topicid, t.topic_title  FROM $tbls s, $tblt t WHERE s.topicid=t.topic_id ORDER BY s.counter DESC";
1509
        $result = $this->db->query($sql, (int)$limit);
1510
        if ($this->db->isResultSet($result)) {
1511
            while (false !== ($myrow = $this->db->fetchArray($result))) {
1512
                $ret2[$myrow['storyid']] = $myrow;
1513
            }
1514
        }
1515
        $ret['mostreadednews'] = $ret2;
1516
        unset($ret2);
1517
1518
        // Less readed articles
1519
        $ret2   = [];
1520
        $sql    = "SELECT s.storyid, s.uid, s.title, s.counter, s.topicid, t.topic_title  FROM $tbls s, $tblt t WHERE s.topicid=t.topic_id ORDER BY s.counter";
1521
        $result = $this->db->query($sql, (int)$limit);
1522
        if ($this->db->isResultSet($result)) {
1523
            while (false !== ($myrow = $this->db->fetchArray($result))) {
1524
                $ret2[$myrow['storyid']] = $myrow;
1525
            }
1526
        }
1527
        $ret['lessreadednews'] = $ret2;
1528
        unset($ret2);
1529
1530
        // Best rated articles
1531
        $ret2   = [];
1532
        $sql    = "SELECT s.storyid, s.uid, s.title, s.rating, s.topicid, t.topic_title  FROM $tbls s, $tblt t WHERE s.topicid=t.topic_id ORDER BY s.rating DESC";
1533
        $result = $this->db->query($sql, (int)$limit);
1534
        if ($this->db->isResultSet($result)) {
1535
            while (false !== ($myrow = $this->db->fetchArray($result))) {
1536
                $ret2[$myrow['storyid']] = $myrow;
1537
            }
1538
        }
1539
        $ret['besratednews'] = $ret2;
1540
        unset($ret2);
1541
1542
        // Most readed authors
1543
        $ret2   = [];
1544
        $sql    = "SELECT Sum(counter) as cpt, uid FROM $tbls GROUP BY uid ORDER BY cpt DESC";
1545
        $result = $this->db->query($sql, (int)$limit);
1546
        if ($this->db->isResultSet($result)) {
1547
            while (false !== ($myrow = $this->db->fetchArray($result))) {
1548
                $ret2[$myrow['uid']] = $myrow['cpt'];
1549
            }
1550
        }
1551
        $ret['mostreadedauthors'] = $ret2;
1552
        unset($ret2);
1553
1554
        // Best rated authors
1555
        $ret2   = [];
1556
        $sql    = "SELECT Avg(rating) as cpt, uid FROM $tbls WHERE votes > 0 GROUP BY uid ORDER BY cpt DESC";
1557
        $result = $this->db->query($sql, (int)$limit);
1558
        if ($this->db->isResultSet($result)) {
1559
            while (false !== ($myrow = $this->db->fetchArray($result))) {
1560
                $ret2[$myrow['uid']] = $myrow['cpt'];
1561
            }
1562
        }
1563
        $ret['bestratedauthors'] = $ret2;
1564
        unset($ret2);
1565
1566
        // Biggest contributors
1567
        $ret2   = [];
1568
        $sql    = "SELECT Count(*) as cpt, uid FROM $tbls GROUP BY uid ORDER BY cpt DESC";
1569
        $result = $this->db->query($sql, (int)$limit);
1570
        if ($this->db->isResultSet($result)) {
1571
            while (false !== ($myrow = $this->db->fetchArray($result))) {
1572
                $ret2[$myrow['uid']] = $myrow['cpt'];
1573
            }
1574
        }
1575
        $ret['biggestcontributors'] = $ret2;
1576
        unset($ret2);
1577
1578
        return $ret;
1579
    }
1580
1581
    /**
1582
     * Get the date of the older and most recent news
1583
     * @param $older
1584
     * @param $recent
1585
     */
1586
    public function getOlderRecentNews(&$older, &$recent): void
1587
    {
1588
        $sql    = 'SELECT min(published) AS minpublish, max(published) AS maxpublish FROM ' . $this->db->prefix('news_stories');
1589
        $result = Utility::queryAndCheck($this->db, $sql);
1590
        if ($this->db->isResultSet($result)) {
1591
            [$older, $recent] = $this->db->fetchRow($result);
0 ignored issues
show
Comprehensibility Best Practice introduced by
This list assign is not used and could be removed.
Loading history...
1592
        } else {
1593
            $older = $recent = 0;
1594
        }
1595
    }
1596
1597
    /*
1598
     * Returns the author's IDs for the Who's who page
1599
     */
1600
1601
    /**
1602
     * @param int $checkRight
1603
     * @param int  $limit
1604
     * @param int  $start
1605
     *
1606
     * @return array|null
1607
     */
1608
    public function getWhosWho(int $checkRight = 0, int $limit = 0, int $start = 0): ?array
0 ignored issues
show
Unused Code introduced by
The parameter $start 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

1608
    public function getWhosWho(int $checkRight = 0, int $limit = 0, /** @scrutinizer ignore-unused */ int $start = 0): ?array

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...
Unused Code introduced by
The parameter $limit 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

1608
    public function getWhosWho(int $checkRight = 0, /** @scrutinizer ignore-unused */ int $limit = 0, int $start = 0): ?array

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...
1609
    {
1610
        $ret = [];
1611
        $sql = 'SELECT DISTINCT(uid) AS uid FROM ' . $this->db->prefix('news_stories') . ' WHERE (published > 0 AND published <= ' . \time() . ') AND (expired = 0 OR expired > ' . \time() . ')';
1612
        if ($checkRight) {
1613
            $topics = Utility::getMyItemIds('news_view');
1614
            if (\count($topics) > 0) {
1615
                $topics = \implode(',', $topics);
1616
                $sql    .= ' AND topicid IN (' . $topics . ')';
1617
            } else {
1618
                return null;
1619
            }
1620
        }
1621
        $sql    .= ' ORDER BY uid';
1622
        $result = $this->db->query($sql);
1623
        if ($this->db->isResultSet($result)) {
1624
            while (false !== ($myrow = $this->db->fetchArray($result))) {
1625
                $ret[] = $myrow['uid'];
1626
            }
1627
        }
1628
1629
        return $ret;
1630
    }
1631
1632
    /**
1633
     * Returns the content of the summary and the titles requires for the list selector
1634
     * @param $text
1635
     * @param $titles
1636
     * @return string
1637
     */
1638
    public function auto_summary($text, &$titles): string
1639
    {
1640
        $auto_summary = '';
1641
        if (Utility::getModuleOption('enhanced_pagenav')) {
1642
            $expr_matches = [];
1643
            $posdeb       = \preg_match_all('/(\[pagebreak:|\[pagebreak).*\]/iU', $text, $expr_matches);
0 ignored issues
show
Unused Code introduced by
The assignment to $posdeb is dead and can be removed.
Loading history...
1644
            if (\count($expr_matches) > 0) {
1645
                $delimiters  = $expr_matches[0];
1646
                $arr_search  = ['[pagebreak:', '[pagebreak', ']'];
1647
                $arr_replace = ['', '', ''];
1648
                $cpt         = 1;
1649
                if (isset($titles) && \is_array($titles)) {
1650
                    $titles[] = \strip_tags(\sprintf(\_NW_PAGE_AUTO_SUMMARY, 1, $this->title()));
1651
                }
1652
                $item         = "<a href='" . XOOPS_URL . '/modules/news/article.php?storyid=' . $this->storyid() . "&page=0'>" . \sprintf(\_NW_PAGE_AUTO_SUMMARY, 1, $this->title()) . '</a><br>';
1653
                $auto_summary .= $item;
1654
1655
                foreach ($delimiters as $item) {
1656
                    ++$cpt;
1657
                    $item = \str_replace($arr_search, $arr_replace, $item);
1658
                    if ('' == \xoops_trim($item)) {
1659
                        $item = $cpt;
1660
                    }
1661
                    $titles[]     = \strip_tags(\sprintf(\_NW_PAGE_AUTO_SUMMARY, $cpt, $item));
1662
                    $item         = "<a href='" . XOOPS_URL . '/modules/news/article.php?storyid=' . $this->storyid() . '&page=' . ($cpt - 1) . "'>" . \sprintf(\_NW_PAGE_AUTO_SUMMARY, $cpt, $item) . '</a><br>';
1663
                    $auto_summary .= $item;
1664
                }
1665
            }
1666
        }
1667
1668
        return $auto_summary;
1669
    }
1670
1671
    /**
1672
     * @param string $format
1673
     *
1674
     * @return array|string|string[]
1675
     */
1676
    public function hometext(string $format = 'Show'): string
1677
    {
1678
        $hometext = '';
1679
        $myts     = \MyTextSanitizer::getInstance();
1680
        $html     = $smiley = $xcodes = 1;
1681
        if ($this->nohtml()) {
1682
            $html = 0;
1683
        }
1684
        if ($this->nosmiley()) {
1685
            $smiley = 0;
1686
        }
1687
        switch ($format) {
1688
            case 'Show':
1689
                $hometext     = $myts->displayTarea($this->hometext, $html, $smiley, $xcodes);
1690
                $tmp          = '';
1691
                $auto_summary = $this->auto_summary($this->bodytext('Show'), $tmp);
1692
                $hometext     = \str_replace('[summary]', $auto_summary, $hometext);
1693
                break;
1694
            case 'Edit':
1695
                $hometext = \htmlspecialchars($this->hometext, \ENT_QUOTES | \ENT_HTML5);
1696
                break;
1697
            case 'Preview':
1698
                $hometext = $myts->previewTarea($this->hometext, $html, $smiley, $xcodes);
1699
                break;
1700
            case 'InForm':
1701
                $hometext = \htmlspecialchars($this->hometext, \ENT_QUOTES | \ENT_HTML5);
1702
                break;
1703
        }
1704
1705
        return $hometext;
1706
    }
1707
1708
    /**
1709
     * @param string $format
1710
     *
1711
     * @return string
1712
     */
1713
    public function bodytext(string $format = 'Show'): string
1714
    {
1715
        $myts   = \MyTextSanitizer::getInstance();
1716
        $html   = 1;
1717
        $smiley = 1;
1718
        $xcodes = 1;
1719
        if ($this->nohtml()) {
1720
            $html = 0;
1721
        }
1722
        if ($this->nosmiley()) {
1723
            $smiley = 0;
1724
        }
1725
        switch ($format) {
1726
            case 'Show':
1727
                $bodytext     = $myts->displayTarea($this->bodytext, $html, $smiley, $xcodes);
1728
                $tmp          = '';
1729
                $auto_summary = $this->auto_summary($bodytext, $tmp);
1730
                $bodytext     = \str_replace('[summary]', $auto_summary, $bodytext);
1731
                break;
1732
            case 'Edit':
1733
                $bodytext = \htmlspecialchars($this->bodytext, \ENT_QUOTES | \ENT_HTML5);
1734
                break;
1735
            case 'Preview':
1736
                $bodytext = $myts->previewTarea($this->bodytext, $html, $smiley, $xcodes);
1737
                break;
1738
            case 'InForm':
1739
                $bodytext = \htmlspecialchars($this->bodytext, \ENT_QUOTES | \ENT_HTML5);
1740
                break;
1741
        }
1742
1743
        return $bodytext;
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $bodytext does not seem to be defined for all execution paths leading up to this point.
Loading history...
1744
    }
1745
1746
    /**
1747
     * Returns stories by Ids
1748
     * @param array|string $ids
1749
     * @param int|null     $checkRight
1750
     * @param bool|null    $asobject
1751
     * @param string|null  $order
1752
     * @param bool         $onlyOnline
1753
     * @return array|null
1754
     */
1755
    public function getStoriesByIds(
1756
        $ids,
1757
        ?int $checkRight = null,
1758
        ?bool $asobject = null,
1759
        ?string $order = null,
1760
        bool $onlyOnline = true
1761
    ): ?array {
1762
        $order      ??= 'published';
1763
        $asobject   ??= true;
1764
        $checkRight ??= true;
1765
        $limit      = $start = 0;
1766
        $myts       = \MyTextSanitizer::getInstance();
0 ignored issues
show
Unused Code introduced by
The assignment to $myts is dead and can be removed.
Loading history...
1767
        $ret        = [];
1768
        $sql        = 'SELECT s.*, t.* FROM ' . $this->db->prefix('news_stories') . ' s, ' . $this->db->prefix('news_topics') . ' t WHERE ';
1769
        if ($ids && \is_array($ids)) {
1770
            \array_walk($ids, '\intval');
1771
        }
1772
        $sql .= ' s.storyid IN (' . \implode(',', $ids) . ') ';
1773
1774
        if ($onlyOnline) {
1775
            $sql .= ' AND (s.published > 0 AND s.published <= ' . \time() . ') AND (s.expired = 0 OR s.expired > ' . \time() . ') ';
1776
        }
1777
        $sql .= ' AND (s.topicid=t.topic_id) ';
1778
        if ($checkRight) {
1779
            $topics = Utility::getMyItemIds('news_view');
1780
            if (\count($topics) > 0) {
1781
                $topics = \implode(',', $topics);
1782
                $sql    .= ' AND s.topicid IN (' . $topics . ')';
1783
            } else {
1784
                return null;
1785
            }
1786
        }
1787
        $sql    .= " ORDER BY s.$order DESC";
1788
        $result = $this->db->query($sql, $limit, $start);
1789
        if ($this->db->isResultSet($result)) {
1790
            while (false !== ($myrow = $this->db->fetchArray($result))) {
1791
                if ($asobject) {
1792
                    $ret[$myrow['storyid']] = new self($myrow);
1793
                } else {
1794
                    $ret[$myrow['storyid']] = \htmlspecialchars($myrow['title'], \ENT_QUOTES | \ENT_HTML5);
1795
                }
1796
            }
1797
        }
1798
        return $ret;
1799
    }
1800
}
1801