Passed
Push — master ( e26f3b...6f3cd3 )
by Daimona
01:37
created

PageRiconferma::getTitle()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 2
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 1
nc 1
nop 0
dl 0
loc 2
rs 10
c 0
b 0
f 0
1
<?php declare( strict_types=1 );
2
3
namespace BotRiconferme;
4
5
use BotRiconferme\Request\RequestBase;
6
7
/**
8
 * Represents a single riconferma page
9
 */
10
class PageRiconferma {
11
	/** @var string */
12
	private $title;
13
	/** @var WikiController */
14
	private $controller;
15
	/** @var string */
16
	private $content;
17
18
	// Sections of the page value is section number
19
	const SECTION_SUPPORT = 3;
20
	const SECTION_OPPOSE = 4;
21
22
	// Possible outcomes of a vote
23
	const OUTCOME_OK = 0;
24
	const OUTCOME_FAIL_VOTES = 1;
25
	const OUTCOME_NO_QUOR = 2;
26
	const OUTCOME_FAIL = self::OUTCOME_FAIL_VOTES | self::OUTCOME_NO_QUOR;
27
28
	/**
29
	 * @param string $title
30
	 * @param WikiController $controller
31
	 */
32
	public function __construct( string $title, WikiController $controller ) {
33
		$this->title = $title;
34
		$this->controller = $controller;
35
	}
36
37
	/**
38
	 * @return string
39
	 */
40
	public function getTitle() : string {
41
		return $this->title;
42
	}
43
44
	/**
45
	 * Get the name of the user from the title
46
	 *
47
	 * @return string
48
	 */
49
	public function getUser() : string {
50
		return explode( '/', $this->title )[2];
51
	}
52
53
	/**
54
	 * Returns the progressive number in the title
55
	 *
56
	 * @return int
57
	 */
58
	public function getNum() : int {
59
		$bits = explode( '/', $this->getTitle() );
60
		return intval( end( $bits ) );
61
	}
62
63
	/**
64
	 * Get the last part of the title as Username/Num
65
	 *
66
	 * @return string
67
	 */
68
	public function getUserNum() : string {
69
		return explode( '/', $this->getTitle(), 3 )[2];
70
	}
71
72
	/**
73
	 * Strip the part with the progressive number
74
	 *
75
	 * @return string
76
	 */
77
	public function getBaseTitle() : string {
78
		// @phan-suppress-next-line PhanTypeMismatchArgumentInternal Phan bug
79
		return substr( $this->getTitle(), 0, strrpos( $this->getTitle(), '/' ) );
80
	}
81
82
	/**
83
	 * Get the content of this page
84
	 *
85
	 * @return string
86
	 */
87
	public function getContent() : string {
88
		if ( $this->content === null ) {
89
			$this->content = $this->controller->getPageContent( $this->title );
90
		}
91
		return $this->content;
92
	}
93
94
	/**
95
	 * Get the amount of opposing votes
96
	 *
97
	 * @return int
98
	 */
99
	public function getOpposingCount() : int {
100
		return $this->getCountForSection( self::SECTION_OPPOSE );
101
	}
102
103
	/**
104
	 * Get the amount support votes
105
	 *
106
	 * @return int
107
	 */
108
	public function getSupportCount() : int {
109
		return $this->getCountForSection( self::SECTION_SUPPORT );
110
	}
111
112
	/**
113
	 * Count the votes in the given section
114
	 *
115
	 * @param int $secNum
116
	 * @return int
117
	 */
118
	protected function getCountForSection( int $secNum ) : int {
119
		$params = [
120
			'action' => 'query',
121
			'prop' => 'revisions',
122
			'titles' => $this->title,
123
			'rvprop' => 'content',
124
			'rvslots' => 'main',
125
			'rvsection' => $secNum
126
		];
127
128
		$res = RequestBase::newFromParams( $params )->execute();
129
		$page = reset( $res->query->pages );
130
		$content = $page->revisions[0]->slots->main->{ '*' };
131
		// Let's hope that this is good enough...
132
		return substr_count( $content, "\n\# *(?![#*])" );
133
	}
134
135
	/**
136
	 * Gets the quorum used for the current page
137
	 */
138
	protected function getQuorum() : int {
139
		$reg = "!soddisfare il \[\[[^|\]]+\|quorum]] di '''(\d+) voti'''!";
140
		$matches = [];
141
		preg_match( $reg, $this->getContent(), $matches );
142
		return intval( $matches[1] );
143
	}
144
145
	/**
146
	 * Whether this page has enough opposing votes
147
	 *
148
	 * @return bool
149
	 */
150
	public function hasOpposition() : bool {
151
		return $this->getOpposingCount() >= 15;
152
	}
153
154
	/**
155
	 * Gets the outcome for the vote
156
	 *
157
	 * @return int One of the OUTCOME_* constants
158
	 * @throws \BadMethodCallException
159
	 */
160
	public function getOutcome() : int {
161
		if ( !$this->isVote() ) {
162
			throw new \BadMethodCallException( 'Cannot get outcome for a non-vote page.' );
163
		}
164
		$totalVotes = $this->getOpposingCount() + $this->getSupportCount();
165
		if ( $this->getSupportCount() < $this->getQuorum() ) {
166
			return self::OUTCOME_NO_QUOR;
167
		} elseif ( $this->getSupportCount() < 2 * $totalVotes / 3 ) {
168
			return self::OUTCOME_FAIL_VOTES;
169
		}
170
		return self::OUTCOME_OK;
171
	}
172
173
	/**
174
	 * Get the result text for the page itself
175
	 *
176
	 * @return string
177
	 * @throws \BadMethodCallException
178
	 */
179
	public function getOutcomeText() : string {
180
		if ( !$this->isVote() ) {
181
			throw new \BadMethodCallException( 'No need for an outcome text.' );
182
		}
183
184
		$text = sprintf(
185
			' Con %d voti a favore e %d contrari',
186
			$this->getSupportCount(),
187
			$this->getOpposingCount()
188
		);
189
		$user = $this->getUser();
190
191
		switch ( $this->getOutcome() ) {
192
			case self::OUTCOME_OK:
193
				$text .= " $user viene riconfermato amministratore.";
194
				break;
195
			/** @noinspection PhpMissingBreakStatementInspection */
196
			case self::OUTCOME_NO_QUOR:
197
				$text .= ', non raggiungendo il quorum,';
198
				// Fall through intended
199
			case self::OUTCOME_FAIL:
200
				$text .= " $user non viene riconfermato amministratore";
201
				break;
202
		}
203
		return $text;
204
	}
205
206
	/**
207
	 * Whether this page is a vote
208
	 *
209
	 * @return bool
210
	 */
211
	public function isVote() : bool {
212
		$sectionReg = '/<!-- SEZIONE DA UTILIZZARE PER/';
213
		return preg_match( $sectionReg, $this->getContent() ) === false;
214
	}
215
216
	/**
217
	 * Get the end time
218
	 *
219
	 * @return int
220
	 */
221
	public function getEndTimestamp() : int {
222
		if ( $this->isVote() ) {
223
			$matches = [];
224
			$reg = "!La votazione ha inizio il.+ e ha termine.+ '''([^']+)''' alle ore '''([^']+)'''!";
225
			preg_match( $reg, $this->getContent(), $matches );
226
			list( , $day, $hours ) = $matches;
227
			$day = preg_replace( '![^\d \w]!', '', $day );
228
			return WikiController::getTimestampFromLocalTime( $day . " alle " . $hours );
229
		} else {
230
			$created = $this->controller->getPageCreationTS( $this->title );
231
			return $created + 60 * 60 * 24 * 7;
232
		}
233
	}
234
235
	public function __toString() {
236
		return $this->getTitle();
237
	}
238
}
239