Issues (371)

Security Analysis    no vulnerabilities found

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

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

class/Utility.php (36 issues)

1
<?php declare(strict_types=1);
2
3
namespace XoopsModules\Publisher;
4
5
/*
6
 You may not change or alter any portion of this comment or credits
7
 of supporting developers from this source code or any supporting source code
8
 which is considered copyrighted (c) material of the original comment or credit authors.
9
10
 This program is distributed in the hope that it will be useful,
11
 but WITHOUT ANY WARRANTY; without even the implied warranty of
12
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13
 */
14
15
/**
16
 * PublisherUtil Class
17
 *
18
 * @copyright   XOOPS Project (https://xoops.org)
19
 * @license     https://www.fsf.org/copyleft/gpl.html GNU public license
20
 * @author      XOOPS Development Team
21
 * @since       1.03
22
 */
23
24
use Xmf\Request;
25
26
/**
27
 * Class Utility
28
 */
29
class Utility extends Common\SysUtility
30
{
31
    //--------------- Custom module methods -----------------------------
32
    /**
33
     * Function responsible for checking if a directory exists, we can also write in and create an index.html file
34
     *
35
     * @param string $folder The full path of the directory to check
36
     */
37
    public static function createFolder($folder): void
38
    {
39
        try {
40
            if (!\is_dir($folder)) {
41
                if (!\is_dir($folder) && !\mkdir($folder) && !\is_dir($folder)) {
42
                    throw new \RuntimeException(\sprintf('Unable to create the %s directory', $folder));
43
                }
44
                file_put_contents($folder . '/index.html', '<script>history.go(-1);</script>');
45
            }
46
        } catch (\Throwable $e) {
47
            echo 'Caught exception: ', $e->getMessage(), "\n", '<br>';
48
        }
49
    }
50
51
    /**
52
     * @param $file
53
     * @param $folder
54
     * @return bool
55
     */
56
    public static function copyFile(string $file, string $folder): bool
57
    {
58
        return \copy($file, $folder);
59
        //        try {
60
        //            if (!is_dir($folder)) {
61
        //                throw new \RuntimeException(sprintf('Unable to copy file as: %s ', $folder));
62
        //            } else {
63
        //                return copy($file, $folder);
64
        //            }
65
        //        } catch (\Exception $e) {
66
        //            echo 'Caught exception: ', $e->getMessage(), "\n", "<br>";
67
        //        }
68
        //        return false;
69
    }
70
71
    /**
72
     * @param $src
73
     * @param $dst
74
     */
75
    public static function recurseCopy($src, $dst): void
76
    {
77
        $dir = \opendir($src);
78
        //    @mkdir($dst);
79
        while (false !== ($file = \readdir($dir))) {
80
            if (('.' !== $file) && ('..' !== $file)) {
81
                if (\is_dir($src . '/' . $file)) {
82
                    self::recurseCopy($src . '/' . $file, $dst . '/' . $file);
83
                } else {
84
                    \copy($src . '/' . $file, $dst . '/' . $file);
85
                }
86
            }
87
        }
88
        \closedir($dir);
89
    }
90
91
    // auto create folders----------------------------------------
92
    //TODO rename this function? And exclude image folder?
93
    public static function createDir(): void
94
    {
95
        // auto crate folders
96
        //        $thePath = static::getUploadDir();
97
98
        if (static::getPathStatus('root', true) < 0) {
99
            $thePath = static::getUploadDir();
100
            $res     = static::mkdir($thePath);
101
            $msg     = $res ? \_AM_PUBLISHER_DIRCREATED : \_AM_PUBLISHER_DIRNOTCREATED;
0 ignored issues
show
The assignment to $msg is dead and can be removed.
Loading history...
102
        }
103
104
        if (static::getPathStatus('images', true) < 0) {
105
            $thePath = static::getImageDir();
106
            $res     = static::mkdir($thePath);
107
108
            if ($res) {
109
                $source = PUBLISHER_ROOT_PATH . '/assets/images/blank.png';
0 ignored issues
show
The constant XoopsModules\Publisher\PUBLISHER_ROOT_PATH was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
110
                $dest   = $thePath . 'blank.png';
111
                static::copyr($source, $dest);
112
            }
113
            $msg = $res ? \_AM_PUBLISHER_DIRCREATED : \_AM_PUBLISHER_DIRNOTCREATED;
114
        }
115
116
        if (static::getPathStatus('images/category', true) < 0) {
117
            $thePath = static::getImageDir('category');
118
            $res     = static::mkdir($thePath);
119
120
            if ($res) {
121
                $source = PUBLISHER_ROOT_PATH . '/assets/images/blank.png';
122
                $dest   = $thePath . 'blank.png';
123
                static::copyr($source, $dest);
124
            }
125
            $msg = $res ? \_AM_PUBLISHER_DIRCREATED : \_AM_PUBLISHER_DIRNOTCREATED;
126
        }
127
128
        if (static::getPathStatus('images/item', true) < 0) {
129
            $thePath = static::getImageDir('item');
130
            $res     = static::mkdir($thePath);
131
132
            if ($res) {
133
                $source = PUBLISHER_ROOT_PATH . '/assets/images/blank.png';
134
                $dest   = $thePath . 'blank.png';
135
                static::copyr($source, $dest);
136
            }
137
            $msg = $res ? \_AM_PUBLISHER_DIRCREATED : \_AM_PUBLISHER_DIRNOTCREATED;
138
        }
139
140
        if (static::getPathStatus('content', true) < 0) {
141
            $thePath = static::getUploadDir(true, 'content');
142
            $res     = static::mkdir($thePath);
143
            $msg     = $res ? \_AM_PUBLISHER_DIRCREATED : \_AM_PUBLISHER_DIRNOTCREATED;
144
        }
145
    }
146
147
    public static function buildTableItemTitleRow(): void
148
    {
149
        echo "<table width='100%' cellspacing='1' cellpadding='3' border='0' class='outer'>";
150
        echo '<tr>';
151
        echo "<th width='40px' class='bg3' align='center'><strong>" . \_AM_PUBLISHER_ITEMID . '</strong></td>';
152
        echo "<th width='100px' class='bg3' align='center'><strong>" . \_AM_PUBLISHER_ITEMCAT . '</strong></td>';
153
        echo "<th class='bg3' align='center'><strong>" . \_AM_PUBLISHER_TITLE . '</strong></td>';
154
        echo "<th width='100px' class='bg3' align='center'><strong>" . \_AM_PUBLISHER_CREATED . '</strong></td>';
155
156
        echo "<th width='50px' class='bg3' align='center'><strong>" . \_CO_PUBLISHER_WEIGHT . '</strong></td>';
157
        echo "<th width='50px' class='bg3' align='center'><strong>" . \_AM_PUBLISHER_HITS . '</strong></td>';
158
        echo "<th width='60px' class='bg3' align='center'><strong>" . \_AM_PUBLISHER_RATE . '</strong></td>';
159
        echo "<th width='50px' class='bg3' align='center'><strong>" . \_AM_PUBLISHER_VOTES . '</strong></td>';
160
        echo "<th width='60px' class='bg3' align='center'><strong>" . \_AM_PUBLISHER_COMMENTS_COUNT . '</strong></td>';
161
162
        echo "<th width='90px' class='bg3' align='center'><strong>" . \_CO_PUBLISHER_STATUS . '</strong></td>';
163
        echo "<th width='90px' class='bg3' align='center'><strong>" . \_AM_PUBLISHER_ACTION . '</strong></td>';
164
        echo '</tr>';
165
    }
166
167
    /**
168
     * @param int $level
169
     */
170
    public static function displayCategory(Category $categoryObj, $level = 0): void
171
    {
172
        $helper       = Helper::getInstance();
173
        $configurator = new Common\Configurator();
174
        $icons        = $configurator->icons;
175
176
        $description = $categoryObj->description;
177
        if (!XOOPS_USE_MULTIBYTES && !empty($description)) {
178
            if (\mb_strlen($description) >= 100) {
179
                $description = \mb_substr($description, 0, 100 - 1) . '...';
0 ignored issues
show
The assignment to $description is dead and can be removed.
Loading history...
180
            }
181
        }
182
        $modify = "<a href='category.php?op=mod&amp;categoryid=" . $categoryObj->categoryid() . '&amp;parentid=' . $categoryObj->parentid() . "'>" . $icons['edit'] . '</a>';
0 ignored issues
show
The method parentid() does not exist on XoopsModules\Publisher\Category. Since you implemented __call, consider adding a @method annotation. ( Ignorable by Annotation )

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

182
        $modify = "<a href='category.php?op=mod&amp;categoryid=" . $categoryObj->categoryid() . '&amp;parentid=' . $categoryObj->/** @scrutinizer ignore-call */ parentid() . "'>" . $icons['edit'] . '</a>';
Loading history...
The method categoryid() does not exist on XoopsModules\Publisher\Category. Since you implemented __call, consider adding a @method annotation. ( Ignorable by Annotation )

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

182
        $modify = "<a href='category.php?op=mod&amp;categoryid=" . $categoryObj->/** @scrutinizer ignore-call */ categoryid() . '&amp;parentid=' . $categoryObj->parentid() . "'>" . $icons['edit'] . '</a>';
Loading history...
183
        $delete = "<a href='category.php?op=del&amp;categoryid=" . $categoryObj->categoryid() . "'>" . $icons['delete'] . '</a>';
184
        $spaces = \str_repeat('&nbsp;', ($level * 3));
185
        /*
186
        $spaces = '';
187
        for ($j = 0; $j < $level; ++$j) {
188
            $spaces .= '&nbsp;&nbsp;&nbsp;';
189
        }
190
        */
191
        echo "<tr>\n"
192
             . "<td class='even center'>"
193
             . $categoryObj->categoryid()
194
             . "</td>\n"
195
             . "<td class='even left'>"
196
             . $spaces
197
             . "<a href='"
198
             . PUBLISHER_URL
0 ignored issues
show
The constant XoopsModules\Publisher\PUBLISHER_URL was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
199
             . '/category.php?categoryid='
200
             . $categoryObj->categoryid()
201
             . "'><img src='"
202
             . PUBLISHER_URL
203
             . "/assets/images/links/subcat.gif' alt=''>&nbsp;"
204
             . $categoryObj->name()
0 ignored issues
show
The method name() does not exist on XoopsModules\Publisher\Category. Since you implemented __call, consider adding a @method annotation. ( Ignorable by Annotation )

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

204
             . $categoryObj->/** @scrutinizer ignore-call */ name()
Loading history...
205
             . "</a></td>\n"
206
             . "<td class='even center'>"
207
             . $categoryObj->weight()
0 ignored issues
show
The method weight() does not exist on XoopsModules\Publisher\Category. Since you implemented __call, consider adding a @method annotation. ( Ignorable by Annotation )

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

207
             . $categoryObj->/** @scrutinizer ignore-call */ weight()
Loading history...
208
             . "</td>\n"
209
             . "<td class='even center'> {$modify} {$delete} </td>\n"
210
             . "</tr>\n";
211
        $subCategoriesObj = $helper->getHandler('Category')
212
                                   ->getCategories(0, 0, $categoryObj->categoryid());
213
        if (\count($subCategoriesObj) > 0) {
214
            ++$level;
215
            foreach ($subCategoriesObj as $thiscat) {
216
                self::displayCategory($thiscat, $level);
217
            }
218
            unset($key);
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $key seems to be never defined.
Loading history...
219
        }
220
        //        unset($categoryObj);
221
    }
222
223
    /**
224
     * @param bool $showmenu
225
     * @param int  $fileid
226
     * @param int  $itemId
227
     */
228
    public static function editFile($showmenu = false, $fileid = 0, $itemId = 0): void
0 ignored issues
show
The parameter $showmenu is not used and could be removed. ( Ignorable by Annotation )

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

228
    public static function editFile(/** @scrutinizer ignore-unused */ $showmenu = false, $fileid = 0, $itemId = 0): void

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

Loading history...
229
    {
230
        $helper = Helper::getInstance();
231
        require_once $GLOBALS['xoops']->path('class/xoopsformloader.php');
232
233
        // if there is a parameter, and the id exists, retrieve data: we're editing a file
234
        if (0 != $fileid) {
235
            // Creating the File object
236
            /** @var \XoopsModules\Publisher\File $fileObj */
237
            $fileObj = $helper->getHandler('File')
238
                              ->get($fileid);
239
240
            if ($fileObj->notLoaded()) {
241
                \redirect_header('<script>javascript:history.go(-1)</script>', 1, \_AM_PUBLISHER_NOFILESELECTED);
242
            }
243
244
            echo "<br>\n";
245
            echo "<span style='color: #2F5376; font-weight: bold; font-size: 16px; margin: 6px 6px 0 0; '>" . \_AM_PUBLISHER_FILE_EDITING . '</span>';
246
            echo '<span style="color: #567; margin: 3px 0 12px 0; font-size: small; display: block; ">' . \_AM_PUBLISHER_FILE_EDITING_DSC . '</span>';
247
            static::openCollapsableBar('editfile', 'editfileicon', \_AM_PUBLISHER_FILE_INFORMATIONS);
248
        } else {
249
            // there's no parameter, so we're adding an item
250
            $fileObj = $helper->getHandler('File')
251
                              ->create();
252
            $fileObj->setVar('itemid', $itemId);
253
            echo "<span style='color: #2F5376; font-weight: bold; font-size: 16px; margin: 6px 6px 0 0; '>" . \_AM_PUBLISHER_FILE_ADDING . '</span>';
254
            echo '<span style="color: #567; margin: 3px 0 12px 0; font-size: small; display: block; ">' . \_AM_PUBLISHER_FILE_ADDING_DSC . '</span>';
255
            static::openCollapsableBar('addfile', 'addfileicon', \_AM_PUBLISHER_FILE_INFORMATIONS);
256
        }
257
258
        // FILES UPLOAD FORM
259
        /** @var File $fileObj */
260
        $uploadForm = $fileObj->getForm();
261
        $uploadForm->display();
262
263
        if (0 != $fileid) {
264
            static::closeCollapsableBar('editfile', 'editfileicon');
265
        } else {
266
            static::closeCollapsableBar('addfile', 'addfileicon');
267
        }
268
    }
269
270
    /**
271
     * @param bool          $showmenu
272
     * @param int           $categoryid
273
     * @param int           $nbSubCats
274
     * @param Category|null $categoryObj
275
     */
276
    public static function editCategory($showmenu = false, $categoryid = 0, $nbSubCats = 4, $categoryObj = null): void
0 ignored issues
show
The parameter $showmenu is not used and could be removed. ( Ignorable by Annotation )

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

276
    public static function editCategory(/** @scrutinizer ignore-unused */ $showmenu = false, $categoryid = 0, $nbSubCats = 4, $categoryObj = null): void

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

Loading history...
277
    {
278
        $helper       = Helper::getInstance();
279
        $configurator = new Common\Configurator();
280
        $icons        = $configurator->icons;
281
282
        // if there is a parameter, and the id exists, retrieve data: we're editing a category
283
        /** @var Category $categoryObj */
284
        if (0 != $categoryid) {
285
            // Creating the category object for the selected category
286
            $categoryObj = $helper->getHandler('Category')
287
                                  ->get($categoryid);
288
            if ($categoryObj->notLoaded()) {
0 ignored issues
show
The method notLoaded() does not exist on XoopsObject. It seems like you code against a sub-type of XoopsObject such as XoopsModules\Publisher\Item or XoopsModules\Publisher\File or XoopsModules\Publisher\Category. ( Ignorable by Annotation )

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

288
            if ($categoryObj->/** @scrutinizer ignore-call */ notLoaded()) {
Loading history...
289
                \redirect_header('category.php', 1, \_AM_PUBLISHER_NOCOLTOEDIT);
290
            }
291
        } elseif (null === $categoryObj) {
292
            $categoryObj = $helper->getHandler('Category')
293
                                  ->create();
294
        }
295
296
        if (0 != $categoryid) {
297
            echo "<br>\n";
298
            static::openCollapsableBar('edittable', 'edittableicon', \_AM_PUBLISHER_EDITCOL, \_AM_PUBLISHER_CATEGORY_EDIT_INFO);
299
        } else {
300
            static::openCollapsableBar('createtable', 'createtableicon', \_AM_PUBLISHER_CATEGORY_CREATE, \_AM_PUBLISHER_CATEGORY_CREATE_INFO);
301
        }
302
303
        $sform = $categoryObj->getForm($nbSubCats);
304
        $sform->display();
305
306
        if ($categoryid) {
307
            static::closeCollapsableBar('edittable', 'edittableicon');
308
        } else {
309
            static::closeCollapsableBar('createtable', 'createtableicon');
310
        }
311
312
        //Added by fx2024
313
        if ($categoryid) {
314
            $selCat = $categoryid;
315
316
            static::openCollapsableBar('subcatstable', 'subcatsicon', \_AM_PUBLISHER_SUBCAT_CAT, \_AM_PUBLISHER_SUBCAT_CAT_DSC);
317
            // Get the total number of sub-categories
318
            $categoriesObj = $helper->getHandler('Category')
319
                                    ->get($selCat);
320
            $totalsubs     = $helper->getHandler('Category')
321
                                    ->getCategoriesCount($selCat);
322
            // creating the categories objects that are published
323
            $subcatsObj    = $helper->getHandler('Category')
324
                                    ->getCategories(0, 0, $categoriesObj->categoryid());
0 ignored issues
show
The method categoryid() does not exist on XoopsObject. It seems like you code against a sub-type of XoopsObject such as XoopsModules\Publisher\Item or XoopsModules\Publisher\File or XoopsModules\Publisher\Category. ( Ignorable by Annotation )

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

324
                                    ->getCategories(0, 0, $categoriesObj->/** @scrutinizer ignore-call */ categoryid());
Loading history...
325
            $totalSCOnPage = \count($subcatsObj);
0 ignored issues
show
The assignment to $totalSCOnPage is dead and can be removed.
Loading history...
326
            echo "<table width='100%' cellspacing=1 cellpadding=3 border=0 class = outer>";
327
            echo '<tr>';
328
            echo "<td width='60' class='bg3' align='left'><strong>" . \_AM_PUBLISHER_CATID . '</strong></td>';
329
            echo "<td width='20%' class='bg3' align='left'><strong>" . \_AM_PUBLISHER_CATCOLNAME . '</strong></td>';
330
            echo "<td class='bg3' align='left'><strong>" . \_AM_PUBLISHER_SUBDESCRIPT . '</strong></td>';
331
            echo "<td width='60' class='bg3' align='right'><strong>" . \_AM_PUBLISHER_ACTION . '</strong></td>';
332
            echo '</tr>';
333
            if ($totalsubs > 0) {
334
                foreach ($subcatsObj as $subcat) {
335
                    $modify = "<a href='category.php?op=mod&amp;categoryid=" . $subcat->categoryid() . "'>" . $icons['edit'] . '</a>';
336
                    $delete = "<a href='category.php?op=del&amp;categoryid=" . $subcat->categoryid() . "'>" . $icons['delete'] . '</a>';
337
                    echo '<tr>';
338
                    echo "<td class='head' align='left'>" . $subcat->categoryid() . '</td>';
339
                    echo "<td class='even' align='left'><a href='" . XOOPS_URL . '/modules/' . $helper->getModule()
340
                                                                                                      ->dirname() . '/category.php?categoryid=' . $subcat->categoryid() . '&amp;parentid=' . $subcat->parentid() . "'>" . $subcat->name() . '</a></td>';
341
                    echo "<td class='even' align='left'>" . $subcat->description() . '</td>';
342
                    echo "<td class='even' align='right'> {$modify} {$delete} </td>";
343
                    echo '</tr>';
344
                }
345
                //                unset($subcat);
346
            } else {
347
                echo '<tr>';
348
                echo "<td class='head' align='center' colspan= '7'>" . \_AM_PUBLISHER_NOSUBCAT . '</td>';
349
                echo '</tr>';
350
            }
351
            echo "</table>\n";
352
            echo "<br>\n";
353
            static::closeCollapsableBar('subcatstable', 'subcatsicon');
354
355
            static::openCollapsableBar('bottomtable', 'bottomtableicon', \_AM_PUBLISHER_CAT_ITEMS, \_AM_PUBLISHER_CAT_ITEMS_DSC);
356
            $startitem = Request::getInt('startitem');
357
            // Get the total number of published ITEMS
358
            $totalitems = $helper->getHandler('Item')
359
                                 ->getItemsCount($selCat, [Constants::PUBLISHER_STATUS_PUBLISHED]);
0 ignored issues
show
array(XoopsModules\Publi...ISHER_STATUS_PUBLISHED) of type array<integer,integer> is incompatible with the type string expected by parameter $status of XoopsModules\Publisher\I...andler::getItemsCount(). ( Ignorable by Annotation )

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

359
                                 ->getItemsCount($selCat, /** @scrutinizer ignore-type */ [Constants::PUBLISHER_STATUS_PUBLISHED]);
Loading history...
360
            // creating the items objects that are published
361
            $itemsObj = $helper->getHandler('Item')
362
                               ->getAllPublished($helper->getConfig('idxcat_perpage'), $startitem, $selCat);
363
            $allcats  = $helper->getHandler('Category')
364
                               ->getObjects(null, true);
365
            echo "<table width='100%' cellspacing=1 cellpadding=3 border=0 class = outer>";
366
            echo '<tr>';
367
            echo "<td width='40' class='bg3' align='center'><strong>" . \_AM_PUBLISHER_ITEMID . '</strong></td>';
368
            echo "<td width='20%' class='bg3' align='left'><strong>" . \_AM_PUBLISHER_ITEMCOLNAME . '</strong></td>';
369
            echo "<td class='bg3' align='left'><strong>" . \_AM_PUBLISHER_ITEMDESC . '</strong></td>';
370
            echo "<td width='90' class='bg3' align='center'><strong>" . \_AM_PUBLISHER_CREATED . '</strong></td>';
371
            echo "<td width='60' class='bg3' align='center'><strong>" . \_AM_PUBLISHER_ACTION . '</strong></td>';
372
            echo '</tr>';
373
            if ($totalitems > 0) {
374
                foreach ($itemsObj as $iValue) {
375
                    $categoryObj = $allcats[$iValue->categoryid()];
376
                    $modify      = "<a href='item.php?op=mod&amp;itemid=" . $iValue->itemid() . "'>" . $icons['edit'] . '</a>';
377
                    $delete      = "<a href='item.php?op=del&amp;itemid=" . $iValue->itemid() . "'>" . $icons['delete'] . '</a>';
378
                    echo '<tr>';
379
                    echo "<td class='head' align='center'>" . $iValue->itemid() . '</td>';
380
                    echo "<td class='even' align='left'>" . $categoryObj->name() . '</td>';
381
                    echo "<td class='even' align='left'>" . $iValue->getitemLink() . '</td>';
382
                    echo "<td class='even' align='center'>" . $iValue->getDatesub('s') . '</td>';
383
                    echo "<td class='even' align='center'> $modify $delete </td>";
384
                    echo '</tr>';
385
                }
386
            } else {
387
                $itemId = -1;
0 ignored issues
show
The assignment to $itemId is dead and can be removed.
Loading history...
388
                echo '<tr>';
389
                echo "<td class='head' align='center' colspan= '7'>" . \_AM_PUBLISHER_NOITEMS . '</td>';
390
                echo '</tr>';
391
            }
392
            echo "</table>\n";
393
            echo "<br>\n";
394
            $parentid         = Request::getInt('parentid', 0, 'GET');
395
            $pagenavExtraArgs = "op=mod&categoryid=$selCat&parentid=$parentid";
396
            \xoops_load('XoopsPageNav');
397
            $pagenav = new \XoopsPageNav($totalitems, $helper->getConfig('idxcat_perpage'), $startitem, 'startitem', $pagenavExtraArgs);
398
            echo '<div style="text-align:right;">' . $pagenav->renderNav() . '</div>';
399
            echo "<input type='button' name='button' onclick=\"location='item.php?op=mod&categoryid=" . $selCat . "'\" value='" . \_AM_PUBLISHER_CREATEITEM . "'>&nbsp;&nbsp;";
400
            echo '</div>';
401
        }
402
        //end of fx2024 code
403
    }
404
405
    //======================== FUNCTIONS =================================
406
407
    /**
408
     * Includes scripts in HTML header
409
     */
410
    public static function cpHeader(): void
411
    {
412
        \xoops_cp_header();
413
414
        //cannot use xoTheme, some conflit with admin gui
415
        echo '<link type="text/css" href="' . XOOPS_URL . '/modules/system/css/ui/' . \xoops_getModuleOption('jquery_theme', 'system') . '/ui.all.css" rel="stylesheet">
0 ignored issues
show
Deprecated Code introduced by
The function xoops_getModuleOption() has been deprecated. ( Ignorable by Annotation )

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

415
        echo '<link type="text/css" href="' . XOOPS_URL . '/modules/system/css/ui/' . /** @scrutinizer ignore-deprecated */ \xoops_getModuleOption('jquery_theme', 'system') . '/ui.all.css" rel="stylesheet">
Loading history...
416
    <link type="text/css" href="' . PUBLISHER_URL . '/assets/css/publisher.css" rel="stylesheet">
0 ignored issues
show
The constant XoopsModules\Publisher\PUBLISHER_URL was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
417
    <script type="text/javascript" src="' . PUBLISHER_URL . '/assets/js/funcs.js"></script>
418
    <script type="text/javascript" src="' . PUBLISHER_URL . '/assets/js/cookies.js"></script>
419
    <script type="text/javascript" src="' . XOOPS_URL . '/browse.php?Frameworks/jquery/jquery.js"></script>
420
    <!-- <script type="text/javascript" src="' . XOOPS_URL . '/browse.php?Frameworks/jquery/jquery-migrate-1.2.1.js"></script> -->
421
    <script type="text/javascript" src="' . XOOPS_URL . '/browse.php?Frameworks/jquery/plugins/jquery.ui.js"></script>
422
    <script type="text/javascript" src="' . PUBLISHER_URL . '/assets/js/ajaxupload.3.9.js"></script>
423
    <script type="text/javascript" src="' . PUBLISHER_URL . '/assets/js/publisher.js"></script>
424
    ';
425
    }
426
427
    /**
428
     * Default sorting for a given order
429
     *
430
     * @param string $sort
431
     * @return string
432
     */
433
    public static function getOrderBy($sort)
434
    {
435
        if ('datesub' === $sort) {
436
            return 'DESC';
437
        }
438
        if ('counter' === $sort) {
439
            return 'DESC';
440
        }
441
        if ('weight' === $sort) {
442
            return 'ASC';
443
        }
444
        if ('votes' === $sort) {
445
            return 'DESC';
446
        }
447
        if ('rating' === $sort) {
448
            return 'DESC';
449
        }
450
        if ('comments' === $sort) {
451
            return 'DESC';
452
        }
453
454
        return null;
455
    }
456
457
    /**
458
     * @credits Thanks to Mithandir
459
     * @param string $str
460
     * @param int    $start
461
     * @param int    $length
462
     * @param string $trimMarker
463
     * @return string
464
     */
465
    public static function substr($str, $start, $length, $trimMarker = '...')
466
    {
467
        // if the string is empty, let's get out ;-)
468
        if ('' == $str) {
469
            return $str;
470
        }
471
472
        // reverse a string that is shortened with '' as trimmarker
473
        $reversedString = \strrev(\xoops_substr($str, $start, $length, ''));
474
475
        // find first space in reversed string
476
        $positionOfSpace = \mb_strpos($reversedString, ' ', 0);
477
478
        // truncate the original string to a length of $length
479
        // minus the position of the last space
480
        // plus the length of the $trimMarker
481
        $truncatedString = \xoops_substr($str, $start, $length - $positionOfSpace + \mb_strlen($trimMarker), $trimMarker);
482
483
        return $truncatedString;
484
    }
485
486
    /**
487
     * @param string $document
488
     * @return mixed
489
     */
490
    public static function html2text($document)
491
    {
492
        // PHP Manual:: function preg_replace
493
        // $document should contain an HTML document.
494
        // This will remove HTML tags, javascript sections
495
        // and white space. It will also convert some
496
        // common HTML entities to their text equivalent.
497
        // Credits : newbb2
498
        $search = [
499
            "'<script[^>]*?>.*?</script>'si", // Strip out javascript
500
            "'<img.*?>'si", // Strip out img tags
501
            "'<[\/\!]*?[^<>]*?>'si", // Strip out HTML tags
502
            "'([\r\n])[\s]+'", // Strip out white space
503
            "'&(quot|#34);'i", // Replace HTML entities
504
            "'&(amp|#38);'i",
505
            "'&(lt|#60);'i",
506
            "'&(gt|#62);'i",
507
            "'&(nbsp|#160);'i",
508
            "'&(iexcl|#161);'i",
509
            "'&(cent|#162);'i",
510
            "'&(pound|#163);'i",
511
            "'&(copy|#169);'i",
512
        ]; // evaluate as php
513
514
        $replace = [
515
            '',
516
            '',
517
            '',
518
            '\\1',
519
            '"',
520
            '&',
521
            '<',
522
            '>',
523
            ' ',
524
            \chr(161),
525
            \chr(162),
526
            \chr(163),
527
            \chr(169),
528
        ];
529
530
        $text = \preg_replace($search, $replace, $document);
531
532
        \preg_replace_callback(
533
            '/&#(\d+);/',
534
            static function ($matches) {
535
                return \chr((int)($matches[1]));
536
            },
537
            $document
538
        );
539
540
        return $text;
541
        //<?php
542
    }
543
544
    /**
545
     * @return array
546
     */
547
    public static function getAllowedImagesTypes()
548
    {
549
        return ['jpg/jpeg', 'image/bmp', 'image/gif', 'image/jpeg', 'image/jpg', 'image/x-png', 'image/png', 'image/pjpeg'];
550
    }
551
552
    /**
553
     * @param bool $withLink
554
     * @return string
555
     */
556
    public static function moduleHome($withLink = true)
557
    {
558
        $helper = Helper::getInstance();
559
560
        if (!$helper->getConfig('format_breadcrumb_modname')) {
561
            return '';
562
        }
563
564
        if (!$withLink) {
565
            return $helper->getModule()
0 ignored issues
show
Bug Best Practice introduced by
The expression return $helper->getModule()->getVar('name') also could return the type array|boolean which is incompatible with the documented return type string.
Loading history...
566
                          ->getVar('name');
567
        }
568
569
        return '<a href="' . PUBLISHER_URL . '/">' . $helper->getModule()
0 ignored issues
show
The constant XoopsModules\Publisher\PUBLISHER_URL was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
570
                                                            ->getVar('name') . '</a>';
571
    }
572
573
    /**
574
     * Copy a file, or a folder and its contents
575
     *
576
     * @param string $source The source
577
     * @param string $dest   The destination
578
     * @return bool   Returns true on success, false on failure
579
     * @version     1.0.0
580
     * @author      Aidan Lister <[email protected]>
581
     */
582
    public static function copyr($source, $dest)
583
    {
584
        // Simple copy for a file
585
        if (\is_file($source)) {
586
            return \copy($source, $dest);
587
        }
588
589
        // Make destination directory
590
        if (!\is_dir($dest) && !\mkdir($dest) && !\is_dir($dest)) {
591
            throw new \RuntimeException(\sprintf('Directory "%s" was not created', $dest));
592
        }
593
594
        // Loop through the folder
595
        $dir = \dir($source);
596
        while (false !== ($entry = $dir->read())) {
597
            // Skip pointers
598
            if ('.' === $entry || '..' === $entry) {
599
                continue;
600
            }
601
602
            // Deep copy directories
603
            if (("$source/$entry" !== $dest) && \is_dir("$source/$entry")) {
604
                static::copyr("$source/$entry", "$dest/$entry");
605
            } else {
606
                \copy("$source/$entry", "$dest/$entry");
607
            }
608
        }
609
610
        // Clean up
611
        $dir->close();
612
613
        return true;
614
    }
615
616
    /**
617
     * .* @credits Thanks to the NewBB2 Development Team
618
     * @param string $item
619
     * @param bool   $getStatus
620
     * @return bool|int|string
621
     */
622
    public static function getPathStatus($item, $getStatus = false)
623
    {
624
        $path = '';
625
        if ('root' !== $item) {
626
            $path = $item;
627
        }
628
629
        $thePath = static::getUploadDir(true, $path);
630
631
        if (empty($thePath)) {
632
            return false;
633
        }
634
        if (\is_writable($thePath)) {
635
            $pathCheckResult = 1;
636
            $pathStatus      = \_AM_PUBLISHER_AVAILABLE;
637
        } elseif (@\is_dir($thePath)) {
638
            $pathCheckResult = -2;
639
            $pathStatus      = \_AM_PUBLISHER_NOTWRITABLE . " <a href='" . PUBLISHER_ADMIN_URL . "/index.php?op=setperm&amp;path={$item}'>" . \_AM_PUBLISHER_SETMPERM . '</a>';
0 ignored issues
show
The constant XoopsModules\Publisher\PUBLISHER_ADMIN_URL was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
640
        } else {
641
            $pathCheckResult = -1;
642
            $pathStatus      = \_AM_PUBLISHER_NOTAVAILABLE . " <a href='" . PUBLISHER_ADMIN_URL . "/index.php?op=createdir&amp;path={$item}'>" . \_AM_PUBLISHER_CREATETHEDIR . '</a>';
643
        }
644
        if (!$getStatus) {
645
            return $pathStatus;
646
        }
647
648
        return $pathCheckResult;
649
    }
650
651
    /**
652
     * @credits Thanks to the NewBB2 Development Team
653
     * @param string $target
654
     * @return bool
655
     */
656
    public static function mkdir($target)
657
    {
658
        // https://www.php.net/manual/en/function.mkdir.php
659
        // saint at corenova.com
660
        // bart at cdasites dot com
661
        if (empty($target) || \is_dir($target)) {
662
            return true; // best case check first
663
        }
664
665
        if (\is_dir($target) && !\is_dir($target)) {
666
            return false;
667
        }
668
669
        if (static::mkdir(\mb_substr($target, 0, \mb_strrpos($target, '/')))) {
670
            if (!\is_dir($target)) {
671
                $res = \mkdir($target, 0777); // crawl back up & create dir tree
672
                static::chmod($target);
673
674
                return $res;
675
            }
676
        }
677
        $res = \is_dir($target);
678
679
        return $res;
680
    }
681
682
    /**
683
     * @credits Thanks to the NewBB2 Development Team
684
     * @param string $target
685
     * @param int    $mode
686
     * @return bool
687
     */
688
    public static function chmod($target, $mode = 0777)
689
    {
690
        return @\chmod($target, $mode);
691
    }
692
693
    /**
694
     * @param bool   $hasPath
695
     * @param string $item
696
     * @return string
697
     */
698
    public static function getUploadDir($hasPath = true, $item = '')
699
    {
700
        if ('' !== $item) {
701
            if ('root' === $item) {
702
                $item = '';
703
            } else {
704
                $item .= '/';
705
            }
706
        }
707
708
        if ($hasPath) {
709
            return PUBLISHER_UPLOAD_PATH . '/' . $item;
0 ignored issues
show
The constant XoopsModules\Publisher\PUBLISHER_UPLOAD_PATH was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
710
        }
711
712
        return PUBLISHER_UPLOAD_URL . '/' . $item;
0 ignored issues
show
The constant XoopsModules\Publisher\PUBLISHER_UPLOAD_URL was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
713
    }
714
715
    /**
716
     * @param string $item
717
     * @param bool   $hasPath
718
     * @return string
719
     */
720
    public static function getImageDir($item = '', $hasPath = true)
721
    {
722
        if ($item) {
723
            $item = "images/{$item}";
724
        } else {
725
            $item = 'images';
726
        }
727
728
        return static::getUploadDir($hasPath, $item);
729
    }
730
731
    /**
732
     * @param array $errors
733
     * @return string
734
     */
735
    public static function formatErrors($errors = [])
736
    {
737
        $ret = '';
738
        foreach ($errors as $key => $value) {
739
            $ret .= '<br> - ' . $value;
740
        }
741
742
        return $ret;
743
    }
744
745
    /**
746
     * Checks if a user is admin of Publisher
747
     *
748
     * @return bool
749
     */
750
    public static function userIsAdmin()
751
    {
752
        $helper = Helper::getInstance();
753
754
        static $publisherIsAdmin;
755
756
        if (null !== $publisherIsAdmin) {
757
            return $publisherIsAdmin;
758
        }
759
760
        if ($GLOBALS['xoopsUser']) {
761
            //            $publisherIsAdmin = $GLOBALS['xoopsUser']->isAdmin($helper->getModule()->getVar('mid'));
762
            $publisherIsAdmin = $helper->isUserAdmin();
763
        } else {
764
            $publisherIsAdmin = false;
765
        }
766
767
        return $publisherIsAdmin;
768
    }
769
770
    /**
771
     * Check is current user is author of a given article
772
     *
773
     * @param \XoopsObject $itemObj
774
     * @return bool
775
     */
776
    public static function userIsAuthor($itemObj)
777
    {
778
        return (\is_object($GLOBALS['xoopsUser']) && \is_object($itemObj) && ($GLOBALS['xoopsUser']->uid() == $itemObj->uid()));
0 ignored issues
show
The method uid() does not exist on XoopsObject. It seems like you code against a sub-type of XoopsObject such as XoopsModules\Publisher\Item or XoopsUser or XoopsModules\Publisher\File or XoopsModules\Publisher\Category. ( Ignorable by Annotation )

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

778
        return (\is_object($GLOBALS['xoopsUser']) && \is_object($itemObj) && ($GLOBALS['xoopsUser']->uid() == $itemObj->/** @scrutinizer ignore-call */ uid()));
Loading history...
779
    }
780
781
    /**
782
     * Check is current user is moderator of a given article
783
     *
784
     * @param \XoopsObject $itemObj
785
     * @return bool
786
     */
787
    public static function userIsModerator($itemObj)
788
    {
789
        $helper            = Helper::getInstance();
790
        $categoriesGranted = $helper->getHandler('Permission')
791
                                    ->getGrantedItems('category_moderation');
792
793
        return (\is_object($itemObj) && \in_array($itemObj->categoryid(), $categoriesGranted, true));
794
    }
795
796
    /**
797
     * Saves permissions for the selected category
798
     *
799
     * @param null|array $groups     : group with granted permission
800
     * @param int        $categoryid : categoryid on which we are setting permissions
801
     * @param string     $permName   : name of the permission
802
     * @return bool : TRUE if the no errors occured
803
     */
804
    public static function saveCategoryPermissions($groups, $categoryid, $permName)
805
    {
806
        $helper = Helper::getInstance();
807
808
        $result = true;
809
810
        $moduleId = $helper->getModule()
811
                           ->getVar('mid');
812
        /** @var \XoopsGroupPermHandler $grouppermHandler */
813
        $grouppermHandler = \xoops_getHandler('groupperm');
814
        // First, if the permissions are already there, delete them
815
        $grouppermHandler->deleteByModule($moduleId, $permName, $categoryid);
816
817
        // Save the new permissions
818
        if (\count($groups) > 0) {
0 ignored issues
show
It seems like $groups can also be of type null; however, parameter $value of count() does only seem to accept Countable|array, maybe add an additional type check? ( Ignorable by Annotation )

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

818
        if (\count(/** @scrutinizer ignore-type */ $groups) > 0) {
Loading history...
819
            foreach ($groups as $groupId) {
820
                $grouppermHandler->addRight($permName, $categoryid, $groupId, $moduleId);
821
            }
822
        }
823
824
        return $result;
825
    }
826
827
    /**
828
     * @param string $tablename
829
     * @param string $iconname
830
     * @param string $tabletitle
831
     * @param string $tabledsc
832
     * @param bool   $open
833
     */
834
    public static function openCollapsableBar($tablename = '', $iconname = '', $tabletitle = '', $tabledsc = '', $open = true): void
835
    {
836
        $image   = 'open12.gif';
837
        $display = 'none';
838
        if ($open) {
839
            $image   = 'close12.gif';
840
            $display = 'block';
841
        }
842
843
        echo "<h3 style=\"color: #2F5376; font-weight: bold; font-size: 14px; margin: 6px 0 0 0; \"><a href='javascript:;' onclick=\"toggle('" . $tablename . "'); toggleIcon('" . $iconname . "')\">";
844
        echo "<img id='" . $iconname . "' src='" . PUBLISHER_URL . '/assets/images/links/' . $image . "' alt=''></a>&nbsp;" . $tabletitle . '</h3>';
0 ignored issues
show
The constant XoopsModules\Publisher\PUBLISHER_URL was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
845
        echo "<div id='" . $tablename . "' style='display: " . $display . ";'>";
846
        if ('' != $tabledsc) {
847
            echo '<span style="color: #567; margin: 3px 0 12px 0; font-size: small; display: block; ">' . $tabledsc . '</span>';
848
        }
849
    }
850
851
    /**
852
     * @param string $name
853
     * @param string $icon
854
     */
855
    public static function closeCollapsableBar($name, $icon): void
856
    {
857
        echo '</div>';
858
859
        $urls = static::getCurrentUrls();
860
        $path = $urls['phpself'];
861
862
        $cookieName = $path . '_publisher_collaps_' . $name;
863
        $cookieName = \str_replace('.', '_', $cookieName);
864
        $cookie     = static::getCookieVar($cookieName, '');
865
866
        if ('none' === $cookie) {
867
            echo '
868
        <script type="text/javascript">
869
     <!--
870
        toggle("' . $name . '"); 
871
        toggleIcon("' . $icon . '");
872
        -->
873
        </script>
874
        ';
875
        }
876
    }
877
878
    /**
879
     * @param string $name
880
     * @param string $value
881
     * @param int    $time
882
     */
883
    public static function setCookieVar($name, $value, $time = 0): void
884
    {
885
        if (0 === $time) {
886
            $time = \time() + 3600 * 24 * 365;
887
        }
888
        //        setcookie($name, $value, $time, '/');
889
        setcookie($name, $value, $time, '/', \ini_get('session.cookie_domain'), (bool)\ini_get('session.cookie_secure'), (bool)\ini_get('session.cookie_httponly'));
890
    }
891
892
    /**
893
     * @param string $name
894
     * @param string $default
895
     * @return string
896
     */
897
    public static function getCookieVar($name, $default = '')
898
    {
899
        //    if (isset($_COOKIE[$name]) && ($_COOKIE[$name] > '')) {
900
        //        return $_COOKIE[$name];
901
        //    } else {
902
        //        return $default;
903
        //    }
904
        return Request::getString($name, $default, 'COOKIE');
905
    }
906
907
    /**
908
     * @return array
909
     */
910
    public static function getCurrentUrls()
911
    {
912
        $http = false === \mb_strpos(XOOPS_URL, 'https://') ? 'https://' : 'https://';
913
        //    $phpself     = $_SERVER['SCRIPT_NAME'];
914
        //    $httphost    = $_SERVER['HTTP_HOST'];
915
        //    $querystring = isset($_SERVER['QUERY_STRING']) ? $_SERVER['QUERY_STRING'] : '';
916
        $phpself     = Request::getString('SCRIPT_NAME', '', 'SERVER');
917
        $httphost    = Request::getString('HTTP_HOST', '', 'SERVER');
918
        $querystring = Request::getString('QUERY_STRING', '', 'SERVER');
919
920
        if ('' != $querystring) {
921
            $querystring = '?' . $querystring;
922
        }
923
924
        $currenturl = $http . $httphost . $phpself . $querystring;
925
926
        $urls                = [];
927
        $urls['http']        = $http;
928
        $urls['httphost']    = $httphost;
929
        $urls['phpself']     = $phpself;
930
        $urls['querystring'] = $querystring;
931
        $urls['full']        = $currenturl;
932
933
        return $urls;
934
    }
935
936
    /**
937
     * @return string
938
     */
939
    public static function getCurrentPage()
940
    {
941
        $urls = static::getCurrentUrls();
942
943
        return $urls['full'];
944
    }
945
946
    /**
947
     * @param null|Category $categoryObj
948
     * @param int|array     $selectedId
949
     * @param int           $level
950
     * @param string        $ret
951
     * @return string
952
     */
953
    public static function addCategoryOption(Category $categoryObj, $selectedId = 0, $level = 0, $ret = '')
954
    {
955
        $helper = Helper::getInstance();
956
957
        $spaces = '';
958
        for ($j = 0; $j < $level; ++$j) {
959
            $spaces .= '--';
960
        }
961
962
        $ret .= "<option value='" . $categoryObj->categoryid() . "'";
963
        if (\is_array($selectedId) && \in_array($categoryObj->categoryid(), $selectedId, true)) {
964
            $ret .= ' selected';
965
        } elseif ($categoryObj->categoryid() == $selectedId) {
966
            $ret .= ' selected';
967
        }
968
        $ret .= '>' . $spaces . $categoryObj->name() . "</option>\n";
969
970
        $subCategoriesObj = $helper->getHandler('Category')
971
                                   ->getCategories(0, 0, $categoryObj->categoryid());
972
        if (\count($subCategoriesObj) > 0) {
973
            ++$level;
974
            foreach ($subCategoriesObj as $catId => $subCategoryObj) {
975
                $ret .= static::addCategoryOption($subCategoryObj, $selectedId, $level);
976
            }
977
        }
978
979
        return $ret;
980
    }
981
982
    /**
983
     * @param int|array|string $selectedId
984
     * @param int              $parentcategory
985
     * @param bool             $allCatOption
986
     * @param string           $selectname
987
     * @param bool             $multiple
988
     * @return string
989
     */
990
    public static function createCategorySelect($selectedId = 0, $parentcategory = 0, $allCatOption = true, $selectname = 'options[1]', $multiple = true)
991
    {
992
        $helper = Helper::getInstance();
993
994
        $selectedId  = \explode(',', $selectedId);
0 ignored issues
show
It seems like $selectedId can also be of type array; however, parameter $string of explode() 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

994
        $selectedId  = \explode(',', /** @scrutinizer ignore-type */ $selectedId);
Loading history...
995
        $selectedId  = \array_map('\intval', $selectedId);
996
        $selMultiple = '';
997
        if ($multiple) {
998
            $selMultiple = " multiple='multiple'";
999
        }
1000
        $ret = "<select name='" . $selectname . "[]'" . $selMultiple . " size='10'>";
1001
        if ($allCatOption) {
1002
            $ret .= "<option value='0'";
1003
            if (\in_array(0, $selectedId, true)) {
1004
                $ret .= ' selected';
1005
            }
1006
            $ret .= '>' . \_MB_PUBLISHER_ALLCAT . '</option>';
1007
        }
1008
1009
        // Creating category objects
1010
        $categoriesObj = $helper->getHandler('Category')
1011
                                ->getCategories(0, 0, $parentcategory);
1012
1013
        if (\count($categoriesObj) > 0) {
1014
            foreach ($categoriesObj as $catId => $categoryObj) {
1015
                $ret .= static::addCategoryOption($categoryObj, $selectedId);
1016
            }
1017
        }
1018
        $ret .= '</select>';
1019
1020
        return $ret;
1021
    }
1022
1023
    /**
1024
     * @param int  $selectedId
1025
     * @param int  $parentcategory
1026
     * @param bool $allCatOption
1027
     * @return string
1028
     */
1029
    public static function createCategoryOptions($selectedId = 0, $parentcategory = 0, $allCatOption = true)
1030
    {
1031
        $helper = Helper::getInstance();
1032
1033
        $ret = '';
1034
        if ($allCatOption) {
1035
            $ret .= "<option value='0'";
1036
            $ret .= '>' . \_MB_PUBLISHER_ALLCAT . "</option>\n";
1037
        }
1038
1039
        // Creating category objects
1040
        $categoriesObj = $helper->getHandler('Category')
1041
                                ->getCategories(0, 0, $parentcategory);
1042
        if (\count($categoriesObj) > 0) {
1043
            foreach ($categoriesObj as $catId => $categoryObj) {
1044
                $ret .= static::addCategoryOption($categoryObj, $selectedId);
1045
            }
1046
        }
1047
1048
        return $ret;
1049
    }
1050
1051
    /**
1052
     * @param array  $errArray
1053
     * @param string $reseturl
1054
     */
1055
    public static function renderErrors($errArray, $reseturl = ''): void
1056
    {
1057
        if ($errArray && \is_array($errArray)) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $errArray of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

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

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

Loading history...
1058
            echo '<div id="readOnly" class="errorMsg" style="border:1px solid #D24D00; background:#FEFECC url(' . PUBLISHER_URL . '/assets/images/important-32.png) no-repeat 7px 50%;color:#333;padding-left:45px;">';
0 ignored issues
show
The constant XoopsModules\Publisher\PUBLISHER_URL was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
1059
1060
            echo '<h4 style="text-align:left;margin:0; padding-top:0;">' . \_AM_PUBLISHER_MSG_SUBMISSION_ERR;
1061
1062
            if ($reseturl) {
1063
                echo ' <a href="' . $reseturl . '">[' . \_AM_PUBLISHER_TEXT_SESSION_RESET . ']</a>';
1064
            }
1065
1066
            echo '</h4><ul>';
1067
1068
            foreach ($errArray as $key => $error) {
1069
                if (\is_array($error)) {
1070
                    foreach ($error as $err) {
1071
                        echo '<li><a href="#' . $key . '" onclick="var e = xoopsGetElementById(\'' . $key . '\'); e.focus();">' . \htmlspecialchars($err, \ENT_QUOTES | \ENT_HTML5) . '</a></li>';
1072
                    }
1073
                } else {
1074
                    echo '<li><a href="#' . $key . '" onclick="var e = xoopsGetElementById(\'' . $key . '\'); e.focus();">' . \htmlspecialchars($error, \ENT_QUOTES | \ENT_HTML5) . '</a></li>';
1075
                }
1076
            }
1077
            echo '</ul></div><br>';
1078
        }
1079
    }
1080
1081
    /**
1082
     * Generate publisher URL
1083
     *
1084
     * @param string $page
1085
     * @param array  $vars
1086
     * @param bool   $encodeAmp
1087
     * @return string
1088
     *
1089
     * @credit : xHelp module, developped by 3Dev
1090
     */
1091
    public static function makeUri($page, $vars = [], $encodeAmp = true)
1092
    {
1093
        $joinStr = '';
1094
1095
        $amp = ($encodeAmp ? '&amp;' : '&');
1096
1097
        if (!\count($vars)) {
1098
            return $page;
1099
        }
1100
1101
        $qs = '';
1102
        foreach ($vars as $key => $value) {
1103
            $qs      .= $joinStr . $key . '=' . $value;
1104
            $joinStr = $amp;
1105
        }
1106
1107
        return $page . '?' . $qs;
1108
    }
1109
1110
    /**
1111
     * @param string $subject
1112
     * @return string
1113
     */
1114
    public static function tellAFriend($subject = '')
1115
    {
1116
        if (false !== \mb_strpos($subject, '%')) {
1117
            $subject = \rawurldecode($subject);
1118
        }
1119
1120
        $targetUri = XOOPS_URL . Request::getString('REQUEST_URI', '', 'SERVER');
1121
1122
        return XOOPS_URL . '/modules/tellafriend/index.php?target_uri=' . \rawurlencode($targetUri) . '&amp;subject=' . \rawurlencode($subject);
1123
    }
1124
1125
    /**
1126
     * @param bool      $another
1127
     * @param bool      $withRedirect
1128
     * @param Item|null $itemObj
1129
     * @return bool|string|null
1130
     */
1131
    public static function uploadFile($another, $withRedirect, &$itemObj = null)
1132
    {
1133
        \xoops_load('XoopsMediaUploader');
1134
        //        require_once PUBLISHER_ROOT_PATH . '/class/uploader.php';
1135
1136
        //    global $publisherIsAdmin;
1137
        $helper = Helper::getInstance();
1138
1139
        $itemId  = Request::getInt('itemid', 0, 'POST');
1140
        $uid     = \is_object($GLOBALS['xoopsUser']) ? $GLOBALS['xoopsUser']->uid() : 0;
1141
        $session = Session::getInstance();
1142
        $session->set('publisher_file_filename', Request::getString('item_file_name', '', 'POST'));
1143
        $session->set('publisher_file_description', Request::getString('item_file_description', '', 'POST'));
1144
        $session->set('publisher_file_status', Request::getInt('item_file_status', 1, 'POST'));
1145
        $session->set('publisher_file_uid', $uid);
1146
        $session->set('publisher_file_itemid', $itemId);
1147
1148
        if (!\is_object($itemObj) && 0 !== $itemId) {
1149
            $itemObj = $helper->getHandler('Item')
1150
                              ->get($itemId);
1151
        }
1152
1153
        $fileObj = $helper->getHandler('File')
1154
                          ->create();
1155
        $fileObj->setVar('name', Request::getString('item_file_name', '', 'POST'));
1156
        $fileObj->setVar('description', Request::getString('item_file_description', '', 'POST'));
1157
        $fileObj->setVar('status', Request::getInt('item_file_status', 1, 'POST'));
1158
        $fileObj->setVar('uid', $uid);
1159
        $fileObj->setVar('itemid', $itemObj->getVar('itemid'));
1160
        $fileObj->setVar('datesub', \time());
1161
1162
        // Get available mimetypes for file uploading
1163
        $allowedMimetypes = $helper->getHandler('Mimetype')
1164
                                   ->getArrayByType();
1165
        // TODO : display the available mimetypes to the user
1166
        $errors = [];
1167
        if ($helper->getConfig('perm_upload') && \is_uploaded_file(($_FILES['item_upload_file']['tmp_name']) ?? '')) {
1168
            if (!$ret = $fileObj->checkUpload('item_upload_file', $allowedMimetypes, $errors)) {
0 ignored issues
show
The method checkUpload() does not exist on XoopsObject. It seems like you code against a sub-type of XoopsObject such as XoopsModules\Publisher\Item or XoopsModules\Publisher\File or XoopsModules\Publisher\Category. ( Ignorable by Annotation )

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

1168
            if (!$ret = $fileObj->/** @scrutinizer ignore-call */ checkUpload('item_upload_file', $allowedMimetypes, $errors)) {
Loading history...
The assignment to $ret is dead and can be removed.
Loading history...
1169
                $errorstxt = \implode('<br>', $errors);
1170
1171
                $message = \sprintf(\_CO_PUBLISHER_MESSAGE_FILE_ERROR, $errorstxt);
1172
                if ($withRedirect) {
1173
                    \redirect_header('file.php?op=mod&itemid=' . $itemId, 5, $message);
1174
                } else {
1175
                    return $message;
1176
                }
1177
            }
1178
        }
1179
1180
        // Storing the file
1181
        if (!$fileObj->store($allowedMimetypes)) {
0 ignored issues
show
The method store() does not exist on XoopsObject. It seems like you code against a sub-type of XoopsObject such as XoopsBlock or XoopsComments or XoopsModules\Publisher\Item or XoopsModules\Publisher\File or XoopsModules\Publisher\Category. ( Ignorable by Annotation )

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

1181
        if (!$fileObj->/** @scrutinizer ignore-call */ store($allowedMimetypes)) {
Loading history...
1182
            //        if ($withRedirect) {
1183
            //            redirect_header("file.php?op=mod&itemid=" . $fileObj->itemid(), 3, _CO_PUBLISHER_FILEUPLOAD_ERROR . static::formatErrors($fileObj->getErrors()));
1184
            //        }
1185
            try {
1186
                if ($withRedirect) {
1187
                    throw new \RuntimeException(\_CO_PUBLISHER_FILEUPLOAD_ERROR . static::formatErrors($fileObj->getErrors()));
1188
                }
1189
            } catch (\Throwable $e) {
1190
                $helper->addLog($e);
1191
                \redirect_header('file.php?op=mod&itemid=' . $fileObj->itemid(), 3, \_CO_PUBLISHER_FILEUPLOAD_ERROR . static::formatErrors($fileObj->getErrors()));
0 ignored issues
show
The method itemid() does not exist on XoopsObject. It seems like you code against a sub-type of XoopsObject such as XoopsModules\Publisher\Item or XoopsModules\Publisher\File or XoopsModules\Publisher\Category. ( Ignorable by Annotation )

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

1191
                \redirect_header('file.php?op=mod&itemid=' . $fileObj->/** @scrutinizer ignore-call */ itemid(), 3, \_CO_PUBLISHER_FILEUPLOAD_ERROR . static::formatErrors($fileObj->getErrors()));
Loading history...
1192
            }
1193
            //    } else {
1194
            //        return _CO_PUBLISHER_FILEUPLOAD_ERROR . static::formatErrors($fileObj->getErrors());
1195
        }
1196
1197
        if ($withRedirect) {
1198
            $redirectPage = $another ? 'file.php' : 'item.php';
1199
            \redirect_header($redirectPage . '?op=mod&itemid=' . $fileObj->itemid(), 2, \_CO_PUBLISHER_FILEUPLOAD_SUCCESS);
1200
        } else {
1201
            return true;
1202
        }
1203
1204
        return null;
1205
    }
1206
1207
    /**
1208
     * @return string
1209
     */
1210
    public static function newFeatureTag()
1211
    {
1212
        $ret = '<span style="padding-right: 4px; font-weight: bold; color: #ff0000;">' . \_CO_PUBLISHER_NEW_FEATURE . '</span>';
1213
1214
        return $ret;
1215
    }
1216
1217
    /**
1218
     * Smarty truncate_tagsafe modifier plugin
1219
     *
1220
     * Type:     modifier<br>
1221
     * Name:     truncate_tagsafe<br>
1222
     * Purpose:  Truncate a string to a certain length if necessary,
1223
     *           optionally splitting in the middle of a word, and
1224
     *           appending the $etc string or inserting $etc into the middle.
1225
     *           Makes sure no tags are left half-open or half-closed
1226
     *           (e.g. "Banana in a <a...")
1227
     * @param mixed $string
1228
     * @param mixed $length
1229
     * @param mixed $etc
1230
     * @param mixed $breakWords
1231
     * @return string
1232
     * @author   Monte Ohrt <monte at ohrt dot com>, modified by Amos Robinson
1233
     *           <amos dot robinson at gmail dot com>
1234
     */
1235
    public static function truncateTagSafe($string, $length = 80, $etc = '...', $breakWords = false)
1236
    {
1237
        if (0 == $length) {
1238
            return '';
1239
        }
1240
1241
        if (\mb_strlen($string) > $length) {
1242
            $length -= \mb_strlen($etc);
1243
            if (!$breakWords) {
1244
                $string = \preg_replace('/\s+?(\S+)?$/', '', \mb_substr($string, 0, $length + 1));
1245
                $string = \preg_replace('/<[^>]*$/', '', $string);
1246
                $string = static::closeTags($string);
1247
            }
1248
1249
            return $string . $etc;
1250
        }
1251
1252
        return $string;
1253
    }
1254
1255
    /**
1256
     * @param string $string
1257
     * @return string
1258
     * @author   Monte Ohrt <monte at ohrt dot com>, modified by Amos Robinson
1259
     *           <amos dot robinson at gmail dot com>
1260
     */
1261
    public static function closeTags($string)
1262
    {
1263
        // match opened tags
1264
        if (\preg_match_all('/<([a-z\:\-]+)[^\/]>/', $string, $startTags)) {
1265
            $startTags = $startTags[1];
1266
            // match closed tags
1267
            if (\preg_match_all('/<\/([a-z]+)>/', $string, $endTags)) {
1268
                $completeTags = [];
1269
                $endTags      = $endTags[1];
1270
1271
                foreach ($startTags as $key => $val) {
1272
                    $posb = \array_search($val, $endTags, true);
1273
                    if (\is_int($posb)) {
1274
                        unset($endTags[$posb]);
1275
                    } else {
1276
                        $completeTags[] = $val;
1277
                    }
1278
                }
1279
            } else {
1280
                $completeTags = $startTags;
1281
            }
1282
1283
            $completeTags = \array_reverse($completeTags);
1284
            foreach ($completeTags as $iValue) {
1285
                $string .= '</' . $iValue . '>';
1286
            }
1287
        }
1288
1289
        return $string;
1290
    }
1291
1292
    /**
1293
     * Get the rating for 5 stars (the original rating)
1294
     * @param int $itemId
1295
     * @return string
1296
     */
1297
    public static function ratingBar($itemId)
1298
    {
1299
        $helper          = Helper::getInstance();
1300
        $ratingUnitWidth = 30;
1301
        $units           = 5;
1302
1303
        $criteria   = new \Criteria('itemid', $itemId);
1304
        $ratingObjs = $helper->getHandler('Rating')
1305
                             ->getObjects($criteria);
1306
        unset($criteria);
1307
1308
        $uid           = \is_object($GLOBALS['xoopsUser']) ? $GLOBALS['xoopsUser']->getVar('uid') : 0;
1309
        $count         = \count($ratingObjs);
1310
        $currentRating = 0;
1311
        $voted         = false;
1312
        $ip            = \getenv('REMOTE_ADDR');
1313
        $rating1       = $rating2 = $ratingWidth = 0;
1314
1315
        foreach ($ratingObjs as $ratingObj) {
1316
            $currentRating += $ratingObj->getVar('rate');
1317
            if ($ratingObj->getVar('ip') == $ip || ($uid > 0 && $uid == $ratingObj->getVar('uid'))) {
1318
                $voted = true;
1319
            }
1320
        }
1321
1322
        $tense = 1 == $count ? \_MD_PUBLISHER_VOTE_VOTE : \_MD_PUBLISHER_VOTE_VOTES; //plural form votes/vote
1323
1324
        // now draw the rating bar
1325
        if (0 != $count) {
1326
            $ratingWidth = \number_format((float)$currentRating / $count, 2) * $ratingUnitWidth;
1327
            $rating1     = \number_format((float)$currentRating / $count, 1);
1328
            $rating2     = \number_format((float)$currentRating / $count, 2);
1329
        }
1330
        $groups = $GLOBALS['xoopsUser'] ? $GLOBALS['xoopsUser']->getGroups() : XOOPS_GROUP_ANONYMOUS;
1331
        /** @var GroupPermHandler $grouppermHandler */
1332
        $grouppermHandler = $helper->getHandler('GroupPerm');
1333
1334
        if (!$grouppermHandler->checkRight(
1335
            'global', Constants::PUBLISHER_RATE, $groups, $helper->getModule()
1336
                                                                 ->getVar('mid')
1337
        )) {
1338
            $staticRater   = [];
1339
            $staticRater[] .= "\n" . '<div class="publisher_ratingblock">';
1340
            $staticRater[] .= '<div id="unit_long' . $itemId . '">';
1341
            $staticRater[] .= '<div id="unit_ul' . $itemId . '" class="publisher_unit-rating" style="width:' . $ratingUnitWidth * $units . 'px;">';
1342
            $staticRater[] .= '<div class="publisher_current-rating" style="width:' . $ratingWidth . 'px;">' . \_MD_PUBLISHER_VOTE_RATING . ' ' . $rating2 . '/' . $units . '</div>';
1343
            $staticRater[] .= '</div>';
1344
            $staticRater[] .= '<div class="publisher_static">' . \_MD_PUBLISHER_VOTE_RATING . ': <strong> ' . $rating1 . '</strong>/' . $units . ' (' . $count . ' ' . $tense . ') <br><em>' . \_MD_PUBLISHER_VOTE_DISABLE . '</em></div>';
1345
            $staticRater[] .= '</div>';
1346
            $staticRater[] .= '</div>' . "\n\n";
1347
1348
            return \implode("\n", $staticRater);
1349
        }
1350
        $rater = '<div class="publisher_ratingblock">';
1351
        $rater .= '<div id="unit_long' . $itemId . '">';
1352
        $rater .= '<div id="unit_ul' . $itemId . '" class="publisher_unit-rating" style="width:' . $ratingUnitWidth * $units . 'px;">';
1353
        $rater .= '<div class="publisher_current-rating" style="width:' . $ratingWidth . 'px;">' . \_MD_PUBLISHER_VOTE_RATING . ' ' . $rating2 . '/' . $units . '</div>';
1354
1355
        for ($ncount = 1; $ncount <= $units; ++$ncount) {
1356
            // loop from 1 to the number of units
1357
            if (!$voted) {
1358
                // if the user hasn't yet voted, draw the voting stars
1359
                $rater .= '<div><a href="' . PUBLISHER_URL . '/rate.php?itemid=' . $itemId . '&amp;rating=' . $ncount . '" title="' . $ncount . ' ' . \_MD_PUBLISHER_VOTE_OUTOF . ' ' . $units . '" class="publisher_r' . $ncount . '-unit rater" rel="nofollow">' . $ncount . '</a></div>';
0 ignored issues
show
The constant XoopsModules\Publisher\PUBLISHER_URL was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
1360
            }
1361
        }
1362
1363
        $ncount = 0; // resets the count
0 ignored issues
show
The assignment to $ncount is dead and can be removed.
Loading history...
1364
        $rater  .= '  </div>';
1365
        $rater  .= '  <div';
1366
1367
        if ($voted) {
1368
            $rater .= ' class="publisher_voted"';
1369
        }
1370
1371
        $rater .= '>' . \_MD_PUBLISHER_VOTE_RATING . ': <strong> ' . $rating1 . '</strong>/' . $units . ' (' . $count . ' ' . $tense . ')';
1372
        $rater .= '  </div>';
1373
        $rater .= '</div>';
1374
        $rater .= '</div>';
1375
1376
        return $rater;
1377
    }
1378
1379
    /**
1380
     * @param array|null $allowedEditors
1381
     * @return array
1382
     */
1383
    public static function getEditors($allowedEditors = null)
1384
    {
1385
        $ret    = [];
1386
        $nohtml = false;
1387
        \xoops_load('XoopsEditorHandler');
1388
        $editorHandler = \XoopsEditorHandler::getInstance();
1389
        //        $editors       = array_flip($editorHandler->getList()); //$editorHandler->getList($nohtml);
1390
        $editors = $editorHandler->getList($nohtml);
1391
        foreach ($editors as $name => $title) {
1392
            $key = static::stringToInt($name);
1393
            if (\is_array($allowedEditors)) {
1394
                //for submit page
1395
                if (\in_array($key, $allowedEditors, true)) {
1396
                    $ret[] = $name;
1397
                }
1398
            } else {
1399
                //for admin permissions page
1400
                $ret[$key]['name']  = $name;
1401
                $ret[$key]['title'] = $title;
1402
            }
1403
        }
1404
1405
        return $ret;
1406
    }
1407
1408
    /**
1409
     * @param string $string
1410
     * @param int    $length
1411
     * @return int
1412
     */
1413
    public static function stringToInt($string = '', $length = 5)
1414
    {
1415
        $final     = '';
1416
        $substring = \mb_substr(\md5($string), $length);
1417
        for ($i = 0; $i < $length; ++$i) {
1418
            $final .= (int)$substring[$i];
1419
        }
1420
1421
        return (int)$final;
1422
    }
1423
1424
    /**
1425
     * @param string $item
1426
     * @return string
1427
     */
1428
    public static function convertCharset($item)
1429
    {
1430
        if (_CHARSET !== 'windows-1256') {
0 ignored issues
show
The condition XoopsModules\Publisher\_...RSET !== 'windows-1256' is always true.
Loading history...
1431
            return \utf8_encode($item);
1432
        }
1433
1434
        if (false !== ($unserialize = \unserialize($item))) {
1435
            foreach ($unserialize as $key => $value) {
1436
                $unserialize[$key] = @\iconv('windows-1256', 'UTF-8', $value);
1437
            }
1438
            $serialize = \serialize($unserialize);
1439
1440
            return $serialize;
1441
        }
1442
1443
        return @\iconv('windows-1256', 'UTF-8', $item);
1444
    }
1445
1446
    /**
1447
     * @param mixed $path
1448
     * @param mixed $image
1449
     * @param mixed $alt
1450
     * @return array
1451
     */
1452
    //    public static function getModuleStats()
1453
    //    {
1454
    //        $helper = Helper::getInstance();
1455
    //        //        $moduleStats = [];
1456
    //        //        if (\count($configurator->moduleStats) > 0) {
1457
    //        //            foreach (\array_keys($configurator->moduleStats) as $i) {
1458
    //        //                $moduleStats[$i] = $configurator->moduleStats[$i];
1459
    //        //            }
1460
    //        //        }
1461
    //
1462
    //        $moduleStats  = [
1463
    //            'totalcategories' => $helper->getHandler('Category')->getCategoriesCount(-1),
1464
    //            'totalitems'      => $helper->getHandler('Item')->getItemsCount(),
1465
    //            'totalsubmitted'  => $helper->getHandler('Item')->getItemsCount(-1, Constants::PUBLISHER_STATUS_SUBMITTED),
1466
    //            'totalpublished'  => $helper->getHandler('Item')->getItemsCount(-1, Constants::PUBLISHER_STATUS_PUBLISHED),
1467
    //            'totaloffline'    => $helper->getHandler('Item')->getItemsCount(-1, Constants::PUBLISHER_STATUS_OFFLINE),
1468
    //            'totalrejected'   => $helper->getHandler('Item')->getItemsCount(-1, Constants::PUBLISHER_STATUS_REJECTED),
1469
    //        ];
1470
    //
1471
    //        return $moduleStats;
1472
    //    }
1473
1474
    /**
1475
     * @param $path
1476
     * @param $image
1477
     * @param $alt
1478
     * @return string
1479
     */
1480
    public static function iconSourceTag($path, $image, $alt)
1481
    {
1482
        $imgSource = "<img src='" . $path . "$image'  alt='" . $alt . "' title='" . $alt . "' align='middle'>";
1483
1484
        return $imgSource;
1485
    }
1486
}
1487