Completed
Push — master ( 0349ad...e37ca9 )
by Dispositif
02:28
created

OuvrageOptimize::doTasks()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 25
Code Lines 16

Duplication

Lines 0
Ratio 0 %

Importance

Changes 3
Bugs 0 Features 0
Metric Value
cc 1
eloc 16
c 3
b 0
f 0
nc 1
nop 0
dl 0
loc 25
rs 9.7333
1
<?php
2
/**
3
 * This file is part of dispositif/wikibot application
4
 * 2019 : Philippe M. <[email protected]>
5
 * For the full copyright and MIT license information, please view the LICENSE file.
6
 */
7
8
declare(strict_types=1);
9
10
namespace App\Domain;
11
12
use App\Domain\Enums\Language;
13
use App\Domain\Models\Wiki\GoogleLivresTemplate;
14
use App\Domain\Models\Wiki\OuvrageTemplate;
15
use App\Domain\Utils\NumberUtil;
16
use App\Domain\Utils\TextUtil;
17
use App\Domain\Utils\WikiTextUtil;
18
use App\Infrastructure\FileManager;
19
use Exception;
20
use Throwable;
21
22
use function mb_strlen;
23
24
/**
25
 * Legacy.
26
 * TODO move methods to OuvrageClean setters
27
 * TODO AbstractProcess
28
 * TODO observer/event (log, MajorEdition)
29
 * Class OuvrageProcess.
30
 */
31
class OuvrageOptimize
32
{
33
    const CONVERT_GOOGLEBOOK_TEMPLATE = false; // change OuvrageOptimizeTest !!
34
35
    const WIKI_LANGUAGE = 'fr';
36
37
    protected $original;
38
39
    private $wikiPageTitle;
40
41
    private $log = [];
42
43
    public $notCosmetic = false;
44
45
    public $major = false;
46
47
    private $ouvrage;
48
49
    private $currentTask;
50
51
    // todo inject TextUtil + ArticleVersion ou WikiRef
52
    public function __construct(OuvrageTemplate $ouvrage, $wikiPageTitle = null)
53
    {
54
        $this->original = $ouvrage;
55
        $this->ouvrage = clone $ouvrage;
56
        $this->wikiPageTitle = ($wikiPageTitle) ?? null;
57
    }
58
59
    public function doTasks(): self
60
    {
61
        $this->cleanAndPredictErrorParameters();
62
63
        $this->processAuthors();
64
65
        $this->processTitle();
66
        $this->processEditeur();
67
        $this->processDates();
68
        $this->externalTemplates();
69
        $this->predictFormatByPattern();
70
71
        $this->convertRoman('tome');
72
        $this->convertRoman('volume');
73
74
        $this->processIsbn();
75
        $this->processBnf();
76
77
        $this->processLang();
78
        $this->processLocation(); // 'lieu'
79
80
        $this->GoogleBookURL('lire en ligne');
81
        $this->GoogleBookURL('présentation en ligne');
82
83
        return $this;
84
    }
85
86
    /**
87
     * Todo: injection dep.
88
     * Todo : "[s. l.]" sans lieu "s.l.n.d." sans lieu ni date.
89
     *
90
     * @throws Exception
91
     */
92
    private function processLocation()
93
    {
94
        $location = $this->getParam('lieu');
95
        if (empty($location)) {
96
            return;
97
        }
98
99
        // typo and unwikify
100
        $memo = $location;
101
        $location = WikiTextUtil::unWikify($location);
102
        $location = TextUtil::mb_ucfirst($location);
103
        if ($memo !== $location) {
104
            $this->setParam('lieu', $location);
105
            $this->log('±lieu');
106
            $this->notCosmetic = true;
107
        }
108
109
        // french translation : "London"->"Londres"
110
        $manager = new FileManager();
111
        $row = $manager->findCSVline(__DIR__.'/resources/traduction_ville.csv', $location);
112
        if (!empty($row) && !empty($row[1])) {
113
            $this->setParam('lieu', $row[1]);
114
            $this->log('lieu francisé');
115
            $this->notCosmetic = true;
116
        }
117
    }
118
119
    private function processBnf()
120
    {
121
        $bnf = $this->getParam('bnf');
122
        if (!$bnf) {
123
            return;
124
        }
125
        $bnf = str_ireplace('FRBNF', '', $bnf);
126
        $this->setParam('bnf', $bnf);
127
    }
128
129
    private function convertRoman(string $param): void
130
    {
131
        $value = $this->getParam($param);
132
        // note : strval() condition because intval('4c') = 4
133
        if ($value && intval($value) > 0 && strval(intval($value)) === $value) {
134
            $number = abs(intval($value));
135
            $roman = NumberUtil::arab2roman($number);
0 ignored issues
show
Bug introduced by
It seems like $number can also be of type double; however, parameter $number of App\Domain\Utils\NumberUtil::arab2roman() 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

135
            $roman = NumberUtil::arab2roman(/** @scrutinizer ignore-type */ $number);
Loading history...
136
            if ($number > 10) {
137
                $roman = '{{'.$roman.'}}';
138
            }
139
            $this->setParam($param, $roman);
140
            $this->log('romain');
141
            $this->notCosmetic = true;
142
        }
143
    }
144
145
    /**
146
     * @throws Exception
147
     */
148
    private function processAuthors()
149
    {
150
        $this->distinguishAuthors();
151
        //$this->fusionFirstNameAndName(); // desactived : no consensus
152
    }
153
154
    /**
155
     * Detect and correct multiple authors in same parameter.
156
     * Like "auteurs=J. M. Waller, M. Bigger, R. J. Hillocks".
157
     *
158
     * @throws Exception
159
     */
160
    private function distinguishAuthors()
161
    {
162
        // merge params of author 1
163
        $auteur1 = $this->getParam('auteur') ?? '';
164
        $auteur1 .= $this->getParam('auteurs') ?? '';
165
        $auteur1 .= $this->getParam('prénom1') ?? '';
166
        $auteur1 .= ' '.$this->getParam('nom1') ?? '';
167
        $auteur1 = trim($auteur1);
168
        // of authors 2
169
        $auteur2 = $this->getParam('auteur2') ?? '';
170
        $auteur2 .= $this->getParam('prénom2') ?? '';
171
        $auteur2 .= ' '.$this->getParam('nom2') ?? '';
172
        $auteur2 = trim($auteur2);
173
174
        // skip if wikilink in author
175
        if (empty($auteur1) || WikiTextUtil::isWikify($auteur1)) {
176
            return;
177
        }
178
179
        $machine = new PredictAuthors();
180
        $res = $machine->predictAuthorNames($auteur1);
181
182
        if (1 === count($res)) {
183
            // auteurs->auteur?
184
            return;
185
        }
186
        // Many authors... and empty "auteur2"
187
        if (count($res) >= 2 && empty($auteur2)) {
188
            // delete author-params
189
            array_map(
190
                function ($param) {
191
                    $this->unsetParam($param);
192
                },
193
                ['auteur', 'auteurs', 'prénom1', 'nom1']
194
            );
195
            // iterate and edit new values
196
            for ($i = 0; $i < count($res); ++$i) {
1 ignored issue
show
Performance Best Practice introduced by
It seems like you are calling the size function count() as part of the test condition. You might want to compute the size beforehand, and not on each iteration.

If the size of the collection does not change during the iteration, it is generally a good practice to compute it beforehand, and not on each iteration:

for ($i=0; $i<count($array); $i++) { // calls count() on each iteration
}

// Better
for ($i=0, $c=count($array); $i<$c; $i++) { // calls count() just once
}
Loading history...
197
                $this->setParam(sprintf('auteur%s', $i + 1), $res[$i]);
198
            }
199
            $this->log('distinction auteurs');
200
            $this->major = true;
201
            $this->notCosmetic = true;
202
        }
203
    }
204
205
    /**
206
     * todo: move/implement.
207
     *
208
     * @throws Exception
209
     */
210
    private function processLang()
211
    {
212
        $lang = $this->getParam('langue') ?? null;
213
214
        if ($lang) {
215
            $lang2 = Language::all2wiki($lang);
216
217
            if ($lang2 && $lang !== $lang2) {
218
                $this->setParam('langue', $lang2);
219
                if (self::WIKI_LANGUAGE !== $lang2) {
220
                    $this->log('±langue');
221
                }
222
            }
223
        }
224
    }
225
226
    /**
227
     * Validate or correct ISBN.
228
     *
229
     * @throws Exception
230
     */
231
    private function processIsbn()
232
    {
233
        $isbn = $this->getParam('isbn') ?? '';
234
235
        if (empty($isbn)) {
236
            return;
237
        }
238
239
        $isbnMachine = new IsbnFacade($isbn);
240
241
        try {
242
            $isbnMachine->validate();
243
            $isbn13 = $isbnMachine->format('ISBN-13');
244
        } catch (Throwable $e) {
245
            // ISBN not validated
246
            // TODO : bot ISBN invalide (queue, message PD...)
247
            $this->setParam(
248
                'isbn invalide',
249
                sprintf('%s %s', $isbn, $e->getMessage() ?? '')
250
            );
251
            $this->log(sprintf('ISBN invalide: %s', $e->getMessage()));
252
            $this->notCosmetic = true;
253
254
            // TODO log file ISBNinvalide
255
            return;
256
        }
257
258
        // ISBN 10 ?
259
        if (10 === mb_strlen(str_replace('-', '', $isbn)) && !$this->getParam('isbn10')) {
260
            $this->setParam('isbn10', $isbn);
261
            $this->log('isbn10');
262
            $this->notCosmetic = true;
263
        }
264
265
        // ISBN correction
266
        if ($isbn13 !== $isbn) {
267
            $this->setParam('isbn', $isbn13);
268
            $this->log('ISBN');
269
            $this->notCosmetic = true;
270
        }
271
    }
272
273
    private function processTitle()
274
    {
275
        $this->currentTask = 'titres';
276
277
        $oldtitre = $this->getParam('titre');
278
        $this->langInTitle();
279
        $this->deWikifyExternalLink('titre');
280
        $this->upperCaseFirstLetter('titre');
281
        $this->typoDeuxPoints('titre');
282
283
        $this->extractSubTitle();
284
285
        // 20-11-2019 : Retiré majuscule à sous-titre
286
287
        if ($this->getParam('titre') !== $oldtitre) {
288
            $this->log('±titre');
289
        }
290
291
        $this->currentTask = 'titre chapitre';
292
        $this->valideNumeroChapitre();
293
        $this->deWikifyExternalLink('titre chapitre');
294
        $this->upperCaseFirstLetter('titre chapitre');
295
        $this->typoDeuxPoints('titre chapitre');
296
    }
297
298
    private function detectColon($param): bool
299
    {
300
        // > 0 don't count a starting colon ":bla"
301
        if (!empty($this->getParam($param)) && mb_strrpos($this->getParam('titre'), ':') > 0) {
302
            return true;
303
        }
304
305
        return false;
306
    }
307
308
    private function extractSubTitle(): void
309
    {
310
        // FIXED bug [[fu:bar]]
311
        if (!$this->getParam('titre') || WikiTextUtil::isWikify($this->getParam('titre'))) {
1 ignored issue
show
Bug introduced by
It seems like $this->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

311
        if (!$this->getParam('titre') || WikiTextUtil::isWikify(/** @scrutinizer ignore-type */ $this->getParam('titre'))) {
Loading history...
312
            return;
313
        }
314
315
        if (!$this->detectColon('titre')) {
316
            return;
317
        }
318
        // Que faire si déjà un sous-titre ?
319
        if (!empty($this->getParam('sous-titre'))) {
320
            return;
321
        }
322
323
        // titre>5 and sous-titre>5 and sous-titre<40
324
        if (preg_match('#^(?<titre>[^:]{5,}):(?<st>.{5,40})$#', $this->getParam('titre'), $matches) > 0) {
325
            $this->setParam('titre', trim($matches['titre']));
326
            $this->setParam('sous-titre', trim($matches['st']));
327
            $this->log('>sous-titre');
328
        }
329
    }
330
331
    /**
332
     * Normalize a Google Book links.
333
     * Clean the useless URL parameters or transform into wiki-template.
334
     *
335
     * @param $param
336
     *
337
     * @throws Exception
338
     */
339
    private function googleBookUrl(string $param): void
340
    {
341
        $url = $this->getParam($param);
342
        if (empty($url)
343
            || !GoogleLivresTemplate::isGoogleBookURL($url)
344
        ) {
345
            return;
346
        }
347
348
        if (self::CONVERT_GOOGLEBOOK_TEMPLATE) {
349
            $template = GoogleLivresTemplate::createFromURL($url);
350
            if ($template) {
1 ignored issue
show
introduced by
$template is of type App\Domain\Models\Wiki\GoogleLivresTemplate, thus it always evaluated to true.
Loading history...
351
                $this->setParam($param, $template->serialize());
352
                $this->log('{Google}');
353
                $this->notCosmetic = true;
354
355
                return;
356
            }
357
        }
358
359
        $goo = GoogleLivresTemplate::simplifyGoogleUrl($url);
360
        if (!empty($goo)) {
361
            $this->setParam($param, $goo);
362
            $this->log('Google');
363
            $this->notCosmetic = true;
364
        }
365
    }
366
367
    /**
368
     * - {{lang|...}} dans titre => langue=... puis titre nettoyé
369
     *  langue=L’utilisation de ce paramètre permet aussi aux synthétiseurs vocaux de reconnaître la langue du titre de
370
     * l’ouvrage.
371
     * Il est possible d'afficher plusieurs langues, en saisissant le nom séparé par des espaces ou des virgules. La première langue doit être celle du titre.
372
     *
373
     * @throws Exception
374
     */
375
    private function langInTitle()
376
    {
377
        if (preg_match(
378
                '#^{{ ?(?:lang|langue) ?\| ?([a-z-]{2,5}) ?\| ?(?:texte=)?([^{}=]+)(?:\|dir=rtl)?}}$#i',
379
                $this->getParam('titre'),
380
                $matches
381
            ) > 0
382
        ) {
383
            $lang = trim($matches[1]);
384
            $newtitre = str_replace($matches[0], trim($matches[2]), $this->getParam('titre'));
385
            $this->setParam('titre', $newtitre);
386
            $this->log('°titre');
387
            if (self::WIKI_LANGUAGE !== $lang && empty($this->getParam('langue'))) {
388
                $this->setParam('langue', $lang);
389
                $this->log('+langue='.$lang);
390
            }
391
        }
392
    }
393
394
    private function processDates()
395
    {
396
        // dewikification
397
        $params = ['date', 'année', 'mois', 'jour'];
398
        foreach ($params as $param) {
399
            if (WikiTextUtil::isWikify(' '.$this->getParam($param))) {
400
                $this->setParam($param, WikiTextUtil::unWikify($this->getParam($param)));
1 ignored issue
show
Bug introduced by
It seems like $this->getParam($param) can also be of type null; however, parameter $text of App\Domain\Utils\WikiTextUtil::unWikify() 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

400
                $this->setParam($param, WikiTextUtil::unWikify(/** @scrutinizer ignore-type */ $this->getParam($param)));
Loading history...
401
            }
402
        }
403
404
        try {
405
            $this->moveDate2Year();
406
        } catch (Exception $e) {
407
            dump($e);
408
        }
409
    }
410
411
    /**
412
     * todo: move to AbstractWikiTemplate ?
413
     * Correction des parametres rejetés à l'hydratation données.
414
     *
415
     * @throws Exception
416
     */
417
    private function cleanAndPredictErrorParameters()
418
    {
419
        if (empty($this->ouvrage->parametersErrorFromHydrate)) {
420
            return;
421
        }
422
        $allParamsAndAlias = $this->ouvrage->getParamsAndAlias();
423
424
        foreach ($this->ouvrage->parametersErrorFromHydrate as $name => $value) {
425
            if (!is_string($name)) {
426
                // example : 1 => "ouvrage collectif" from |ouvrage collectif|
427
                continue;
428
            }
429
430
            // delete error parameter if no value
431
            if (empty($value)) {
432
                unset($this->ouvrage->parametersErrorFromHydrate[$name]);
433
434
                continue;
435
            }
436
437
            $maxDistance = 1;
438
            if (mb_strlen($name) >= 4) {
439
                $maxDistance = 2;
440
            }
441
            if (mb_strlen($name) >= 8) {
442
                $maxDistance = 3;
443
            }
444
445
            $predName = TextUtil::predictCorrectParam($name, $allParamsAndAlias, $maxDistance);
446
            if ($predName && mb_strlen($name) >= 5) {
447
                if (empty($this->getParam($predName))) {
448
                    $predName = $this->ouvrage->getAliasParam($predName);
449
                    $this->setParam($predName, $value);
450
                    $this->log(sprintf('%s⇒%s ?', $name, $predName));
451
                    $this->notCosmetic = true;
452
                    unset($this->ouvrage->parametersErrorFromHydrate[$name]);
453
                }
454
            }
455
        }
456
    }
457
458
    /**
459
     * TODO : return "" instead of null ?
460
     *
461
     * @param $name
462
     *
463
     * @return string|null
464
     * @throws Exception
465
     */
466
    private function getParam(string $name): ?string
467
    {
468
        return $this->ouvrage->getParam($name);
469
    }
470
471
    private function setParam($name, $value)
472
    {
473
        // todo : overwrite setParam() ?
474
        if (!empty($value) || $this->ouvrage->getParam($name)) {
475
            $this->ouvrage->setParam($name, $value);
476
        }
477
    }
478
479
    private function log(string $string): void
480
    {
481
        if (!empty($string)) {
482
            $this->log[] = trim($string);
483
        }
484
    }
485
486
    /**
487
     * Bool ?
488
     * déwikification du titre : consensus Bistro 27 août 2011
489
     * idem  'titre chapitre'.
490
     *
491
     * @param string $param
492
     *
493
     * @throws Exception
494
     */
495
    private function deWikifyExternalLink(string $param): void
496
    {
497
        if (empty($this->getParam($param))) {
498
            return;
499
        }
500
        if (preg_match('#^\[(http[^ \]]+) ([^]]+)]#i', $this->getParam($param), $matches) > 0) {
501
            $this->setParam($param, str_replace($matches[0], $matches[2], $this->getParam($param)));
502
            $this->log('±'.$param);
503
504
            if (in_array($param, ['titre', 'titre chapitre'])) {
505
                if (empty($this->getParam('lire en ligne'))) {
506
                    $this->setParam('lire en ligne', $matches[1]);
507
                    $this->log('+lire en ligne');
508
509
                    return;
510
                }
511
                $this->log('autre lien externe: '.$matches[1]);
512
            }
513
        }
514
    }
515
516
    private function upperCaseFirstLetter($param)
517
    {
518
        if (empty($this->getParam($param))) {
519
            return;
520
        }
521
        $newValue = TextUtil::mb_ucfirst(trim($this->getParam($param)));
522
        $this->setParam($param, $newValue);
523
    }
524
525
    /**
526
     * Typo internationale 'titre : sous-titre'.
527
     * Fix fantasy typo of subtitle with '. ' or ' - '.
528
     * International Standard Bibliographic Description :
529
     * https://fr.wikipedia.org/wiki/Wikip%C3%A9dia:Le_Bistro/13_janvier_2016#Modif_du_mod%C3%A8le:Ouvrage.
530
     *
531
     * @param $param
532
     *
533
     * @throws Exception
534
     */
535
    private function typoDeuxPoints($param)
536
    {
537
        $origin = $this->getParam($param) ?? '';
538
        if (empty($origin)) {
539
            return;
540
        }
541
        // FIXED bug [[fu:bar]]
542
        if (WikiTextUtil::isWikify($origin)) {
543
            return;
544
        }
545
546
        $origin = TextUtil::replaceNonBreakingSpaces($origin);
547
548
        $strTitle = $origin;
549
550
        // CORRECTING TYPO FANTASY OF SUBTITLE
551
552
        // Replace first '.' by ':' if no ': ' and no numbers around (as PHP 7.3)
553
        // exlude pattern "blabla... blabla"
554
        // TODO: statistics
555
556
        // Replace ' - ' or ' / ' (spaced!) by ' : ' if no ':' and no numbers after (as PHP 7.3 or 1939-1945)
557
        if (!mb_strpos(':', $strTitle) && preg_match('#.{6,} ?[-/] ?[^0-9)]{6,}#', $strTitle) > 0) {
558
            $strTitle = preg_replace('#(.{6,}) [-/] ([^0-9)]{6,})#', '$1 : $2', $strTitle);
559
        }
560
561
        // international typo style " : " (first occurrence)
562
        $strTitle = preg_replace('#[ ]*:[ ]*#', ' : ', $strTitle);
563
564
        if ($strTitle !== $origin) {
565
            $this->setParam($param, $strTitle);
566
            $this->log(sprintf(':%s', $param));
567
        }
568
    }
569
570
    private function valideNumeroChapitre()
571
    {
572
        $value = $this->getParam('numéro chapitre');
573
        if (empty($value)) {
574
            return;
575
        }
576
        // "12" ou "VI", {{II}}, II:3
577
        if (preg_match('#^[0-9IVXL\-.:{}]+$#i', $value) > 0) {
578
            return;
579
        }
580
        // déplace vers "titre chapitre" ?
581
        if (!$this->getParam('titre chapitre')) {
582
            $this->unsetParam('numéro chapitre');
583
            $this->setParam('titre chapitre', $value);
584
        }
585
        $this->log('≠numéro chapitre');
586
    }
587
588
    private function unsetParam($name)
589
    {
590
        $this->ouvrage->unsetParam($name);
591
    }
592
593
    /**
594
     * TODO move+refac
595
     * TODO PlumeTemplate CommentaireBiblioTemplate  ExtraitTemplate
596
     * Probleme {{commentaire biblio}} <> {{commentaire biblio SRL}}
597
     * Generate supplementary templates from obsoletes params.
598
     *
599
     * @throws Exception
600
     */
601
    protected function externalTemplates()
602
    {
603
        // "plume=bla" => {{plume}}
604
        // =oui selon doc, mais testé OK avec "non"
605
        // todo detect duplication ouvrage/plume dans externalTemplate ?
606
        if (!empty($this->getParam('plume'))) {
607
            $plumeValue = $this->getParam('plume');
608
            $this->ouvrage->externalTemplates[] = (object)[
609
                'template' => 'plume',
610
                '1' => $plumeValue,
611
                'raw' => '{{nobr|. {{plume}}}}',
612
            ];
613
            $this->unsetParam('plume');
614
            $this->log('{plume}');
615
        }
616
617
        // "extrait=bla" => {{citation bloc|bla}}
618
        if (!empty($this->getParam('extrait'))) {
619
            $extrait = $this->getParam('extrait');
620
            // todo bug {{citation bloc}} si "=" ou "|" dans texte de citation
621
            // Legacy : use {{début citation}} ... {{fin citation}}
622
            if (preg_match('#[=|]#', $extrait) > 0) {
623
                $this->ouvrage->externalTemplates[] = (object)[
624
                    'template' => 'début citation',
625
                    '1' => '',
626
                    'raw' => '{{début citation}}'.$extrait.'{{fin citation}}',
627
                ];
628
                $this->log('{début citation}');
629
                $this->notCosmetic = true;
630
            } else {
631
                // StdClass
632
                $this->ouvrage->externalTemplates[] = (object)[
633
                    'template' => 'citation bloc',
634
                    '1' => $extrait,
635
                    'raw' => '{{extrait|'.$extrait.'}}',
636
                ];
637
                $this->log('{extrait}');
638
                $this->notCosmetic = true;
639
            }
640
641
            $this->unsetParam('extrait');
642
            $this->notCosmetic = true;
643
        }
644
645
        // "commentaire=bla" => {{Commentaire biblio|1=bla}}
646
        if (!empty($this->getParam('commentaire'))) {
647
            $commentaire = $this->getParam('commentaire');
648
            $this->ouvrage->externalTemplates[] = (object)[
649
                'template' => 'commentaire biblio',
650
                '1' => $commentaire,
651
                'raw' => '{{commentaire biblio|'.$commentaire.'}}',
652
            ];
653
            $this->unsetParam('commentaire');
654
            $this->log('{commentaire}');
655
            $this->notCosmetic = true;
656
        }
657
    }
658
659
    // ----------------------
660
    // ----------------------
661
    // ----------------------
662
663
    /**
664
     * Date->année (nécessaire pour OuvrageComplete).
665
     *
666
     * @throws Exception
667
     */
668
    private function moveDate2Year()
669
    {
670
        $date = $this->getParam('date') ?? false;
671
        if ($date) {
672
            if (preg_match('#^-?[12][0-9][0-9][0-9]$#', $date)) {
673
                $this->setParam('année', $date);
674
                $this->unsetParam('date');
675
                //$this->log('>année');
676
            }
677
        }
678
    }
679
680
    private function predictFormatByPattern()
681
    {
682
        if (($value = $this->getParam('format'))) {
683
            // predict if 'format électronique'
684
            // format electronique lié au champ 'lire en ligne'
685
            // 2015 https://fr.wikipedia.org/wiki/Discussion_mod%C3%A8le:Ouvrage#format,_format_livre,_format_%C3%A9lectronique
686
            //            if (preg_match('#(pdf|epub|html|kindle|audio|\{\{aud|jpg)#i', $value) > 0) {
687
            //
688
            //                $this->setParam('format électronique', $value);
689
            //                $this->unsetParam('format');
690
            //                $this->log('format:électronique?');
691
            //
692
            //                return;
693
            //            }
694
            if (preg_match(
695
                    '#(ill\.|couv\.|in-[0-9]|in-fol|poche|broché|relié|{{unité|{{Dunité|[0-9]{2} ?cm|\|cm}}|vol\.|A4)#i',
696
                    $value
697
                ) > 0
698
            ) {
699
                $this->setParam('format livre', $value);
700
                $this->unsetParam('format');
701
                $this->log('format:livre?');
702
                $this->notCosmetic = true;
703
            }
704
            // Certainement 'format électronique'...
705
        }
706
    }
707
708
    /**
709
     * @return bool
710
     * @throws Exception
711
     */
712
    public function checkMajorEdit(): bool
713
    {
714
        // Correction paramètre
715
        if ($this->ouvrage->parametersErrorFromHydrate !== $this->original->parametersErrorFromHydrate) {
716
            return true;
717
        }
718
        // Complétion langue ?
719
        if (!empty($this->getParam('langue')) && empty($this->original->getParam('langue'))
720
            && self::WIKI_LANGUAGE !== $this->getParam('langue')
721
        ) {
722
            return true;
723
        }
724
        // TODO replace conditions ci-dessous par event flagMajor()
725
        // Retire le param/value 'langue' (pas major si conversion nom langue)
726
        $datOuvrage = $this->ouvrage->toArray();
727
        $datOriginal = $this->original->toArray();
728
        unset($datOriginal['langue'], $datOuvrage['langue']);
729
730
        // Modification données
731
        if ($datOriginal !== $datOuvrage) {
732
            return true;
733
        }
734
735
        return false;
736
    }
737
738
    /**
739
     * @return array
740
     */
741
    public function getLog(): array
742
    {
743
        return $this->log;
744
    }
745
746
    /**
747
     * @return OuvrageTemplate
748
     */
749
    public function getOuvrage(): OuvrageTemplate
750
    {
751
        return $this->ouvrage;
752
    }
753
754
    /**
755
     * todo : vérif lien rouge
756
     * todo 'lien éditeur' affiché 1x par page
757
     * opti : Suppression lien éditeur si c'est l'article de l'éditeur.
758
     *
759
     * @throws Exception
760
     */
761
    private function processEditeur()
762
    {
763
        $editeur = $this->getParam('éditeur');
764
        if (empty($editeur)) {
765
            return;
766
        }
767
768
        // FIX bug "GEO Art ([[Prisma Media]]) ; [[Le Monde]]"
769
        if (preg_match('#\[.*\[.*\[#', $editeur) > 0) {
770
            return;
771
        }
772
        // FIX bug "[[Fu|Bar]] bla" => [[Fu|Bar bla]]
773
        if (preg_match('#(.+\[\[|\]\].+)#', $editeur) > 0) {
774
            return;
775
        }
776
777
        // [[éditeur]]
778
        if (preg_match('#\[\[([^|]+)]]#', $editeur, $matches) > 0) {
779
            $editeurUrl = $matches[1];
780
        }
781
        // [[bla|éditeur]]
782
        if (preg_match('#\[\[([^]|]+)\|.+]]#', $editeur, $matches) > 0) {
783
            $editeurUrl = $matches[1];
784
        }
785
786
        // abréviations communes
787
        // ['éd. de ', 'éd. du ', 'éd.', 'ed.', 'Éd. de ', 'Éd.', 'édit.', 'Édit.', '(éd.)', '(ed.)', 'Ltd.']
788
789
        $editeurStr = WikiTextUtil::unWikify($editeur);
790
        // On garde minuscule sur éditeur, pour nuance Éditeur/éditeur permettant de supprimer "éditeur"
791
        // ex: "éditions Milan" => "Milan"
792
793
        //        $editeurStr = TextUtil::mb_ucfirst($editeurStr);
794
795
        // Déconseillé : 'lien éditeur' (obsolete 2019)
796
        if (!empty($this->getParam('lien éditeur'))) {
797
            if (empty($editeurUrl)) {
798
                $editeurUrl = $this->getParam('lien éditeur');
799
            }
800
            $this->unsetParam('lien éditeur');
801
        }
802
803
        //        if (isset($editeurUrl)) {
804
        //            $editeurUrl = TextUtil::mb_ucfirst($editeurUrl);
805
        //        }
806
        $newEditeur = $editeurStr;
807
        if (isset($editeurUrl) && $editeurUrl !== $editeurStr) {
808
            $newEditeur = '[['.$editeurUrl.'|'.$editeurStr.']]';
809
        }
810
        if (isset($editeurUrl) && $editeurUrl === $editeurStr) {
811
            $newEditeur = '[['.$editeurStr.']]';
812
        }
813
814
        if ($newEditeur !== $editeur) {
815
            $this->setParam('éditeur', $newEditeur);
816
            $this->log('±éditeur');
817
            $this->notCosmetic = true;
818
        }
819
    }
820
}
821