Passed
Push — master ( 10aa7b...8214a5 )
by Daimona
01:42
created

PageRiconferma::__construct()   A

Complexity

Conditions 3
Paths 4

Size

Total Lines 4
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

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