Passed
Branch master (ee24dc)
by Dispositif
03:19 queued 39s
created

TitleHandler::typoDeuxPoints()   A

Complexity

Conditions 6
Paths 6

Size

Total Lines 32
Code Lines 13

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 13
c 1
b 0
f 0
dl 0
loc 32
rs 9.2222
cc 6
nc 6
nop 1
1
<?php
2
/*
3
 * This file is part of dispositif/wikibot application (@github)
4
 * 2019-2023 © Philippe M./Irønie  <[email protected]>
5
 * For the full copyright and MIT license information, view the license file.
6
 */
7
8
declare(strict_types=1);
9
10
namespace App\Domain\WikiOptimizer\Handlers;
11
12
use App\Domain\Utils\TextUtil;
13
use App\Domain\Utils\WikiTextUtil;
14
use Exception;
15
16
/**
17
 * todo Extract other Handlers from this class.
18
 */
19
class TitleHandler extends AbstractOuvrageHandler
20
{
21
    public function handle()
22
    {
23
        $oldtitre = $this->ouvrage->getParam('titre');
24
        $this->langInTitle();
25
        $this->extractExternalLink('titre');
26
        $this->upperCaseFirstLetter('titre');
27
        $this->typoDeuxPoints('titre');
28
29
        $this->extractSubTitle();
30
31
        // 20-11-2019 : Retiré majuscule à sous-titre
32
33
        if ($this->ouvrage->getParam('titre') !== $oldtitre) {
34
            $this->optiStatus->addSummaryLog('±titre');
35
        }
36
37
        $this->valideNumeroChapitre();
38
        $this->extractExternalLink('titre chapitre');
39
        $this->upperCaseFirstLetter('titre chapitre');
40
    }
41
42
    /**
43
     * - {{lang|...}} dans titre => langue=... puis titre nettoyé
44
     * langue=L’utilisation de ce paramètre permet aussi aux synthétiseurs vocaux de reconnaître la langue du titre de
45
     * l’ouvrage.
46
     * Il est possible d'afficher plusieurs langues, en saisissant le nom séparé par des espaces ou des virgules.
47
     * La première langue doit être celle du titre.
48
     * @throws Exception
49
     */
50
    protected function langInTitle(): void
51
    {
52
        if (preg_match(
53
                '#^{{ ?(?:lang|langue) ?\| ?([a-z-]{2,5}) ?\| ?(?:texte=)?([^{}=]+)(?:\|dir=rtl)?}}$#i',
54
                $this->ouvrage->getParam('titre'),
0 ignored issues
show
Bug introduced by
It seems like $this->ouvrage->getParam('titre') can also be of type null; however, parameter $subject of preg_match() 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

54
                /** @scrutinizer ignore-type */ $this->ouvrage->getParam('titre'),
Loading history...
55
                $matches
56
            ) > 0
57
        ) {
58
            $lang = trim($matches[1]);
59
            $newtitre = str_replace($matches[0], trim($matches[2]), $this->ouvrage->getParam('titre'));
60
61
            // problème : titre anglais de livre français
62
            // => conversion {{lang}} du titre seulement si langue= défini
63
            // opti : restreindre à ISBN zone 2 fr ?
64
            if ($lang === $this->ouvrage->getParam('langue')) {
65
                $this->ouvrage->setParam('titre', $newtitre);
66
                $this->optiStatus->addSummaryLog('°titre');
67
            }
68
69
            // desactivé à cause de l'exception décrite ci-dessus
70
            // si langue=VIDE : ajout langue= à partir de langue titre
71
            //            if (self::WIKI_LANGUAGE !== $lang && empty($this->ouvrage->getParam('langue'))) {
72
            //                $this->setParam('langue', $lang);
73
            //                $this->log('+langue='.$lang);
74
            //            }
75
        }
76
    }
77
78
    /**
79
     * Bool ?
80
     * Retire lien externe du titre : consensus Bistro 27 août 2011
81
     * idem  'titre chapitre'.
82
     * Lien externe déplacé éventuellement dans "lire en ligne"
83
     *
84
     * @param string $param
85
     *
86
     * @throws Exception
87
     */
88
    protected function extractExternalLink(string $param): void
89
    {
90
        if (empty($this->ouvrage->getParam($param))) {
91
            return;
92
        }
93
        if (preg_match('#^\[(http[^ \]]+) ([^]]+)]#i', $this->ouvrage->getParam($param), $matches) > 0) {
0 ignored issues
show
Bug introduced by
It seems like $this->ouvrage->getParam($param) can also be of type null; however, parameter $subject of preg_match() 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

93
        if (preg_match('#^\[(http[^ \]]+) ([^]]+)]#i', /** @scrutinizer ignore-type */ $this->ouvrage->getParam($param), $matches) > 0) {
Loading history...
94
            $this->ouvrage->setParam($param, str_replace($matches[0], $matches[2], $this->ouvrage->getParam($param)));
95
            $this->optiStatus->addSummaryLog('±' . $param);
96
97
            if (in_array($param, ['titre', 'titre chapitre'])) {
98
                if (empty($this->ouvrage->getParam('lire en ligne'))) {
99
                    $this->ouvrage->setParam('lire en ligne', $matches[1]);
100
                    $this->optiStatus->addSummaryLog('+lire en ligne');
101
102
                    return;
103
                }
104
                $this->optiStatus->addSummaryLog('autre lien externe: ' . $matches[1]);
105
            }
106
        }
107
    }
108
109
    protected function upperCaseFirstLetter($param)
110
    {
111
        if (!$this->ouvrage->hasParamValue($param)) {
112
            return;
113
        }
114
        $newValue = TextUtil::mb_ucfirst(trim($this->ouvrage->getParam($param)));
0 ignored issues
show
Bug introduced by
It seems like $this->ouvrage->getParam($param) can also be of type null; however, parameter $string of trim() 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

114
        $newValue = TextUtil::mb_ucfirst(trim(/** @scrutinizer ignore-type */ $this->ouvrage->getParam($param)));
Loading history...
115
        $this->ouvrage->setParam($param, $newValue);
116
    }
117
118
    /**
119
     * Typo internationale 'titre : sous-titre'.
120
     * Fix fantasy typo of subtitle with '. ' or ' - '.
121
     * International Standard Bibliographic Description :
122
     * https://fr.wikipedia.org/wiki/Wikip%C3%A9dia:Le_Bistro/13_janvier_2016#Modif_du_mod%C3%A8le:Ouvrage.
123
     *
124
     * @param $param
125
     *
126
     * @throws Exception
127
     */
128
    protected function typoDeuxPoints($param)
129
    {
130
        $origin = $this->ouvrage->getParam($param) ?? '';
131
        if (empty($origin)) {
132
            return;
133
        }
134
        // FIXED bug [[fu:bar]]
135
        if (WikiTextUtil::isWikify($origin)) {
136
            return;
137
        }
138
139
        $origin = TextUtil::replaceNonBreakingSpaces($origin);
140
141
        $strTitle = $origin;
142
143
        // CORRECTING TYPO FANTASY OF SUBTITLE
144
145
        // Replace first '.' by ':' if no ': ' and no numbers around (as PHP 7.3)
146
        // exlude pattern "blabla... blabla"
147
        // TODO: statistics
148
149
        // Replace ' - ' or ' / ' (spaced!) by ' : ' if no ':' and no numbers after (as PHP 7.3 or 1939-1945)
150
        if (!mb_strpos(':', $strTitle) && preg_match('#.{6,} ?[-/] ?[^0-9)]{6,}#', $strTitle) > 0) {
151
            $strTitle = preg_replace('#(.{6,}) [-/] ([^0-9)]{6,})#', '$1 : $2', $strTitle);
152
        }
153
154
        // international typo style " : " (first occurrence)
155
        $strTitle = preg_replace('#[ ]*:[ ]*#', ' : ', $strTitle);
156
157
        if ($strTitle !== $origin) {
158
            $this->ouvrage->setParam($param, $strTitle);
159
            $this->optiStatus->addSummaryLog(sprintf(':%s', $param));
160
        }
161
    }
162
163
    protected function extractSubTitle(): void
164
    {
165
        // FIXED bug [[fu:bar]]
166
        if (
167
            !$this->ouvrage->getParam('titre')
168
            || WikiTextUtil::isWikify($this->ouvrage->getParam('titre'))
0 ignored issues
show
Bug introduced by
It seems like $this->ouvrage->getParam('titre') can also be of type null; however, parameter $text of App\Domain\Utils\WikiTextUtil::isWikify() 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

168
            || WikiTextUtil::isWikify(/** @scrutinizer ignore-type */ $this->ouvrage->getParam('titre'))
Loading history...
169
        ) {
170
            return;
171
        }
172
173
        if (!$this->detectColon('titre')) {
174
            return;
175
        }
176
        // Que faire si déjà un sous-titre ?
177
        if ($this->ouvrage->hasParamValue('sous-titre')) {
178
            return;
179
        }
180
181
        // titre>5 and sous-titre>5 and sous-titre<40
182
        if (preg_match(
183
                '#^(?<titre>[^:]{5,}):(?<st>.{5,40})$#',
184
                $this->ouvrage->getParam('titre') ?? '',
185
                $matches
186
            ) > 0) {
187
            $this->ouvrage->setParam('titre', trim($matches['titre']));
188
            $this->ouvrage->setParam('sous-titre', trim($matches['st']));
189
            $this->optiStatus->addSummaryLog('>sous-titre');
190
        }
191
    }
192
193
    protected function detectColon($param): bool
194
    {
195
        // > 0 don't count a starting colon ":bla"
196
        return $this->ouvrage->hasParamValue($param) && mb_strrpos($this->ouvrage->getParam('titre'), ':') > 0;
0 ignored issues
show
Bug introduced by
It seems like $this->ouvrage->getParam('titre') can also be of type null; however, parameter $haystack of mb_strrpos() 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

196
        return $this->ouvrage->hasParamValue($param) && mb_strrpos(/** @scrutinizer ignore-type */ $this->ouvrage->getParam('titre'), ':') > 0;
Loading history...
197
    }
198
199
200
    protected function valideNumeroChapitre()
201
    {
202
        $value = $this->ouvrage->getParam('numéro chapitre');
203
        if (empty($value)) {
204
            return;
205
        }
206
        // "12" ou "VI", {{II}}, II:3
207
        if (preg_match('#^[0-9IVXL\-.:{}]+$#i', $value) > 0) {
208
            return;
209
        }
210
        // déplace vers "titre chapitre" ?
211
        if (!$this->ouvrage->getParam('titre chapitre')) {
212
            $this->ouvrage->unsetParam('numéro chapitre');
213
            $this->ouvrage->setParam('titre chapitre', $value);
214
        }
215
        $this->optiStatus->addSummaryLog('≠numéro chapitre');
216
    }
217
}