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

news_getWysiwygForm()   B

Complexity

Conditions 8
Paths 9

Size

Total Lines 46
Code Lines 33

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 8
eloc 33
c 0
b 0
f 0
nc 9
nop 6
dl 0
loc 46
rs 8.1475
1
<?php declare(strict_types=1);
2
/*
3
 * You may not change or alter any portion of this comment or credits
4
 * of supporting developers from this source code or any supporting source code
5
 * which is considered copyrighted (c) material of the original comment or credit authors.
6
 *
7
 * This program is distributed in the hope that it will be useful,
8
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
10
 */
11
12
/**
13
 * @copyright      {@link https://xoops.org/ XOOPS Project}
14
 * @license        {@link https://www.gnu.org/licenses/gpl-2.0.html GNU GPL 2 or later}
15
 * @author         XOOPS Development Team
16
 * @author         Hervé Thouzard (https://www.herve-thouzard.com)
17
 */
18
19
/**
20
 * Returns a module's option
21
 *
22
 * Return's a module's option (for the news module)
23
 *
24
 * @param string $option module option's name
25
 *
26
 * @param string $repmodule
27
 *
28
 * @return bool
29
 */
30
31
use WideImage\WideImage;
32
use Xmf\Request;
0 ignored issues
show
Bug introduced by
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...
33
use XoopsModules\News\{
34
    Blacklist,
35
    NewsTopic,
36
    Registryfile,
37
    Utility
38
};
39
40
/**
41
 * @param string $option
42
 * @param string $repmodule
43
 * @return bool|mixed
44
 */
45
function news_getmoduleoption(string $option, string $repmodule = 'news')
46
{
47
    global $xoopsModuleConfig, $xoopsModule;
48
    static $tbloptions = [];
49
    if (is_array($tbloptions) && array_key_exists($option, $tbloptions)) {
50
        return $tbloptions[$option];
51
    }
52
53
    $retval = false;
54
    if (isset($xoopsModuleConfig)
55
        && (is_object($xoopsModule) && $xoopsModule->getVar('dirname') == $repmodule
56
            && $xoopsModule->getVar('isactive'))) {
57
        if (isset($xoopsModuleConfig[$option])) {
58
            $retval = $xoopsModuleConfig[$option];
59
        }
60
    } else {
61
        /** @var \XoopsModuleHandler $moduleHandler */
62
        $moduleHandler = xoops_getHandler('module');
63
        $module        = $moduleHandler->getByDirname($repmodule);
64
        /** @var \XoopsConfigHandler $configHandler */
65
        $configHandler = xoops_getHandler('config');
66
        if ($module) {
67
            $moduleConfig = $configHandler->getConfigsByCat(0, $module->getVar('mid'));
68
            if (isset($moduleConfig[$option])) {
69
                $retval = $moduleConfig[$option];
70
            }
71
        }
72
    }
73
    $tbloptions[$option] = $retval;
74
75
    return $retval;
76
}
77
78
/**
79
 * Updates rating data in item table for a given item
80
 *
81
 * @param $storyid
82
 * @author        Hervé Thouzard (https://www.herve-thouzard.com)
83
 * @copyright (c) Hervé Thouzard
84
 */
85
function news_updaterating($storyid): void
86
{
87
    global $xoopsDB;
88
    $sql       = 'SELECT rating FROM ' . $xoopsDB->prefix('news_stories_votedata') . ' WHERE storyid = ' . $storyid;
89
    $result = Utility::queryAndCheck($xoopsDB, $sql);
90
    $votesDB     = $xoopsDB->getRowsNum($result);
91
    $totalrating = 0;
92
    while ([$rating] = $xoopsDB->fetchRow($result)) {
93
        $totalrating += $rating;
94
    }
95
    $finalrating = $totalrating / $votesDB;
96
    $finalrating =number_format((float)$finalrating, 4);
97
    $sql         = sprintf('UPDATE `%s` SET rating = %u, votes = %u WHERE storyid = %u', $xoopsDB->prefix('news_stories'), $finalrating, $votesDB, $storyid);
98
    $xoopsDB->queryF($sql);
99
}
100
101
/**
102
 * Internal function for permissions
103
 *
104
 * Returns a list of all the permitted topics Ids for the current user
105
 *
106
 * @param string $permtype
107
 *
108
 * @return array    Permitted topics Ids
109
 *
110
 * @author        Hervé Thouzard (https://www.herve-thouzard.com)
111
 * @copyright (c) Hervé Thouzard
112
 */
113
function news_MygetItemIds(string $permtype = 'news_view'): array
114
{
115
    global $xoopsUser;
116
    static $tblperms = [];
117
    if (is_array($tblperms) && array_key_exists($permtype, $tblperms)) {
118
        return $tblperms[$permtype];
119
    }
120
121
    /** @var \XoopsModuleHandler $moduleHandler */
122
    $moduleHandler = xoops_getHandler('module');
123
    $newsModule    = $moduleHandler->getByDirname('news');
124
    $groups        = is_object($xoopsUser) ? $xoopsUser->getGroups() : XOOPS_GROUP_ANONYMOUS;
125
    /** @var \XoopsGroupPermHandler $grouppermHandler */
126
    $grouppermHandler    = xoops_getHandler('groupperm');
127
    $topics              = $grouppermHandler->getItemIds($permtype, $groups, $newsModule->getVar('mid'));
128
    $tblperms[$permtype] = $topics;
129
130
    return $topics;
131
}
132
133
/**
134
 * @param $document
135
 *
136
 * @return array|string|string[]|null
137
 */
138
function news_html2text($document)
139
{
140
    // PHP Manual:: function preg_replace
141
    // $document should contain an HTML document.
142
    // This will remove HTML tags, javascript sections
143
    // and white space. It will also convert some
144
    // common HTML entities to their text equivalent.
145
146
    $search = [
147
        "'<script[^>]*?>.*?</script>'si", // Strip out javascript
148
        "'<img.*?>'si", // Strip out img tags
149
        "'<[\/\!]*?[^<>]*?>'i", // Strip out HTML tags
150
        "'([\r\n])[\s]+'", // Strip out white space
151
        "'&(quot|#34);'i", // Replace HTML entities
152
        "'&(amp|#38);'i",
153
        "'&(lt|#60);'i",
154
        "'&(gt|#62);'i",
155
        "'&(nbsp|#160);'i",
156
        "'&(iexcl|#161);'i",
157
        "'&(cent|#162);'i",
158
        "'&(pound|#163);'i",
159
        "'&(copy|#169);'i",
160
    ]; // evaluate as php
161
162
    $replace = [
163
        '',
164
        '',
165
        '',
166
        '\\1',
167
        '"',
168
        '&',
169
        '<',
170
        '>',
171
        ' ',
172
        chr(161),
173
        chr(162),
174
        chr(163),
175
        chr(169),
176
    ];
177
178
    $text = preg_replace($search, $replace, $document);
179
180
    preg_replace_callback(
181
        '/&#(\d+);/',
182
        static function ($matches) {
183
            return chr($matches[1]);
184
        },
185
        $document
186
    );
187
188
    return $text;
189
}
190
191
/**
192
 * Is Xoops 2.3.x ?
193
 *
194
 * @return bool need to say it ?
195
 */
196
function news_isX23(): bool
197
{
198
    $x23 = false;
199
    $xv  = str_replace('XOOPS ', '', XOOPS_VERSION);
200
    if (mb_substr($xv, 2, 1) >= '3') {
201
        $x23 = true;
202
    }
203
204
    return $x23;
205
}
206
207
/**
208
 * Retrieve an editor according to the module's option "form_options"
209
 *
210
 * @param string $caption
211
 * @param string $name
212
 * @param string $value
213
 * @param string $width
214
 * @param string $height
215
 * @param string $supplemental
216
 * @return bool|XoopsFormEditor|\XoopsFormTextArea
217
 * @author        Hervé Thouzard (https://www.herve-thouzard.com)
218
 * @copyright (c) Hervé Thouzard
219
 */
220
function news_getWysiwygForm(string $caption, string $name, string $value = '', string $width = '100%', string $height = '400px', string $supplemental = '')
0 ignored issues
show
Unused Code introduced by
The parameter $width 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

220
function news_getWysiwygForm(string $caption, string $name, string $value = '', /** @scrutinizer ignore-unused */ string $width = '100%', string $height = '400px', string $supplemental = '')

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

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

220
function news_getWysiwygForm(string $caption, string $name, string $value = '', string $width = '100%', /** @scrutinizer ignore-unused */ string $height = '400px', string $supplemental = '')

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...
221
{
222
    $editor_option            = \mb_strtolower(news_getmoduleoption('form_options'));
0 ignored issues
show
Bug introduced by
It seems like news_getmoduleoption('form_options') can also be of type boolean; however, parameter $string of mb_strtolower() 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

222
    $editor_option            = \mb_strtolower(/** @scrutinizer ignore-type */ news_getmoduleoption('form_options'));
Loading history...
223
    $editor                   = false;
224
    $editor_configs           = [];
225
    $editor_configs['name']   = $name;
226
    $editor_configs['value']  = $value;
227
    $editor_configs['rows']   = 35;
228
    $editor_configs['cols']   = 60;
229
    $editor_configs['width']  = '100%';
230
    $editor_configs['height'] = '350px';
231
    $editor_configs['editor'] = $editor_option;
232
233
    if (news_isX23()) {
234
        $editor = new \XoopsFormEditor($caption, $name, $editor_configs);
235
236
        return $editor;
237
    }
238
239
    // Only for Xoops 2.0.x
240
    switch ($editor_option) {
241
        case 'dhtmltextarea':
242
        case 'dhtml':
243
            $editor = new \XoopsFormDhtmlTextArea($caption, $name, $value, 10, 50, $supplemental);
244
            break;
245
        case 'textarea':
246
            $editor = new \XoopsFormTextArea($caption, $name, $value);
247
            break;
248
        case 'tinyeditor':
249
        case 'tinymce':
250
            if (is_readable(XOOPS_ROOT_PATH . '/class/xoopseditor/tinyeditor/formtinyeditortextarea.php')) {
251
                require_once XOOPS_ROOT_PATH . '/class/xoopseditor/tinyeditor/formtinyeditortextarea.php';
252
                $editor = new \XoopsFormTinyeditorTextArea(
0 ignored issues
show
Bug introduced by
The type XoopsFormTinyeditorTextArea was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
253
                    [
254
                        'caption' => $caption,
255
                        'name'    => $name,
256
                        'value'   => $value,
257
                        'width'   => '100%',
258
                        'height'  => '400px',
259
                    ]
260
                );
261
            }
262
            break;
263
    }
264
265
    return $editor;
266
}
267
268
/**
269
 * Internal function
270
 *
271
 * @param $text
272
 * @return array|string|string[]
273
 * @copyright (c) Hervé Thouzard
274
 * @author        Hervé Thouzard (https://www.herve-thouzard.com)
275
 */
276
function DublinQuotes($text)
277
{
278
    return str_replace('"', ' ', $text);
279
}
280
281
/**
282
 * Creates all the metadatas :
283
 * - For Mozilla/Netscape and Opera the site navigation's bar
284
 * - The Dublin's Core Metadata
285
 * - The link for Firefox 2 micro summaries
286
 * - The meta keywords
287
 * - The meta description
288
 *
289
 * @param null $story
0 ignored issues
show
Documentation Bug introduced by
Are you sure the doc-type for parameter $story is correct as it would always require null to be passed?
Loading history...
290
 * @author        Hervé Thouzard (https://www.herve-thouzard.com)
291
 * @copyright (c) Hervé Thouzard
292
 */
293
function news_CreateMetaDatas($story = null): void
294
{
295
    global $xoopsConfig, $xoTheme, $xoopsTpl;
296
    $content = '';
297
    $myts    = \MyTextSanitizer::getInstance();
0 ignored issues
show
Unused Code introduced by
The assignment to $myts is dead and can be removed.
Loading history...
298
    //    require_once XOOPS_ROOT_PATH . '/modules/news/class/class.newstopic.php';
299
300
    /**
301
     * Firefox and Opera Navigation's Bar
302
     */
303
    if (news_getmoduleoption('sitenavbar')) {
304
        $content .= sprintf("<link rel=\"Home\" title=\"%s\" href=\"%s/\">\n", $xoopsConfig['sitename'], XOOPS_URL);
305
        $content .= sprintf("<link rel=\"Contents\" href=\"%s\">\n", XOOPS_URL . '/modules/news/index.php');
306
        $content .= sprintf("<link rel=\"Search\" href=\"%s\">\n", XOOPS_URL . '/search.php');
307
        $content .= sprintf("<link rel=\"Glossary\" href=\"%s\">\n", XOOPS_URL . '/modules/news/archive.php');
308
        $content .= sprintf("<link rel=\"%s\" href=\"%s\">\n", htmlspecialchars(_NW_SUBMITNEWS, ENT_QUOTES | ENT_HTML5), XOOPS_URL . '/modules/news/submit.php');
309
        $content .= sprintf("<link rel=\"alternate\" type=\"application/rss+xml\" title=\"%s\" href=\"%s/\">\n", $xoopsConfig['sitename'], XOOPS_URL . '/backend.php');
310
311
        // Create chapters
312
        require_once XOOPS_ROOT_PATH . '/class/tree.php';
313
        //        require_once XOOPS_ROOT_PATH . '/modules/news/class/class.newstopic.php';
314
        $xt         = new NewsTopic();
315
        $allTopics  = $xt->getAllTopics(news_getmoduleoption('restrictindex'));
316
        $topic_tree = new \XoopsObjectTree($allTopics, 'topic_id', 'topic_pid');
317
        $topics_arr = $topic_tree->getAllChild(0);
318
        foreach ($topics_arr as $onetopic) {
319
            $content .= sprintf("<link rel=\"Chapter\" title=\"%s\" href=\"%s\">\n", $onetopic->topic_title(), XOOPS_URL . '/modules/news/index.php?storytopic=' . $onetopic->topic_id());
320
        }
321
    }
322
323
    /**
324
     * Meta Keywords and Description
325
     * If you have set this module's option to 'yes' and if the information was entered, then they are rendered in the page else they are computed
326
     */
327
    $meta_keywords = '';
328
    if (isset($story) && is_object($story)) {
329
        if ('' !== xoops_trim($story->keywords())) {
330
            $meta_keywords = $story->keywords();
331
        } else {
332
            $meta_keywords = news_createmeta_keywords($story->hometext() . ' ' . $story->bodytext());
333
        }
334
        if ('' !== xoops_trim($story->description())) {
335
            $meta_description = strip_tags($story->description);
336
        } else {
337
            $meta_description = strip_tags($story->title);
338
        }
339
        if (isset($xoTheme) && is_object($xoTheme)) {
340
            $xoTheme->addMeta('meta', 'keywords', $meta_keywords);
341
            $xoTheme->addMeta('meta', 'description', $meta_description);
342
        } elseif (isset($xoopsTpl) && is_object($xoopsTpl)) { // Compatibility for old Xoops versions
343
            $xoopsTpl->assign('xoops_meta_keywords', $meta_keywords);
344
            $xoopsTpl->assign('xoops_meta_description', $meta_description);
345
        }
346
    }
347
348
    /**
349
     * Dublin Core's metadatas
350
     */
351
    if (news_getmoduleoption('dublincore') && isset($story) && is_object($story)) {
352
        /** @var \XoopsConfigHandler $configHandler */
353
        $configHandler         = xoops_getHandler('config');
354
        $xoopsConfigMetaFooter = $configHandler->getConfigsByCat(XOOPS_CONF_METAFOOTER);
355
        $content               .= '<meta name="DC.Title" content="' . Utility::getDublinQuotes($story->title()) . "\">\n";
356
        $content               .= '<meta name="DC.Creator" content="' . Utility::getDublinQuotes($story->uname()) . "\">\n";
357
        $content               .= '<meta name="DC.Subject" content="' . Utility::getDublinQuotes($meta_keywords) . "\">\n";
358
        $content               .= '<meta name="DC.Description" content="' . Utility::getDublinQuotes($story->title()) . "\">\n";
359
        $content               .= '<meta name="DC.Publisher" content="' . Utility::getDublinQuotes($xoopsConfig['sitename']) . "\">\n";
360
        $content               .= '<meta name="DC.Date.created" scheme="W3CDTF" content="' . date('Y-m-d', $story->created) . "\">\n";
361
        $content               .= '<meta name="DC.Date.issued" scheme="W3CDTF" content="' . date('Y-m-d', $story->published) . "\">\n";
362
        $content               .= '<meta name="DC.Identifier" content="' . XOOPS_URL . '/modules/news/article.php?storyid=' . $story->storyid() . "\">\n";
363
        $content               .= '<meta name="DC.Source" content="' . XOOPS_URL . "\">\n";
364
        $content               .= '<meta name="DC.Language" content="' . _LANGCODE . "\">\n";
365
        $content               .= '<meta name="DC.Relation.isReferencedBy" content="' . XOOPS_URL . '/modules/news/index.php?storytopic=' . $story->topicid() . "\">\n";
366
        if (isset($xoopsConfigMetaFooter['meta_copyright'])) {
367
            $content .= '<meta name="DC.Rights" content="' . Utility::getDublinQuotes($xoopsConfigMetaFooter['meta_copyright']) . "\">\n";
368
        }
369
    }
370
371
    /**
372
     * Firefox 2 micro summaries
373
     */
374
    if (news_getmoduleoption('firefox_microsummaries')) {
375
        $content .= sprintf("<link rel=\"microsummary\" href=\"%s\">\n", XOOPS_URL . '/modules/news/micro_summary.php');
376
    }
377
378
    if (isset($xoopsTpl) && is_object($xoopsTpl)) {
379
        $xoopsTpl->assign('xoops_module_header', $content);
380
    }
381
}
382
383
/**
384
 * Create the meta keywords based on the content
385
 *
386
 * @param $content
387
 * @return string
388
 * @copyright (c) Hervé Thouzard
389
 * @author        Hervé Thouzard (https://www.herve-thouzard.com)
390
 */
391
function news_createmeta_keywords($content): string
392
{
393
    require_once XOOPS_ROOT_PATH . '/modules/news/config.php';
394
    // require_once XOOPS_ROOT_PATH . '/modules/news/class/blacklist.php';
395
    // require_once XOOPS_ROOT_PATH . '/modules/news/class/registryfile.php';
396
397
    if (!$cfg['meta_keywords_auto_generate']) {
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $cfg seems to be never defined.
Loading history...
398
        return '';
399
    }
400
    $registry = new Registryfile('news_metagen_options.txt');
401
    //    $tcontent = '';
402
    $tcontent = $registry->getfile();
403
    if ('' !== xoops_trim($tcontent)) {
404
        [$keywordscount, $keywordsorder] = explode(',', $tcontent);
405
    } else {
406
        $keywordscount = $cfg['meta_keywords_count'];
407
        $keywordsorder = $cfg['meta_keywords_order'];
408
    }
409
410
    $tmp = [];
411
    // Search for the "Minimum keyword length"
412
    if (Request::hasVar('news_keywords_limit', 'SESSION')) {
413
        $limit = $_SESSION['news_keywords_limit'];
414
    } else {
415
        /** @var \XoopsConfigHandler $configHandler */
416
        $configHandler                   = xoops_getHandler('config');
417
        $xoopsConfigSearch               = $configHandler->getConfigsByCat(XOOPS_CONF_SEARCH);
418
        $limit                           = $xoopsConfigSearch['keyword_min'];
419
        $_SESSION['news_keywords_limit'] = $limit;
420
    }
421
    $myts            = \MyTextSanitizer::getInstance();
422
    $content         = str_replace('<br>', ' ', $content);
423
    $content         = $myts->undoHtmlSpecialChars($content);
424
    $content         = strip_tags($content);
425
    $content         = \mb_strtolower($content);
426
    $search_pattern  = [
427
        '&nbsp;',
428
        "\t",
429
        "\r\n",
430
        "\r",
431
        "\n",
432
        ',',
433
        '.',
434
        "'",
435
        ';',
436
        ':',
437
        ')',
438
        '(',
439
        '"',
440
        '?',
441
        '!',
442
        '{',
443
        '}',
444
        '[',
445
        ']',
446
        '<',
447
        '>',
448
        '/',
449
        '+',
450
        '-',
451
        '_',
452
        '\\',
453
        '*',
454
    ];
455
    $replace_pattern = [
456
        ' ',
457
        ' ',
458
        ' ',
459
        ' ',
460
        ' ',
461
        ' ',
462
        ' ',
463
        ' ',
464
        '',
465
        '',
466
        '',
467
        '',
468
        '',
469
        '',
470
        '',
471
        '',
472
        '',
473
        '',
474
        '',
475
        '',
476
        '',
477
        '',
478
        '',
479
        '',
480
        '',
481
        '',
482
        '',
483
    ];
484
    $content         = str_replace($search_pattern, $replace_pattern, $content);
485
    $keywords        = explode(' ', $content);
486
    switch ($keywordsorder) {
487
        case 0: // Ordre d'apparition dans le texte
488
            $keywords = array_unique($keywords);
489
            break;
490
        case 1: // Ordre de fréquence des mots
491
            $keywords = array_count_values($keywords);
492
            asort($keywords);
493
            $keywords = array_keys($keywords);
494
            break;
495
        case 2: // Ordre inverse de la fréquence des mots
496
            $keywords = array_count_values($keywords);
497
            arsort($keywords);
498
            $keywords = array_keys($keywords);
499
            break;
500
    }
501
    // Remove black listed words
502
    $metablack = new Blacklist();
503
    $words     = $metablack->getAllKeywords();
0 ignored issues
show
Unused Code introduced by
The assignment to $words is dead and can be removed.
Loading history...
504
    $keywords  = $metablack->remove_blacklisted($keywords);
505
506
    foreach ($keywords as $keyword) {
507
        if (mb_strlen($keyword) >= $limit && !is_numeric($keyword)) {
508
            $tmp[] = $keyword;
509
        }
510
    }
511
    $tmp = array_slice($tmp, 0, $keywordscount);
512
    if (count($tmp) > 0) {
513
        return implode(',', $tmp);
514
    }
515
    if (!isset($configHandler) || !is_object($configHandler)) {
516
        /** @var \XoopsConfigHandler $configHandler */
517
        $configHandler = xoops_getHandler('config');
518
    }
519
    $xoopsConfigMetaFooter = $configHandler->getConfigsByCat(XOOPS_CONF_METAFOOTER);
520
    return $xoopsConfigMetaFooter['meta_keywords'] ?? '';
521
}
522
523
/**
524
 * Remove module's cache
525
 *
526
 * @author        Hervé Thouzard (https://www.herve-thouzard.com)
527
 * @copyright (c) Hervé Thouzard
528
 */
529
function news_updateCache(): void
530
{
531
    global $xoopsModule;
532
    $folder  = $xoopsModule->getVar('dirname');
533
    $tpllist = [];
0 ignored issues
show
Unused Code introduced by
The assignment to $tpllist is dead and can be removed.
Loading history...
534
    require_once XOOPS_ROOT_PATH . '/class/xoopsblock.php';
535
    require_once XOOPS_ROOT_PATH . '/class/template.php';
536
    /** @var \XoopsTplfileHandler $tplfileHandler */
537
    $tplfileHandler = xoops_getHandler('tplfile');
538
    $tpllist        = $tplfileHandler->find(null, null, null, $folder);
539
    $xoopsTpl       = new \XoopsTpl();
0 ignored issues
show
Unused Code introduced by
The assignment to $xoopsTpl is dead and can be removed.
Loading history...
540
    xoops_template_clear_module_cache($xoopsModule->getVar('mid')); // Clear module's blocks cache
541
542
    // Remove cache for each page.
543
    foreach ($tpllist as $onetemplate) {
544
        if ('module' === $onetemplate->getVar('tpl_type')) {
545
            // Note, I've been testing all the other methods (like the one of Smarty) and none of them run, that's why I have used this code
546
            $files_del = [];
0 ignored issues
show
Unused Code introduced by
The assignment to $files_del is dead and can be removed.
Loading history...
547
            $files_del = glob(XOOPS_CACHE_PATH . '/*' . $onetemplate->getVar('tpl_file') . '*', GLOB_NOSORT);
548
            if (count($files_del) > 0) {
549
                foreach ($files_del as $one_file) {
550
                    unlink($one_file);
551
                }
552
            }
553
        }
554
    }
555
}
556
557
/**
558
 * Verify that a mysql table exists
559
 *
560
 * @param $tablename
561
 * @return bool
562
 * @copyright (c) Hervé Thouzard
563
 * @author        Hervé Thouzard (https://www.herve-thouzard.com)
564
 */
565
function news_TableExists($tablename): bool
566
{
567
    global $xoopsDB;
568
569
    $sql = "SHOW TABLES LIKE '$tablename'";
570
    $result = Utility::queryFAndCheck($xoopsDB, $sql);
571
572
    return ($xoopsDB->getRowsNum($result) > 0);
573
}
574
575
/**
576
 * Verify that a field exists inside a mysql table
577
 *
578
 * @param $fieldname
579
 * @param $table
580
 * @return bool
581
 * @author        Hervé Thouzard (https://www.herve-thouzard.com)
582
 * @copyright (c) Hervé Thouzard
583
 */
584
function news_FieldExists($fieldname, $table): bool
585
{
586
    global $xoopsDB;
587
    $sql = "SHOW COLUMNS FROM   $table LIKE '$fieldname'";
588
    $result = Utility::queryFAndCheck($xoopsDB, $sql);
589
590
    return ($xoopsDB->getRowsNum($result) > 0);
591
}
592
593
/**
594
 * Add a field to a mysql table
595
 *
596
 * @param $field
597
 * @param $table
598
 * @return bool|\mysqli_result
599
 * @author        Hervé Thouzard (https://www.herve-thouzard.com)
600
 * @copyright (c) Hervé Thouzard
601
 */
602
function news_AddField($field, $table)
603
{
604
    global $xoopsDB;
605
    $result = $xoopsDB->queryF('ALTER TABLE ' . $table . " ADD $field;");
606
607
    return $result;
608
}
609
610
/**
611
 * Verify that the current user is a member of the Admin group
612
 */
613
function news_is_admin_group(): bool
614
{
615
    global $xoopsUser, $xoopsModule;
616
    if (is_object($xoopsUser)) {
617
        if (in_array('1', $xoopsUser->getGroups(), true)) {
618
            return true;
619
        }
620
        if ($xoopsUser->isAdmin($xoopsModule->mid())) {
621
            return true;
622
        }
623
624
        return false;
625
    }
626
627
    return false;
628
}
629
630
/**
631
 * Verify if the current "user" is a bot or not
632
 *
633
 * If you have a problem with this function, insert the folowing code just before the line if (\Xmf\Request::hasVar('news_cache_bot', 'SESSION'))) { :
634
 * return false;
635
 *
636
 * @author        Hervé Thouzard (https://www.herve-thouzard.com)
637
 * @copyright (c) Hervé Thouzard
638
 */
639
function news_isbot()
640
{
641
    if (Request::hasVar('news_cache_bot', 'SESSION')) {
642
        return $_SESSION['news_cache_bot'];
643
    }
644
    // Add here every bot you know separated by a pipe | (not matter with the upper or lower cases)
645
    // If you want to see the result for yourself, add your navigator's user agent at the end (mozilla for example)
646
    $botlist      = 'AbachoBOT|Arachnoidea|ASPSeek|Atomz|cosmos|crawl25-public.alexa.com|CrawlerBoy Pinpoint.com|Crawler|DeepIndex|EchO!|exabot|Excalibur Internet Spider|FAST-WebCrawler|Fluffy the spider|GAIS Robot/1.0B2|GaisLab data gatherer|Google|Googlebot-Image|googlebot|Gulliver|ia_archiver|Infoseek|Links2Go|Lycos_Spider_(modspider)|Lycos_Spider_(T-Rex)|MantraAgent|Mata Hari|Mercator|MicrosoftPrototypeCrawler|[email protected]|MSNBOT|NEC Research Agent|NetMechanic|Nokia-WAPToolkit|nttdirectory_robot|Openfind|Oracle Ultra Search|PicoSearch|Pompos|Scooter|Slider_Search_v1-de|Slurp|Slurp.so|SlySearch|Spider|Spinne|SurferF3|Surfnomore Spider|suzuran|teomaagent1|TurnitinBot|Ultraseek|VoilaBot|vspider|W3C_Validator|Web Link Validator|WebTrends|WebZIP|whatUseek_winona|WISEbot|Xenu Link Sleuth|ZyBorg';
647
    $botlist      = \mb_strtoupper($botlist);
648
    $currentagent = \mb_strtoupper(xoops_getenv('HTTP_USER_AGENT'));
649
    $retval       = false;
650
    $botarray     = explode('|', $botlist);
651
    foreach ($botarray as $onebot) {
652
        if (false !== mb_strpos($currentagent, $onebot)) {
653
            $retval = true;
654
            break;
655
        }
656
    }
657
658
    $_SESSION['news_cache_bot'] = $retval;
659
660
    return $retval;
661
}
662
663
/**
664
 * Create an infotip
665
 *
666
 * @param $text
667
 * @return string|null
668
 * @copyright (c) Hervé Thouzard
669
 * @author        Hervé Thouzard (https://www.herve-thouzard.com)
670
 */
671
function news_make_infotips($text): ?string
672
{
673
    $infotips = news_getmoduleoption('infotips');
674
    if ($infotips > 0) {
675
        $myts = \MyTextSanitizer::getInstance();
0 ignored issues
show
Unused Code introduced by
The assignment to $myts is dead and can be removed.
Loading history...
676
677
        return htmlspecialchars(xoops_substr(strip_tags($text), 0, $infotips), ENT_QUOTES | ENT_HTML5);
0 ignored issues
show
Bug introduced by
It seems like $infotips can also be of type boolean; however, parameter $length of xoops_substr() 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

677
        return htmlspecialchars(xoops_substr(strip_tags($text), 0, /** @scrutinizer ignore-type */ $infotips), ENT_QUOTES | ENT_HTML5);
Loading history...
678
    }
679
680
    return null;
681
}
682
683
/**
684
 * @param string $string
685
 * @return string
686
 * @author   Monte Ohrt <monte at ohrt dot com>, modified by Amos Robinson
687
 *           <amos dot robinson at gmail dot com>
688
 */
689
function news_close_tags(string $string): string
690
{
691
    // match opened tags
692
    if (preg_match_all('/<([a-z\:\-]+)[^\/]>/', $string, $start_tags)) {
693
        $start_tags = $start_tags[1];
694
        // match closed tags
695
        if (preg_match_all('/<\/([a-z]+)>/', $string, $end_tags)) {
696
            $complete_tags = [];
697
            $end_tags      = $end_tags[1];
698
699
            foreach ($start_tags as $key => $val) {
700
                $posb = array_search($val, $end_tags, true);
701
                if (is_int($posb)) {
702
                    unset($end_tags[$posb]);
703
                } else {
704
                    $complete_tags[] = $val;
705
                }
706
            }
707
        } else {
708
            $complete_tags = $start_tags;
709
        }
710
711
        $complete_tags = array_reverse($complete_tags);
712
        foreach ($complete_tags as $iValue) {
713
            $string .= '</' . $iValue . '>';
714
        }
715
    }
716
717
    return $string;
718
}
719
720
/**
721
 * Smarty truncate_tagsafe modifier plugin
722
 *
723
 * Type:     modifier<br>
724
 * Name:     truncate_tagsafe<br>
725
 * Purpose:  Truncate a string to a certain length if necessary,
726
 *           optionally splitting in the middle of a word, and
727
 *           appending the $etc string or inserting $etc into the middle.
728
 *           Makes sure no tags are left half-open or half-closed
729
 *           (e.g. "Banana in a <a...")
730
 *
731
 * @param mixed $string
732
 * @param mixed $length
733
 * @param mixed $etc
734
 * @param mixed $break_words
735
 *
736
 * @return string
737
 * @author   Monte Ohrt <monte at ohrt dot com>, modified by Amos Robinson
738
 *           <amos dot robinson at gmail dot com>
739
 */
740
function news_truncate_tagsafe($string, $length = 80, $etc = '...', $break_words = false): string
741
{
742
    if (0 == $length) {
743
        return '';
744
    }
745
    if (mb_strlen($string) > $length) {
746
        $length -= \mb_strlen($etc);
747
        if (!$break_words) {
748
            $string = preg_replace('/\s+?(\S+)?$/', '', mb_substr($string, 0, $length + 1));
749
            $string = preg_replace('/<[^>]*$/', '', $string);
750
            $string = news_close_tags($string);
751
        }
752
753
        return $string . $etc;
754
    }
755
756
    return $string;
757
}
758
759
/**
760
 * Resize a Picture to some given dimensions (using the wideImage library)
761
 *
762
 * @param string $src_path      Picture's source
763
 * @param string $dst_path      Picture's destination
764
 * @param int    $param_width   Maximum picture's width
765
 * @param int    $param_height  Maximum picture's height
766
 * @param bool   $keep_original Do we have to keep the original picture ?
767
 * @param string $fit           Resize mode (see the wideImage library for more information)
768
 *
769
 * @return bool
770
 */
771
function news_resizePicture(
772
    string $src_path,
773
    string $dst_path,
774
    int    $param_width,
775
    int    $param_height,
776
    bool   $keep_original = false,
777
    string $fit = 'inside'
778
): bool {
779
    //    require_once XOOPS_PATH . '/vendor/wideimage/WideImage.php';
780
    $resize            = true;
781
    $pictureDimensions = getimagesize($src_path);
782
    if (is_array($pictureDimensions)) {
0 ignored issues
show
introduced by
The condition is_array($pictureDimensions) is always true.
Loading history...
783
        $pictureWidth  = $pictureDimensions[0];
784
        $pictureHeight = $pictureDimensions[1];
785
        if ($pictureWidth < $param_width && $pictureHeight < $param_height) {
786
            $resize = false;
787
        }
788
    }
789
790
    $img = WideImage::load($src_path);
791
    if ($resize) {
792
        $result = $img->resize($param_width, $param_height, $fit);
793
        $result->saveToFile($dst_path);
794
    } else {
795
        @copy($src_path, $dst_path);
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition for copy(). This can introduce security issues, and is generally not recommended. ( Ignorable by Annotation )

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

795
        /** @scrutinizer ignore-unhandled */ @copy($src_path, $dst_path);

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

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

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
796
    }
797
    if (!$keep_original) {
798
        @unlink($src_path);
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition for unlink(). This can introduce security issues, and is generally not recommended. ( Ignorable by Annotation )

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

798
        /** @scrutinizer ignore-unhandled */ @unlink($src_path);

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

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

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
799
    }
800
801
    return true;
802
}
803