Passed
Branch master (5b6d04)
by Michael
03:42
created

Metagen   B

Complexity

Total Complexity 43

Size/Duplication

Total Lines 415
Duplicated Lines 0 %

Importance

Changes 3
Bugs 0 Features 0
Metric Value
eloc 199
c 3
b 0
f 0
dl 0
loc 415
rs 8.96
wmc 43

16 Methods

Rating   Name   Duplication   Size   Complexity  
A createMetaKeywords() 0 11 2
A autoBuildMetaKeywords() 0 2 1
A emptyString() 0 3 1
C setTitle() 0 26 12
A findMetaKeywords() 0 18 5
B generateSeoTitle() 0 72 4
A __construct() 0 12 2
A setKeywords() 0 3 1
A purifyText() 0 32 2
A setDescription() 0 5 1
A createMetaTags() 0 11 4
A setCategoryPath() 0 4 1
A createMetaDescription() 0 17 3
A buildAutoMetaTags() 0 4 1
A createTitleTag() 0 2 1
A html2text() 0 54 2

How to fix   Complexity   

Complex Class

Complex classes like Metagen often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use Metagen, and based on these observations, apply Extract Interface, too.

1
<?php
2
3
declare(strict_types=1);
4
5
namespace XoopsModules\Publisher;
6
7
/*
8
 You may not change or alter any portion of this comment or credits
9
 of supporting developers from this source code or any supporting source code
10
 which is considered copyrighted (c) material of the original comment or credit authors.
11
12
 This program is distributed in the hope that it will be useful,
13
 but WITHOUT ANY WARRANTY; without even the implied warranty of
14
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
15
 */
16
17
/**
18
 * @copyright       The XUUPS Project http://sourceforge.net/projects/xuups/
19
 * @license         http://www.fsf.org/copyleft/gpl.html GNU public license
20
 * @since           1.0
21
 * @author          trabis <[email protected]>
22
 * @author          The SmartFactory <www.smartfactory.ca>
23
 */
24
25
use XoopsModules\Publisher\Helper;
26
27
require_once \dirname(__DIR__) . '/include/common.php';
28
29
/**
30
 * Class Metagen
31
 */
32
class Metagen
33
{
34
    /**
35
     * @var Helper
36
     */
37
    public $helper;
38
    /**
39
     * @var \MyTextSanitizer
40
     */
41
    public $myts;
42
    /**
43
     * @var string
44
     */
45
    public $title;
46
    /**
47
     * @var string
48
     */
49
    public $originalTitle;
50
    /**
51
     * @var string
52
     */
53
    public $keywords;
54
    /**
55
     * @var string
56
     */
57
    public $categoryPath;
58
    /**
59
     * @var string
60
     */
61
    public $description;
62
    /**
63
     * @var int
64
     */
65
    public $minChar = 4;
66
67
    /**
68
     * @param string $title
69
     * @param string $keywords
70
     * @param string $description
71
     * @param string $categoryPath
72
     */
73
    public function __construct($title, $keywords = '', $description = '', $categoryPath = '')
74
    {
75
        /** @var Helper $this- >helper */
76
        $this->helper = Helper::getInstance();
77
        $this->myts   = \MyTextSanitizer::getInstance();
78
        $this->setCategoryPath($categoryPath);
79
        $this->setTitle($title);
80
        $this->setDescription($description);
81
        if ('' == $keywords) {
82
            $keywords = $this->createMetaKeywords();
83
        }
84
        $this->setKeywords($keywords);
85
    }
86
87
    /**
88
     * @param string $title
89
     */
90
    public function setTitle($title)
91
    {
92
        $this->title         = $this->html2text($title);
93
        $this->originalTitle = $this->title;
94
        $titleTag            = [];
95
        $titleTag['module']  = $this->helper->getModule()->getVar('name');
96
        if (isset($this->title) && ('' != $this->title) && (\mb_strtoupper($this->title) != \mb_strtoupper($titleTag['module']))) {
0 ignored issues
show
Bug introduced by
It seems like $titleTag['module'] can also be of type array and array; however, parameter $str of mb_strtoupper() 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

96
        if (isset($this->title) && ('' != $this->title) && (\mb_strtoupper($this->title) != \mb_strtoupper(/** @scrutinizer ignore-type */ $titleTag['module']))) {
Loading history...
97
            $titleTag['title'] = $this->title;
98
        }
99
        if (isset($this->categoryPath) && ('' != $this->categoryPath)) {
100
            $titleTag['category'] = $this->categoryPath;
101
        }
102
        $ret = $titleTag['title'] ?? '';
103
        if (isset($titleTag['category']) && '' != $titleTag['category']) {
104
            if ('' != $ret) {
105
                $ret .= ' - ';
106
            }
107
            $ret .= $titleTag['category'];
108
        }
109
        if (isset($titleTag['module']) && '' != $titleTag['module']) {
110
            if ('' != $ret) {
111
                $ret .= ' - ';
112
            }
113
            $ret .= $titleTag['module'];
114
        }
115
        $this->title = $ret;
116
    }
117
118
    /**
119
     * @param string $keywords
120
     */
121
    public function setKeywords($keywords)
122
    {
123
        $this->keywords = $keywords;
124
    }
125
126
    /**
127
     * @param string $categoryPath
128
     */
129
    public function setCategoryPath($categoryPath)
130
    {
131
        $categoryPath       = $this->html2text($categoryPath);
132
        $this->categoryPath = $categoryPath;
133
    }
134
135
    /**
136
     * @param string $description
137
     */
138
    public function setDescription($description)
139
    {
140
        $description       = $this->html2text($description);
141
        $description       = $this->purifyText($description);
142
        $this->description = $description;
143
    }
144
145
    /**
146
     * Does nothing
147
     */
148
    public function createTitleTag()
149
    {
150
    }
151
152
    /**
153
     * @param int $maxWords
154
     *
155
     * @return string
156
     */
157
    public function createMetaDescription($maxWords = 30)
0 ignored issues
show
Unused Code introduced by
The parameter $maxWords 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

157
    public function createMetaDescription(/** @scrutinizer ignore-unused */ $maxWords = 30)

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...
158
    {
159
        $description = $this->purifyText($this->description);
160
        $description = $this->html2text($description);
161
        $words       = \explode(' ', $description);
162
        $ret         = '';
163
        $i           = 1;
164
        $wordCount   = \count($words);
165
        foreach ($words as $word) {
166
            $ret .= $word;
167
            if ($i < $wordCount) {
168
                $ret .= ' ';
169
            }
170
            ++$i;
171
        }
172
173
        return $ret;
174
    }
175
176
    /**
177
     * @param string $text
178
     * @param int    $minChar
179
     *
180
     * @return array
181
     */
182
    public function findMetaKeywords($text, $minChar)
183
    {
184
        $keywords         = [];
185
        $text             = $this->purifyText($text);
186
        $text             = $this->html2text($text);
187
        $originalKeywords = \explode(' ', $text);
188
        foreach ($originalKeywords as $originalKeyword) {
189
            $secondRoundKeywords = \explode("'", $originalKeyword);
190
            foreach ($secondRoundKeywords as $secondRoundKeyword) {
191
                if (\mb_strlen($secondRoundKeyword) >= $minChar) {
192
                    if (!\in_array($secondRoundKeyword, $keywords, true)) {
193
                        $keywords[] = \trim($secondRoundKeyword);
194
                    }
195
                }
196
            }
197
        }
198
199
        return $keywords;
200
    }
201
202
    /**
203
     * @return string
204
     */
205
    public function createMetaKeywords()
206
    {
207
        $keywords       = $this->findMetaKeywords($this->originalTitle . ' ' . $this->description, $this->minChar);
208
        $moduleKeywords = $this->helper->getConfig('seo_meta_keywords');
209
        if ('' != $moduleKeywords) {
210
            $moduleKeywords = \explode(',', $moduleKeywords);
211
            $keywords       = \array_merge($keywords, \array_map('\trim', $moduleKeywords));
212
        }
213
        $ret = \implode(',', $keywords);
214
215
        return $ret;
216
    }
217
218
    /**
219
     * Does nothing
220
     */
221
    public function autoBuildMetaKeywords()
222
    {
223
    }
224
225
    /**
226
     * Build Metatags
227
     */
228
    public function buildAutoMetaTags()
229
    {
230
        $this->keywords    = $this->createMetaKeywords();
231
        $this->description = $this->createMetaDescription();
232
        //$this->title = $this->createTitleTag();
233
    }
234
235
    /**
236
     * Creates meta tags
237
     */
238
    public function createMetaTags()
239
    {
240
        global $xoopsTpl, $xoTheme;
241
        if ('' != $this->keywords) {
242
            $xoTheme->addMeta('meta', 'keywords', $this->keywords);
243
        }
244
        if ('' != $this->description) {
245
            $xoTheme->addMeta('meta', 'description', $this->description);
246
        }
247
        if ('' != $this->title) {
248
            $xoopsTpl->assign('xoops_pagetitle', $this->title);
249
        }
250
    }
251
252
    /**
253
     * Return true if the string is length > 0
254
     *
255
     * @credit psylove
256
     * @param mixed $var
257
     * @return bool
258
     */
259
    public static function emptyString($var)
260
    {
261
        return ('' !== $var);
262
    }
263
264
    /**
265
     * Create a title for the short_url field of an article
266
     *
267
     * @credit psylove
268
     *
269
     * @param string|array $title   title of the article
270
     * @param bool         $withExt do we add an html extension or not
271
     *
272
     * @return string short url for article
273
     */
274
    public static function generateSeoTitle($title = '', $withExt = true)
275
    {
276
        // Transformation de la chaine en minuscule
277
        // Codage de la chaine afin d'éviter les erreurs 500 en cas de caractères imprévus
278
        $title = \rawurlencode(\mb_strtolower($title));
0 ignored issues
show
Bug introduced by
It seems like $title can also be of type array; however, parameter $str 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

278
        $title = \rawurlencode(\mb_strtolower(/** @scrutinizer ignore-type */ $title));
Loading history...
279
        // Transformation des ponctuations
280
281
        $pattern = [
282
            '/%09/', // Tab
283
            '/%20/', // Space
284
            '/%21/', // !
285
            '/%22/', // "
286
            '/%23/', // #
287
            '/%25/', // %
288
            '/%26/', // &
289
            '/%27/', // '
290
            '/%28/', // (
291
            '/%29/', // )
292
            '/%2C/', // ,
293
            '/%2F/', // /
294
            '/%3A/', // :
295
            '/%3B/', // ;
296
            '/%3C/', // <
297
            '/%3D/', // =
298
            '/%3E/', // >
299
            '/%3F/', // ?
300
            '/%40/', // @
301
            '/%5B/', // [
302
            '/%5C/', // \
303
            '/%5D/', // ]
304
            '/%5E/', // ^
305
            '/%7B/', // {
306
            '/%7C/', // |
307
            '/%7D/', // }
308
            '/%7E/', // ~
309
            "/\./", // .
310
        ];
311
        $repPat  = ['-', '-', '-', '-', '-', '-100', '-', '-', '-', '-', '-', '-', '-', '-', '-', '-', '-', '-', '-at-', '-', '-', '-', '-', '-', '-', '-', '-', '-'];
312
        $title   = \preg_replace($pattern, $repPat, $title);
313
        // Transformation des caractères accentués
314
        $pattern = [
315
            '/%B0/', // °
316
            '/%E8/', // è
317
            '/%E9/', // é
318
            '/%EA/', // ê
319
            '/%EB/', // ë
320
            '/%E7/', // ç
321
            '/%E0/', // à
322
            '/%E2/', // â
323
            '/%E4/', // ä
324
            '/%EE/', // î
325
            '/%EF/', // ï
326
            '/%F9/', // ù
327
            '/%FC/', // ü
328
            '/%FB/', // û
329
            '/%F4/', // ô
330
            '/%F6/', // ö
331
        ];
332
        $repPat  = ['-', 'e', 'e', 'e', 'e', 'c', 'a', 'a', 'a', 'i', 'i', 'u', 'u', 'u', 'o', 'o'];
333
        $title   = \preg_replace($pattern, $repPat, $title);
334
        $tableau = \explode('-', $title); // Transforms the string in table //Transforme la chaine de caractères en tableau
335
        $tableau = \array_filter($tableau, [__CLASS__, 'emptyString']); // Remove empty strings of the table //Supprime les chaines vides du tableau
336
        $title   = \implode('-', $tableau); // Transforms a character string in table separated by a hyphen //Transforme un tableau en chaine de caractères séparé par un tiret
337
        if ($title && !(\is_array($title))) {
338
            if ($withExt) {
339
                $title .= '.html';
340
            }
341
342
            return $title;
343
        }
344
345
        return '';
346
    }
347
348
    /**
349
     * @param      $text
350
     * @param bool $keyword
351
     *
352
     * @return mixed
353
     */
354
    public function purifyText($text, $keyword = false)
355
    {
356
        //        $text = str_replace(['&nbsp;', ' '], ['<br>', ' '], $text); //for php 5.4
357
        $text = \str_replace('&nbsp;', ' ', $text);
358
        $text = \str_replace('<br>', ' ', $text);
359
        $text = \strip_tags($text);
360
        $text = \html_entity_decode($text);
361
        $text = $this->myts->undoHtmlSpecialChars($text);
362
363
        $text = \str_replace(')', ' ', $text);
364
        $text = \str_replace('(', ' ', $text);
365
        $text = \str_replace(':', ' ', $text);
366
        $text = \str_replace('&euro', ' euro ', $text);
367
        $text = \str_replace('&hellip', '...', $text);
368
        $text = \str_replace('&rsquo', ' ', $text);
369
        $text = \str_replace('!', ' ', $text);
370
        $text = \str_replace('?', ' ', $text);
371
        $text = \str_replace('"', ' ', $text);
372
        $text = \str_replace('-', ' ', $text);
373
        $text = \str_replace('\n', ' ', $text);
374
375
        //        $text = str_replace([')','(',':','&euro','&hellip','&rsquo','!','?','"','-','\n'], [' ' , ' ',  ' ',  ' euro ',  '...',  ' ', ' ', ' ',  ' ', ' ',  ' '], $text); //for PHP 5.4
376
377
        if ($keyword) {
378
            $text = \str_replace('.', ' ', $text);
379
            $text = \str_replace(',', ' ', $text);
380
            $text = \str_replace('\'', ' ', $text);
381
            //            $text = str_replace(['.', ' '], [',', ' '], ['\'', ' '], $text); //for PHP 5.4
382
        }
383
        $text = \str_replace(';', ' ', $text);
384
385
        return $text;
386
    }
387
388
    /**
389
     * @param string $document
390
     *
391
     * @return mixed
392
     */
393
    public function html2text($document)
394
    {
395
        if (empty($document)) {
396
            return '';
397
        }
398
        // PHP Manual:: function preg_replace
399
        // $document should contain an HTML document.
400
        // This will remove HTML tags, javascript sections
401
        // and white space. It will also convert some
402
        // common HTML entities to their text equivalent.
403
        // Credits : newbb2
404
        $search = [
405
            "'<script[^>]*?>.*?</script>'si", // Strip out javascript
406
            "'<img.*?>'si", // Strip out img tags
407
            "'<[\/\!]*?[^<>]*?>'si", // Strip out HTML tags
408
            "'([\r\n])[\s]+'", // Strip out white space
409
            "'&(quot|#34);'i", // Replace HTML entities
410
            "'&(amp|#38);'i",
411
            "'&(lt|#60);'i",
412
            "'&(gt|#62);'i",
413
            "'&(nbsp|#160);'i",
414
            "'&(iexcl|#161);'i",
415
            "'&(cent|#162);'i",
416
            "'&(pound|#163);'i",
417
            "'&(copy|#169);'i",
418
        ]; // evaluate as php
419
420
        $replace = [
421
            '',
422
            '',
423
            '',
424
            '\\1',
425
            '"',
426
            '&',
427
            '<',
428
            '>',
429
            ' ',
430
            \chr(161),
431
            \chr(162),
432
            \chr(163),
433
            \chr(169),
434
        ];
435
436
        $text = \preg_replace($search, $replace, $document);
437
438
        \preg_replace_callback(
439
            '/&#(\d+);/',
440
            static function ($matches) {
441
                return \chr($matches[1]);
442
            },
443
            $document
444
        );
445
446
        return $text;
447
    }
448
}
449