Passed
Push — master ( adc4b8...42aaff )
by Daimona
01:39
created

ClosePages::requestRemoval()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 36
Code Lines 24

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 24
nc 2
nop 1
dl 0
loc 36
rs 9.536
c 0
b 0
f 0
1
<?php declare( strict_types=1 );
2
3
namespace BotRiconferme\Task\Subtask;
4
5
use BotRiconferme\Page;
6
use BotRiconferme\PageRiconferma;
7
use BotRiconferme\TaskResult;
8
9
/**
10
 * For each open page, close it if the time's up and no more than 15 opposing votes were added
11
 * @fixme Avoid duplication with UpdatesAround etc.
12
 */
13
class ClosePages extends Subtask {
14
	/**
15
	 * @inheritDoc
16
	 */
17
	public function run() : TaskResult {
18
		$this->getLogger()->info( 'Starting task ClosePages' );
19
20
		$pages = $this->getDataProvider()->getPagesToClose();
21
		$protectReason = $this->getConfig()->get( 'close-protect-summary' );
22
		foreach ( $pages as $page ) {
23
			if ( $page->isVote() ) {
24
				$this->addVoteCloseText( $page );
25
			}
26
			$this->getController()->protectPage( $page->getTitle(), $protectReason );
27
			$this->updateBasePage( $page );
28
		}
29
30
		$this->removeFromMainPage( $pages );
31
		$this->addToArchive( $pages );
32
		$this->updateVote( $pages );
33
		$this->updateNews( $pages );
34
		$this->updateAdminList( $pages );
35
		$this->updateCUList( $pages );
36
37
		$failed = $this->getFailures( $pages );
38
		if ( $failed ) {
39
			$this->updateBurList( $failed );
40
			$this->requestRemoval( $failed );
41
			$this->updateAnnunci( $failed );
42
			$this->updateUltimeNotizie( $failed );
43
		}
44
45
		$this->getLogger()->info( 'Task ClosePages completed successfully' );
46
		return new TaskResult( self::STATUS_OK );
47
	}
48
49
	/**
50
	 * Extract the list of failed votes from the given list of pages
51
	 *
52
	 * @param PageRiconferma[] $pages
53
	 * @return PageRiconferma[]
54
	 */
55
	private function getFailures( array $pages ) : array {
56
		$ret = [];
57
		foreach ( $pages as $page ) {
58
			if ( $page->getOutcome() & PageRiconferma::OUTCOME_FAIL ) {
59
				$ret[] = $page;
60
			}
61
		}
62
		return $ret;
63
	}
64
65
	/**
66
	 * @param PageRiconferma $page
67
	 */
68
	protected function addVoteCloseText( PageRiconferma $page ) {
69
		$content = $page->getContent();
70
		$beforeReg = '!è necessario ottenere una maggioranza .+ votanti\.!';
71
		$newContent = preg_replace( $beforeReg, '$0' . "\n" . $page->getOutcomeText(), $content );
72
73
		$params = [
74
			'text' => $newContent,
75
			'summary' => $this->getConfig()->get( 'close-result-summary' )
76
		];
77
		$page->edit( $params );
78
	}
79
80
	/**
81
	 * Removes pages from WP:A/Riconferme annuali
82
	 *
83
	 * @param PageRiconferma[] $pages
84
	 * @see UpdatesAround::addToMainPage()
85
	 */
86
	protected function removeFromMainPage( array $pages ) {
87
		$this->getLogger()->info(
88
			'Removing from main: ' . implode( ', ', array_map( 'strval', $pages ) )
89
		);
90
91
		$mainPage = new Page( $this->getConfig()->get( 'ric-main-page' ) );
92
		$translations = [];
93
		foreach ( $pages as $page ) {
94
			$translations[ '{{' . $page->getTitle() . '}}' ] = '';
95
		}
96
97
		$params = [
98
			'title' => $mainPage,
99
			'text' => strtr( $mainPage->getContent(), $translations ),
100
			'summary' => $this->getConfig()->get( 'close-main-summary' )
101
		];
102
		$this->getController()->editPage( $params );
103
	}
104
105
	/**
106
	 * Adds closed pages to the current archive
107
	 *
108
	 * @param PageRiconferma[] $pages
109
	 */
110
	protected function addToArchive( array $pages ) {
111
		$this->getLogger()->info(
112
			'Adding to archive: ' . implode( ', ', array_map( 'strval', $pages ) )
113
		);
114
115
		$simple = $votes = [];
116
		foreach ( $pages as $page ) {
117
			if ( $page->isVote() ) {
118
				$votes[] = $page;
119
			} else {
120
				$simple[] = $page;
121
			}
122
		}
123
124
		$simpleTitle = $this->getConfig()->get( 'close-simple-archive-title' );
125
		$voteTitle = $this->getConfig()->get( 'close-vote-archive-title' );
126
127
		$this->reallyAddToArchive( $simpleTitle, $simple );
128
		$this->reallyAddToArchive( $voteTitle, $votes );
129
	}
130
131
	/**
132
	 * Really add $pages to the given archive
133
	 *
134
	 * @param string $archiveTitle
135
	 * @param array $pages
136
	 */
137
	private function reallyAddToArchive( string $archiveTitle, array $pages ) {
138
		$curTitle = "$archiveTitle/" . date( 'Y' );
139
140
		$append = '';
141
		$archivedList = [];
142
		foreach ( $pages as $page ) {
143
			$append .= '{{' . $page->getTitle() . "}}\n";
144
			$archivedList[] = $page->getUserNum();
145
		}
146
147
		if ( count( $archivedList ) > 1 ) {
148
			$last = array_pop( $archivedList );
149
			$userNums = implode( ', ', $archivedList ) . " e $last";
150
		} else {
151
			$userNums = $archivedList[0];
152
		}
153
154
		$summary = $this->msg( 'close-archive-summary' )
155
			->params( [ '$usernums' => $userNums ] )->text();
156
157
		$params = [
158
			'title' => $curTitle,
159
			'appendtext' => $append,
160
			'summary' => $summary
161
		];
162
163
		$this->getController()->editPage( $params );
164
	}
165
166
	/**
167
	 * @param PageRiconferma $page
168
	 * @see CreatePages::updateBasePage()
169
	 */
170
	protected function updateBasePage( PageRiconferma $page ) {
171
		$this->getLogger()->info( "Updating base page for $page" );
172
173
		$basePage = new Page( $page->getBaseTitle() );
174
		$current = $basePage->getContent();
175
176
		$outcomeText = $page->getOutcome() & PageRiconferma::OUTCOME_FAIL ?
177
			'non riconfermato' :
178
			'riconfermato';
179
		$text = $page->isVote() ? "votazione: $outcomeText" : 'riconferma tacita';
180
181
		$newContent = str_replace( 'riconferma in corso', $text, $current );
182
		$params = [
183
			'text' => $newContent,
184
			'summary' => $this->getConfig()->get( 'close-base-page-summary-update' )
185
		];
186
187
		$basePage->edit( $params );
188
	}
189
190
	/**
191
	 * @param PageRiconferma[] $pages
192
	 * @see UpdatesAround::addVote()
193
	 */
194
	protected function updateVote( array $pages ) {
195
		$this->getLogger()->info(
196
			'Updating votazioni: ' . implode( ', ', array_map( 'strval', $pages ) )
197
		);
198
		$votePage = new Page( $this->getConfig()->get( 'ric-vote-page' ) );
199
		$content = $votePage->getContent();
200
201
		$titles = [];
202
		foreach ( $pages as $page ) {
203
			$titles[] = preg_quote( $page->getTitle() );
204
		}
205
206
		$titleReg = implode( '|', array_map( 'preg_quote', $titles ) );
207
		$search = "!^\*.+ La \[\[($titleReg)\|procedura]] termina.+\n!gm";
208
209
		$newContent = preg_replace( $search, '', $content );
210
		// Make sure the last line ends with a full stop in every section
211
		$simpleSectReg = '!(^;È in corso.+riconferma tacita.+amministrat.+\n(?:\*.+[;\.]\n)+\*.+)[\.;]!m';
212
		$voteSectReg = '!(^;Si vota per la .+riconferma .+amministratori.+\n(?:\*.+[;\.]\n)+\*.+)[\.;]!m';
213
		$newContent = preg_replace( $simpleSectReg, '$1.', $newContent );
214
		$newContent = preg_replace( $voteSectReg, '$1.', $newContent );
215
216
		// @fixme Remove empty sections, and add the "''Nessuna riconferma o votazione in corso''" message
217
		// if the page is empty! Or just wait for the page to be restyled...
218
219
		$summary = $this->msg( 'close-vote-page-summary' )
220
			->params( [ '$num' => count( $pages ) ] )->text();
221
222
		$params = [
223
			'text' => $newContent,
224
			'summary' => $summary
225
		];
226
227
		$votePage->edit( $params );
228
	}
229
230
	/**
231
	 * @param array $pages
232
	 * @see UpdatesAround::addNews()
233
	 */
234
	protected function updateNews( array $pages ) {
235
		$simpleAmount = $voteAmount = 0;
236
		foreach ( $pages as $page ) {
237
			if ( $page->isVote() ) {
238
				$voteAmount++;
239
			} else {
240
				$simpleAmount++;
241
			}
242
		}
243
244
		$this->getLogger()->info(
245
			"Decreasing the news counter: $simpleAmount simple, $voteAmount votes."
246
		);
247
248
		$newsPage = new Page( $this->getConfig()->get( 'ric-news-page' ) );
249
250
		$content = $newsPage->getContent();
251
		$simpleReg = '!(\| *riconferme[ _]tacite[ _]amministratori *= *)(\d+)!';
252
		$voteReg = '!(\| *riconferme[ _]voto[ _]amministratori *= *)(\d+)!';
253
254
		$simpleMatches = $voteMatches = [];
255
		preg_match( $simpleReg, $content, $simpleMatches );
256
		preg_match( $voteReg, $content, $voteMatches );
257
258
		$newSimp = (int)$simpleMatches[2] - $simpleAmount ?: '';
259
		$newVote = (int)$voteMatches[2] - $voteAmount ?: '';
260
		$newContent = preg_replace( $simpleReg, '${1}' . $newSimp, $content );
261
		$newContent = preg_replace( $voteReg, '${1}' . $newVote, $newContent );
262
263
		$summary = $this->msg( 'close-news-page-summary' )
264
			->params( [ '$num' => count( $pages ) ] )->text();
265
266
		$params = [
267
			'text' => $newContent,
268
			'summary' => $summary
269
		];
270
271
		$newsPage->edit( $params );
272
	}
273
274
	/**
275
	 * Update date on WP:Amministratori/Lista
276
	 *
277
	 * @param PageRiconferma[] $pages
278
	 */
279
	protected function updateAdminList( array $pages ) {
280
		$this->getLogger()->info(
281
			'Updating admin list: ' . implode( ', ', array_map( 'strval', $pages ) )
282
		);
283
		$adminsPage = new Page( $this->getConfig()->get( 'admins-list' ) );
284
		$newContent = $adminsPage->getContent();
285
		$newDate = date( 'Ymd', strtotime( '+1 year' ) );
286
287
		$riconfNames = $removeNames = [];
288
		foreach ( $pages as $page ) {
289
			$user = $page->getUser();
290
			$reg = "!(\{\{Amministratore\/riga\|$user.+\| *)\d+( *\|(?: *pausa)? *\}\}\n)!";
291
			if ( $page->getOutcome() & PageRiconferma::OUTCOME_FAIL ) {
292
				// Remove the line
293
				$newContent = preg_replace( $reg, '', $newContent );
294
				$removeNames[] = $user;
295
			} else {
296
				$newContent = preg_replace( $reg, '$1' . $newDate . '$2', $newContent );
297
				$riconfNames[] = $user;
298
			}
299
		}
300
301
		if ( count( $riconfNames ) > 1 ) {
302
			$lastUser = array_pop( $riconfNames );
303
			$riconfList = implode( ', ', $riconfNames ) . " e $lastUser";
304
		} elseif ( $riconfNames ) {
305
			$riconfList = $riconfNames[0];
306
		} else {
307
			$riconfList = 'nessuno';
308
		}
309
310
		if ( count( $removeNames ) > 1 ) {
311
			$lastUser = array_pop( $removeNames );
312
			$removeList = implode( ', ', $removeNames ) . " e $lastUser";
313
		} elseif ( $removeNames ) {
314
			$removeList = $removeNames[0];
315
		} else {
316
			$removeList = 'nessuno';
317
		}
318
319
		$summary = $this->msg( 'close-update-list-summary' )
320
			->params( [
321
				'$riconf' => $riconfList,
322
				'$remove' => $removeList
323
			] )
324
			->text();
325
326
		$params = [
327
			'text' => $newContent,
328
			'summary' => $summary
329
		];
330
331
		$adminsPage->edit( $params );
332
	}
333
334
	/**
335
	 * @param PageRiconferma[] $pages
336
	 */
337
	protected function updateCUList( array $pages ) {
338
		$this->getLogger()->info( 'Checking if CU list needs updating.' );
339
		$cuList = new Page( $this->getConfig()->get( 'cu-list-title' ) );
340
		$admins = $this->getDataProvider()->getUsersList();
341
		$newContent = $cuList->getContent();
342
343
		$riconfNames = $removeNames = [];
344
		foreach ( $pages as $page ) {
345
			$user = $page->getUser();
346
			if ( array_key_exists( 'checkuser', $admins[ $user ] ) ) {
347
				$reg = "!(\{\{ *Checkuser *\| *$user *\|[^}]+\| *)[\w \d](}}.*\n)!";
348
				if ( $page->getOutcome() & PageRiconferma::OUTCOME_FAIL ) {
349
					// Remove the line
350
					$newContent = preg_replace( $reg, '', $newContent );
351
					$removeNames[] = $user;
352
				} else {
353
					$newContent = preg_replace( $reg, '$1{{subst:#time:j F Y}}$2', $newContent );
354
					$riconfNames[] = $user;
355
				}
356
			}
357
		}
358
359
		if ( !$riconfNames || !$removeNames ) {
0 ignored issues
show
introduced by
$riconfNames is of type array|string[], thus it always evaluated to false.
Loading history...
360
			return;
361
		}
362
363
		$this->getLogger()->info(
364
			'Updating CU list. Riconf: ' . implode( ', ', $riconfNames ) .
365
			'; remove: ' . implode( ', ', $removeNames )
366
		);
367
		if ( count( $riconfNames ) > 1 ) {
368
			$lastUser = array_pop( $riconfNames );
369
			$riconfList = implode( ', ', $riconfNames ) . " e $lastUser";
370
		} elseif ( $riconfNames ) {
371
			$riconfList = $riconfNames[0];
372
		} else {
373
			$riconfList = 'nessuno';
374
		}
375
376
		if ( count( $removeNames ) > 1 ) {
377
			$lastUser = array_pop( $removeNames );
378
			$removeList = implode( ', ', $removeNames ) . " e $lastUser";
379
		} elseif ( $removeNames ) {
380
			$removeList = $removeNames[0];
381
		} else {
382
			$removeList = 'nessuno';
383
		}
384
385
		$summary = $this->msg( 'cu-list-update-summary' )
386
			->params( [
387
				'$riconf' => $riconfList,
388
				'$remove' => $removeList
389
			] )
390
			->text();
391
392
		$params = [
393
			'text' => $newContent,
394
			'summary' => $summary
395
		];
396
		$cuList->edit( $params );
397
	}
398
399
	/**
400
	 * @param PageRiconferma[] $pages
401
	 */
402
	protected function updateBurList( array $pages ) {
403
		$this->getLogger()->info( 'Checking if bur list needs updating.' );
404
		$admins = $this->getDataProvider()->getUsersList();
405
406
		$remove = [];
407
		foreach ( $pages as $page ) {
408
			$user = $page->getUser();
409
			if ( array_key_exists( 'bureaucrat', $admins[ $user ] ) &&
410
				$page->getOutcome() & PageRiconferma::OUTCOME_FAIL
411
			) {
412
				$remove[] = $user;
413
			}
414
		}
415
416
		if ( !$remove ) {
417
			return;
418
		}
419
420
		$this->getLogger()->info( 'Updating bur list. Removing: ' . implode( ', ', $remove ) );
421
		$remList = implode( '|', array_map( 'preg_quote', $remove ) );
422
		$burList = new Page( $this->getConfig()->get( 'bur-list-title' ) );
423
		$content = $burList->getContent();
424
		$reg = "!^\#\{\{ *Burocrate *\| *($remList).+\n!m";
425
		$newContent = preg_replace( $reg, '', $content );
426
427
		if ( count( $remove ) > 1 ) {
428
			$lastUser = array_pop( $remove );
429
			$removeList = implode( ', ', $remove ) . " e $lastUser";
430
		} else {
431
			$removeList = $remove[0];
432
		}
433
434
		$summary = $this->msg( 'bur-list-update-summary' )
435
			->params( [ '$remove' => $removeList ] )
436
			->text();
437
438
		$params = [
439
			'text' => $newContent,
440
			'summary' => $summary
441
		];
442
		$burList->edit( $params );
443
	}
444
445
	/**
446
	 * Request the removal of the flag on meta
447
	 *
448
	 * @param PageRiconferma[] $pages
449
	 */
450
	protected function requestRemoval( array $pages ) {
451
		$this->getLogger()->info(
452
			'Requesting removal on meta for: ' . implode( ', ', array_map( 'strval', $pages ) )
453
		);
454
		$admins = $this->getDataProvider()->getUsersList();
455
456
		$flagRemPage = new Page(
457
			$this->getConfig()->get( 'flag-removal-page' ),
458
			'https://meta.wikimedia.org/w/api.php'
459
		);
460
		$section = $this->getConfig()->get( 'flag-removal-section' );
461
		$baseText = $this->getConfig()->get( 'flag-removal-text' );
462
463
		$newContent = $flagRemPage->getContent( $section );
464
		foreach ( $pages as $page ) {
465
			$curText = strtr(
466
				$baseText,
467
				[
468
					'$username' => $page->getUser(),
469
					'$link' => '[[:it:' . $page->getTitle() . ']]',
470
					'$groups' => implode( ', ', array_keys( $admins[ $page->getUser() ] ) )
471
				]
472
			);
473
			$newContent .= $curText;
474
		}
475
476
		$summary = $this->msg( 'flag-removal-summary' )
477
			->params( [ '$num' => count( $pages ) ] )
478
			->text();
479
480
		$params = [
481
			'section' => $section,
482
			'text' => $newContent,
483
			'summary' => $summary
484
		];
485
		$flagRemPage->edit( $params );
486
	}
487
488
	/**
489
	 * Update [[Wikipedia:Wikipediano/Annunci]]
490
	 *
491
	 * @param PageRiconferma[] $pages
492
	 */
493
	protected function updateAnnunci( array $pages ) {
494
		$this->getLogger()->info( 'Updating annunci' );
495
496
		$names = [];
497
		$text = '';
498
		foreach ( $pages as $page ) {
499
			$user = $page->getUser();
500
			$names[] = $user;
501
			$text .= "{{Breve|admin|{{subst:#time:j}}|[[Utente:$user|]] " .
502
				"non è stato riconfermato [[WP:A|amministratore]].}}\n";
503
		}
504
505
		$oldLoc = setlocale( LC_TIME, 'it_IT', 'Italian_Italy', 'Italian' );
506
		$month = ucfirst( strftime( '%B', time() ) );
507
		setlocale( LC_TIME, $oldLoc );
508
509
		$annunciPage = new Page( $this->getConfig()->get( 'annunci-title' ) );
510
		$content = $annunciPage->getContent( 1 );
511
		$secReg = "!=== *$month *===!";
512
		if ( preg_match( $secReg, $content ) !== false ) {
513
			$newContent = preg_replace( $secReg, '$0' . "\n" . $text, $content );
514
		} else {
515
			$re = '!</div>\s*}}\s*</includeonly>!';
516
			$newContent = preg_replace( $re, '$0' . "\n=== $month ===\n" . $text, $content );
517
		}
518
519
		if ( count( $names ) > 1 ) {
520
			$lastUser = array_pop( $names );
521
			$namesList = implode( ', ', $names ) . " e $lastUser";
522
		} else {
523
			$namesList = $names[0];
524
		}
525
526
		$summary = $this->msg( 'annunci-summary' )
527
			->params( [ '$names' => $namesList ] )
528
			->text();
529
530
		$params = [
531
			'text' => $newContent,
532
			'summary' => $summary
533
		];
534
		$annunciPage->edit( $params );
535
	}
536
537
	/**
538
	 * Update [[Wikipedia:Ultime notizie]]
539
	 *
540
	 * @param PageRiconferma[] $pages
541
	 */
542
	protected function updateUltimeNotizie( array $pages ) {
543
		$this->getLogger()->info( 'Updating ultime notizie' );
544
		$notiziePage = new Page( $this->getConfig()->get( 'ultimenotizie-title' ) );
545
546
		$names = [];
547
		$text = '';
548
		foreach ( $pages as $page ) {
549
			$user = $page->getUser();
550
			$title = $page->getTitle();
551
			$names[] = $user;
552
			$text .= "'''{{subst:#time:j F}}''': [[Utente:$user|]] non è stato [[$title|riconfermato]] " .
553
				'[[WP:A|amministratore]]; ora gli admin sono {{subst:#expr: {{NUMBEROFADMINS}} - 1}}.';
554
		}
555
556
		$content = $notiziePage->getContent();
557
		$year = date( 'Y' );
558
		$secReg = "!== *$year *==!";
559
		if ( preg_match( $secReg, $content ) !== false ) {
560
			$newContent = preg_replace( $secReg, '$0' . "\n" . $text, $content );
561
		} else {
562
			$re = '!si veda la \[\[[^\]+relativa discussione]]\.\n!';
563
			$newContent = preg_replace( $re, '$0' . "\n== $year ==\n" . $text, $content );
564
		}
565
566
		if ( count( $names ) > 1 ) {
567
			$lastUser = array_pop( $names );
568
			$namesList = implode( ', ', $names ) . " e $lastUser";
569
		} else {
570
			$namesList = $names[0];
571
		}
572
573
		$summary = $this->msg( 'ultimenotizie-summary' )
574
			->params( [ '$names' => $namesList ] )
575
			->text();
576
577
		$params = [
578
			'text' => $newContent,
579
			'summary' => $summary
580
		];
581
		$notiziePage->edit( $params );
582
	}
583
}
584