Passed
Push — master ( df8555...a1b33e )
by Daimona
02:22 queued 28s
created

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