Passed
Push — master ( 9959d3...6697c9 )
by Daimona
01:30
created

ClosePages::getPagesList()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 9
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 3
eloc 6
nc 3
nop 0
dl 0
loc 9
rs 10
c 0
b 0
f 0
1
<?php declare( strict_types=1 );
2
3
namespace BotRiconferme\Task;
4
5
use BotRiconferme\PageRiconferma;
6
use BotRiconferme\Request\RequestBase;
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 Task {
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 = $this->getConfig()->get( 'ric-main-page' );
108
		$content = $this->getController()->getPageContent( $mainPage );
109
		$translations = [];
110
		foreach ( $pages as $page ) {
111
			$translations[ '{{' . $page->getTitle() . '}}' ] = '';
112
		}
113
114
		$params = [
115
			'title' => $mainPage,
116
			'text' => strtr( $content, $translations ),
117
			'summary' => $this->getConfig()->get( 'close-main-summary' )
118
		];
119
		$this->getController()->editPage( $params );
120
	}
121
122
	/**
123
	 * Adds closed pages to the current archive
124
	 *
125
	 * @param PageRiconferma[] $pages
126
	 */
127
	protected function addToArchive( array $pages ) {
128
		$this->getLogger()->info(
129
			'Adding to archive: ' . implode( ', ', array_map( 'strval', $pages ) )
130
		);
131
132
		$simple = $votes = [];
133
		foreach ( $pages as $page ) {
134
			if ( $page->isVote() ) {
135
				$votes[] = $page;
136
			} else {
137
				$simple[] = $page;
138
			}
139
		}
140
141
		$simpleTitle = $this->getConfig()->get( 'close-simple-archive-title' );
142
		$voteTitle = $this->getConfig()->get( 'close-vote-archive-title' );
143
144
		$this->reallyAddToArchive( $simpleTitle, $simple );
145
		$this->reallyAddToArchive( $voteTitle, $votes );
146
	}
147
148
	/**
149
	 * Really add $pages to the given archive
150
	 *
151
	 * @param string $archiveTitle
152
	 * @param array $pages
153
	 */
154
	private function reallyAddToArchive( string $archiveTitle, array $pages ) {
155
		$curTitle = "$archiveTitle/" . date( 'Y' );
156
157
		$append = '';
158
		$archivedList = [];
159
		foreach ( $pages as $page ) {
160
			$append .= '{{' . $page->getTitle() . "}}\n";
161
			$archivedList[] = $page->getUserNum();
162
		}
163
164
		if ( count( $archivedList ) > 1 ) {
165
			$last = array_pop( $archivedList );
166
			$userNums = implode( ', ', $archivedList ) . " e $last";
167
		} else {
168
			$userNums = $archivedList[0];
169
		}
170
171
		$summary = strtr(
172
			$this->getConfig()->get( 'close-archive-summary' ),
173
			[ '$usernums' => $userNums ]
174
		);
175
176
		$params = [
177
			'title' => $curTitle,
178
			'appendtext' => $append,
179
			'summary' => $summary
180
		];
181
182
		$this->getController()->editPage( $params );
183
	}
184
185
	/**
186
	 * @param PageRiconferma $page
187
	 * @see CreatePages::updateBasePage()
188
	 */
189
	protected function updateBasePage( PageRiconferma $page ) {
190
		$this->getLogger()->info( "Updating base page for $page" );
191
192
		$current = $this->getController()->getPageContent( $page->getBaseTitle() );
193
194
		$outcomeText = $page->getOutcome() & PageRiconferma::OUTCOME_FAIL ?
195
			'non riconfermato' :
196
			'riconfermato';
197
		$text = $page->isVote() ? "votazione: $outcomeText" : 'riconferma tacita';
198
199
		$newContent = str_replace( 'riconferma in corso', $text, $current );
200
		$params = [
201
			'title' => $page->getTitle(),
202
			'text' => $newContent,
203
			'summary' => $this->getConfig()->get( 'close-base-page-summary-update' )
204
		];
205
206
		$this->getController()->editPage( $params );
207
	}
208
209
	/**
210
	 * @param PageRiconferma[] $pages
211
	 * @see UpdatesAround::addVote()
212
	 */
213
	protected function updateVote( array $pages ) {
214
		$votePage = $this->getConfig()->get( 'ric-vote-page' );
215
		$content = $this->getController()->getPageContent( $votePage );
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 = strtr(
236
			$this->getConfig()->get( 'close-vote-page-summary' ),
237
			[ '$num' => count( $pages ) ]
238
		);
239
		$summary = preg_replace_callback(
240
			'!\{\{$plur|(\d+)|([^|]+)|([^|]+)}}!',
241
			function ( $matches ) {
242
				return intval( $matches[1] ) > 1 ? trim( $matches[3] ) : trim( $matches[2] );
243
			},
244
			$summary
245
		);
246
247
		$params = [
248
			'title' => $votePage,
249
			'text' => $newContent,
250
			'summary' => $summary
251
		];
252
253
		$this->getController()->editPage( $params );
254
	}
255
256
	/**
257
	 * @param array $pages
258
	 * @see UpdatesAround::addNews()
259
	 */
260
	protected function updateNews( array $pages ) {
261
		$simpleAmount = $voteAmount = 0;
262
		foreach ( $pages as $page ) {
263
			if ( $page->isVote() ) {
264
				$voteAmount++;
265
			} else {
266
				$simpleAmount++;
267
			}
268
		}
269
270
		$this->getLogger()->info(
271
			"Decreasing the news counter: $simpleAmount simple, $voteAmount votes."
272
		);
273
274
		$newsPage = $this->getConfig()->get( 'ric-news-page' );
275
276
		$content = $this->getController()->getPageContent( $newsPage );
277
		$simpleReg = '!(\| *riconferme[ _]tacite[ _]amministratori *= *)(\d+)!';
278
		$voteReg = '!(\| *riconferme[ _]voto[ _]amministratori *= *)(\d+)!';
279
280
		$simpleMatches = $voteMatches = [];
281
		preg_match( $simpleReg, $content, $simpleMatches );
282
		preg_match( $voteReg, $content, $voteMatches );
283
284
		$newSimp = (int)$simpleMatches[2] - $simpleAmount ?: '';
285
		$newVote = (int)$voteMatches[2] - $voteAmount ?: '';
286
		$newContent = preg_replace( $simpleReg, '${1}' . $newSimp, $content );
287
		$newContent = preg_replace( $voteReg, '${1}' . $newVote, $newContent );
288
289
		$summary = strtr(
290
			$this->getConfig()->get( 'close-news-page-summary' ),
291
			[ '$num' => count( $pages ) ]
292
		);
293
		$summary = preg_replace_callback(
294
			'!\{\{$plur|(\d+)|([^|]+)|([^|]+)}}!',
295
			function ( $matches ) {
296
				return intval( $matches[1] ) > 1 ? trim( $matches[3] ) : trim( $matches[2] );
297
			},
298
			$summary
299
		);
300
301
		$params = [
302
			'title' => $newsPage,
303
			'text' => $newContent,
304
			'summary' => $summary
305
		];
306
307
		$this->getController()->editPage( $params );
308
	}
309
310
	/**
311
	 * Update date on WP:Amministratori/Lista
312
	 *
313
	 * @param PageRiconferma[] $pages
314
	 */
315
	protected function updateAdminList( array $pages ) {
316
		$listTitle = $this->getConfig()->get( 'admins-list' );
317
		$newContent = $this->getController()->getPageContent( $listTitle );
318
		$newDate = date( 'Ymd', strtotime( '+1 year' ) );
319
320
		$riconfNames = $removeNames = [];
321
		foreach ( $pages as $page ) {
322
			$user = $page->getUser();
323
			$reg = "!(\{\{Amministratore\/riga\|$user.+\| *)\d+( *\|(?: *pausa)? *\}\}\n)!";
324
			if ( $page->getOutcome() & PageRiconferma::OUTCOME_FAIL ) {
325
				// Remove the line
326
				$newContent = preg_replace( $reg, '', $newContent );
327
				$removeNames[] = $user;
328
			} else {
329
				$newContent = preg_replace( $reg, '$1' . $newDate . '$2', $newContent );
330
				$riconfNames[] = $user;
331
			}
332
		}
333
334
		if ( count( $riconfNames ) > 1 ) {
335
			$lastUser = array_pop( $riconfNames );
336
			$riconfList = implode( ', ', $riconfNames ) . " e $lastUser";
337
		} elseif ( $riconfNames ) {
338
			$riconfList = $riconfNames[0];
339
		} else {
340
			$riconfList = 'nessuno';
341
		}
342
343
		if ( count( $removeNames ) > 1 ) {
344
			$lastUser = array_pop( $removeNames );
345
			$removeList = implode( ', ', $removeNames ) . " e $lastUser";
346
		} elseif ( $removeNames ) {
347
			$removeList = $removeNames[0];
348
		} else {
349
			$removeList = 'nessuno';
350
		}
351
352
		$summary = strtr(
353
			$this->getConfig()->get( 'close-update-list-summary' ),
354
			[
355
				'$riconf' => $riconfList,
356
				'$remove' => $removeList
357
			]
358
		);
359
360
		$params = [
361
			'title' => $listTitle,
362
			'text' => $newContent,
363
			'summary' => $summary
364
		];
365
366
		$this->getController()->editPage( $params );
367
	}
368
369
	/**
370
	 * @param PageRiconferma[] $pages
371
	 */
372
	protected function updateCUList( array $pages ) {
373
		$cuListTitle = $this->getConfig()->get( 'cu-list-title' );
374
		$listTitle = $this->getConfig()->get( 'list-title' );
375
		$admins = json_decode( $this->getController()->getPageContent( $listTitle ), true );
376
		$newContent = $this->getController()->getPageContent( $cuListTitle );
377
378
		$riconfNames = $removeNames = [];
379
		foreach ( $pages as $page ) {
380
			$user = $page->getUser();
381
			if ( array_key_exists( 'checkuser', $admins[ $user ] ) ) {
382
				$reg = "!(\{\{ *Checkuser *\| *$user *\|[^}]+\| *)[\w \d](}}.*\n)!";
383
				if ( $page->getOutcome() & PageRiconferma::OUTCOME_FAIL ) {
384
					// Remove the line
385
					$newContent = preg_replace( $reg, '', $newContent );
386
					$removeNames[] = $user;
387
				} else {
388
					$newContent = preg_replace( $reg, '$1{{subst:#time:j F Y}}$2', $newContent );
389
					$riconfNames[] = $user;
390
				}
391
			}
392
		}
393
394
		if ( !$riconfNames && !$removeNames ) {
0 ignored issues
show
introduced by
$riconfNames is of type array|string[], thus it always evaluated to false.
Loading history...
395
			return;
396
		}
397
398
		if ( count( $riconfNames ) > 1 ) {
399
			$lastUser = array_pop( $riconfNames );
400
			$riconfList = implode( ', ', $riconfNames ) . " e $lastUser";
401
		} elseif ( $riconfNames ) {
402
			$riconfList = $riconfNames[0];
403
		} else {
404
			$riconfList = 'nessuno';
405
		}
406
407
		if ( count( $removeNames ) > 1 ) {
408
			$lastUser = array_pop( $removeNames );
409
			$removeList = implode( ', ', $removeNames ) . " e $lastUser";
410
		} elseif ( $removeNames ) {
411
			$removeList = $removeNames[0];
412
		} else {
413
			$removeList = 'nessuno';
414
		}
415
416
		$summary = strtr(
417
			$this->getConfig()->get( 'cu-list-update-summary' ),
418
			[
419
				'$riconf' => $riconfList,
420
				'$remove' => $removeList
421
			]
422
		);
423
424
		$params = [
425
			'title' => $cuListTitle,
426
			'text' => $newContent,
427
			'summary' => $summary
428
		];
429
		$this->getController()->editPage( $params );
430
	}
431
432
	/**
433
	 * @param PageRiconferma[] $pages
434
	 */
435
	protected function updateBurList( array $pages ) {
436
		$listTitle = $this->getConfig()->get( 'list-title' );
437
		$admins = json_decode( $this->getController()->getPageContent( $listTitle ), true );
438
439
		$remove = [];
440
		foreach ( $pages as $page ) {
441
			$user = $page->getUser();
442
			if ( array_key_exists( 'bureaucrat', $admins[ $user ] ) &&
443
				$page->getOutcome() & PageRiconferma::OUTCOME_FAIL
444
			) {
445
				$remove[] = $user;
446
			}
447
		}
448
449
		if ( !$remove ) {
450
			return;
451
		}
452
453
		$remList = implode( '|', array_map( 'preg_quote', $remove ) );
454
		$burListTitle = $this->getConfig()->get( 'bur-list-title' );
455
		$content = $this->getController()->getPageContent( $burListTitle );
456
		$reg = "!^\#\{\{ *Burocrate *\| *($remList).+\n!m";
457
		$newContent = preg_replace( $reg, '', $content );
458
459
		if ( count( $remove ) > 1 ) {
460
			$lastUser = array_pop( $remove );
461
			$removeList = implode( ', ', $remove ) . " e $lastUser";
462
		} else {
463
			$removeList = $remove[0];
464
		}
465
466
		$summary = strtr(
467
			$this->getConfig()->get( 'bur-list-update-summary' ),
468
			[
469
				'$remove' => $removeList
470
			]
471
		);
472
473
		$params = [
474
			'title' => $burListTitle,
475
			'text' => $newContent,
476
			'summary' => $summary
477
		];
478
		$this->getController()->editPage( $params );
479
	}
480
481
	/**
482
	 * Request the removal of the flag on meta
483
	 *
484
	 * @param PageRiconferma[] $pages
485
	 */
486
	protected function requestRemoval( array $pages ) {
487
		$listTitle = $this->getConfig()->get( 'list-title' );
488
		$admins = json_decode( $this->getController()->getPageContent( $listTitle ), true );
489
490
		$oldUrl = RequestBase::$url;
491
		RequestBase::$url = 'https://meta.wikimedia.org/w/api.php';
492
		$pageTitle = $this->getConfig()->get( 'flag-removal-page' );
493
		$section = $this->getConfig()->get( 'flag-removal-section' );
494
		$baseText = $this->getConfig()->get( 'flag-removal-text' );
495
496
		$newContent = $this->getController()->getPageContent( $pageTitle, $section );
497
		foreach ( $pages as $page ) {
498
			$curText = strtr(
499
				$baseText,
500
				[
501
					'$username' => $page->getUser(),
502
					'$link' => '[[:it:' . $page->getTitle() . ']]',
503
					'$groups' => implode( ', ', array_keys( $admins[ $page->getUser() ] ) )
504
				]
505
			);
506
			$newContent .= $curText;
507
		}
508
509
		$summary = strtr(
510
			$this->getConfig()->get( 'flag-removal-summary' ),
511
			[
512
				'$num' => count( $pages )
513
			]
514
		);
515
516
		$params = [
517
			'title' => $pageTitle,
518
			'text' => $newContent,
519
			'summary' => $summary
520
		];
521
		$this->getController()->editPage( $params );
522
523
		RequestBase::$url = $oldUrl;
524
	}
525
526
	/**
527
	 * Update [[Wikipedia:Wikipediano/Annunci]]
528
	 *
529
	 * @param PageRiconferma[] $pages
530
	 */
531
	protected function updateAnnunci( array $pages ) {
532
		$title = $this->getConfig()->get( 'annunci-title' );
533
534
		$names = [];
535
		$text = '';
536
		foreach ( $pages as $page ) {
537
			$user = $page->getUser();
538
			$names[] = $user;
539
			$text .= "{{Breve|admin|{{subst:#time:j}}|[[Utente:$user|]] non è stato riconfermato [[WP:A|amministratore]].}}\n";
540
		}
541
542
		$oldLoc = setlocale( LC_TIME, 'it_IT', 'Italian_Italy', 'Italian' );
543
		$month = ucfirst( strftime( '%B', time() ) );
544
		setlocale( LC_TIME, $oldLoc );
545
546
		$content = $this->getController()->getPageContent( $title, 1 );
547
		$secReg = "!=== *$month *===!";
548
		if ( preg_match( $secReg, $content ) !== false ) {
549
			$newContent = preg_replace( $secReg, '$0' . "\n" . $text, $content );
550
		} else {
551
			$re = '!</div>\s*}}\s*</includeonly>!';
552
			$newContent = preg_replace( $re, '$0' . "\n=== $month ===\n" . $text, $content );
553
		}
554
555
		if ( count( $names ) > 1 ) {
556
			$lastUser = array_pop( $names );
557
			$namesList = implode( ', ', $names ) . " e $lastUser";
558
		} else {
559
			$namesList = $names[0];
560
		}
561
562
		$summary = strtr(
563
			$this->getConfig()->get( 'annunci-summary' ),
564
			[ '$names' => $namesList ]
565
		);
566
567
		$params = [
568
			'title' => $title,
569
			'text' => $newContent,
570
			'summary' => $summary
571
		];
572
		$this->getController()->editPage( $params );
573
	}
574
575
	/**
576
	 * Update [[Wikipedia:Ultime notizie]]
577
	 *
578
	 * @param PageRiconferma[] $pages
579
	 */
580
	protected function updateUltimeNotizie( array $pages ) {
581
		$title = $this->getConfig()->get( 'ultimenotizie-title' );
582
583
		$names = [];
584
		$text = '';
585
		foreach ( $pages as $page ) {
586
			$user = $page->getUser();
587
			$title = $page->getTitle();
588
			$names[] = $user;
589
			$text .= "'''{{subst:#time:j F}}''': [[Utente:$user|]] non è stato [[$title|riconfermato]] [[WP:A|amministratore]]; ora gli admin sono {{subst:#expr: {{NUMBEROFADMINS}} - 1}}.";
590
		}
591
592
		$content = $this->getController()->getPageContent( $title );
593
		$year = date( 'Y' );
594
		$secReg = "!== *$year *==!";
595
		if ( preg_match( $secReg, $content ) !== false ) {
596
			$newContent = preg_replace( $secReg, '$0' . "\n" . $text, $content );
597
		} else {
598
			$re = '!si veda la \[\[[^\]+relativa discussione]]\.\n!';
599
			$newContent = preg_replace( $re, '$0' . "\n== $year ==\n" . $text, $content );
600
		}
601
602
		if ( count( $names ) > 1 ) {
603
			$lastUser = array_pop( $names );
604
			$namesList = implode( ', ', $names ) . " e $lastUser";
605
		} else {
606
			$namesList = $names[0];
607
		}
608
609
		$summary = strtr(
610
			$this->getConfig()->get( 'ultimenotizie-summary' ),
611
			[ '$names' => $namesList ]
612
		);
613
614
		$params = [
615
			'title' => $title,
616
			'text' => $newContent,
617
			'summary' => $summary
618
		];
619
		$this->getController()->editPage( $params );
620
	}
621
}
622