Passed
Push — master ( b85d4e...511693 )
by Dispositif
02:38
created

OuvrageOptimize::parametersErrorFromHydrate()   B

Complexity

Conditions 10
Paths 16

Size

Total Lines 36
Code Lines 22

Duplication

Lines 0
Ratio 0 %

Importance

Changes 5
Bugs 0 Features 0
Metric Value
cc 10
eloc 22
c 5
b 0
f 0
nc 16
nop 0
dl 0
loc 36
rs 7.6666

How to fix   Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

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\Models\Wiki\GoogleLivresTemplate;
13
use App\Domain\Models\Wiki\OuvrageTemplate;
14
use App\Domain\Utils\TextUtil;
15
use App\Domain\Utils\WikiTextUtil;
16
use App\Infrastructure\FileManager;
17
use Exception;
18
use function mb_strlen;
19
use Throwable;
20
21
/**
22
 * Legacy.
23
 * TODO move methods to OuvrageClean setters
24
 * TODO AbstractProcess
25
 * TODO observer/event (log, MajorEdition)
26
 * Class OuvrageProcess.
27
 */
28
class OuvrageOptimize
29
{
30
    const CONVERT_GOOGLEBOOK_TEMPLATE = false; // change OuvrageOptimizeTest !!
31
32
    const WIKI_LANGUAGE = 'fr';
33
34
    protected $original;
35
36
    private $wikiPageTitle;
37
38
    private $log = [];
39
40
    public $notCosmetic = false;
41
42
    public $major = false;
43
44
    private $ouvrage;
45
46
    private $currentTask;
47
48
    // todo inject TextUtil + ArticleVersion ou WikiRef
49
    public function __construct(OuvrageTemplate $ouvrage, $wikiPageTitle = null)
50
    {
51
        $this->original = $ouvrage;
52
        $this->ouvrage = clone $ouvrage;
53
        $this->wikiPageTitle = ($wikiPageTitle) ?? null;
54
    }
55
56
    public function doTasks(): self
57
    {
58
        $this->cleanAndPredictErrorParameters();
59
60
        $this->processAuthors();
61
62
        $this->processTitle();
63
        $this->processEditeur();
64
        $this->processDates();
65
        $this->externalTemplates();
66
        $this->predictFormatByPattern();
67
68
        $this->processIsbn();
69
        $this->processBnf();
70
71
        $this->processLang();
72
        $this->processLocation(); // 'lieu'
73
74
        $this->GoogleBookURL('lire en ligne');
75
        $this->GoogleBookURL('présentation en ligne');
76
77
        return $this;
78
    }
79
80
    /**
81
     * Todo: injection dep.
82
     * Todo : "[s. l.]" sans lieu "s.l.n.d." sans lieu ni date.
83
     *
84
     * @throws Exception
85
     */
86
    private function processLocation()
87
    {
88
        $location = $this->getParam('lieu');
89
        if (empty($location)) {
90
            return;
91
        }
92
93
        // typo and unwikify
94
        $memo = $location;
95
        $location = WikiTextUtil::unWikify($location);
96
        $location = TextUtil::mb_ucfirst($location);
97
        if ($memo !== $location) {
98
            $this->setParam('lieu', $location);
99
            $this->log('±lieu');
100
            $this->notCosmetic = true;
101
        }
102
103
        // french translation : "London"->"Londres"
104
        $manager = new FileManager();
105
        $row = $manager->findCSVline(__DIR__.'/resources/traduction_ville.csv', $location);
106
        if (!empty($row) && !empty($row[1])) {
107
            $this->setParam('lieu', $row[1]);
108
            $this->log('lieu francisé');
109
            $this->notCosmetic = true;
110
        }
111
    }
112
113
    private function processBnf()
114
    {
115
        $bnf = $this->getParam('bnf');
116
        if (!$bnf) {
117
            return;
118
        }
119
        $bnf = str_ireplace('FRBNF', '', $bnf);
120
        $this->setParam('bnf', $bnf);
121
    }
122
123
    /**
124
     * @throws Exception
125
     */
126
    private function processAuthors()
127
    {
128
        $this->distinguishAuthors();
129
        //$this->fusionFirstNameAndName(); // desactived : no consensus
130
    }
131
132
    /**
133
     * Detect and correct multiple authors in same parameter.
134
     * Like "auteurs=J. M. Waller, M. Bigger, R. J. Hillocks".
135
     *
136
     * @throws Exception
137
     */
138
    private function distinguishAuthors()
139
    {
140
        // merge params of author 1
141
        $auteur1 = $this->getParam('auteur') ?? '';
142
        $auteur1 .= $this->getParam('auteurs') ?? '';
143
        $auteur1 .= $this->getParam('prénom1') ?? '';
144
        $auteur1 .= ' '.$this->getParam('nom1') ?? '';
145
        $auteur1 = trim($auteur1);
146
        // of authors 2
147
        $auteur2 = $this->getParam('auteur2') ?? '';
148
        $auteur2 .= $this->getParam('prénom2') ?? '';
149
        $auteur2 .= ' '.$this->getParam('nom2') ?? '';
150
        $auteur2 = trim($auteur2);
151
152
        // skip if wikilink in author
153
        if (empty($auteur1) || WikiTextUtil::isWikify($auteur1)) {
154
            return;
155
        }
156
157
        $machine = new PredictAuthors();
158
        $res = $machine->predictAuthorNames($auteur1);
159
160
        if (1 === count($res)) {
161
            // auteurs->auteur?
162
            return;
163
        }
164
        // Many authors... and empty "auteur2"
165
        if (count($res) >= 2 && empty($auteur2)) {
166
            // delete author-params
167
            array_map(
168
                function ($param) {
169
                    $this->unsetParam($param);
170
                },
171
                ['auteur', 'auteurs', 'prénom1', 'nom1']
172
            );
173
            // iterate and edit new values
174
            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...
175
                $this->setParam(sprintf('auteur%s', $i + 1), $res[$i]);
176
            }
177
            $this->log('distinction auteurs');
178
            $this->major = true;
179
            $this->notCosmetic = true;
180
        }
181
    }
182
183
    /**
184
     * todo: move/implement.
185
     *
186
     * @throws Exception
187
     */
188
    private function processLang()
189
    {
190
        $lang = $this->getParam('langue') ?? null;
191
192
        if ($lang) {
193
            $replace = [
194
                'french' => 'fr',
195
                'française' => 'fr',
196
                'français' => 'fr',
197
                'anglaise' => 'en',
198
                'anglais' => 'en',
199
                'english' => 'en',
200
                'japonais' => 'ja',
201
                'japanese' => 'ja',
202
                'allemand' => 'de',
203
                'deutsch' => 'de',
204
                'german' => 'de',
205
                'espagnol' => 'es',
206
                'spanish' => 'es',
207
                'español' => 'es',
208
            ];
209
            $lang2 = str_ireplace(
210
                array_keys($replace),
211
                array_values($replace),
212
                mb_strtolower($lang)
213
            );
214
215
            if ($lang !== $lang2) {
216
                $this->setParam('langue', $lang2);
217
                if (self::WIKI_LANGUAGE !== $lang2) {
218
                    $this->log('±langue');
219
                }
220
            }
221
        }
222
    }
223
224
    /**
225
     * Validate or correct ISBN.
226
     *
227
     * @throws Exception
228
     */
229
    private function processIsbn()
230
    {
231
        $isbn = $this->getParam('isbn') ?? '';
232
233
        if (empty($isbn)) {
234
            return;
235
        }
236
237
        $isbnMachine = new IsbnFacade($isbn);
238
239
        try {
240
            $isbnMachine->validate();
241
            $isbn13 = $isbnMachine->format('ISBN-13');
242
        } catch (Throwable $e) {
243
            // ISBN not validated
244
            // TODO : bot ISBN invalide (queue, message PD...)
245
            $this->setParam(
246
                'isbn invalide',
247
                sprintf('%s %s', $isbn, $e->getMessage() ?? '')
248
            );
249
            $this->log(sprintf('ISBN invalide: %s', $e->getMessage()));
250
            $this->notCosmetic = true;
251
252
            // TODO log file ISBNinvalide
253
            return;
254
        }
255
256
        // ISBN 10 ?
257
        if (10 === mb_strlen(str_replace('-', '', $isbn)) && !$this->getParam('isbn10')) {
258
            $this->setParam('isbn10', $isbn);
259
            $this->log('isbn10');
260
            $this->notCosmetic = true;
261
        }
262
263
        // ISBN correction
264
        if ($isbn13 !== $isbn) {
265
            $this->setParam('isbn', $isbn13);
266
            $this->log('ISBN');
267
            $this->notCosmetic = true;
268
        }
269
    }
270
271
    private function processTitle()
272
    {
273
        $this->currentTask = 'titres';
274
275
        $oldtitre = $this->getParam('titre');
276
        $this->langInTitle();
277
        $this->deWikifyExternalLink('titre');
278
        $this->upperCaseFirstLetter('titre');
279
        $this->typoDeuxPoints('titre');
280
281
        $this->extractSubTitle();
282
283
        // 20-11-2019 : Retiré majuscule à sous-titre
284
285
        if ($this->getParam('titre') !== $oldtitre) {
286
            $this->log('±titre');
287
        }
288
289
        $this->currentTask = 'titre chapitre';
290
        $this->valideNumeroChapitre();
291
        $this->deWikifyExternalLink('titre chapitre');
292
        $this->upperCaseFirstLetter('titre chapitre');
293
        $this->typoDeuxPoints('titre chapitre');
294
    }
295
296
    private function detectColon($param): bool
297
    {
298
        // > 0 don't count a starting colon ":bla"
299
        if (!empty($this->getParam($param)) && mb_strrpos($this->getParam('titre'), ':') > 0) {
300
            return true;
301
        }
302
303
        return false;
304
    }
305
306
    private function extractSubTitle(): void
307
    {
308
        // FIXED bug [[fu:bar]]
309
        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

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

398
                $this->setParam($param, WikiTextUtil::unWikify(/** @scrutinizer ignore-type */ $this->getParam($param)));
Loading history...
399
            }
400
        }
401
402
        try {
403
            $this->moveDate2Year();
404
        } catch (Exception $e) {
405
            dump($e);
406
        }
407
    }
408
409
    /**
410
     * todo: move to AbstractWikiTemplate ?
411
     * Correction des parametres rejetés à l'hydratation données.
412
     *
413
     * @throws Exception
414
     */
415
    private function cleanAndPredictErrorParameters()
416
    {
417
        if (empty($this->ouvrage->parametersErrorFromHydrate)) {
418
            return;
419
        }
420
        $allParamsAndAlias = $this->ouvrage->getParamsAndAlias();
421
422
        foreach ($this->ouvrage->parametersErrorFromHydrate as $name => $value) {
423
            if (!is_string($name)) {
424
                // example : 1 => "ouvrage collectif" from |ouvrage collectif|
425
                continue;
426
            }
427
428
            // delete error parameter if no value
429
            if (empty($value)) {
430
                unset($this->ouvrage->parametersErrorFromHydrate[$name]);
431
432
                continue;
433
            }
434
435
            $maxDistance = 1;
436
            if (mb_strlen($name) >= 4) {
437
                $maxDistance = 2;
438
            }
439
            if (mb_strlen($name) >= 8) {
440
                $maxDistance = 3;
441
            }
442
443
            $predName = TextUtil::predictCorrectParam($name, $allParamsAndAlias, $maxDistance);
444
            if ($predName && mb_strlen($name) >= 5) {
445
                if (empty($this->getParam($predName))) {
446
                    $predName = $this->ouvrage->getAliasParam($predName);
447
                    $this->setParam($predName, $value);
448
                    $this->log(sprintf('%s⇒%s ?', $name, $predName));
449
                    $this->notCosmetic = true;
450
                    unset($this->ouvrage->parametersErrorFromHydrate[$name]);
451
                }
452
            }
453
        }
454
    }
455
456
    /**
457
     * TODO : return "" instead of null ?
458
     *
459
     * @param $name
460
     *
461
     * @return string|null
462
     *
463
     * @throws Exception
464
     */
465
    private function getParam(string $name): ?string
466
    {
467
        return $this->ouvrage->getParam($name);
468
    }
469
470
    private function setParam($name, $value)
471
    {
472
        // todo : overwrite setParam() ?
473
        if (!empty($value) || $this->ouvrage->getParam($name)) {
474
            $this->ouvrage->setParam($name, $value);
475
        }
476
    }
477
478
    private function log(string $string): void
479
    {
480
        if (!empty($string)) {
481
            $this->log[] = trim($string);
482
        }
483
    }
484
485
    /**
486
     * Bool ?
487
     * déwikification du titre : consensus Bistro 27 août 2011
488
     * idem  'titre chapitre'.
489
     *
490
     * @param string $param
491
     *
492
     * @throws Exception
493
     */
494
    private function deWikifyExternalLink(string $param): void
495
    {
496
        if (empty($this->getParam($param))) {
497
            return;
498
        }
499
        if (preg_match('#^\[(http[^ \]]+) ([^]]+)]#i', $this->getParam($param), $matches) > 0) {
500
            $this->setParam($param, str_replace($matches[0], $matches[2], $this->getParam($param)));
501
            $this->log('±'.$param);
502
503
            if (in_array($param, ['titre', 'titre chapitre'])) {
504
                if (empty($this->getParam('lire en ligne'))) {
505
                    $this->setParam('lire en ligne', $matches[1]);
506
                    $this->log('+lire en ligne');
507
508
                    return;
509
                }
510
                $this->log('autre lien externe: '.$matches[1]);
511
            }
512
        }
513
    }
514
515
    private function upperCaseFirstLetter($param)
516
    {
517
        if (empty($this->getParam($param))) {
518
            return;
519
        }
520
        $newValue = TextUtil::mb_ucfirst(trim($this->getParam($param)));
521
        $this->setParam($param, $newValue);
522
    }
523
524
    /**
525
     * Typo internationale 'titre : sous-titre'.
526
     * Fix fantasy typo of subtitle with '. ' or ' - '.
527
     * International Standard Bibliographic Description :
528
     * https://fr.wikipedia.org/wiki/Wikip%C3%A9dia:Le_Bistro/13_janvier_2016#Modif_du_mod%C3%A8le:Ouvrage.
529
     *
530
     * @param $param
531
     *
532
     * @throws Exception
533
     */
534
    private function typoDeuxPoints($param)
535
    {
536
        $origin = $this->getParam($param) ?? '';
537
        if (empty($origin)) {
538
            return;
539
        }
540
        // FIXED bug [[fu:bar]]
541
        if (WikiTextUtil::isWikify($origin)) {
542
            return;
543
        }
544
545
        $origin = TextUtil::replaceNonBreakingSpaces($origin);
546
547
        $strTitle = $origin;
548
549
        // CORRECTING TYPO FANTASY OF SUBTITLE
550
551
        // Replace first '.' by ':' if no ': ' and no numbers around (as PHP 7.3)
552
        // exlude pattern "blabla... blabla"
553
        // TODO: statistics
554
555
        // Replace ' - ' or ' / ' (spaced!) by ' : ' if no ':' and no numbers after (as PHP 7.3 or 1939-1945)
556
        if (!mb_strpos(':', $strTitle) && preg_match('#.{6,} ?[-/] ?[^0-9)]{6,}#', $strTitle) > 0) {
557
            $strTitle = preg_replace('#(.{6,}) [-/] ([^0-9)]{6,})#', '$1 : $2', $strTitle);
558
        }
559
560
        // international typo style " : " (first occurrence)
561
        $strTitle = preg_replace('#[ ]*:[ ]*#', ' : ', $strTitle);
562
563
        if ($strTitle !== $origin) {
564
            $this->setParam($param, $strTitle);
565
            $this->log(sprintf(':%s', $param));
566
        }
567
    }
568
569
    private function valideNumeroChapitre()
570
    {
571
        $value = $this->getParam('numéro chapitre');
572
        if (empty($value)) {
573
            return;
574
        }
575
        // "12" ou "VI", {{II}}, II:3
576
        if (preg_match('#^[0-9IVXL\-.:{}]+$#i', $value) > 0) {
577
            return;
578
        }
579
        // déplace vers "titre chapitre" ?
580
        if (!$this->getParam('titre chapitre')) {
581
            $this->unsetParam('numéro chapitre');
582
            $this->setParam('titre chapitre', $value);
583
        }
584
        $this->log('≠numéro chapitre');
585
    }
586
587
    private function unsetParam($name)
588
    {
589
        $this->ouvrage->unsetParam($name);
590
    }
591
592
    /**
593
     * TODO move+refac
594
     * TODO PlumeTemplate CommentaireBiblioTemplate  ExtraitTemplate
595
     * Probleme {{commentaire biblio}} <> {{commentaire biblio SRL}}
596
     * Generate supplementary templates from obsoletes params.
597
     *
598
     * @throws Exception
599
     */
600
    protected function externalTemplates()
601
    {
602
        // "plume=bla" => {{plume}}
603
        // =oui selon doc, mais testé OK avec "non"
604
        // todo detect duplication ouvrage/plume dans externalTemplate ?
605
        if (!empty($this->getParam('plume'))) {
606
            $plumeValue = $this->getParam('plume');
607
            $this->ouvrage->externalTemplates[] = (object) [
608
                'template' => 'plume',
609
                '1' => $plumeValue,
610
                'raw' => '{{nobr|. {{plume}}}}',
611
            ];
612
            $this->unsetParam('plume');
613
            $this->log('{plume}');
614
        }
615
616
        // "extrait=bla" => {{citation bloc|bla}}
617
        if (!empty($this->getParam('extrait'))) {
618
            $extrait = $this->getParam('extrait');
619
            // todo bug {{citation bloc}} si "=" ou "|" dans texte de citation
620
            // Legacy : use {{début citation}} ... {{fin citation}}
621
            if (preg_match('#[=|]#', $extrait) > 0) {
622
                $this->ouvrage->externalTemplates[] = (object) [
623
                    'template' => 'début citation',
624
                    '1' => '',
625
                    'raw' => '{{début citation}}'.$extrait.'{{fin citation}}',
626
                ];
627
                $this->log('{début citation}');
628
                $this->notCosmetic = true;
629
            } else {
630
                // StdClass
631
                $this->ouvrage->externalTemplates[] = (object) [
632
                    'template' => 'citation bloc',
633
                    '1' => $extrait,
634
                    'raw' => '{{extrait|'.$extrait.'}}',
635
                ];
636
                $this->log('{extrait}');
637
                $this->notCosmetic = true;
638
            }
639
640
            $this->unsetParam('extrait');
641
            $this->notCosmetic = true;
642
        }
643
644
        // "commentaire=bla" => {{Commentaire biblio|1=bla}}
645
        if (!empty($this->getParam('commentaire'))) {
646
            $commentaire = $this->getParam('commentaire');
647
            $this->ouvrage->externalTemplates[] = (object) [
648
                'template' => 'commentaire biblio',
649
                '1' => $commentaire,
650
                'raw' => '{{commentaire biblio|'.$commentaire.'}}',
651
            ];
652
            $this->unsetParam('commentaire');
653
            $this->log('{commentaire}');
654
            $this->notCosmetic = true;
655
        }
656
    }
657
658
    // ----------------------
659
    // ----------------------
660
    // ----------------------
661
662
    /**
663
     * Date->année (nécessaire pour OuvrageComplete).
664
     *
665
     * @throws Exception
666
     */
667
    private function moveDate2Year()
668
    {
669
        $date = $this->getParam('date') ?? false;
670
        if ($date) {
671
            if (preg_match('#^-?[12][0-9][0-9][0-9]$#', $date)) {
672
                $this->setParam('année', $date);
673
                $this->unsetParam('date');
674
                $this->log('>année');
675
            }
676
        }
677
    }
678
679
    private function predictFormatByPattern()
680
    {
681
        if (($value = $this->getParam('format'))) {
682
            // predict if 'format électronique'
683
            // format electronique lié au champ 'lire en ligne'
684
            // 2015 https://fr.wikipedia.org/wiki/Discussion_mod%C3%A8le:Ouvrage#format,_format_livre,_format_%C3%A9lectronique
685
            //            if (preg_match('#(pdf|epub|html|kindle|audio|\{\{aud|jpg)#i', $value) > 0) {
686
            //
687
            //                $this->setParam('format électronique', $value);
688
            //                $this->unsetParam('format');
689
            //                $this->log('format:électronique?');
690
            //
691
            //                return;
692
            //            }
693
            if (preg_match(
694
                    '#(ill\.|couv\.|in-[0-9]|in-fol|poche|broché|relié|{{unité|{{Dunité|[0-9]{2} ?cm|\|cm}}|vol\.|A4)#i',
695
                    $value
696
                ) > 0
697
            ) {
698
                $this->setParam('format livre', $value);
699
                $this->unsetParam('format');
700
                $this->log('format:livre?');
701
                $this->notCosmetic = true;
702
            }
703
            // Certainement 'format électronique'...
704
        }
705
    }
706
707
    /**
708
     * @return bool
709
     *
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