Passed
Push — master ( 35639c...18326f )
by Daimona
01:42
created

ClosePages::updateAnnunci()   A

Complexity

Conditions 4
Paths 8

Size

Total Lines 42
Code Lines 31

Duplication

Lines 0
Ratio 0 %

Importance

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