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

NewsStory::getAllPublished()   C

Complexity

Conditions 14
Paths 100

Size

Total Lines 71
Code Lines 43

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 14
eloc 43
c 1
b 0
f 0
nc 100
nop 8
dl 0
loc 71
rs 6.2666

How to fix   Long Method    Complexity    Many Parameters   

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:

Many Parameters

Methods with many parameters are not only hard to understand, but their parameters also often become inconsistent when you need more, or different data.

There are several approaches to avoid long parameter lists:

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