Passed
Push — master ( b237e3...69f046 )
by Daimona
01:32
created

ClosePages   A

Complexity

Total Complexity 20

Size/Duplication

Total Lines 229
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
eloc 113
dl 0
loc 229
rs 10
c 0
b 0
f 0
wmc 20

10 Methods

Rating   Name   Duplication   Size   Complexity  
A hasOpposition() 0 13 1
A removeFromMainPage() 0 16 2
A updateAdminList() 0 17 2
A updateVote() 0 19 1
A updateBasePage() 0 14 1
A updateNews() 0 22 2
A addToArchive() 0 18 2
A getTranscludedPages() 0 19 3
A run() 0 17 2
A getPagesList() 0 10 4
1
<?php declare( strict_types=1 );
2
3
namespace BotRiconferme\Task;
4
5
use BotRiconferme\TaskResult;
6
use BotRiconferme\Request\RequestBase;
7
use BotRiconferme\Exception\TaskException;
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
		$titles = $this->getPagesList();
21
		foreach ( $titles as $title ) {
22
			$this->getController()->protectPage( $title, $this->getConfig()->get( 'close-protect-summary' ) );
23
			$this->updateBasePage( $title );
24
		}
25
26
		$this->removeFromMainPage( $titles );
27
		$this->addToArchive( $titles );
28
		$this->updateVote( $titles );
29
		$this->updateNews( count( $titles ) );
30
		$this->updateAdminList( $titles );
31
32
		$this->getLogger()->info( 'Task ClosePages completed successfully' );
33
		return new TaskResult( self::STATUS_OK );
34
	}
35
36
	/**
37
	 * Get a list of pages to close
38
	 *
39
	 * @return string[]
40
	 */
41
	protected function getPagesList() : array {
42
		$allPages = $this->getTranscludedPages();
43
		$ret = [];
44
		foreach ( $allPages as $page ) {
45
			$created = $this->getController()->getPageCreationTS( $page );
46
			if ( time() - $created <= 60 * 60 * 24 * 7 && !$this->hasOpposition( $page ) ) {
47
				$ret[] = $page;
48
			}
49
		}
50
		return $ret;
51
	}
52
53
	/**
54
	 * Get a list of pages transcluded in the main one
55
	 *
56
	 * @return string[]
57
	 */
58
	protected function getTranscludedPages() : array {
59
		$baseTitle = $this->getConfig()->get( 'ric-main-page' );
60
		$params = [
61
			'action' => 'query',
62
			'prop' => 'templates',
63
			'titles' => $baseTitle,
64
			'tl_namespace' => 4,
65
			'tllimit' => 'max'
66
		];
67
68
		$res = RequestBase::newFromParams( $params )->execute();
69
		$pages = $res->query->pages;
70
		$ret = [];
71
		foreach ( reset( $pages )->templates as $page ) {
72
			if ( preg_match( "!$baseTitle\/[^\/]+\/\d!", $page->title ) !== false ) {
73
				$ret[] = $page->title;
74
			}
75
		}
76
		return $ret;
77
	}
78
79
	/**
80
	 * @param string $page
81
	 * @return bool
82
	 */
83
	protected function hasOpposition( string $page ) : bool {
84
		$params = [
85
			'action' => 'query',
86
			'prop' => 'revisions',
87
			'titles' => $page,
88
			'rvprop' => 'content',
89
			'rvslots' => 'main',
90
			'rvsection' => 4
91
		];
92
		$content = RequestBase::newFromParams( $params )->execute();
93
		// Let's hope that this is good enough...
94
		$votes = substr_count( $content, "\n\# *(?![#*])" );
0 ignored issues
show
Bug introduced by
$content of type stdClass is incompatible with the type string expected by parameter $haystack of substr_count(). ( Ignorable by Annotation )

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

94
		$votes = substr_count( /** @scrutinizer ignore-type */ $content, "\n\# *(?![#*])" );
Loading history...
95
		return $votes >= 15;
96
	}
97
98
	/**
99
	 * Removes pages from WP:A/Riconferme annuali
100
	 * @param string[] $titles
101
	 * @see UpdatesAround::addToMainPage()
102
	 */
103
	protected function removeFromMainPage( array $titles ) {
104
		$this->getLogger()->info( 'Removing from main: ' . implode( ', ', $titles ) );
105
106
		$mainPage = $this->getConfig()->get( 'ric-main-page' );
107
		$content = $this->getController()->getPageContent( $mainPage );
108
		$translations = [];
109
		foreach ( $titles as $title ) {
110
			$translations[ '{{' . $title . '}}' ] = '';
111
		}
112
113
		$params = [
114
			'title' => $mainPage,
115
			'text' => strtr( $content, $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 string[] $titles
125
	 */
126
	protected function addToArchive( array $titles ) {
127
		$this->getLogger()->info( 'Adding to archive: ' . implode( ', ', $titles ) );
128
129
		$archiveTitle = $this->getConfig()->get( 'close-archive-title' );
130
		$archiveTitle = "$archiveTitle/" . date( 'Y' );
131
132
		$append = '';
133
		foreach ( $titles as $page ) {
134
			$append .= '{{' . $page . "}}\n";
135
		}
136
137
		$params = [
138
			'title' => $archiveTitle,
139
			'appendtext' => $append,
140
			'summary' => $this->getConfig()->get( 'close-archive-summary' )
141
		];
142
143
		$this->getController()->editPage( $params );
144
	}
145
146
	/**
147
	 * @param string $title
148
	 * @see CreatePages::updateBasePage()
149
	 */
150
	protected function updateBasePage( string $title ) {
151
		$this->getLogger()->info( "Updating base page $title" );
152
153
		$baseTitle = substr( $title, 0, strrpos( $title, '/' ) );
154
		$current = $this->getController()->getPageContent( $baseTitle );
155
156
		$newContent = str_replace( 'riconferma in corso', 'riconferma tacita', $current );
157
		$params = [
158
			'title' => $title,
159
			'text' => $newContent,
160
			'summary' => $this->getConfig()->get( 'close-base-page-summary-update' )
161
		];
162
163
		$this->getController()->editPage( $params );
164
	}
165
166
	/**
167
	 * @param string[] $titles
168
	 * @see UpdatesAround::addVote()
169
	 */
170
	protected function updateVote( array $titles ) {
171
		$votePage = $this->getConfig()->get( 'ric-vote-page' );
172
		$content = $this->getController()->getPageContent( $votePage );
173
174
		$titleReg = implode( '|', array_map( 'preg_quote', $titles ) );
175
		$search = "!^\*.+ La \[\[($titleReg)\|procedura]] termina.+\n!gm";
176
177
		$newContent = preg_replace( $search, '', $content );
178
		// Make sure the last line ends with a full stop
179
		$sectionReg = '!(^;È in corso.+riconferma tacita.+amministratori.+\n(?:\*.+[;\.]\n)+\*.+)[\.;]!m';
180
		$newContent = preg_replace( $sectionReg, '$1.', $newContent );
181
182
		$params = [
183
			'title' => $votePage,
184
			'text' => $newContent,
185
			'summary' => $this->getConfig()->get( 'close-vote-page-summary' )
186
		];
187
188
		$this->getController()->editPage( $params );
189
	}
190
191
	/**
192
	 * @param int $amount
193
	 * @throws TaskException
194
	 * @see UpdatesAround::addNews()
195
	 */
196
	protected function updateNews( int $amount ) {
197
		$this->getLogger()->info( "Decreasing the news counter by $amount" );
198
		$newsPage = $this->getConfig()->get( 'ric-news-page' );
199
200
		$content = $this->getController()->getPageContent( $newsPage );
201
		$reg = '!(\| *riconferme[ _]tacite[ _]amministratori *= *)(\d+)!';
202
203
		$matches = [];
204
		if ( preg_match( $reg, $content, $matches ) === false ) {
205
			throw new TaskException( 'Param not found in news page' );
206
		}
207
208
		$newNum = (int)$matches[2] - $amount;
209
		$newContent = preg_replace( $reg, '${1}' . $newNum, $content );
210
211
		$params = [
212
			'title' => $newsPage,
213
			'text' => $newContent,
214
			'summary' => $this->getConfig()->get( 'close-news-page-summary' )
215
		];
216
217
		$this->getController()->editPage( $params );
218
	}
219
220
	/**
221
	 * Update date on WP:Amministratori/Lista
222
	 *
223
	 * @param string[] $titles
224
	 */
225
	protected function updateAdminList( array $titles ) {
226
		$listTitle = $this->getConfig()->get( 'admins-list' );
227
		$content = $this->getController()->getPageContent( $listTitle );
228
		$newDate = date( 'Ymd', strtotime( '+1 year' ) );
229
		foreach ( $titles as $title ) {
230
			$user = explode( '/', $title )[2];
231
			$reg = "!(\{\{Amministratore\/riga\|$user.+\| *)\d+(?= *\|(?: *pausa)? *\}\})!";
232
			$content = preg_replace( $reg, '$1' . $newDate, $content );
233
		}
234
235
		$params = [
236
			'title' => $listTitle,
237
			'text' => $content,
238
			'summary' => $this->getConfig()->get( 'close-update-list-summary' )
239
		];
240
241
		$this->getController()->editPage( $params );
242
	}
243
}
244