Completed
Push — master ( c4ce9d...69540b )
by Dispositif
03:31
created

EditProcess::checkErrorWarning()   C

Complexity

Conditions 11
Paths 257

Size

Total Lines 52
Code Lines 28

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 11
eloc 28
c 1
b 0
f 0
nc 257
nop 1
dl 0
loc 52
rs 5.7708

How to fix   Long Method    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\Application\Examples;
11
12
use App\Application\Bot;
13
use App\Application\Memory;
14
use App\Application\WikiPageAction;
15
use App\Domain\Utils\WikiTextUtil;
16
use App\Infrastructure\DbAdapter;
17
use App\Infrastructure\ServiceFactory;
18
use Mediawiki\DataModel\EditInfo;
19
use Throwable;
20
21
//use App\Application\CLI;
22
23
include __DIR__.'/../myBootstrap.php';
24
25
$process = new EditProcess();
26
$process->run();
27
28
/**
29
 * TODO refac
30
 * Class EditProcess
31
 *
32
 * @package App\Application\Examples
33
 */
34
class EditProcess
35
{
36
    const TASK_NAME              = 'Amélioration bibliographique';
37
    const EDIT_SIGNALEMENT       = false;
38
39
    const CITATION_LIMIT         = 100;
40
    const DELAY_BOTFLAG_SECONDS  = 30;
41
    const DELAY_NOBOT_IN_SECONDS = 150;
42
    const ERROR_MSG_TEMPLATE     = __DIR__.'/../templates/message_errors.wiki';
43
44
    private $db;
45
    private $bot;
46
    private $wiki;
47
    private $wikiText;
48
    private $citationSummary;
49
    private $citationVersion = '';
50
    private $errorWarning = [];
51
    private $importantSummary = [];
52
    private $nbRows;
53
54
    // Minor flag on edit
55
    private $minorFlag = true;
56
    // Bot flag on edit
57
    private $botFlag = true;
58
59
    public function __construct()
60
    {
61
        $this->db = new DbAdapter();
62
        $this->bot = new Bot();
63
64
        $this->wiki = ServiceFactory::wikiApi();
65
    }
66
67
    public function run()
68
    {
69
        $memory = new Memory();
70
        while (true) {
71
            echo "\n-------------------------------------\n\n";
72
            echo date("Y-m-d H:i")."\n";
73
            $memory->echoMemory(true);
74
75
            $this->pageProcess();
76
        }
77
    }
78
79
    private function pageProcess()
80
    {
81
        $this->initialize();
82
83
        // get a random queue line
84
        $json = $this->db->getAllRowsToEdit(self::CITATION_LIMIT);
85
        $data = json_decode($json, true);
86
87
        if (empty($data)) {
88
            echo "SKIP : no rows to process\n";
89
90
            return false;
91
        }
92
93
        try {
94
            $title = $data[0]['page'];
95
            echo "$title \n";
96
            $page = new WikiPageAction($this->wiki, $title);
97
        } catch (\Exception $e) {
98
            echo "*** WikiPageAction error : $title \n";
99
            sleep(60);
100
101
            return false;
102
        }
103
104
        // TODO : HACK
105
        if (in_array($page->getLastEditor(), [getenv('BOT_NAME'), getenv('BOT_OWNER')])) {
106
            echo "SKIP : édité recemment par bot/dresseur.\n";
107
            $this->db->skipRow($title);
108
109
            return false;
110
        }
111
        $this->wikiText = $page->getText();
112
113
        if ($this->bot->minutesSinceLastEdit($title) < 15) {
114
            echo "SKIP : édition humaine dans les dernières 15 minutes.\n";
115
116
            return false;
117
        }
118
119
        // Skip AdQ
120
        if (preg_match('#{{ ?En-tête label#i', $this->wikiText) > 0) {
121
            echo "SKIP : AdQ ou BA.\n";
122
            $this->db->skipRow($title);
123
124
            return false;
125
        }
126
127
        // GET all article lines from db
128
        echo sprintf(">> %s rows to process\n", count($data));
129
130
        // foreach line
131
        $changed = false;
132
        foreach ($data as $dat) {
133
            // hack temporaire pour éviter articles dont CompleteProcess incomplet
134
            if (empty($dat['opti']) || empty($dat['optidate']) || $dat['optidate'] < DbAdapter::OPTI_VALID_DATE) {
135
                echo "SKIP : Complètement incomplet de l'article \n";
136
137
                return false;
138
            }
139
            $success = $this->dataProcess($dat);
140
            $changed = ($success) ? true : $changed;
141
        }
142
        if (!$changed) {
143
            echo "Rien à changer...\n\n";
144
145
            return false;
146
        }
147
148
        // EDIT THE PAGE
149
        if (!$this->wikiText) {
150
            return false;
151
        }
152
153
        $miniSummary = $this->generateSummary();
154
        echo "Edition ?\n".$miniSummary."\n\n";
155
        echo "sleep 30...\n";
156
        sleep(30);
157
158
        $editInfo = new EditInfo($miniSummary, $this->minorFlag, $this->botFlag);
159
        $success = $page->editPage(\Normalizer::normalize($this->wikiText), $editInfo);
160
        echo ($success) ? "Ok\n" : "***** Erreur edit\n";
161
162
        if ($success) {
163
            // updata DB
164
            foreach ($data as $dat) {
165
                $this->db->sendEditedData(['id' => $dat['id']]);
166
            }
167
168
            try {
169
                if (self::EDIT_SIGNALEMENT) {
170
                    $this->sendErrorMessage($data);
171
                }
172
            } catch (Throwable $e) {
173
                dump($e);
174
                unset($e);
175
            }
176
177
            if (!$this->botFlag) {
178
                echo "sleep ".self::DELAY_NOBOT_IN_SECONDS."\n";
179
                sleep(self::DELAY_NOBOT_IN_SECONDS);
180
            }
181
            echo "sleep ".self::DELAY_BOTFLAG_SECONDS."\n";
182
            sleep(self::DELAY_BOTFLAG_SECONDS);
183
        }
184
185
        return $success;
186
    }
187
188
    private function dataProcess(array $data): bool
189
    {
190
        $origin = $data['raw'];
191
        $completed = $data['opti'];
192
193
        dump($origin, $completed, $data['modifs'], $data['version']);
194
195
        if (WikiTextUtil::isCommented($origin)) {
196
            echo "SKIP: template avec commentaire HTML\n";
197
198
            return false;
199
        }
200
201
        $find = mb_strpos($this->wikiText, $origin);
202
        if (!$find) {
203
            echo "String non trouvée. \n\n";
204
205
            return false;
206
        }
207
208
        $this->checkErrorWarning($data);
209
210
        // Replace text
211
        $newText = WikiPageAction::replaceTemplateInText($this->wikiText, $origin, $completed);
212
213
        if (!$newText || $newText === $this->wikiText) {
214
            echo "newText error\n";
215
216
            return false;
217
        }
218
        $this->wikiText = $newText;
219
        $this->minorFlag = ('1' === $data['major']) ? false : $this->minorFlag;
220
        $this->citationVersion = $data['version'];
221
        $this->citationSummary[] = $data['modifs'];
222
        $this->nbRows++;
223
224
        return true;
225
    }
226
227
    /**
228
     * Generate wiki edition summary.
229
     *
230
     * @return string
231
     */
232
    public function generateSummary(): string
233
    {
234
        // Start summary with "Bot" when using botflag, else "*"
235
        $prefix = ($this->botFlag) ? 'bot' : '☆';
236
        // add "/!\" when errorWarning
237
        $prefix = (!empty($this->errorWarning) && !$this->botFlag) ? '⚠' : $prefix;
238
239
240
        // basic modifs
241
        $citeSummary = implode(' ', $this->citationSummary);
242
        // replace by list of modifs to verify by humans
243
        if (!empty($this->importantSummary)) {
244
            $citeSummary = implode(', ', $this->importantSummary);
245
        }
246
247
        $summary = sprintf(
248
            '%s [%s/%s] %s %s : %s',
249
            $prefix,
250
            str_replace('v', '', $this->bot::getGitVersion()),
251
            str_replace('v0.', '', $this->citationVersion),
252
            self::TASK_NAME,
253
            $this->nbRows,
254
            $citeSummary
255
        );
256
257
        // shrink long summary if no important details to verify
258
        if (empty($this->importantSummary)) {
259
            $length = strlen($summary);
260
            $summary = substr($summary, 0, 80);
261
            $summary .= ($length > strlen($summary)) ? '…' : '';
262
        }
263
264
        return $summary;
265
    }
266
267
    /**
268
     * Vérifie alerte d'erreurs humaines.
269
     *
270
     * @param array $data
271
     *
272
     * @throws \Exception
273
     */
274
    private function checkErrorWarning(array $data): void
275
    {
276
        if (!isset($data['opti'])) {
277
            throw new \LogicException('Opti NULL');
278
        }
279
280
        // paramètre inconnu
281
        if (preg_match(
282
                "#\|[^|]+<!-- ?(PARAMETRE [^>]+ N'EXISTE PAS) ?-->#",
283
                $data['opti'],
284
                $matches
285
            ) > 0
286
        ) {
287
            $this->errorWarning[$data['page']][] = $matches[0];
288
            $this->botFlag = false;
289
            $this->addSummaryTag('paramètre non corrigé');
290
        }
291
292
        // ISBN invalide
293
        if (preg_match("#isbn invalide ?=[^|}]+#i", $data['opti'], $matches) > 0) {
294
            $this->errorWarning[$data['page']][] = $matches[0];
295
            $this->botFlag = false;
296
            $this->addSummaryTag('ISBN invalide');
297
        }
298
299
        // Edits avec ajout conséquent de donnée
300
        if (preg_match('#distinction des auteurs#', $data['modifs']) > 0) {
301
            $this->botFlag = false;
302
            $this->addSummaryTag('distinction des auteurs');
303
        }
304
        // prédiction paramètre correct
305
        if (preg_match('#[^,]+=>[^,]+#', $data['modifs'], $matches) > 0) {
306
            $this->botFlag = false;
307
            $this->addSummaryTag(sprintf('%s', $matches[0]));
308
        }
309
        if (preg_match('#\+\+sous-titre#', $data['modifs']) > 0) {
310
            $this->botFlag = false;
311
            $this->addSummaryTag('+sous-titre');
312
        }
313
        if (preg_match('#\+lieu#', $data['modifs']) > 0) {
314
            $this->addSummaryTag('+lieu');
315
        }
316
        if (preg_match('#\+éditeur#', $data['modifs']) > 0) {
317
            $this->addSummaryTag('éditeur');
318
        }
319
        //        if (preg_match('#\+langue#', $data['modifs']) > 0) {
320
        //            $this->addSummaryTag('langue');
321
        //        }
322
323
        // mention BnF si ajout donnée + ajout identifiant bnf=
324
        if (!empty($this->importantSummary) && preg_match('#\+bnf#i', $data['modifs'], $matches) > 0) {
325
            $this->addSummaryTag('[[BnF]]');
326
        }
327
    }
328
329
    /**
330
     * For substantive or ambiguous modifications done.
331
     *
332
     * @param string $tag
333
     */
334
    private function addSummaryTag(string $tag)
335
    {
336
        if (!in_array($tag, $this->importantSummary)) {
337
            $this->importantSummary[] = $tag;
338
        }
339
    }
340
341
    /**
342
     * @param array $rows Collection of citations
343
     */
344
    private function sendErrorMessage(array $rows): void
345
    {
346
        if (empty($this->errorWarning[$rows[0]['page']])) {
347
            return;
348
        }
349
        echo "** Send Error Message on talk page. Wait 10... \n";
350
        sleep(10);
351
352
        // format wiki message
353
        $errorList = '';
354
        foreach ($this->errorWarning[$rows[0]['page']] as $error) {
355
            $errorList .= sprintf("* <span style=\"background:#FCDFE8\"><nowiki>%s</nowiki></span> \n", $error);
356
        }
357
        $errorMessage = file_get_contents(self::ERROR_MSG_TEMPLATE);
358
        $errorMessage = str_replace('##ERROR LIST##', trim($errorList), $errorMessage);
359
        $errorMessage = str_replace('##ARTICLE##', $rows[0]['page'], $errorMessage);
360
361
        // Edit wiki talk page
362
        try {
363
            $talkPage = new WikiPageAction($this->wiki, 'Discussion:'.$rows[0]['page']);
364
            $editInfo = new EditInfo('Signalement erreur {ouvrage}', false, false, 5);
0 ignored issues
show
Unused Code introduced by
The call to Mediawiki\DataModel\EditInfo::__construct() has too many arguments starting with 5. ( Ignorable by Annotation )

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

364
            $editInfo = /** @scrutinizer ignore-call */ new EditInfo('Signalement erreur {ouvrage}', false, false, 5);

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress. Please note the @ignore annotation hint above.

Loading history...
365
            $talkPage->addToBottomOfThePage($errorMessage, $editInfo);
366
        } catch (\Throwable $e) {
367
            unset($e);
368
        }
369
    }
370
371
    private function initialize(): void
372
    {
373
        // initialisation vars
374
        $this->botFlag = true;
375
        $this->errorWarning = [];
376
        $this->wikiText = null;
377
        $this->citationSummary = [];
378
        $this->importantSummary = [];
379
        $this->minorFlag = true;
380
        $this->nbRows = 0;
381
382
        $this->bot->checkStopOnTalkpage();
383
    }
384
385
}
386