Issues (384)

Security Analysis    not enabled

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

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

admin/index.php (30 issues)

1
<?php declare(strict_types=1);
2
//
3
// ------------------------------------------------------------------------ //
4
// XOOPS - PHP Content Management System                                    //
5
// Copyright (c) 2000-2020 XOOPS.org                                             //
6
// <https://xoops.org>                                                  //
7
// ------------------------------------------------------------------------ //
8
// This program is free software; you can redistribute it and/or modify     //
9
// it under the terms of the GNU General Public License as published by     //
10
// the Free Software Foundation; either version 2 of the License, or        //
11
// (at your option) any later version.                                      //
12
//                                                                          //
13
// You may not change or alter any portion of this comment or credits       //
14
// of supporting developers from this source code or any supporting         //
15
// source code which is considered copyrighted (c) material of the          //
16
// original comment or credit authors.                                      //
17
//                                                                          //
18
// This program is distributed in the hope that it will be useful,          //
19
// but WITHOUT ANY WARRANTY; without even the implied warranty of           //
20
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the            //
21
// GNU General Public License for more details.                             //
22
//                                                                          //
23
// You should have received a copy of the GNU General Public License        //
24
// along with this program; if not, write to the Free Software              //
25
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA //
26
// ------------------------------------------------------------------------ //
27
28
use Xmf\Module\Admin;
29
use Xmf\Request;
0 ignored issues
show
This use statement conflicts with another class in this namespace, Request. Consider defining an alias.

Let?s assume that you have a directory layout like this:

.
|-- OtherDir
|   |-- Bar.php
|   `-- Foo.php
`-- SomeDir
    `-- Foo.php

and let?s assume the following content of Bar.php:

// Bar.php
namespace OtherDir;

use SomeDir\Foo; // This now conflicts the class OtherDir\Foo

If both files OtherDir/Foo.php and SomeDir/Foo.php are loaded in the same runtime, you will see a PHP error such as the following:

PHP Fatal error:  Cannot use SomeDir\Foo as Foo because the name is already in use in OtherDir/Foo.php

However, as OtherDir/Foo.php does not necessarily have to be loaded and the error is only triggered if it is loaded before OtherDir/Bar.php, this problem might go unnoticed for a while. In order to prevent this error from surfacing, you must import the namespace with a different alias:

// Bar.php
namespace OtherDir;

use SomeDir\Foo as SomeDirFoo; // There is no conflict anymore.
Loading history...
30
use Xmf\Yaml;
31
use XoopsModules\News\{
32
    Blacklist,
33
    Common,
34
    Common\TestdataButtons,
35
    Files,
36
    Helper,
37
    NewsStory,
38
    NewsTopic,
39
    ObjectTree,
40
    PageNav,
41
    Registryfile,
42
    Utility
43
};
44
45
/** @var Admin $adminObject */
46
/** @var Helper $helper */
47
/** @var Utility $utility */
48
require_once __DIR__ . '/admin_header.php';
49
// require_once XOOPS_ROOT_PATH . '/modules/news/class/xoopstopic.php';
50
require_once XOOPS_ROOT_PATH . '/class/xoopslists.php';
51
require_once XOOPS_ROOT_PATH . '/modules/news/config.php';
52
//require_once XOOPS_ROOT_PATH . '/modules/news/class/class.newsstory.php';
53
//require_once XOOPS_ROOT_PATH . '/modules/news/class/class.newstopic.php';
54
//require_once XOOPS_ROOT_PATH . '/modules/news/class/class.sfiles.php';
55
//require_once XOOPS_ROOT_PATH . '/modules/news/class/blacklist.php';
56
//require_once XOOPS_ROOT_PATH . '/modules/news/class/registryfile.php';
57
require_once XOOPS_ROOT_PATH . '/class/uploader.php';
58
//require_once XOOPS_ROOT_PATH . '/class/pagenav.php';
59
require_once XOOPS_ROOT_PATH . '/modules/news/admin/functions.php';
60
61
$helper = Helper::getInstance();
62
63
// require_once XOOPS_ROOT_PATH . '/modules/news/class/tree.php';
64
$dateformat  = Utility::getModuleOption('dateformat');
65
$myts        = \MyTextSanitizer::getInstance();
66
$topicscount = 0;
67
68
$storiesTableName = $xoopsDB->prefix('news_stories');
69
if (!Utility::existField('picture', $storiesTableName)) {
70
    Utility::addField('`picture` VARCHAR( 50 ) NOT NULL', $storiesTableName);
71
}
72
73
/**
74
 * Show new submissions
75
 *
76
 * This list can be view in the module's admin when you click on the tab named "Post/Edit News"
77
 * Submissions are news that was submit by users but who are not approved, so you need to edit
78
 * them to approve them.
79
 * Actually you can see the the story's title, the topic, the posted date, the author and a
80
 * link to delete the story. If you click on the story's title, you will be able to edit the news.
81
 * The table contains the last x new submissions.
82
 * The system's block called "Waiting Contents" is listing the number of those news.
83
 */
84
function newSubmissions(): void
85
{
86
    global $dateformat, $pathIcon16;
87
    $start       = Request::getInt('startnew', 0, 'GET');
88
    $newsubcount = NewsStory::getAllStoriesCount(3, false);
89
    $storyarray  = NewsStory::getAllSubmitted(Utility::getModuleOption('storycountadmin'), true, Utility::getModuleOption('restrictindex'), $start);
0 ignored issues
show
It seems like XoopsModules\News\Utilit...tion('storycountadmin') can also be of type boolean; however, parameter $limit of XoopsModules\News\NewsStory::getAllSubmitted() does only seem to accept integer, 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

89
    $storyarray  = NewsStory::getAllSubmitted(/** @scrutinizer ignore-type */ Utility::getModuleOption('storycountadmin'), true, Utility::getModuleOption('restrictindex'), $start);
Loading history...
90
    if (count($storyarray) > 0) {
91
        $pagenav = new PageNav($newsubcount, Utility::getModuleOption('storycountadmin'), $start, 'startnew', 'op=newarticle');
0 ignored issues
show
It seems like XoopsModules\News\Utilit...tion('storycountadmin') can also be of type boolean; however, parameter $items_perpage of XoopsModules\News\PageNav::__construct() does only seem to accept integer, 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

91
        $pagenav = new PageNav($newsubcount, /** @scrutinizer ignore-type */ Utility::getModuleOption('storycountadmin'), $start, 'startnew', 'op=newarticle');
Loading history...
92
        news_collapsableBar('newsub', 'topnewsubicon');
93
        echo "<img onclick=\"toggle('toptable'); toggleIcon('toptableicon');\" id='topnewsubicon' name='topnewsubicon' src='" . $pathIcon16 . "/close12.gif' alt=''></a>&nbsp;" . _AM_NEWSUB . '</h4>';
94
        echo "<div id='newsub'>";
95
        echo '<br>';
96
        echo "<div class='center;'><table width='100%' cellspacing='1' cellpadding='3' border='0' class='outer'><tr class='bg3'><th align='center'>"
97
             . _AM_TITLE
98
             . "</th><th align='center'>"
99
             . _AM_TOPIC
100
             . "</th><th align='center'>"
101
             . _AM_POSTED
102
             . "</th><th align='center'>"
103
             . _AM_POSTER
104
             . "</th><th align='center'>"
105
             . _AM_NEWS_ACTION
106
             . "</th></tr>\n";
107
        $class = '';
108
        foreach ($storyarray as $newstory) {
109
            $class = ('even' === $class) ? 'odd' : 'even';
110
            echo "<tr class='" . $class . "'><td align='left'>\n";
111
            $title = $newstory->title();
112
            if (!isset($title) || ('' === $title)) {
113
                echo "<a href='" . XOOPS_URL . '/modules/news/admin/index.php?op=edit&amp;returnside=1&amp;storyid=' . $newstory->storyid() . "'>" . _MD_NEWS_NOSUBJECT . "</a>\n";
114
            } else {
115
                echo "&nbsp;<a href='" . XOOPS_URL . '/modules/news/submit.php?returnside=1&amp;op=edit&amp;storyid=' . $newstory->storyid() . "'>" . $title . "</a>\n";
116
            }
117
            echo '</td><td>'
118
                 . $newstory->topic_title()
119
                 . "</td><td align='center' class='nw'>"
120
                 . formatTimestamp($newstory->created(), $dateformat)
121
                 . "</td><td align='center'><a href='"
122
                 . XOOPS_URL
123
                 . '/userinfo.php?uid='
124
                 . $newstory->uid()
125
                 . "'>"
126
                 . $newstory->uname()
127
                 . "</a></td><td align='center'><a href='"
128
                 . XOOPS_URL
129
                 . '/modules/news/submit.php?returnside=1&amp;op=edit&amp;storyid='
130
                 . $newstory->storyid()
131
                 . "'><img src='"
132
                 . $pathIcon16
133
                 . "/edit.png' title='"
134
                 . _AM_EDIT
135
                 . "'></a><a href='"
136
                 . XOOPS_URL
137
                 . '/modules/news/admin/index.php?op=delete&amp;storyid='
138
                 . $newstory->storyid()
139
                 . "'><img src='"
140
                 . $pathIcon16
141
                 . "/delete.png' title='"
142
                 . _AM_DELETE
143
                 . "'></a></td></tr>\n";
144
        }
145
146
        echo '</table></div>';
147
        echo "<div align='right'>" . $pagenav->renderNav() . '</div><br>';
148
        echo '<br></div><br>';
149
    }
150
}
151
152
/**
153
 * Shows all automated stories
154
 *
155
 * Automated stories are stories that have a publication's date greater than "now"
156
 * This list can be view in the module's admin when you click on the tab named "Post/Edit News"
157
 * Actually you can see the story's ID, its title, the topic, the author, the
158
 * programmed date and time, the expiration's date  and two links. The first link is
159
 * used to edit the story while the second is used to remove the story.
160
 * The list only contains the last (x) automated news
161
 */
162
function autoStories(): void
163
{
164
    global $dateformat, $pathIcon16;
165
166
    $start        = Request::getInt('startauto', 0, 'GET');
167
    $storiescount = NewsStory::getAllStoriesCount(2, false);
168
    $storyarray   = NewsStory::getAllAutoStory(Utility::getModuleOption('storycountadmin'), true, $start);
0 ignored issues
show
It seems like XoopsModules\News\Utilit...tion('storycountadmin') can also be of type boolean; however, parameter $limit of XoopsModules\News\NewsStory::getAllAutoStory() does only seem to accept integer, 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

168
    $storyarray   = NewsStory::getAllAutoStory(/** @scrutinizer ignore-type */ Utility::getModuleOption('storycountadmin'), true, $start);
Loading history...
169
    $class        = '';
170
    if (count($storyarray) > 0) {
171
        $pagenav = new PageNav($storiescount, Utility::getModuleOption('storycountadmin'), $start, 'startauto', 'op=newarticle');
0 ignored issues
show
It seems like XoopsModules\News\Utilit...tion('storycountadmin') can also be of type boolean; however, parameter $items_perpage of XoopsModules\News\PageNav::__construct() does only seem to accept integer, 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

171
        $pagenav = new PageNav($storiescount, /** @scrutinizer ignore-type */ Utility::getModuleOption('storycountadmin'), $start, 'startauto', 'op=newarticle');
Loading history...
172
        news_collapsableBar('autostories', 'topautostories');
173
        echo "<img onclick=\"toggle('toptable'); toggleIcon('toptableicon');\" id='topautostories' name='topautostories' src='" . $pathIcon16 . "/close12.gif' alt=''></a>&nbsp;" . _AM_AUTOARTICLES . '</h4>';
174
        echo "<div id='autostories'>";
175
        echo '<br>';
176
        echo "<div class='center;'>\n";
177
        echo "<table width='100%' cellspacing='1' cellpadding='3' border='0' class='outer'><tr class='bg3'><th align='center'>"
178
             . _AM_STORYID
179
             . "</th><th align='center'>"
180
             . _AM_TITLE
181
             . "</th><th align='center'>"
182
             . _AM_TOPIC
183
             . "</th><th align='center'>"
184
             . _AM_POSTER
185
             . "</th><th align='center' class='nw'>"
186
             . _AM_PROGRAMMED
187
             . "</th><th align='center' class='nw'>"
188
             . _AM_EXPIRED
189
             . "</th><th align='center'>"
190
             . _AM_NEWS_ACTION
191
             . '</th></tr>';
192
        foreach ($storyarray as $autostory) {
193
            $topic  = $autostory->topic();
194
            $expire = ($autostory->expired() > 0) ? formatTimestamp($autostory->expired(), $dateformat) : '';
195
            $class  = ('even' === $class) ? 'odd' : 'even';
196
            echo "<tr class='" . $class . "'>";
197
            echo "<td align='center'><b>"
198
                 . $autostory->storyid()
199
                 . "</b>
200
                </td><td align='left'><a href='"
201
                 . XOOPS_URL
202
                 . '/modules/news/article.php?storyid='
203
                 . $autostory->storyid()
204
                 . "'>"
205
                 . $autostory->title()
206
                 . "</a>
207
                </td><td align='center'>"
208
                 . $topic->topic_title()
209
                 . "
210
                </td><td align='center'><a href='"
211
                 . XOOPS_URL
212
                 . '/userinfo.php?uid='
213
                 . $autostory->uid()
214
                 . "'>"
215
                 . $autostory->uname()
216
                 . "</a></td><td align='center' class='nw'>"
217
                 . formatTimestamp($autostory->published(), $dateformat)
218
                 . "</td><td align='center'>"
219
                 . $expire
220
                 . "</td><td align='center'><a href='"
221
                 . XOOPS_URL
222
                 . '/modules/news/submit.php?returnside=1&amp;op=edit&amp;storyid='
223
                 . $autostory->storyid()
224
                 . "'><img src='"
225
                 . $pathIcon16
226
                 . "/edit.png' title="
227
                 . _AM_EDIT
228
                 . "> </a> <a href='"
229
                 . XOOPS_URL
230
                 . '/modules/news/admin/index.php?op=delete&amp;storyid='
231
                 . $autostory->storyid()
232
                 . "'><img src='"
233
                 . $pathIcon16
234
                 . "/delete.png' title='"
235
                 . _AM_DELETE
236
                 . "'></a>";
237
238
            echo "</td></tr>\n";
239
        }
240
        echo '</table></div>';
241
        echo "<div align='right'>" . $pagenav->renderNav() . '</div><br>';
242
        echo '</div><br>';
243
    }
244
}
245
246
/**
247
 * Shows last x published stories
248
 *
249
 * This list can be view in the module's admin when you click on the tab named "Post/Edit News"
250
 * Actually you can see the the story's ID, its title, the topic, the author, the number of hits
251
 * and two links. The first link is used to edit the story while the second is used to remove the story.
252
 * The table only contains the last X published stories.
253
 * You can modify the number of visible stories with the module's option named
254
 * "Number of new articles to display in admin area".
255
 * As the number of displayed stories is limited, below this list you can find a text box
256
 * that you can use to enter a story's Id, then with the scrolling list you can select
257
 * if you want to edit or delete the story.
258
 */
259
function lastStories(): void
260
{
261
    global $dateformat, $pathIcon16;
262
    news_collapsableBar('laststories', 'toplaststories');
263
    echo "<img onclick=\"toggle('toptable'); toggleIcon('toptableicon');\" id='toplaststories' name='toplaststories' src='" . $pathIcon16 . "/close12.gif' alt=''></a>&nbsp;" . sprintf(_AM_LAST10ARTS, Utility::getModuleOption('storycountadmin')) . '</h4>';
264
    echo "<div id='laststories'>";
265
    echo '<br>';
266
    echo "<div class='center;'>";
267
    $start        = Request::getInt('start', 0, 'GET');
268
    $storyarray   = NewsStory::getAllPublished(Utility::getModuleOption('storycountadmin'), $start, false, 0, 1);
0 ignored issues
show
It seems like XoopsModules\News\Utilit...tion('storycountadmin') can also be of type boolean; however, parameter $limit of XoopsModules\News\NewsStory::getAllPublished() does only seem to accept integer, 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

268
    $storyarray   = NewsStory::getAllPublished(/** @scrutinizer ignore-type */ Utility::getModuleOption('storycountadmin'), $start, false, 0, 1);
Loading history...
269
    $storiescount = NewsStory::getAllStoriesCount(4, false);
270
    $pagenav      = new PageNav($storiescount, Utility::getModuleOption('storycountadmin'), $start, 'start', 'op=newarticle');
0 ignored issues
show
It seems like XoopsModules\News\Utilit...tion('storycountadmin') can also be of type boolean; however, parameter $items_perpage of XoopsModules\News\PageNav::__construct() does only seem to accept integer, 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

270
    $pagenav      = new PageNav($storiescount, /** @scrutinizer ignore-type */ Utility::getModuleOption('storycountadmin'), $start, 'start', 'op=newarticle');
Loading history...
271
    $class        = '';
272
    echo "<table width='100%' cellspacing='1' cellpadding='3' border='0' class='outer'><tr class='bg3'><th align='center'>"
273
         . _AM_STORYID
274
         . "</th><th align='center'>"
275
         . _AM_TITLE
276
         . "</th><th align='center'>"
277
         . _AM_TOPIC
278
         . "</th><th align='center'>"
279
         . _AM_POSTER
280
         . "</th><th align='center' class='nw'>"
281
         . _AM_PUBLISHED
282
         . "</th><th align='center' class='nw'>"
283
         . _AM_HITS
284
         . "</th><th align='center'>"
285
         . _AM_NEWS_ACTION
286
         . '</th></tr>';
287
    foreach ($storyarray as $eachstory) {
288
        $published = formatTimestamp($eachstory->published(), $dateformat);
289
        // $expired = ( $eachstory -> expired() > 0 ) ? formatTimestamp($eachstory->expired(),$dateformat) : '---';
290
        $topic = $eachstory->topic();
291
        $class = ('even' === $class) ? 'odd' : 'even';
292
        echo "<tr class='" . $class . "'>";
293
        echo "<td align='center'><b>" . $eachstory->storyid() . "</b>
294
            </td><td align='left'><a href='" . XOOPS_URL . '/modules/news/article.php?storyid=' . $eachstory->storyid() . "'>" . $eachstory->title() . "</a>
295
            </td><td align='center'>" . $topic->topic_title() . "
296
            </td><td align='center'><a href='" . XOOPS_URL . '/userinfo.php?uid=' . $eachstory->uid() . "'>" . $eachstory->uname() . "</a></td><td align='center' class='nw'>" . $published . "</td><td align='center'>" . $eachstory->counter() . "</td><td align='center'>
297
            <a href='" . XOOPS_URL . '/modules/news/submit.php?returnside=1&amp;op=edit&amp;storyid=' . $eachstory->storyid() . "'> <img src='" . $pathIcon16 . "/edit.png' title=" . _AM_EDIT . "> </a>
298
            <a href='" . XOOPS_URL . '/modules/news/admin/index.php?op=delete&amp;storyid=' . $eachstory->storyid() . "'><img src='" . $pathIcon16 . "/delete.png' title='" . _AM_DELETE . "'></a>";
299
300
        echo "</td></tr>\n";
301
    }
302
    echo '</table><br>';
303
    echo "<div align='right'>" . $pagenav->renderNav() . '</div><br>';
304
305
    echo "<form action='index.php' method='get'>" . _AM_STORYID . " <input type='text' name='storyid' size='10'>
306
        <select name='op'>
307
            <option value='edit' selected>" . _AM_EDIT . "</option>
308
            <option value='delete'>" . _AM_DELETE . "</option>
309
        </select>
310
        <input type='hidden' name='returnside' value='1'>
311
        <input type='submit' value='" . _AM_GO . "'>
312
        </form>
313
    </div>";
314
    echo '</div><br>';
315
}
316
317
/**
318
 * Display a list of the expired stories
319
 *
320
 * This list can be view in the module's admin when you click on the tab named "Post/Edit News"
321
 * Actually you can see the story's ID, the title, the topic, the author,
322
 * the creation and expiration's date and you have two links, one to delete
323
 * the story and the other to edit the story.
324
 * The table only contains the last X expired stories.
325
 * You can modify the number of visible stories with the module's option named
326
 * "Number of new articles to display in admin area".
327
 * As the number of displayed stories is limited, below this list you can find a text box
328
 * that you can use to enter a story's Id, then with the scrolling list you can select
329
 * if you want to edit or delete the story.
330
 */
331
function expStories(): void
332
{
333
    global $dateformat, $pathIcon16;
334
    $start        = Request::getInt('startexp', 0, 'GET');
335
    $expiredcount = NewsStory::getAllStoriesCount(1, false);
336
    $storyarray   = NewsStory::getAllExpired(Utility::getModuleOption('storycountadmin'), $start, 0, 1);
0 ignored issues
show
It seems like XoopsModules\News\Utilit...tion('storycountadmin') can also be of type boolean; however, parameter $limit of XoopsModules\News\NewsStory::getAllExpired() does only seem to accept integer, 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

336
    $storyarray   = NewsStory::getAllExpired(/** @scrutinizer ignore-type */ Utility::getModuleOption('storycountadmin'), $start, 0, 1);
Loading history...
337
    $pagenav      = new PageNav($expiredcount, Utility::getModuleOption('storycountadmin'), $start, 'startexp', 'op=newarticle');
0 ignored issues
show
It seems like XoopsModules\News\Utilit...tion('storycountadmin') can also be of type boolean; however, parameter $items_perpage of XoopsModules\News\PageNav::__construct() does only seem to accept integer, 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

337
    $pagenav      = new PageNav($expiredcount, /** @scrutinizer ignore-type */ Utility::getModuleOption('storycountadmin'), $start, 'startexp', 'op=newarticle');
Loading history...
338
339
    if (count($storyarray) > 0) {
340
        $class = '';
341
        news_collapsableBar('expstories', 'topexpstories');
342
        echo "<img onclick=\"toggle('toptable'); toggleIcon('toptableicon');\" id='topexpstories' name='topexpstories' src='" . $pathIcon16 . "/close12.gif' alt=''></a>&nbsp;" . _AM_EXPARTS . '</h4>';
343
        echo "<div id='expstories'>";
344
        echo '<br>';
345
        echo "<div class='center;'>";
346
        echo "<table width='100%' cellspacing='1' cellpadding='3' border='0' class='outer'><tr class='bg3'><th align='center'>"
347
             . _AM_STORYID
348
             . "</th><th align='center'>"
349
             . _AM_TITLE
350
             . "</th><th align='center'>"
351
             . _AM_TOPIC
352
             . "</th><th align='center'>"
353
             . _AM_POSTER
354
             . "</th><th align='center' class='nw'>"
355
             . _AM_CREATED
356
             . "</th><th align='center' class='nw'>"
357
             . _AM_EXPIRED
358
             . "</th><th align='center'>"
359
             . _AM_NEWS_ACTION
360
             . '</th></tr>';
361
        foreach ($storyarray as $eachstory) {
362
            $created = formatTimestamp($eachstory->created(), $dateformat);
363
            $expired = formatTimestamp($eachstory->expired(), $dateformat);
364
            $topic   = $eachstory->topic();
365
            // added exired value field to table
366
            $class = ('even' === $class) ? 'odd' : 'even';
367
            echo "<tr class='" . $class . "'>";
368
            echo "<td align='center'><b>" . $eachstory->storyid() . "</b>
369
                </td><td align='left'><a href='" . XOOPS_URL . '/modules/news/article.php?returnside=1&amp;storyid=' . $eachstory->storyid() . "'>" . $eachstory->title() . "</a>
370
                </td><td align='center'>" . $topic->topic_title() . "
371
                </td><td align='center'><a href='" . XOOPS_URL . '/userinfo.php?uid=' . $eachstory->uid() . "'>" . $eachstory->uname() . "</a></td><td align='center' class='nw'>" . $created . "</td><td align='center' class='nw'>" . $expired . "</td><td align='center'>
372
                <a href='" . XOOPS_URL . '/modules/news/submit.php?returnside=1&amp;op=edit&amp;storyid=' . $eachstory->storyid() . "'> <img src='" . $pathIcon16 . "/edit.png' title=" . _AM_EDIT . "></a>
373
                <a href='" . XOOPS_URL . '/modules/news/admin/index.php?op=delete&amp;storyid=' . $eachstory->storyid() . "'><img src='" . $pathIcon16 . "/delete.png' title='" . _AM_DELETE . "'></a>";
374
375
            echo "</td></tr>\n";
376
        }
377
        echo '</table><br>';
378
        echo "<div align='right'>" . $pagenav->renderNav() . '</div><br>';
379
        echo "<form action='index.php' method='get'>
380
            " . _AM_STORYID . " <input type='text' name='storyid' size='10'>
381
            <select name='op'>
382
                <option value='edit' selected>" . _AM_EDIT . "</option>
383
                <option value='delete'>" . _AM_DELETE . "</option>
384
            </select>
385
            <input type='hidden' name='returnside' value='1'>
386
            <input type='submit' value='" . _AM_GO . "'>
387
            </form>
388
        </div>";
389
        echo '</div><br>';
390
    }
391
}
392
393
/**
394
 * Delete (purge/prune) old stories
395
 *
396
 * You can use this function in the module's admin when you click on the tab named "Prune News"
397
 * It's useful to remove old stories. It is, of course, recommended
398
 * to backup (or export) your news before to purge news.
399
 * You must first specify a date. This date will be used as a reference, everything
400
 * that was published before this date will be deleted.
401
 * The option "Only remove stories who have expired" will enable you to only remove
402
 * expired stories published before the given date.
403
 * Finally, you can select the topics inside wich you will remove news.
404
 * Once you have set all the parameters, the script will first show you a confirmation's
405
 * message with the number of news that will be removed.
406
 * Note, the topics are not deleted (even if there are no more news inside them).
407
 */
408
function setPruneManager(): void
409
{
410
    require_once XOOPS_ROOT_PATH . '/class/xoopsformloader.php';
411
    xoops_cp_header();
412
    $adminObject = Admin::getInstance();
413
    $adminObject->displayNavigation('index.php?op=prune');
414
    echo '<br><br><br>';
415
    $sform = new \XoopsThemeForm(_AM_NEWS_PRUNENEWS, 'pruneform', XOOPS_URL . '/modules/news/admin/index.php', 'post', true);
416
    $sform->addElement(new \XoopsFormTextDateSelect(_AM_NEWS_PRUNE_BEFORE, 'prune_date', 15, time()), true);
417
    $onlyexpired = new \XoopsFormCheckBox('', 'onlyexpired');
418
    $onlyexpired->addOption(1, _AM_NEWS_PRUNE_EXPIREDONLY);
419
    $sform->addElement($onlyexpired, false);
420
    $sform->addElement(new \XoopsFormHidden('op', 'confirmbeforetoprune'), false);
421
    $topiclist  = new \XoopsFormSelect(_AM_NEWS_PRUNE_TOPICS, 'pruned_topics', '', 5, true);
422
    $topics_arr = [];
0 ignored issues
show
The assignment to $topics_arr is dead and can be removed.
Loading history...
423
    $xt         = new NewsTopic();
424
    $allTopics  = $xt->getAllTopics(false); // The webmaster can see everything
425
    $topic_tree = new ObjectTree($allTopics, 'topic_id', 'topic_pid');
426
    $topics_arr = $topic_tree->getAllChild(0);
427
    if (count($topics_arr)) {
428
        foreach ($topics_arr as $onetopic) {
429
            $topiclist->addOption($onetopic->topic_id(), $onetopic->topic_title());
430
        }
431
    }
432
    $topiclist->setDescription(_AM_NEWS_EXPORT_PRUNE_DSC);
433
    $sform->addElement($topiclist, false);
434
    $buttonTray = new \XoopsFormElementTray('', '');
435
    $submit_btn = new \XoopsFormButton('', 'post', _SUBMIT, 'submit');
436
    $buttonTray->addElement($submit_btn);
437
    $sform->addElement($buttonTray);
438
    $sform->display();
439
}
440
441
// A confirmation is asked before to prune stories
442
function confirmBeforePrune(): void
443
{
444
    global $dateformat;
445
    $story = new NewsStory();
446
    xoops_cp_header();
447
    $topiclist = '';
448
    if (Request::hasVar('pruned_topics', 'POST')) {
449
        $topiclist = implode(',', $_POST['pruned_topics']);
450
    }
451
    echo '<h4>' . _AM_NEWS_PRUNENEWS . '</h4>';
452
    $expired = 0;
453
    if (Request::hasVar('onlyexpired', 'POST')) {
454
        $expired = Request::getInt('onlyexpired', 0, 'POST');
455
    }
456
    $date      = $_POST['prune_date'];
457
    $timestamp = mktime(0, 0, 0, (int)mb_substr($date, 5, 2), (int)mb_substr($date, 8, 2), (int)mb_substr($date, 0, 4));
458
    $count     = $story->getCountStoriesPublishedBefore($timestamp, $expired, $topiclist);
459
    if ($count) {
460
        $displaydate = formatTimestamp($timestamp, $dateformat);
461
        $msg         = sprintf(_AM_NEWS_PRUNE_CONFIRM, $displaydate, $count);
462
        xoops_confirm(
463
            [
464
                'op'            => 'prunenews',
465
                'expired'       => $expired,
466
                'pruned_topics' => $topiclist,
467
                'prune_date'    => $timestamp,
468
                'ok'            => 1,
469
            ],
470
            'index.php',
471
            $msg
472
        );
473
    } else {
474
        printf(_AM_NEWS_NOTHING_PRUNE);
475
    }
476
    unset($story);
477
}
478
479
// Effectively delete stories (published before a date), no more confirmation
480
function pruneNews(): void
481
{
482
    $story     = new NewsStory();
0 ignored issues
show
The assignment to $story is dead and can be removed.
Loading history...
483
    $timestamp = Request::getInt('prune_date', 0, 'POST');
484
    $expired   = Request::getInt('expired', 0, 'POST');
485
    $topiclist = '';
486
    if (Request::hasVar('pruned_topics', 'POST')) {
487
        $topiclist = $_POST['pruned_topics'];
488
    }
489
490
    if (1 == Request::getInt('ok', 0, 'POST')) {
491
        $story = new NewsStory();
492
        xoops_cp_header();
493
        $count = $story->getCountStoriesPublishedBefore($timestamp, $expired, $topiclist);
494
        $msg   = sprintf(_AM_NEWS_PRUNE_DELETED, $count);
495
        $story->deleteBeforeDate($timestamp, $expired, $topiclist);
496
        unset($story);
497
        Utility::updateCache();
498
        redirect_header('index.php', 3, $msg);
499
    }
500
}
501
502
/**
503
 * Newsletter's configuration
504
 *
505
 * You can create a newsletter's content from the admin part of the News module when you click on the tab named "Newsletter"
506
 * First, let be clear, this module'functionality will not send the newsletter but it will prepare its content for you.
507
 * To send the newsletter, you can use many specialized modules like evennews.
508
 * You first select a range of dates and if you want, a selection of topics to use for the search.
509
 * Once it's done, the script will use the file named /xoops/modules/language/yourlanguage/newsletter.php to create
510
 * the newsletter's content. When it's finished, the script generates a file in the upload folder.
511
 */
512
function createNewsletter(): void
513
{
514
    require_once XOOPS_ROOT_PATH . '/class/xoopsformloader.php';
515
    xoops_cp_header();
516
    $adminObject = Admin::getInstance();
517
    $adminObject->displayNavigation('index.php?op=configurenewsletter');
518
    echo '<br><br><br>';
519
    $sform      = new \XoopsThemeForm(_AM_NEWS_NEWSLETTER, 'newsletterform', XOOPS_URL . '/modules/news/admin/index.php', 'post', true);
520
    $dates_tray = new \XoopsFormElementTray(_AM_NEWS_NEWSLETTER_BETWEEN);
521
    $date1      = new \XoopsFormTextDateSelect('', 'date1', 15, time());
522
    $date2      = new \XoopsFormTextDateSelect(_AM_NEWS_EXPORT_AND, 'date2', 15, time());
523
    $dates_tray->addElement($date1);
524
    $dates_tray->addElement($date2);
525
    $sform->addElement($dates_tray);
526
527
    $topiclist  = new \XoopsFormSelect(_AM_NEWS_PRUNE_TOPICS, 'export_topics', '', 5, true);
528
    $topics_arr = [];
0 ignored issues
show
The assignment to $topics_arr is dead and can be removed.
Loading history...
529
    $xt         = new NewsTopic();
530
    $allTopics  = $xt->getAllTopics(false); // The webmaster can see everything
531
    $topic_tree = new ObjectTree($allTopics, 'topic_id', 'topic_pid');
532
    $topics_arr = $topic_tree->getAllChild(0);
533
    if (count($topics_arr)) {
534
        foreach ($topics_arr as $onetopic) {
535
            $topiclist->addOption($onetopic->topic_id(), $onetopic->topic_title());
536
        }
537
    }
538
    $topiclist->setDescription(_AM_NEWS_EXPORT_PRUNE_DSC);
539
    $sform->addElement($topiclist, false);
540
    $sform->addElement(new \XoopsFormHidden('op', 'launchnewsletter'), false);
541
    $sform->addElement(new \XoopsFormRadioYN(_AM_NEWS_REMOVE_BR, 'removebr', 1), false);
542
    $sform->addElement(new \XoopsFormRadioYN(_AM_NEWS_NEWSLETTER_HTML_TAGS, 'removehtml', 0), false);
543
    $sform->addElement(new \XoopsFormTextArea(_AM_NEWS_NEWSLETTER_HEADER, 'header', '', 4, 70), false);
544
    $sform->addElement(new \XoopsFormTextArea(_AM_NEWS_NEWSLETTER_FOOTER, 'footer', '', 4, 70), false);
545
    $buttonTray = new \XoopsFormElementTray('', '');
546
    $submit_btn = new \XoopsFormButton('', 'post', _SUBMIT, 'submit');
547
    $buttonTray->addElement($submit_btn);
548
    $sform->addElement($buttonTray);
549
    $sform->display();
550
}
551
552
/**
553
 * Launch the creation of the newsletter's content
554
 */
555
function launchNewsletter(): void
556
{
557
    global $xoopsConfig, $dateformat;
558
    xoops_cp_header();
559
    $adminObject = Admin::getInstance();
560
    $adminObject->displayNavigation('index.php?op=configurenewsletter');
561
    $newslettertemplate = '';
562
    $helper             = Helper::getInstance();
563
    $helper->loadLanguage('newsletter');
564
    echo '<br>';
565
    $story           = new NewsStory();
566
    $exportedstories = [];
0 ignored issues
show
The assignment to $exportedstories is dead and can be removed.
Loading history...
567
    $topiclist       = '';
568
    $removebr        = Request::getInt('removebr', 0, 'POST');
569
    $removehtml      = Request::getInt('removehtml', 0, 'POST');
570
    $header          = Request::getString('header', '', 'POST');
571
    $footer          = Request::getString('footer', '', 'POST');
572
    $date1           = $_POST['date1'];
573
    $date2           = $_POST['date2'];
574
    $timestamp1      = mktime(0, 0, 0, (int)mb_substr($date1, 5, 2), (int)mb_substr($date1, 8, 2), (int)mb_substr($date1, 0, 4));
575
    $timestamp2      = mktime(23, 59, 59, (int)mb_substr($date2, 5, 2), (int)mb_substr($date2, 8, 2), (int)mb_substr($date2, 0, 4));
576
    if (Request::hasVar('export_topics', 'POST')) {
577
        $topiclist = implode(',', $_POST['export_topics']);
578
    }
579
    $tbltopics       = [];
580
    $exportedstories = $story->exportNews($timestamp1, $timestamp2, $topiclist, 0, $tbltopics);
581
    $newsfile        = XOOPS_ROOT_PATH . '/uploads/news/letter.txt';
582
    if (count($exportedstories)) {
583
        $fp = fopen($newsfile, 'wb');
584
        if (!$fp) {
0 ignored issues
show
$fp is of type resource, thus it always evaluated to false.
Loading history...
585
            redirect_header('index.php', 4, sprintf(_AM_NEWS_EXPORT_ERROR, $newsfile));
586
        }
587
        if ('' !== xoops_trim($header)) {
588
            fwrite($fp, $header);
589
        }
590
        foreach ($exportedstories as $onestory) {
591
            $content         = $newslettertemplate;
592
            $search_pattern  = [
593
                '%title%',
594
                '%uname%',
595
                '%created%',
596
                '%published%',
597
                '%expired%',
598
                '%hometext%',
599
                '%bodytext%',
600
                '%description%',
601
                '%keywords%',
602
                '%reads%',
603
                '%topicid%',
604
                '%topic_title%',
605
                '%comments%',
606
                '%rating%',
607
                '%votes%',
608
                '%publisher%',
609
                '%publisher_id%',
610
                '%link%',
611
            ];
612
            $replace_pattern = [
613
                $onestory->title(),
614
                $onestory->uname(),
615
                formatTimestamp($onestory->created(), $dateformat),
616
                formatTimestamp($onestory->published(), $dateformat),
617
                formatTimestamp($onestory->expired(), $dateformat),
618
                $onestory->hometext(),
619
                $onestory->bodytext(),
620
                $onestory->description(),
621
                $onestory->keywords(),
622
                $onestory->counter(),
623
                $onestory->topicid(),
624
                $onestory->topic_title(),
625
                $onestory->comments(),
626
                $onestory->rating(),
627
                $onestory->votes(),
628
                $onestory->uname(),
629
                $onestory->uid(),
630
                XOOPS_URL . '/modules/news/article.php?storyid=' . $onestory->storyid(),
631
            ];
632
            $content         = str_replace($search_pattern, $replace_pattern, $content);
633
            if ($removebr) {
634
                $content = str_replace('<br>', "\r\n", $content);
635
            }
636
            if ($removehtml) {
637
                $content = strip_tags($content);
638
            }
639
            fwrite($fp, $content);
640
        }
641
        if ('' !== xoops_trim($footer)) {
642
            fwrite($fp, $footer);
643
        }
644
        fclose($fp);
645
        $newsfile = XOOPS_URL . '/uploads/news/newsletter.txt';
646
        printf(_AM_NEWS_NEWSLETTER_READY, $newsfile, XOOPS_URL . '/modules/news/admin/index.php?op=deletefile&amp;type=newsletter');
647
    } else {
648
        printf(_AM_NEWS_NOTHING);
649
    }
650
}
651
652
/**
653
 * News export
654
 *
655
 * You can use this function in the module's admin when you click on the tab named "News Export"
656
 * First select a range of date, possibly a range of topics and if you want, check the option "Include Topics Definitions"
657
 * to also export the topics.
658
 * News, and topics, will be exported to the XML format.
659
 */
660
function exportNews(): void
661
{
662
    require_once XOOPS_ROOT_PATH . '/class/xoopsformloader.php';
663
    xoops_cp_header();
664
    $adminObject = Admin::getInstance();
665
    $adminObject->displayNavigation('index.php?op=export');
666
    echo '<br><br><br>';
667
    $sform      = new \XoopsThemeForm(_AM_NEWS_EXPORT_NEWS, 'exportform', XOOPS_URL . '/modules/news/admin/index.php', 'post', true);
668
    $dates_tray = new \XoopsFormElementTray(_AM_NEWS_EXPORT_BETWEEN);
669
    $date1      = new \XoopsFormTextDateSelect('', 'date1', 15, time());
670
    $date2      = new \XoopsFormTextDateSelect(_AM_NEWS_EXPORT_AND, 'date2', 15, time());
671
    $dates_tray->addElement($date1);
672
    $dates_tray->addElement($date2);
673
    $sform->addElement($dates_tray);
674
675
    $topiclist  = new \XoopsFormSelect(_AM_NEWS_PRUNE_TOPICS, 'export_topics', '', 5, true);
676
    $topics_arr = [];
0 ignored issues
show
The assignment to $topics_arr is dead and can be removed.
Loading history...
677
    $xt         = new NewsTopic();
678
    $allTopics  = $xt->getAllTopics(false); // The webmaster can see everything
679
    $topic_tree = new ObjectTree($allTopics, 'topic_id', 'topic_pid');
680
    $topics_arr = $topic_tree->getAllChild(0);
681
    if (count($topics_arr)) {
682
        foreach ($topics_arr as $onetopic) {
683
            $topiclist->addOption($onetopic->topic_id(), $onetopic->topic_title());
684
        }
685
    }
686
    $topiclist->setDescription(_AM_NEWS_EXPORT_PRUNE_DSC);
687
    $sform->addElement($topiclist, false);
688
    $sform->addElement(new \XoopsFormRadioYN(_AM_NEWS_EXPORT_INCTOPICS, 'includetopics', 0), false);
689
    $sform->addElement(new \XoopsFormHidden('op', 'launchexport'), false);
690
    $buttonTray = new \XoopsFormElementTray('', '');
691
    $submit_btn = new \XoopsFormButton('', 'post', _SUBMIT, 'submit');
692
    $buttonTray->addElement($submit_btn);
693
    $sform->addElement($buttonTray);
694
    $sform->display();
695
}
696
697
/**
698
 * @param $text
699
 *
700
 * @return string
701
 */
702
function news_utf8_encode($text)
703
{
704
    return xoops_utf8_encode($text);
705
}
706
707
// Launch stories export (to the xml's format)
708
function launchExport(): void
709
{
710
    xoops_cp_header();
711
    $adminObject = Admin::getInstance();
712
    $adminObject->displayNavigation('index.php?op=export');
713
    echo '<br>';
714
    $story           = new NewsStory();
715
    $topic           = new NewsTopic();
0 ignored issues
show
The assignment to $topic is dead and can be removed.
Loading history...
716
    $exportedstories = [];
0 ignored issues
show
The assignment to $exportedstories is dead and can be removed.
Loading history...
717
    $date1           = $_POST['date1'];
718
    $date2           = $_POST['date2'];
719
    $timestamp1      = mktime(0, 0, 0, (int)mb_substr($date1, 5, 2), (int)mb_substr($date1, 8, 2), (int)mb_substr($date1, 0, 4));
720
    $timestamp2      = mktime(23, 59, 59, (int)mb_substr($date2, 5, 2), (int)mb_substr($date2, 8, 2), (int)mb_substr($date2, 0, 4));
721
    $topiclist       = '';
722
    if (Request::hasVar('export_topics', 'POST')) {
723
        $topiclist = implode(',', $_POST['export_topics']);
724
    }
725
    $topicsexport    = Request::getInt('includetopics', 0, 'POST');
726
    $tbltopics       = [];
727
    $exportedstories = $story->exportNews($timestamp1, $timestamp2, $topiclist, $topicsexport, $tbltopics);
728
    if (count($exportedstories)) {
729
        $xmlfile = XOOPS_ROOT_PATH . '/uploads/news/stories.xml';
730
        $fp      = fopen($xmlfile, 'wb');
731
        if (!$fp) {
0 ignored issues
show
$fp is of type resource, thus it always evaluated to false.
Loading history...
732
            redirect_header('index.php', 4, sprintf(_AM_NEWS_EXPORT_ERROR, $xmlfile));
733
        }
734
735
        fwrite($fp, news_utf8_encode("<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n"));
736
        fwrite($fp, news_utf8_encode("<news_stories>\n"));
737
        if ($topicsexport) {
738
            foreach ($tbltopics as $onetopic) {
739
                $topic   = new NewsTopic($onetopic);
740
                $content = "<news_topic>\n";
741
                $content .= sprintf("\t<topic_id>%u</topic_id>\n", $topic->topic_id());
742
                $content .= sprintf("\t<topic_pid>%u</topic_pid>\n", $topic->topic_pid());
743
                $content .= sprintf("\t<topic_imgurl>%s</topic_imgurl>\n", $topic->topic_imgurl());
744
                $content .= sprintf("\t<topic_title>%s</topic_title>\n", $topic->topic_title('F'));
745
                $content .= sprintf("\t<menu>%d</menu>\n", $topic->menu());
746
                $content .= sprintf("\t<topic_frontpage>%d</topic_frontpage>\n", $topic->topic_frontpage());
747
                $content .= sprintf("\t<topic_rssurl>%s</topic_rssurl>\n", $topic->topic_rssurl('E'));
748
                $content .= sprintf("\t<topic_description>%s</topic_description>\n", $topic->topic_description());
749
                $content .= "</news_topic>\n";
750
                $content = news_utf8_encode($content);
751
                fwrite($fp, $content);
752
            }
753
        }
754
755
        foreach ($exportedstories as $onestory) {
756
            $content = "<xoops_story>\n";
757
            $content .= sprintf("\t<storyid>%u</storyid>\n", $onestory->storyid());
758
            $content .= sprintf("\t<uid>%u</uid>\n", $onestory->uid());
759
            $content .= sprintf("\t<uname>%s</uname>\n", $onestory->uname());
760
            $content .= sprintf("\t<title>%s</title>\n", $onestory->title());
761
            $content .= sprintf("\t<created>%u</created>\n", $onestory->created());
762
            $content .= sprintf("\t<published>%u</published>\n", $onestory->published());
763
            $content .= sprintf("\t<expired>%u</expired>\n", $onestory->expired());
764
            $content .= sprintf("\t<hostname>%s</hostname>\n", $onestory->hostname());
765
            $content .= sprintf("\t<nohtml>%d</nohtml>\n", $onestory->nohtml());
766
            $content .= sprintf("\t<nosmiley>%d</nosmiley>\n", $onestory->nosmiley());
767
            $content .= sprintf("\t<hometext>%s</hometext>\n", $onestory->hometext());
768
            $content .= sprintf("\t<bodytext>%s</bodytext>\n", $onestory->bodytext());
769
            $content .= sprintf("\t<description>%s</description>\n", $onestory->description());
770
            $content .= sprintf("\t<keywords>%s</keywords>\n", $onestory->keywords());
771
            $content .= sprintf("\t<counter>%u</counter>\n", $onestory->counter());
772
            $content .= sprintf("\t<topicid>%u</topicid>\n", $onestory->topicid());
773
            $content .= sprintf("\t<ihome>%d</ihome>\n", $onestory->ihome());
774
            $content .= sprintf("\t<notifypub>%d</notifypub>\n", $onestory->notifypub());
775
            $content .= sprintf("\t<story_type>%s</story_type>\n", $onestory->type());
776
            $content .= sprintf("\t<topicdisplay>%d</topicdisplay>\n", $onestory->topicdisplay());
777
            $content .= sprintf("\t<topicalign>%s</topicalign>\n", $onestory->topicalign());
778
            $content .= sprintf("\t<comments>%u</comments>\n", $onestory->comments());
779
            $content .= sprintf("\t<rating>%f</rating>\n", $onestory->rating());
780
            $content .= sprintf("\t<votes>%u</votes>\n", $onestory->votes());
781
            $content .= "</xoops_story>\n";
782
            $content = news_utf8_encode($content);
783
            fwrite($fp, $content);
784
        }
785
        fwrite($fp, news_utf8_encode("</news_stories>\n"));
786
        fclose($fp);
787
        $xmlfile = XOOPS_URL . '/uploads/news/stories.xml';
788
        printf(_AM_NEWS_EXPORT_READY, $xmlfile, XOOPS_URL . '/modules/news/admin/index.php?op=deletefile&amp;type=xml');
789
    } else {
790
        printf(_AM_NEWS_EXPORT_NOTHING);
791
    }
792
}
793
794
/*
795
* Topics manager
796
*
797
* It's from here that you can list, add, modify an delete topics
798
* At first, you can see a list of all the topics in your databases. This list contains the topic's ID, its name,
799
* its parent topic, if it should be visible in the Xoops main menu and an action (Edit or Delete topic)
800
* Below this list you find the form used to create and edit the topics.
801
* use this form to :
802
* - Type the topic's title
803
* - Enter its description
804
* - Select its parent topic
805
* - Choose a color
806
* - Select if it must appear in the Xoops main menu
807
* - Choose if you want to see in the front page. If it's not the case, visitors will have to use the navigation box to see it
808
* - And finally you ca select an image to represent the topic
809
* The text box called "URL of RSS feed" is, for this moment, not used.
810
*/
811
function topicsmanager(): void
812
{
813
    global $xoopsDB, $xoopsConfig, $xoopsModule, $myts;
814
    require_once XOOPS_ROOT_PATH . '/class/xoopsformloader.php';
815
    xoops_cp_header();
816
    $adminObject = Admin::getInstance();
817
    $adminObject->displayNavigation('index.php?op=topicsmanager');
818
819
    global $pathIcon16;
820
821
    $uploadfolder   = sprintf(_AM_UPLOAD_WARNING, XOOPS_URL . '/uploads/news/image');
0 ignored issues
show
The assignment to $uploadfolder is dead and can be removed.
Loading history...
822
    $uploadirectory = '/uploads/news/image';
823
    $start          = Request::getInt('start', 0, 'GET');
824
825
    $xt          = new NewsTopic($xoopsDB->prefix('news_topics'), 'topic_id', 'topic_pid');
0 ignored issues
show
The call to XoopsModules\News\NewsTopic::__construct() has too many arguments starting with 'topic_id'. ( Ignorable by Annotation )

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

825
    $xt          = /** @scrutinizer ignore-call */ new NewsTopic($xoopsDB->prefix('news_topics'), 'topic_id', 'topic_pid');

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress. Please note the @ignore annotation hint above.

Loading history...
826
    $topics_arr  = $xt->getChildTreeArray(0, 'topic_title');
827
    $totaltopics = count($topics_arr);
828
    $class       = '';
829
830
    //echo '<h4>' . _AM_CONFIG . '</h4>';
831
    //news_collapsableBar('topicsmanager', 'toptopicsmanager');
832
833
    //echo "<img onclick=\"toggle('toptable'); toggleIcon('toptableicon');\" id='toptopicsmanager' name='toptopicsmanager' src='" . $pathIcon16."/close12.gif' alt=''></a>&nbsp;"._AM_TOPICSMNGR . ' (' . $totaltopics . ')'."</h4>";
834
835
    echo "<div id='topicsmanager'>";
836
    echo '<br>';
837
    echo "<div class='center;'>";
838
    echo "<table width='100%' cellspacing='1' cellpadding='3' border='0' class='outer'><tr class='bg3'><th align='center'>"
839
         . _AM_TOPIC
840
         . "</th><th align='left'>"
841
         . _AM_TOPICNAME
842
         . "</th><th align='center'>"
843
         . _AM_PARENTTOPIC
844
         . "</th><th align='center'>"
845
         . _AM_SUB_MENU_YESNO
846
         . "</th><th align='center'>"
847
         . _AM_NEWS_ACTION
848
         . '</th></tr>';
849
    if (is_array($topics_arr) && $totaltopics) {
850
        $cpt    = 1;
851
        $tmpcpt = $start;
852
        $ok     = true;
853
        $output = '';
854
        while ($ok) {
855
            if ($tmpcpt < $totaltopics) {
856
                $action_edit   = '<a href=index.php?op=topicsmanager&amp;topic_id=' . $topics_arr[$tmpcpt]['topic_id'] . '><img src=' . $pathIcon16 . 'edit.png title=' . _AM_EDIT . '></a>';
857
                $action_delete = '<a href=index.php?op=delTopic&amp;topic_id=' . $topics_arr[$tmpcpt]['topic_id'] . '><img src=' . $pathIcon16 . '/delete.png title=' . _AM_DELETE . "'></a>";
858
859
                $parent = '&nbsp;';
860
                if ($topics_arr[$tmpcpt]['topic_pid'] > 0) {
861
                    $xttmp  = new XoopsTopic($xoopsDB->prefix('news_topics'), $topics_arr[$tmpcpt]['topic_pid']);
862
                    $parent = $xttmp->topic_title();
863
                    unset($xttmp);
864
                }
865
                if (0 != $topics_arr[$tmpcpt]['topic_pid']) {
866
                    $topics_arr[$tmpcpt]['prefix'] = str_replace('.', '-', $topics_arr[$tmpcpt]['prefix']) . '&nbsp;';
867
                } else {
868
                    $topics_arr[$tmpcpt]['prefix'] = str_replace('.', '', $topics_arr[$tmpcpt]['prefix']);
869
                }
870
                $submenu = $topics_arr[$tmpcpt]['menu'] ? _YES : _NO;
871
                $class   = ('even' === $class) ? 'odd' : 'even';
872
873
                $output .= "<tr class='" . $class . "'><td>" . $topics_arr[$tmpcpt]['topic_id'] . "</td><td align='left'>" . $topics_arr[$tmpcpt]['prefix'] . $myts->displayTarea($topics_arr[$tmpcpt]['topic_title']) . "</td><td align='left'>" . $parent . "</td><td align='center'>" . $submenu . "</td><td align='center'>" . $action_edit . $action_delete . '</td></tr>';
874
            } else {
875
                $ok = false;
876
            }
877
            if ($cpt >= Utility::getModuleOption('storycountadmin')) {
878
                $ok = false;
879
            }
880
            ++$tmpcpt;
881
            ++$cpt;
882
        }
883
        echo $output;
884
    }
885
    $pagenav = new PageNav($totaltopics, Utility::getModuleOption('storycountadmin'), $start, 'start', 'op=topicsmanager');
0 ignored issues
show
It seems like XoopsModules\News\Utilit...tion('storycountadmin') can also be of type boolean; however, parameter $items_perpage of XoopsModules\News\PageNav::__construct() does only seem to accept integer, 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

885
    $pagenav = new PageNav($totaltopics, /** @scrutinizer ignore-type */ Utility::getModuleOption('storycountadmin'), $start, 'start', 'op=topicsmanager');
Loading history...
886
    echo "</table><div align='right'>" . $pagenav->renderNav() . '</div><br>';
887
    echo "</div></div><br>\n";
888
889
    $topic_id = Request::getInt('topic_id', 0, 'GET');
890
    if ($topic_id > 0) {
891
        $xtmod             = new NewsTopic($topic_id);
892
        $topic_title       = $xtmod->topic_title('E');
893
        $topic_description = $xtmod->topic_description('E');
894
        $topic_rssfeed     = $xtmod->topic_rssurl('E');
0 ignored issues
show
The assignment to $topic_rssfeed is dead and can be removed.
Loading history...
895
        $op                = 'modTopicS';
896
        if ('' !== xoops_trim($xtmod->topic_imgurl())) {
897
            $topicimage = $xtmod->topic_imgurl();
898
        } else {
899
            $topicimage = 'blank.png';
900
        }
901
        $btnlabel        = _AM_MODIFY;
902
        $parent          = $xtmod->topic_pid();
903
        $formlabel       = _AM_MODIFYTOPIC;
904
        $submenu         = $xtmod->menu();
905
        $topic_frontpage = $xtmod->topic_frontpage();
906
        $topic_color     = $xtmod->topic_color();
907
        unset($xtmod);
908
    } else {
909
        $topic_title       = '';
910
        $topic_frontpage   = 1;
911
        $topic_description = '';
912
        $op                = 'addTopic';
913
        $topicimage        = 'xoops.gif';
914
        $btnlabel          = _AM_ADD;
915
        $parent            = -1;
916
        $submenu           = 0;
917
        $topic_rssfeed     = '';
918
        $formlabel         = _AM_ADD_TOPIC;
919
        $topic_color       = '000000';
920
    }
921
922
    $sform = new \XoopsThemeForm($formlabel, 'topicform', XOOPS_URL . '/modules/' . $xoopsModule->getVar('dirname') . '/admin/index.php', 'post', true);
923
    $sform->setExtra('enctype="multipart/form-data"');
924
    $sform->addElement(new \XoopsFormText(_AM_TOPICNAME, 'topic_title', 50, 255, $topic_title), true);
925
    $editor = Utility::getWysiwygForm(_AM_TOPIC_DESCR, 'topic_description', $topic_description, 15, 60, 'hometext_hidden');
926
    if ($editor) {
927
        $sform->addElement($editor, false);
928
    }
929
930
    $sform->addElement(new \XoopsFormHidden('op', $op), false);
931
    $sform->addElement(new \XoopsFormHidden('topic_id', $topic_id), false);
932
933
    //    require_once XOOPS_ROOT_PATH . '/modules/news/class/class.newstopic.php';
934
    $xt = new NewsTopic();
935
    $sform->addElement(new \XoopsFormLabel(_AM_PARENTTOPIC, $xt->makeMyTopicSelBox(1, $parent, 'topic_pid', '', false)));
936
    // Topic's color
937
    // Code stolen to Zoullou, thank you Zoullou ;-)
938
    $select_color = "\n<select name='topic_color'  onchange='xoopsGetElementById(\"NewsColorSelect\").style.backgroundColor = \"#\" + this.options[this.selectedIndex].value;'>\n<option value='000000'>" . _AM_NEWS_COLOR . "</option>\n";
939
    $color_values = [
940
        '000000',
941
        '000033',
942
        '000066',
943
        '000099',
944
        '0000CC',
945
        '0000FF',
946
        '003300',
947
        '003333',
948
        '003366',
949
        '0033CC',
950
        '0033FF',
951
        '006600',
952
        '006633',
953
        '006666',
954
        '006699',
955
        '0066CC',
956
        '0066FF',
957
        '009900',
958
        '009933',
959
        '009966',
960
        '009999',
961
        '0099CC',
962
        '0099FF',
963
        '00CC00',
964
        '00CC33',
965
        '00CC66',
966
        '00CC99',
967
        '00CCCC',
968
        '00CCFF',
969
        '00FF00',
970
        '00FF33',
971
        '00FF66',
972
        '00FF99',
973
        '00FFCC',
974
        '00FFFF',
975
        '330000',
976
        '330033',
977
        '330066',
978
        '330099',
979
        '3300CC',
980
        '3300FF',
981
        '333300',
982
        '333333',
983
        '333366',
984
        '333399',
985
        '3333CC',
986
        '3333FF',
987
        '336600',
988
        '336633',
989
        '336666',
990
        '336699',
991
        '3366CC',
992
        '3366FF',
993
        '339900',
994
        '339933',
995
        '339966',
996
        '339999',
997
        '3399CC',
998
        '3399FF',
999
        '33CC00',
1000
        '33CC33',
1001
        '33CC66',
1002
        '33CC99',
1003
        '33CCCC',
1004
        '33CCFF',
1005
        '33FF00',
1006
        '33FF33',
1007
        '33FF66',
1008
        '33FF99',
1009
        '33FFCC',
1010
        '33FFFF',
1011
        '660000',
1012
        '660033',
1013
        '660066',
1014
        '660099',
1015
        '6600CC',
1016
        '6600FF',
1017
        '663300',
1018
        '663333',
1019
        '663366',
1020
        '663399',
1021
        '6633CC',
1022
        '6633FF',
1023
        '666600',
1024
        '666633',
1025
        '666666',
1026
        '666699',
1027
        '6666CC',
1028
        '6666FF',
1029
        '669900',
1030
        '669933',
1031
        '669966',
1032
        '669999',
1033
        '6699CC',
1034
        '6699FF',
1035
        '66CC00',
1036
        '66CC33',
1037
        '66CC66',
1038
        '66CC99',
1039
        '66CCCC',
1040
        '66CCFF',
1041
        '66FF00',
1042
        '66FF33',
1043
        '66FF66',
1044
        '66FF99',
1045
        '66FFCC',
1046
        '66FFFF',
1047
        '990000',
1048
        '990033',
1049
        '990066',
1050
        '990099',
1051
        '9900CC',
1052
        '9900FF',
1053
        '993300',
1054
        '993333',
1055
        '993366',
1056
        '993399',
1057
        '9933CC',
1058
        '9933FF',
1059
        '996600',
1060
        '996633',
1061
        '996666',
1062
        '996699',
1063
        '9966CC',
1064
        '9966FF',
1065
        '999900',
1066
        '999933',
1067
        '999966',
1068
        '999999',
1069
        '9999CC',
1070
        '9999FF',
1071
        '99CC00',
1072
        '99CC33',
1073
        '99CC66',
1074
        '99CC99',
1075
        '99CCCC',
1076
        '99CCFF',
1077
        '99FF00',
1078
        '99FF33',
1079
        '99FF66',
1080
        '99FF99',
1081
        '99FFCC',
1082
        '99FFFF',
1083
        'CC0000',
1084
        'CC0033',
1085
        'CC0066',
1086
        'CC0099',
1087
        'CC00CC',
1088
        'CC00FF',
1089
        'CC3300',
1090
        'CC3333',
1091
        'CC3366',
1092
        'CC3399',
1093
        'CC33CC',
1094
        'CC33FF',
1095
        'CC6600',
1096
        'CC6633',
1097
        'CC6666',
1098
        'CC6699',
1099
        'CC66CC',
1100
        'CC66FF',
1101
        'CC9900',
1102
        'CC9933',
1103
        'CC9966',
1104
        'CC9999',
1105
        'CC99CC',
1106
        'CC99FF',
1107
        'CCCC00',
1108
        'CCCC33',
1109
        'CCCC66',
1110
        'CCCC99',
1111
        'CCCCCC',
1112
        'CCCCFF',
1113
        'CCFF00',
1114
        'CCFF33',
1115
        'CCFF66',
1116
        'CCFF99',
1117
        'CCFFCC',
1118
        'CCFFFF',
1119
        'FF0000',
1120
        'FF0033',
1121
        'FF0066',
1122
        'FF0099',
1123
        'FF00CC',
1124
        'FF00FF',
1125
        'FF3300',
1126
        'FF3333',
1127
        'FF3366',
1128
        'FF3399',
1129
        'FF33CC',
1130
        'FF33FF',
1131
        'FF6600',
1132
        'FF6633',
1133
        'FF6666',
1134
        'FF6699',
1135
        'FF66CC',
1136
        'FF66FF',
1137
        'FF9900',
1138
        'FF9933',
1139
        'FF9966',
1140
        'FF9999',
1141
        'FF99CC',
1142
        'FF99FF',
1143
        'FFCC00',
1144
        'FFCC33',
1145
        'FFCC66',
1146
        'FFCC99',
1147
        'FFCCCC',
1148
        'FFCCFF',
1149
        'FFFF00',
1150
        'FFFF33',
1151
        'FFFF66',
1152
        'FFFF99',
1153
        'FFFFCC',
1154
        'FFFFFF',
1155
    ];
1156
1157
    foreach ($color_values as $color_value) {
1158
        if ($topic_color == $color_value) {
1159
            $selected = ' selected';
1160
        } else {
1161
            $selected = '';
1162
        }
1163
        $select_color .= '<option' . $selected . " value='" . $color_value . "' style='background-color:#" . $color_value . ';color:#' . $color_value . ";'>#" . $color_value . "</option>\n";
1164
    }
1165
1166
    $select_color .= "</select>&nbsp;\n<span id='NewsColorSelect'>&nbsp;&nbsp;&nbsp;&nbsp;</span>";
1167
    $sform->addElement(new \XoopsFormLabel(_AM_NEWS_TOPIC_COLOR, $select_color));
1168
    // Sub menu ?
1169
    $sform->addElement(new \XoopsFormRadioYN(_AM_SUB_MENU, 'submenu', $submenu, _YES, _NO));
1170
    $sform->addElement(new \XoopsFormRadioYN(_AM_PUBLISH_FRONTPAGE, 'topic_frontpage', $topic_frontpage, _YES, _NO));
1171
    // Unused for this moment... sorry
1172
    //$sform->addElement(new \XoopsFormText(_AM_NEWS_RSS_URL, 'topic_rssfeed', 50, 255, $topic_rssfeed), false);
1173
    // ********** Picture
1174
    $imgtray = new \XoopsFormElementTray(_AM_TOPICIMG, '<br>');
1175
1176
    $imgpath      = sprintf(_AM_IMGNAEXLOC, 'uploads/news/image/');
1177
    $imageselect  = new \XoopsFormSelect($imgpath, 'topic_imgurl', $topicimage);
1178
    $topics_array = \XoopsLists:: getImgListAsArray(XOOPS_ROOT_PATH . '/uploads/news/image/');
1179
    foreach ($topics_array as $image) {
1180
        $imageselect->addOption((string)$image, $image);
1181
    }
1182
    $imageselect->setExtra("onchange='showImgSelected(\"image3\", \"topic_imgurl\", \"" . $uploadirectory . '", "", "' . XOOPS_URL . "\")'");
1183
    $imgtray->addElement($imageselect, false);
1184
    $imgtray->addElement(new XoopsFormLabel('', "<br><img src='" . XOOPS_URL . $uploadirectory . '/' . $topicimage . "' name='image3' id='image3' alt=''>"));
1185
1186
    $uploadfolder = sprintf(_AM_UPLOAD_WARNING, XOOPS_URL . '/uploads/news/image');
1187
    $fileseltray  = new \XoopsFormElementTray('', '<br>');
1188
    $fileseltray->addElement(new \XoopsFormFile(_AM_TOPIC_PICTURE, 'attachedfile', Utility::getModuleOption('maxuploadsize')), false);
0 ignored issues
show
It seems like XoopsModules\News\Utilit...Option('maxuploadsize') can also be of type boolean; however, parameter $maxfilesize of XoopsFormFile::__construct() does only seem to accept integer, 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

1188
    $fileseltray->addElement(new \XoopsFormFile(_AM_TOPIC_PICTURE, 'attachedfile', /** @scrutinizer ignore-type */ Utility::getModuleOption('maxuploadsize')), false);
Loading history...
1189
    $fileseltray->addElement(new \XoopsFormLabel($uploadfolder), false);
1190
    $imgtray->addElement($fileseltray);
1191
    $sform->addElement($imgtray);
1192
1193
    // Permissions
1194
    /** @var \XoopsMemberHandler $memberHandler */
1195
    $memberHandler = xoops_getHandler('member');
1196
    $group_list    = $memberHandler->getGroupList();
1197
    /** @var \XoopsGroupPermHandler $grouppermHandler */
1198
    $grouppermHandler = xoops_getHandler('groupperm');
1199
    $full_list        = array_keys($group_list);
1200
1201
    $groups_ids = [];
1202
    if ($topic_id > 0) { // Edit mode
1203
        $groups_ids                       = $grouppermHandler->getGroupIds('news_approve', $topic_id, $xoopsModule->getVar('mid'));
1204
        $groups_ids                       = array_values($groups_ids);
1205
        $groups_news_can_approve_checkbox = new \XoopsFormCheckBox(_AM_APPROVEFORM, 'groups_news_can_approve[]', $groups_ids);
1206
    } else { // Creation mode
1207
        $groups_news_can_approve_checkbox = new \XoopsFormCheckBox(_AM_APPROVEFORM, 'groups_news_can_approve[]', $full_list);
1208
    }
1209
    $groups_news_can_approve_checkbox->addOptionArray($group_list);
1210
    $sform->addElement($groups_news_can_approve_checkbox);
1211
1212
    $groups_ids = [];
1213
    if ($topic_id > 0) { // Edit mode
1214
        $groups_ids                      = $grouppermHandler->getGroupIds('news_submit', $topic_id, $xoopsModule->getVar('mid'));
1215
        $groups_ids                      = array_values($groups_ids);
1216
        $groups_news_can_submit_checkbox = new \XoopsFormCheckBox(_AM_SUBMITFORM, 'groups_news_can_submit[]', $groups_ids);
1217
    } else { // Creation mode
1218
        $groups_news_can_submit_checkbox = new \XoopsFormCheckBox(_AM_SUBMITFORM, 'groups_news_can_submit[]', $full_list);
1219
    }
1220
    $groups_news_can_submit_checkbox->addOptionArray($group_list);
1221
    $sform->addElement($groups_news_can_submit_checkbox);
1222
1223
    $groups_ids = [];
0 ignored issues
show
The assignment to $groups_ids is dead and can be removed.
Loading history...
1224
    if ($topic_id > 0) { // Edit mode
1225
        $groups_ids                    = $grouppermHandler->getGroupIds('news_view', $topic_id, $xoopsModule->getVar('mid'));
1226
        $groups_ids                    = array_values($groups_ids);
1227
        $groups_news_can_view_checkbox = new \XoopsFormCheckBox(_AM_VIEWFORM, 'groups_news_can_view[]', $groups_ids);
1228
    } else { // Creation mode
1229
        $groups_news_can_view_checkbox = new \XoopsFormCheckBox(_AM_VIEWFORM, 'groups_news_can_view[]', $full_list);
1230
    }
1231
    $groups_news_can_view_checkbox->addOptionArray($group_list);
1232
    $sform->addElement($groups_news_can_view_checkbox);
1233
1234
    // Submit buttons
1235
    $buttonTray = new \XoopsFormElementTray('', '');
1236
    $submit_btn = new \XoopsFormButton('', 'post', $btnlabel, 'submit');
1237
    $buttonTray->addElement($submit_btn);
1238
    $sform->addElement($buttonTray);
1239
    $sform->display();
1240
    echo "<script type='text/javascript'>\n";
1241
    echo 'xoopsGetElementById("NewsColorSelect").style.backgroundColor = "#' . $topic_color . '";';
1242
    echo "</script>\n";
1243
}
1244
1245
// Save a topic after it has been modified
1246
function modTopicS(): void
1247
{
1248
    global $xoopsDB, $xoopsModule;
1249
    $helper = Helper::getInstance();
1250
1251
    $xt = new NewsTopic(Request::getInt('topic_id', 0, 'POST'));
1252
    if (Request::getInt('topic_pid', 0, 'POST') == Request::getInt('topic_id', 0, 'POST')) {
1253
        redirect_header('index.php?op=topicsmanager', 2, _AM_ADD_TOPIC_ERROR1);
1254
    }
1255
    $xt->setTopicPid(Request::getInt('topic_pid', 0, 'POST'));
1256
    if (empty($_POST['topic_title'])) {
1257
        redirect_header('index.php?op=topicsmanager', 2, _AM_ERRORTOPICNAME);
1258
    }
1259
    if (Request::hasVar('items_count', 'SESSION')) {
1260
        $_SESSION['items_count'] = -1;
1261
    }
1262
    $xt->setTopicTitle($_POST['topic_title']);
1263
    if (Request::hasVar('topic_imgurl', 'POST') && '' !== $_POST['topic_imgurl']) {
1264
        $xt->setTopicImgurl($_POST['topic_imgurl']);
1265
    }
1266
    $xt->setMenu(Request::getInt('submenu', 0, 'POST'));
1267
    $xt->setTopicFrontpage(Request::getInt('topic_frontpage', 0, 'POST'));
1268
    if (Request::hasVar('topic_description', 'POST')) {
1269
        $xt->setTopicDescription($_POST['topic_description']);
1270
    } else {
1271
        $xt->setTopicDescription('');
1272
    }
1273
    //$xt->setTopicRssUrl($_POST['topic_rssfeed']);
1274
    $xt->setTopic_color($_POST['topic_color']);
1275
1276
    if (Request::hasVar('xoops_upload_file', 'POST')) {
1277
        $fldname = $_FILES[$_POST['xoops_upload_file'][0]];
1278
        $fldname = $fldname['name'];
1279
        if (xoops_trim('' !== $fldname)) {
1280
            $sfiles         = new Files();
1281
            $dstpath        = XOOPS_ROOT_PATH . '/uploads/news/image';
1282
            $destname       = $sfiles->createUploadName($dstpath, $fldname, true);
1283
            $permittedtypes = ['image/gif', 'image/jpeg', 'image/pjpeg', 'image/x-png', 'image/png'];
1284
            $uploader       = new \XoopsMediaUploader($dstpath, $permittedtypes, $helper->getConfig('maxuploadsize'));
1285
            $uploader->setTargetFileName($destname);
1286
            if ($uploader->fetchMedia($_POST['xoops_upload_file'][0])) {
1287
                if ($uploader->upload()) {
1288
                    $xt->setTopicImgurl(basename($destname));
1289
                } else {
1290
                    echo _AM_UPLOAD_ERROR . ' ' . $uploader->getErrors();
1291
                }
1292
            } else {
1293
                echo $uploader->getErrors();
1294
            }
1295
        }
1296
    }
1297
    $xt->store();
1298
1299
    // Permissions
1300
    /** @var \XoopsGroupPermHandler $grouppermHandler */
1301
    $grouppermHandler = xoops_getHandler('groupperm');
1302
    $criteria         = new \CriteriaCompo();
1303
    $criteria->add(new \Criteria('gperm_itemid', $xt->topic_id(), '='));
1304
    $criteria->add(new \Criteria('gperm_modid', $xoopsModule->getVar('mid'), '='));
1305
    $criteria->add(new \Criteria('gperm_name', 'news_approve', '='));
1306
    $grouppermHandler->deleteAll($criteria);
1307
1308
    $criteria = new \CriteriaCompo();
1309
    $criteria->add(new \Criteria('gperm_itemid', $xt->topic_id(), '='));
1310
    $criteria->add(new \Criteria('gperm_modid', $xoopsModule->getVar('mid'), '='));
1311
    $criteria->add(new \Criteria('gperm_name', 'news_submit', '='));
1312
    $grouppermHandler->deleteAll($criteria);
1313
1314
    $criteria = new \CriteriaCompo();
1315
    $criteria->add(new \Criteria('gperm_itemid', $xt->topic_id(), '='));
1316
    $criteria->add(new \Criteria('gperm_modid', $xoopsModule->getVar('mid'), '='));
1317
    $criteria->add(new \Criteria('gperm_name', 'news_view', '='));
1318
    $grouppermHandler->deleteAll($criteria);
1319
1320
    if (Request::hasVar('groups_news_can_approve', 'POST')) {
1321
        foreach ($_POST['groups_news_can_approve'] as $onegroup_id) {
1322
            $grouppermHandler->addRight('news_approve', $xt->topic_id(), $onegroup_id, $xoopsModule->getVar('mid'));
1323
        }
1324
    }
1325
1326
    if (Request::hasVar('groups_news_can_submit', 'POST')) {
1327
        foreach ($_POST['groups_news_can_submit'] as $onegroup_id) {
1328
            $grouppermHandler->addRight('news_submit', $xt->topic_id(), $onegroup_id, $xoopsModule->getVar('mid'));
1329
        }
1330
    }
1331
1332
    if (Request::hasVar('groups_news_can_view', 'POST')) {
1333
        foreach ($_POST['groups_news_can_view'] as $onegroup_id) {
1334
            $grouppermHandler->addRight('news_view', $xt->topic_id(), $onegroup_id, $xoopsModule->getVar('mid'));
1335
        }
1336
    }
1337
1338
    Utility::updateCache();
1339
    redirect_header('index.php?op=topicsmanager', 1, _AM_DBUPDATED);
1340
}
1341
1342
// Delete a topic and its subtopics and its stories and the related stories
1343
function delTopic(): void
1344
{
1345
    global $xoopsDB, $xoopsModule;
1346
    if (!isset($_POST['ok'])) {
1347
        xoops_cp_header();
1348
        echo '<h4>' . _AM_CONFIG . '</h4>';
1349
        $xt = new XoopsTopic($xoopsDB->prefix('news_topics'), Request::getInt('topic_id', 0, 'GET'));
1350
        xoops_confirm(['op' => 'delTopic', 'topic_id' => Request::getInt('topic_id', 0, 'GET'), 'ok' => 1], 'index.php', _AM_WAYSYWTDTTAL . '<br>' . $xt->topic_title('S'));
1351
    } else {
1352
        xoops_cp_header();
1353
        $xt = new \XoopsTopic($xoopsDB->prefix('news_topics'), Request::getInt('topic_id', 0, 'POST'));
1354
        if (Request::hasVar('items_count', 'SESSION')) {
1355
            $_SESSION['items_count'] = -1;
1356
        }
1357
        // get all subtopics under the specified topic
1358
        $topic_arr   = $xt->getAllChildTopics();
1359
        $topic_arr[] = $xt;
1360
        foreach ($topic_arr as $eachtopic) {
1361
            // get all stories in each topic
1362
            $story_arr = NewsStory::getByTopic($eachtopic->topic_id());
1363
            foreach ($story_arr as $eachstory) {
1364
                if (false !== $eachstory->delete()) {
1365
                    xoops_comment_delete($xoopsModule->getVar('mid'), $eachstory->storyid());
1366
                    xoops_notification_deletebyitem($xoopsModule->getVar('mid'), 'story', $eachstory->storyid());
1367
                }
1368
            }
1369
            // all stories for each topic is deleted, now delete the topic data
1370
            $eachtopic->delete();
1371
            // Delete also the notifications and permissions
1372
            xoops_notification_deletebyitem($xoopsModule->getVar('mid'), 'category', $eachtopic->topic_id);
1373
            xoops_groupperm_deletebymoditem($xoopsModule->getVar('mid'), 'news_approve', $eachtopic->topic_id);
1374
            xoops_groupperm_deletebymoditem($xoopsModule->getVar('mid'), 'news_submit', $eachtopic->topic_id);
1375
            xoops_groupperm_deletebymoditem($xoopsModule->getVar('mid'), 'news_view', $eachtopic->topic_id);
1376
        }
1377
        Utility::updateCache();
1378
        redirect_header('index.php?op=topicsmanager', 1, _AM_DBUPDATED);
1379
    }
1380
}
1381
1382
// Add a new topic
1383
function addTopic(): void
1384
{
1385
    global $xoopsDB, $xoopsModule;
1386
    $helper = Helper::getInstance();
1387
1388
    $topicpid = Request::getInt('topic_pid', 0, 'POST');
1389
    $xt       = new NewsTopic();
1390
    if (!$xt->topicExists($topicpid, $_POST['topic_title'])) {
1391
        $xt->setTopicPid($topicpid);
1392
        if (empty($_POST['topic_title']) || '' == xoops_trim($_POST['topic_title'])) {
1393
            redirect_header('index.php?op=topicsmanager', 2, _AM_ERRORTOPICNAME);
1394
        }
1395
        $xt->setTopicTitle($_POST['topic_title']);
1396
        //$xt->setTopicRssUrl($_POST['topic_rssfeed']);
1397
        $xt->setTopic_color($_POST['topic_color']);
1398
        if (Request::hasVar('topic_imgurl', 'POST') && '' !== $_POST['topic_imgurl']) {
1399
            $xt->setTopicImgurl($_POST['topic_imgurl']);
1400
        }
1401
        $xt->setMenu(Request::getInt('submenu', 0, 'POST'));
1402
        $xt->setTopicFrontpage(Request::getInt('topic_frontpage', 0, 'POST'));
1403
        if (Request::hasVar('items_count', 'SESSION')) {
1404
            $_SESSION['items_count'] = -1;
1405
        }
1406
        if (Request::hasVar('xoops_upload_file', 'POST')) {
1407
            $fldname = $_FILES[$_POST['xoops_upload_file'][0]];
1408
            $fldname = $fldname['name'];
1409
            if ('' !== xoops_trim($fldname)) {
1410
                $sfiles         = new Files();
1411
                $dstpath        = XOOPS_ROOT_PATH . '/uploads/news/image';
1412
                $destname       = $sfiles->createUploadName($dstpath, $fldname, true);
1413
                $permittedtypes = ['image/gif', 'image/jpeg', 'image/pjpeg', 'image/x-png', 'image/png'];
1414
                $uploader       = new \XoopsMediaUploader($dstpath, $permittedtypes, $helper->getConfig('maxuploadsize'));
1415
                $uploader->setTargetFileName($destname);
1416
                if ($uploader->fetchMedia($_POST['xoops_upload_file'][0])) {
1417
                    if ($uploader->upload()) {
1418
                        $xt->setTopicImgurl(basename($destname));
1419
                    } else {
1420
                        echo _AM_UPLOAD_ERROR . ' ' . $uploader->getErrors();
1421
                    }
1422
                } else {
1423
                    echo $uploader->getErrors();
1424
                }
1425
            }
1426
        }
1427
        if (Request::hasVar('topic_description', 'POST')) {
1428
            $xt->setTopicDescription($_POST['topic_description']);
1429
        } else {
1430
            $xt->setTopicDescription('');
1431
        }
1432
        $xt->store();
1433
        // Permissions
1434
        /** @var \XoopsGroupPermHandler $grouppermHandler */
1435
        $grouppermHandler = xoops_getHandler('groupperm');
1436
        if (Request::hasVar('groups_news_can_approve', 'POST')) {
1437
            foreach ($_POST['groups_news_can_approve'] as $onegroup_id) {
1438
                $grouppermHandler->addRight('news_approve', $xt->topic_id(), $onegroup_id, $xoopsModule->getVar('mid'));
1439
            }
1440
        }
1441
1442
        if (Request::hasVar('groups_news_can_submit', 'POST')) {
1443
            foreach ($_POST['groups_news_can_submit'] as $onegroup_id) {
1444
                $grouppermHandler->addRight('news_submit', $xt->topic_id(), $onegroup_id, $xoopsModule->getVar('mid'));
1445
            }
1446
        }
1447
1448
        if (Request::hasVar('groups_news_can_view', 'POST')) {
1449
            foreach ($_POST['groups_news_can_view'] as $onegroup_id) {
1450
                $grouppermHandler->addRight('news_view', $xt->topic_id(), $onegroup_id, $xoopsModule->getVar('mid'));
1451
            }
1452
        }
1453
        Utility::updateCache();
1454
        /** @var \XoopsNotificationHandler $notificationHandler */
1455
        $notificationHandler = xoops_getHandler('notification');
1456
        $tags                = [];
1457
        $tags['TOPIC_NAME']  = $_POST['topic_title'];
1458
        $notificationHandler->triggerEvent('global', 0, 'new_category', $tags);
1459
        redirect_header('index.php?op=topicsmanager', 1, _AM_DBUPDATED);
1460
    } else {
1461
        redirect_header('index.php?op=topicsmanager', 2, _AM_ADD_TOPIC_ERROR);
1462
    }
1463
}
1464
1465
/**
1466
 * Statistics about stories, topics and authors
1467
 *
1468
 * You can reach the statistics from the admin part of the news module by clicking on the "Statistics" tabs
1469
 * The number of visible elements in each table is equal to the module's option called "storycountadmin"
1470
 * There are 3 kind of different statistics :
1471
 * - Topics statistics
1472
 *   For each topic you can see its number of articles, the number of time each topics was viewed, the number
1473
 *   of attached files, the number of expired articles and the number of unique authors.
1474
 * - Articles statistics
1475
 *   This part is decomposed in 3 tables :
1476
 *   a) Most readed articles
1477
 *      This table resumes, for all the news in your database, the most readed articles.
1478
 *      The table contains, for each news, its topic, its title, the author and the number of views.
1479
 *   b) Less readed articles
1480
 *      That's the opposite action of the previous table and its content is the same
1481
 *   c) Best rated articles
1482
 *      You will find here the best rated articles, the content is the same that the previous tables, the last column is just changing and contains the article's rating
1483
 * - Authors statistics
1484
 *   This part is also decomposed in 3 tables
1485
 *   a) Most readed authors
1486
 *        To create this table, the program compute the total number of reads per author and displays the most readed author and the number of views
1487
 *   b) Best rated authors
1488
 *      To created this table's content, the program compute the rating's average of each author and create a table
1489
 *   c) Biggest contributors
1490
 *      The goal of this table is to know who is creating the biggest number of articles.
1491
 */
1492
function getStats(): void
1493
{
1494
    global $xoopsModule, $xoopsConfig;
1495
    xoops_cp_header();
1496
    $myts   = \MyTextSanitizer::getInstance();
1497
    $helper = Helper::getInstance();
1498
    $helper->loadLanguage('main');
1499
1500
    $adminObject = Admin::getInstance();
1501
    $adminObject->displayNavigation('index.php?op=stats');
1502
    $news   = new NewsStory();
1503
    $stats  = [];
0 ignored issues
show
The assignment to $stats is dead and can be removed.
Loading history...
1504
    /** @var array $stats */
1505
    $stats  = $news->getStats(Utility::getModuleOption('storycountadmin'));
1506
    $totals = [0, 0, 0, 0, 0];
1507
    //printf("<h1>%s</h1>\n",_AM_NEWS_STATS);
1508
1509
    // First part of the stats, everything about topics
1510
    $storiespertopic = $stats['storiespertopic'];
1511
    $readspertopic   = $stats['readspertopic'];
1512
    $filespertopic   = $stats['filespertopic'];
1513
    $expiredpertopic = $stats['expiredpertopic'];
1514
    $authorspertopic = $stats['authorspertopic'];
1515
    $class           = '';
1516
1517
    echo "<div class='center;'><b>" . _AM_NEWS_STATS0 . "</b><br>\n";
1518
    echo "<table border='0' width='100%'><tr class='bg3'><th align='center'>" . _AM_TOPIC . "</th><th align='center'>" . _NW_ARTICLES . '</th><th>' . _NW_VIEWS . '</th><th>' . _AM_UPLOAD_ATTACHFILE . '</th><th>' . _AM_EXPARTS . '</th><th>' . _AM_NEWS_STATS1 . '</th></tr>';
1519
    foreach ($storiespertopic as $topicid => $data) {
1520
        $url   = XOOPS_URL . '/modules/' . $xoopsModule->dirname() . '/index.php?storytopic=' . $topicid;
1521
        $views = 0;
1522
        if (array_key_exists($topicid, $readspertopic)) {
1523
            $views = $readspertopic[$topicid];
1524
        }
1525
        $attachedfiles = 0;
1526
        if (array_key_exists($topicid, $filespertopic)) {
1527
            $attachedfiles = $filespertopic[$topicid];
1528
        }
1529
        $expired = 0;
1530
        if (array_key_exists($topicid, $expiredpertopic)) {
1531
            $expired = $expiredpertopic[$topicid];
1532
        }
1533
        $authors = 0;
1534
        if (array_key_exists($topicid, $authorspertopic)) {
1535
            $authors = $authorspertopic[$topicid];
1536
        }
1537
        $articles = $data['cpt'];
1538
1539
        $totals[0] += $articles;
1540
        $totals[1] += $views;
1541
        $totals[2] += $attachedfiles;
1542
        $totals[3] += $expired;
1543
        $class     = ('even' === $class) ? 'odd' : 'even';
1544
        printf(
1545
            "<tr class='" . $class . "'><td align='left'><a href='%s' target ='_blank'>%s</a></td><td align='right'>%u</td><td align='right'>%u</td><td align='right'>%u</td><td align='right'>%u</td><td align='right'>%u</td></tr>\n",
1546
            $url,
1547
            $myts->displayTarea($data['topic_title']),
1548
            $articles,
1549
            $views,
1550
            $attachedfiles,
1551
            $expired,
1552
            $authors
1553
        );
1554
    }
1555
    $class = ('even' === $class) ? 'odd' : 'even';
1556
    printf("<tr class='" . $class . "'><td align='center'><b>%s</b></td><td align='right'><b>%u</b></td><td align='right'><b>%u</b></td><td align='right'><b>%u</b></td><td align='right'><b>%u</b></td><td>&nbsp;</td>\n", _AM_NEWS_STATS2, $totals[0], $totals[1], $totals[2], $totals[3]);
1557
    echo '</table></div><br><br><br>';
1558
1559
    // Second part of the stats, everything about stories
1560
    // a) Most readed articles
1561
    $mostreadednews = $stats['mostreadednews'];
1562
    echo "<div class='center;'><b>" . _AM_NEWS_STATS3 . '</b><br><br>' . _AM_NEWS_STATS4 . "<br>\n";
1563
    echo "<table border='0' width='100%'><tr class='bg3'><th align='center'>" . _AM_TOPIC . "</th><th align='center'>" . _AM_TITLE . '</th><th>' . _AM_POSTER . '</th><th>' . _NW_VIEWS . "</th></tr>\n";
1564
    foreach ($mostreadednews as $storyid => $data) {
1565
        $url1  = XOOPS_URL . '/modules/' . $xoopsModule->dirname() . '/index.php?storytopic=' . $data['topicid'];
1566
        $url2  = XOOPS_URL . '/modules/' . $xoopsModule->dirname() . '/article.php?storyid=' . $storyid;
1567
        $url3  = XOOPS_URL . '/userinfo.php?uid=' . $data['uid'];
1568
        $class = ('even' === $class) ? 'odd' : 'even';
1569
        printf(
1570
            "<tr class='" . $class . "'><td align='left'><a href='%s' target ='_blank'>%s</a></td><td align='left'><a href='%s' target='_blank'>%s</a></td><td><a href='%s' target='_blank'>%s</a></td><td align='right'>%u</td></tr>\n",
1571
            $url1,
1572
            $myts->displayTarea($data['topic_title']),
1573
            $url2,
1574
            $myts->displayTarea($data['title']),
1575
            $url3,
1576
            htmlspecialchars($news->uname($data['uid']), ENT_QUOTES | ENT_HTML5),
0 ignored issues
show
It seems like $news->uname($data['uid']) can also be of type null; however, parameter $string of htmlspecialchars() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

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

1576
            htmlspecialchars(/** @scrutinizer ignore-type */ $news->uname($data['uid']), ENT_QUOTES | ENT_HTML5),
Loading history...
1577
            $data['counter']
1578
        );
1579
    }
1580
    echo '</table>';
1581
1582
    // b) Less readed articles
1583
    $lessreadednews = $stats['lessreadednews'];
1584
    echo '<br><br>' . _AM_NEWS_STATS5;
1585
    echo "<table border='0' width='100%'><tr class='bg3'><th align='center'>" . _AM_TOPIC . "</th><th align='center'>" . _AM_TITLE . '</th><th>' . _AM_POSTER . '</th><th>' . _NW_VIEWS . "</th></tr>\n";
1586
    foreach ($lessreadednews as $storyid => $data) {
1587
        $url1  = XOOPS_URL . '/modules/' . $xoopsModule->dirname() . '/index.php?storytopic=' . $data['topicid'];
1588
        $url2  = XOOPS_URL . '/modules/' . $xoopsModule->dirname() . '/article.php?storyid=' . $storyid;
1589
        $url3  = XOOPS_URL . '/userinfo.php?uid=' . $data['uid'];
1590
        $class = ('even' === $class) ? 'odd' : 'even';
1591
        printf(
1592
            "<tr class='" . $class . "'><td align='left'><a href='%s' target ='_blank'>%s</a></td><td align='left'><a href='%s' target='_blank'>%s</a></td><td><a href='%s' target='_blank'>%s</a></td><td align='right'>%u</td></tr>\n",
1593
            $url1,
1594
            $myts->displayTarea($data['topic_title']),
1595
            $url2,
1596
            $myts->displayTarea($data['title']),
1597
            $url3,
1598
            htmlspecialchars($news->uname($data['uid']), ENT_QUOTES | ENT_HTML5),
1599
            $data['counter']
1600
        );
1601
    }
1602
    echo '</table>';
1603
1604
    // c) Best rated articles (this is an average)
1605
    $besratednews = $stats['besratednews'];
1606
    echo '<br><br>' . _AM_NEWS_STATS6;
1607
    echo "<table border='0' width='100%'><tr class='bg3'><th align='center'>" . _AM_TOPIC . "</th><th align='center'>" . _AM_TITLE . '</th><th>' . _AM_POSTER . '</th><th>' . _NW_RATING . "</th></tr>\n";
1608
    foreach ($besratednews as $storyid => $data) {
1609
        $url1  = XOOPS_URL . '/modules/' . $xoopsModule->dirname() . '/index.php?storytopic=' . $data['topicid'];
1610
        $url2  = XOOPS_URL . '/modules/' . $xoopsModule->dirname() . '/article.php?storyid=' . $storyid;
1611
        $url3  = XOOPS_URL . '/userinfo.php?uid=' . $data['uid'];
1612
        $class = ('even' === $class) ? 'odd' : 'even';
1613
        printf(
1614
            "<tr class='" . $class . "'><td align='left'><a href='%s' target ='_blank'>%s</a></td><td align='left'><a href='%s' target='_blank'>%s</a></td><td><a href='%s' target='_blank'>%s</a></td><td align='right'>%s</td></tr>\n",
1615
            $url1,
1616
            $myts->displayTarea($data['topic_title']),
1617
            $url2,
1618
            $myts->displayTarea($data['title']),
1619
            $url3,
1620
            htmlspecialchars($news->uname($data['uid']), ENT_QUOTES | ENT_HTML5),
1621
            number_format((float)$data['rating'], 2)
1622
        );
1623
    }
1624
    echo '</table></div><br><br><br>';
1625
1626
    // Last part of the stats, everything about authors
1627
    // a) Most readed authors
1628
    $mostreadedauthors = $stats['mostreadedauthors'];
1629
    echo "<div class='center;'><b>" . _AM_NEWS_STATS10 . '</b><br><br>' . _AM_NEWS_STATS7 . "<br>\n";
1630
    echo "<table border='0' width='100%'><tr class='bg3'><th>" . _AM_POSTER . '</th><th>' . _NW_VIEWS . "</th></tr>\n";
1631
    foreach ($mostreadedauthors as $uid => $reads) {
1632
        $url   = XOOPS_URL . '/userinfo.php?uid=' . $uid;
1633
        $class = ('even' === $class) ? 'odd' : 'even';
1634
        printf("<tr class='" . $class . "'><td align='left'><a href='%s' target ='_blank'>%s</a></td><td align='right'>%u</td></tr>\n", $url, htmlspecialchars($news->uname($uid), ENT_QUOTES | ENT_HTML5), $reads);
1635
    }
1636
    echo '</table>';
1637
1638
    // b) Best rated authors
1639
    $bestratedauthors = $stats['bestratedauthors'];
1640
    echo '<br><br>' . _AM_NEWS_STATS8;
1641
    echo "<table border='0' width='100%'><tr class='bg3'><th>" . _AM_POSTER . '</th><th>' . _NW_RATING . "</th></tr>\n";
1642
    foreach ($bestratedauthors as $uid => $rating) {
1643
        $url   = XOOPS_URL . '/userinfo.php?uid=' . $uid;
1644
        $class = ('even' === $class) ? 'odd' : 'even';
1645
        printf("<tr class='" . $class . "'><td align='left'><a href='%s' target ='_blank'>%s</a></td><td align='right'>%u</td></tr>\n", $url, htmlspecialchars($news->uname($uid), ENT_QUOTES | ENT_HTML5), $rating);
1646
    }
1647
    echo '</table>';
1648
1649
    // c) Biggest contributors
1650
    $biggestcontributors = $stats['biggestcontributors'];
1651
    echo '<br><br>' . _AM_NEWS_STATS9;
1652
    echo "<table border='0' width='100%'><tr class='bg3'><th>" . _AM_POSTER . '</th><th>' . _AM_NEWS_STATS11 . "</th></tr>\n";
1653
    foreach ($biggestcontributors as $uid => $count) {
1654
        $url   = XOOPS_URL . '/userinfo.php?uid=' . $uid;
1655
        $class = ('even' === $class) ? 'odd' : 'even';
1656
        printf("<tr class='" . $class . "'><td align='left'><a href='%s' target ='_blank'>%s</a></td><td align='right'>%u</td></tr>\n", $url, htmlspecialchars($news->uname($uid), ENT_QUOTES | ENT_HTML5), $count);
1657
    }
1658
    echo '</table></div><br>';
1659
}
1660
1661
/**
1662
 * Metagen
1663
 *
1664
 * Metagen is a system that can help you to have your page best indexed by search engines.
1665
 * Except if you type meta keywords and meta descriptions yourself, the module will automatically create them.
1666
 * From here you can also manage some other options like the maximum number of meta keywords to create and
1667
 * the keywords apparition's order.
1668
 */
1669
function getMetagen(): void
1670
{
1671
    require_once XOOPS_ROOT_PATH . '/class/xoopsformloader.php';
1672
    global $xoopsModule, $xoopsConfig, $cfg;
1673
    $helper = Helper::getInstance();
0 ignored issues
show
The assignment to $helper is dead and can be removed.
Loading history...
1674
1675
    xoops_cp_header();
1676
    $myts   = \MyTextSanitizer::getInstance();
0 ignored issues
show
The assignment to $myts is dead and can be removed.
Loading history...
1677
    $helper = Helper::getInstance();
1678
    $helper->loadLanguage('main');
1679
1680
    $adminObject = Admin::getInstance();
1681
    $adminObject->displayNavigation('index.php?op=metagen');
1682
    //echo "<h1>"._AM_NEWS_METAGEN."</h1>";
1683
    echo _AM_NEWS_METAGEN_DESC . '<br><br>';
1684
1685
    // Metagen Options
1686
    $registry = new Registryfile('news_metagen_options.txt');
1687
    /** @var string $content */
1688
    $content = $registry->getfile();
1689
    if ('' !== xoops_trim($content)) {
1690
        [$keywordscount, $keywordsorder] = explode(',', $content);
1691
    } else {
1692
        $keywordscount = $cfg['meta_keywords_count'];
1693
        $keywordsorder = $cfg['meta_keywords_order'];
1694
    }
1695
    $sform = new \XoopsThemeForm(_OPTIONS, 'metagenoptions', XOOPS_URL . '/modules/news/admin/index.php', 'post', true);
1696
    $sform->addElement(new \XoopsFormHidden('op', 'metagenoptions'), false);
1697
    $sform->addElement(new \XoopsFormText(_AM_NEWS_META_KEYWORDS_CNT, 'keywordscount', 4, 6, $keywordscount), true);
1698
    $keywordsorder = new \XoopsFormRadio(_AM_NEWS_META_KEYWORDS_ORDER, 'keywordsorder', $keywordsorder);
1699
    $keywordsorder->addOption(0, _AM_NEWS_META_KEYWORDS_INTEXT);
1700
    $keywordsorder->addOption(1, _AM_NEWS_META_KEYWORDS_FREQ1);
1701
    $keywordsorder->addOption(2, _AM_NEWS_META_KEYWORDS_FREQ2);
1702
    $sform->addElement($keywordsorder, false);
1703
    $buttonTray = new \XoopsFormElementTray('', '');
1704
    $submit_btn = new \XoopsFormButton('', 'post', _AM_MODIFY, 'submit');
1705
    $buttonTray->addElement($submit_btn);
1706
    $sform->addElement($buttonTray);
1707
    $sform->display();
1708
1709
    // Blacklist
1710
    $sform = new \XoopsThemeForm(_AM_NEWS_BLACKLIST, 'metagenblacklist', XOOPS_URL . '/modules/news/admin/index.php', 'post', true);
1711
    $sform->addElement(new \XoopsFormHidden('op', 'metagenblacklist'), false);
1712
1713
    // Remove words
1714
    $remove_tray = new \XoopsFormElementTray(_AM_NEWS_BLACKLIST);
1715
    $remove_tray->setDescription(_AM_NEWS_BLACKLIST_DESC);
1716
    $blacklist = new \XoopsFormSelect('', 'blacklist', '', 5, true);
1717
    $words     = [];
0 ignored issues
show
The assignment to $words is dead and can be removed.
Loading history...
1718
1719
    $metablack = new Blacklist();
1720
    $words     = $metablack->getAllKeywords();
1721
    if ($words && is_array($words)) {
1722
        foreach ($words as $key => $value) {
1723
            $blacklist->addOption($key, $value);
1724
        }
1725
    }
1726
1727
    $blacklist->setDescription(_AM_NEWS_BLACKLIST_DESC);
1728
    $remove_tray->addElement($blacklist, false);
1729
    $remove_btn = new \XoopsFormButton('', 'go', _AM_DELETE, 'submit');
1730
    $remove_tray->addElement($remove_btn, false);
1731
    $sform->addElement($remove_tray);
1732
1733
    // Add some words
1734
    $add_tray = new \XoopsFormElementTray(_AM_NEWS_BLACKLIST_ADD);
1735
    $add_tray->setDescription(_AM_NEWS_BLACKLIST_ADD_DSC);
1736
    $add_field = new \XoopsFormTextArea('', 'keywords', '', 5, 70);
1737
    $add_tray->addElement($add_field, false);
1738
    $add_btn = new \XoopsFormButton('', 'go', _AM_ADD, 'submit');
1739
    $add_tray->addElement($add_btn, false);
1740
    $sform->addElement($add_tray);
1741
    $sform->display();
1742
}
1743
1744
/**
1745
 * Save metagen's blacklist words
1746
 */
1747
function saveMetagenBlackList(): void
1748
{
1749
    $blacklist = new Blacklist();
1750
    $words     = $blacklist->getAllKeywords();
0 ignored issues
show
The assignment to $words is dead and can be removed.
Loading history...
1751
1752
    if (Request::hasVar('go', 'POST') && _AM_DELETE == $_POST['go']) {
1753
        foreach ($_POST['blacklist'] as $black_id) {
1754
            $blacklist->delete($black_id);
1755
        }
1756
        $blacklist->store();
1757
    } elseif (Request::hasVar('go', 'POST') && _AM_ADD == $_POST['go']) {
1758
        $p_keywords = $_POST['keywords'];
1759
        $keywords   = explode("\n", $p_keywords);
1760
        foreach ($keywords as $keyword) {
1761
            if ('' !== xoops_trim($keyword)) {
1762
                $blacklist->addkeywords(xoops_trim($keyword));
1763
            }
1764
        }
1765
        $blacklist->store();
1766
    }
1767
    redirect_header('index.php?op=metagen', 0, _AM_DBUPDATED);
1768
}
1769
1770
/**
1771
 * Save Metagen Options
1772
 */
1773
function saveMetagenOptions(): void
1774
{
1775
    $registry = new Registryfile('news_metagen_options.txt');
1776
    $registry->savefile(Request::getInt('keywordscount', 0, 'POST') . ',' . Request::getInt('keywordsorder', 0, 'POST'));
1777
    redirect_header('index.php?op=metagen', 0, _AM_DBUPDATED);
1778
}
1779
1780
// **********************************************************************************************************************************************
1781
// **** Main
1782
// **********************************************************************************************************************************************
1783
$op          = Request::getString('op', 'default');
1784
$adminObject = Admin::getInstance();
1785
switch ($op) {
1786
    case 'deletefile':
1787
        xoops_cp_header();
1788
        if ('newsletter' === $_GET['type']) {
1789
            $newsfile = XOOPS_ROOT_PATH . '/uploads/news/newsletter.txt';
1790
            if (unlink($newsfile)) {
1791
                redirect_header('index.php', 2, _AM_NEWS_DELETED_OK);
1792
            } else {
1793
                redirect_header('index.php', 2, _AM_NEWS_DELETED_PB);
1794
            }
1795
        } elseif ('xml' === $_GET['type']) {
1796
            $xmlfile = XOOPS_ROOT_PATH . '/uploads/news/stories.xml';
1797
            if (unlink($xmlfile)) {
1798
                redirect_header('index.php', 2, _AM_NEWS_DELETED_OK);
1799
            } else {
1800
                redirect_header('index.php', 2, _AM_NEWS_DELETED_PB);
1801
            }
1802
        }
1803
        break;
1804
    case 'newarticle':
1805
        xoops_cp_header();
1806
        $adminObject->displayNavigation('index.php?op=newarticle');
1807
        echo '<h4>' . _AM_CONFIG . '</h4>';
1808
        require_once XOOPS_ROOT_PATH . '/class/module.textsanitizer.php';
1809
        newSubmissions();
1810
        autoStories();
1811
        lastStories();
1812
        expStories();
1813
        echo '<br>';
1814
        echo '<h4>' . _AM_POSTNEWARTICLE . '</h4>';
1815
        $type         = 'admin';
1816
        $title        = '';
1817
        $topicdisplay = 0;
1818
        $topicalign   = 'R';
1819
        $ihome        = 0;
1820
        $hometext     = '';
1821
        $bodytext     = '';
1822
        $notifypub    = 1;
1823
        $nohtml       = 0;
1824
        $approve      = 0;
1825
        $nosmiley     = 0;
1826
        $autodate     = '';
1827
        $expired      = '';
1828
        $topicid      = 0;
1829
        $returnside   = 1;
1830
        $published    = 0;
1831
        $description  = '';
1832
        $keywords     = '';
1833
        $helper       = Helper::getInstance();
1834
        $helper->loadLanguage('main');
1835
1836
        if (1 == $helper->getConfig('autoapprove')) {
1837
            $approve = 1;
1838
        } elseif (1 == $helper->getConfig('moduleAdminApproveChecked') && (is_object($xoopsUser) && $xoopsUser->isAdmin($xoopsModule->getVar('mid')))) {
1839
            $approve = 1;
1840
        }
1841
        $approveprivilege = 1;
1842
        require_once XOOPS_ROOT_PATH . '/modules/news/include/storyform.original.php';
1843
        break;
1844
    case 'delete':
1845
        $storyid = 0;
1846
        if (Request::hasVar('storyid', 'GET')) {
1847
            $storyid = Request::getInt('storyid', 0, 'GET');
1848
        } elseif (Request::hasVar('storyid', 'POST')) {
1849
            $storyid = Request::getInt('storyid', 0, 'POST');
1850
        }
1851
1852
        if (Request::hasVar('ok', 'POST')) {
1853
            if (empty($storyid)) {
1854
                redirect_header('index.php?op=newarticle', 2, _AM_EMPTYNODELETE);
1855
            }
1856
            $story = new NewsStory($storyid);
1857
            $story->delete();
1858
            $sfiles   = new Files();
1859
            /** @var array $filesarr */
1860
            $filesarr = $sfiles->getAllbyStory($storyid);
1861
            if (count($filesarr) > 0) {
1862
                foreach ($filesarr as $onefile) {
1863
                    $onefile->delete();
1864
                }
1865
            }
1866
            xoops_comment_delete($xoopsModule->getVar('mid'), $storyid);
1867
            xoops_notification_deletebyitem($xoopsModule->getVar('mid'), 'story', $storyid);
1868
            Utility::updateCache();
1869
            redirect_header('index.php?op=newarticle', 1, _AM_DBUPDATED);
1870
        } else {
1871
            $story = new NewsStory($storyid);
1872
            xoops_cp_header();
1873
            echo '<h4>' . _AM_CONFIG . '</h4>';
1874
            xoops_confirm(['op' => 'delete', 'storyid' => $storyid, 'ok' => 1], 'index.php', _AM_RUSUREDEL . '<br>' . $story->title());
1875
        }
1876
        break;
1877
    case 'topicsmanager':
1878
        topicsmanager();
1879
        break;
1880
    case 'addTopic':
1881
        addTopic();
1882
        break;
1883
    case 'delTopic':
1884
        delTopic();
1885
        break;
1886
    case 'modTopicS':
1887
        modTopicS();
1888
        break;
1889
    case 'edit':
1890
        $helper = Helper::getInstance();
1891
        $helper->loadLanguage('main');
1892
        require_once XOOPS_ROOT_PATH . '/modules/news/submit.php';
1893
        break;
1894
    case 'prune':
1895
        setPruneManager();
1896
        break;
1897
    case 'confirmbeforetoprune':
1898
        confirmBeforePrune();
1899
        break;
1900
    case 'prunenews':
1901
        pruneNews();
1902
        break;
1903
    case 'export':
1904
        exportNews();
1905
        break;
1906
    case 'launchexport':
1907
        launchExport();
1908
        break;
1909
    case 'configurenewsletter':
1910
        createNewsletter();
1911
        break;
1912
    case 'launchnewsletter':
1913
        launchNewsletter();
1914
        break;
1915
    case 'stats':
1916
        getStats();
1917
        break;
1918
    case 'metagen':
1919
        getMetagen();
1920
        break;
1921
    case 'metagenoptions':
1922
        saveMetagenOptions();
1923
        break;
1924
    case 'metagenblacklist':
1925
        saveMetagenBlackList();
1926
        break;
1927
    case 'verifydb':
1928
        xoops_cp_header();
1929
        //news_adminmenu();
1930
        $tbllist = $xoopsDB->prefix('news_stories') . ',' . $xoopsDB->prefix('news_topics') . ',' . $xoopsDB->prefix('news_stories_files') . ',' . $xoopsDB->prefix('news_stories_votedata');
1931
        $xoopsDB->queryF('OPTIMIZE TABLE ' . $tbllist);
1932
        $xoopsDB->queryF('CHECK TABLE ' . $tbllist);
1933
        $xoopsDB->queryF('ANALYZE TABLE ' . $tbllist);
1934
        redirect_header('index.php', 3, _AM_DBUPDATED);
1935
        break;
1936
    case 'default':
1937
    default:
1938
        xoops_cp_header();
1939
1940
        $folder = [
1941
            XOOPS_ROOT_PATH . '/uploads/news/',
1942
            XOOPS_ROOT_PATH . '/uploads/news/file',
1943
            XOOPS_ROOT_PATH . '/uploads/news/image',
1944
        ];
1945
1946
        $topicsHandler  = $helper->getHandler('NewsTopics');
1947
        $storiesHandler = $helper->getHandler('NewsStories');
1948
1949
        //compte "total"
1950
        $count_stories = $storiesHandler->getCount();
1951
        //compte "attente"
1952
        $criteria = new \CriteriaCompo();
1953
        $criteria->add(new \Criteria('ihome', 1));
1954
        $stories_ihome = $storiesHandler->getCount($criteria);
1955
1956
        $criteria = new \CriteriaCompo();
1957
        $criteria->add(new \Criteria('published', 0, '>'));
1958
        $stories_published = $storiesHandler->getCount($criteria);
1959
1960
        $stories_need_approval = $count_stories - $stories_published;
1961
1962
        $criteria = new \CriteriaCompo();
1963
        $criteria->add(new \Criteria('expired', 0, '>'));
1964
        $criteria->add(new \Criteria('expired', time(), '<'));
1965
        $stories_expired = $storiesHandler->getCount($criteria);
1966
1967
        $criteria = new \CriteriaCompo();
1968
        $criteria->add(new \Criteria('expired', 0, '>'));
1969
        $criteria->add(new \Criteria('expired', time(), '>'));
1970
        $stories_expired_soon = $storiesHandler->getCount($criteria);
1971
1972
        //compte "total"
1973
        $count_topics = $topicsHandler->getCount();
1974
        //compte "attente"
1975
        $criteria = new \CriteriaCompo();
1976
        $criteria->add(new \Criteria('menu', 1));
1977
        $topics_menu = $topicsHandler->getCount($criteria);
1978
1979
        $clr_count_stories = (0 == $count_stories) ? 'red' : 'green';
1980
        $clr_count_topics  = (0 == $count_topics) ? 'red' : 'green';
1981
        $clr_ihome_stories = (0 == $stories_ihome) ? 'red' : 'green';
1982
        $clr_menu_topics   = (0 == $topics_menu) ? 'red' : 'green';
1983
1984
        $clr_published_stories         = (0 == $stories_published) ? 'red' : 'green';
1985
        $clr_need_approval_stories     = (0 == $stories_need_approval) ? 'green' : 'red';
1986
        $clr_expired_stories           = (0 == $stories_expired) ? 'red' : 'green';
1987
        $clr_need_expired_soon_stories = (0 == $stories_expired_soon) ? 'red' : 'green';
1988
1989
        $adminObject->addInfoBox(_AM_NEWS_STATISTICS);
1990
        $adminObject->addInfoBoxLine(sprintf(_AM_NEWS_THEREARE_TOPICS, $count_topics), '', $clr_count_topics);
1991
        $adminObject->addInfoBoxLine(sprintf(_AM_NEWS_THEREARE_TOPICS_ONLINE, $topics_menu), '', $clr_menu_topics);
1992
        $adminObject->addInfoBoxLine(sprintf(_AM_NEWS_THEREARE_STORIES, $count_stories), '', $clr_count_stories);
1993
        $adminObject->addInfoBoxLine(sprintf(_AM_NEWS_THEREARE_STORIES_ONLINE, $stories_ihome), '', $clr_ihome_stories);
1994
1995
        $adminObject->addInfoBoxLine(sprintf(_AM_NEWS_THEREARE_STORIES_APPROVED, $stories_published), '', $clr_ihome_stories);
1996
        $adminObject->addInfoBoxLine(sprintf(_AM_NEWS_THEREARE_STORIES_NEED_APPROVAL, $stories_need_approval), '', $clr_need_approval_stories);
1997
        $adminObject->addInfoBoxLine(sprintf(_AM_NEWS_THEREARE_STORIES_EXPIRED, $stories_expired), '', $clr_expired_stories);
1998
        $adminObject->addInfoBoxLine(sprintf(_AM_NEWS_THEREARE_STORIES_EXPIRED_SOON, $stories_expired_soon), '', $clr_need_expired_soon_stories);
1999
2000
        foreach (array_keys($folder) as $i) {
2001
            $adminObject->addConfigBoxLine($folder[$i], 'folder');
2002
            $adminObject->addConfigBoxLine([$folder[$i], '777'], 'chmod');
2003
        }
2004
2005
        $adminObject->displayNavigation(basename(__FILE__));
2006
2007
        //check for latest release
2008
        //$newRelease = $utility::checkVerModule($helper);
2009
        //if (null !== $newRelease) {
2010
        //    $adminObject->addItemButton($newRelease[0], $newRelease[1], 'download', 'style="color : Red"');
2011
        //}
2012
2013
        //------------- Test Data Buttons ----------------------------
2014
        if ($helper->getConfig('displaySampleButton')) {
2015
            TestdataButtons::loadButtonConfig($adminObject);
2016
            $adminObject->displayButton('left', '');
2017
        }
2018
        $op = Request::getString('op', 0, 'GET');
2019
        switch ($op) {
2020
            case 'hide_buttons':
2021
                TestdataButtons::hideButtons();
2022
                break;
2023
            case 'show_buttons':
2024
                TestdataButtons::showButtons();
2025
                break;
2026
        }
2027
        //------------- End Test Data Buttons ----------------------------
2028
2029
        $adminObject->displayIndex();
2030
2031
        echo $utility::getServerStats();
2032
2033
        break;
2034
}
2035
require_once __DIR__ . '/admin_footer.php';
2036