Scrutinizer GitHub App not installed

We could not synchronize checks via GitHub's checks API since Scrutinizer's GitHub App is not installed for this repository.

Install GitHub App

Passed
Push — master ( 9a021b...f0ef9c )
by Dan
05:02
created

SmrAlliance::allRecruitTypes()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 4
nc 1
nop 0
dl 0
loc 6
rs 10
c 0
b 0
f 0
1
<?php declare(strict_types=1);
2
3
class SmrAlliance {
4
	protected static $CACHE_ALLIANCES = array();
5
6
	protected $db;
7
	protected $SQL;
8
9
	protected $gameID;
10
	protected $allianceID;
11
	protected $allianceName;
12
	protected $description;
13
	protected $password;
14
	protected $recruiting;
15
	protected $leaderID;
16
	protected $bank;
17
	protected $kills;
18
	protected $deaths;
19
	protected $motd;
20
	protected $imgSrc;
21
	protected $discordServer;
22
	protected $discordChannel;
23
	protected $ircChannel;
24
	protected $flagshipID;
25
26
	protected $memberList;
27
	protected $seedlist;
28
29
	// Recruit type constants
30
	const RECRUIT_OPEN = "open";
31
	const RECRUIT_CLOSED = "closed";
32
	const RECRUIT_PASSWORD = "password";
33
34
	public static function getAlliance($allianceID, $gameID, $forceUpdate = false) {
35
		if ($forceUpdate || !isset(self::$CACHE_ALLIANCES[$gameID][$allianceID])) {
36
			self::$CACHE_ALLIANCES[$gameID][$allianceID] = new SmrAlliance($allianceID, $gameID);
37
		}
38
		return self::$CACHE_ALLIANCES[$gameID][$allianceID];
39
	}
40
41
	public static function getAllianceByDiscordChannel($channel, $forceUpdate = false) {
42
		$db = new SmrMySqlDatabase();
43
		$db->query('SELECT alliance_id, game_id FROM alliance JOIN game USING(game_id) WHERE discord_channel = ' . $db->escapeString($channel) . ' AND game.end_time > ' . $db->escapeNumber(time()) . ' ORDER BY game_id DESC LIMIT 1');
44
		if ($db->nextRecord()) {
45
			return self::getAlliance($db->getInt('alliance_id'), $db->getInt('game_id'), $forceUpdate);
46
		} else {
47
			return null;
48
		}
49
	}
50
51
	public static function getAllianceByIrcChannel($channel, $forceUpdate = false) {
52
		$db = new SmrMySqlDatabase();
53
		$db->query('SELECT alliance_id, game_id FROM irc_alliance_has_channel WHERE channel = ' . $db->escapeString($channel) . ' LIMIT 1');
54
		if ($db->nextRecord()) {
55
			return self::getAlliance($db->getInt('alliance_id'), $db->getInt('game_id'), $forceUpdate);
56
		}
57
		$return = null;
58
		return $return;
59
	}
60
61
	public static function getAllianceByName($name, $gameID, $forceUpdate = false) {
62
		$db = new SmrMySqlDatabase();
63
		$db->query('SELECT alliance_id FROM alliance WHERE alliance_name = ' . $db->escapeString($name) . ' AND game_id = ' . $db->escapeNumber($gameID) . ' LIMIT 1');
64
		if ($db->nextRecord()) {
65
			return self::getAlliance($db->getInt('alliance_id'), $gameID, $forceUpdate);
66
		} else {
67
			return null;
68
		}
69
	}
70
71
	protected function __construct($allianceID, $gameID) {
72
		$this->db = new SmrMySqlDatabase();
73
74
		$this->allianceID = $allianceID;
75
		$this->gameID = $gameID;
76
		$this->SQL = 'alliance_id=' . $this->db->escapeNumber($allianceID) . ' AND game_id=' . $this->db->escapeNumber($gameID);
77
78
		if ($allianceID != 0) {
79
			$this->db->query('SELECT * FROM alliance WHERE ' . $this->SQL);
80
			$this->db->nextRecord();
81
			$this->allianceName = $this->db->getField('alliance_name');
82
			$this->password = stripslashes($this->db->getField('alliance_password'));
83
			$this->recruiting = $this->db->getBoolean('recruiting');
84
			$this->description = $this->db->getField('alliance_description');
85
			$this->leaderID = $this->db->getInt('leader_id');
86
			$this->bank = $this->db->getInt('alliance_account');
87
			$this->kills = $this->db->getInt('alliance_kills');
88
			$this->deaths = $this->db->getInt('alliance_deaths');
89
			$this->motd = $this->db->getField('mod');
90
			$this->imgSrc = $this->db->getField('img_src');
91
			$this->discordServer = $this->db->getField('discord_server');
92
			$this->discordChannel = $this->db->getField('discord_channel');
93
			$this->flagshipID = $this->db->getInt('flagship_id');
94
95
			if (empty($this->kills)) {
96
				$this->kills = 0;
97
			}
98
			if (empty($this->deaths)) {
99
				$this->deaths = 0;
100
			}
101
		}
102
	}
103
104
	/**
105
	 * Create an alliance and return the new object.
106
	 * Starts alliance with "closed" recruitment (for safety).
107
	 */
108
	public static function createAlliance($gameID, $name) {
109
		$db = new SmrMySqlDatabase();
110
111
		// check if the alliance name already exists
112
		$db->query('SELECT 1 FROM alliance WHERE alliance_name = ' . $db->escapeString($name) . ' AND game_id = ' . $db->escapeNumber($gameID) . ' LIMIT 1');
113
		if ($db->getNumRows() > 0) {
114
			create_error('That alliance name already exists!');
115
		}
116
117
		// get the next alliance id (ignoring reserved ID's)
118
		$db->query('SELECT max(alliance_id) FROM alliance WHERE game_id = ' . $db->escapeNumber($gameID) . ' AND (alliance_id < ' . $db->escapeNumber(NHA_ID) . ' OR alliance_id > ' . $db->escapeNumber(NHA_ID + 7) . ') LIMIT 1');
119
		$db->nextRecord();
120
		$allianceID = $db->getInt('max(alliance_id)') + 1;
121
		if ($allianceID >= NHA_ID && $allianceID <= NHA_ID + 7) {
122
			$allianceID = NHA_ID + 8;
123
		}
124
125
		// actually create the alliance here
126
		$db->query('INSERT INTO alliance (alliance_id, game_id, alliance_name, alliance_password, recruiting) VALUES(' . $db->escapeNumber($allianceID) . ', ' . $db->escapeNumber($gameID) . ', ' . $db->escapeString($name) . ', \'\', \'FALSE\')');
127
128
		return self::getAlliance($allianceID, $gameID);
129
	}
130
131
	/**
132
	 * Returns true if the alliance ID is associated with allianceless players.
133
	 */
134
	public function isNone() {
135
		return $this->allianceID == 0;
136
	}
137
138
	public function getAllianceID() {
139
		return $this->allianceID;
140
	}
141
142
	public function getAllianceBBLink() {
143
		return '[alliance=' . $this->allianceID . ']';
144
	}
145
146
	public function getAllianceDisplayName($linked = false, $includeAllianceID = false) {
147
		$name = htmlentities($this->allianceName);
148
		if ($includeAllianceID) {
149
			$name .= ' (' . $this->allianceID . ')';
150
		}
151
		if ($linked === true && !$this->hasDisbanded()) {
152
			return create_link(Globals::getAllianceRosterHREF($this->getAllianceID()), $name);
153
		}
154
		return $name;
155
	}
156
157
	/**
158
	 * Returns the alliance name.
159
	 * Use getAllianceDisplayName for an HTML-safe version.
160
	 */
161
	public function getAllianceName() {
162
		return $this->allianceName;
163
	}
164
165
	public function getGameID() {
166
		return $this->gameID;
167
	}
168
169
	public function getGame() {
170
		return SmrGame::getGame($this->gameID);
171
	}
172
173
	public function hasDisbanded() {
174
		return !$this->hasLeader();
175
	}
176
177
	public function hasLeader() {
178
		return $this->getLeaderID() != 0;
179
	}
180
181
	public function getLeaderID() {
182
		return $this->leaderID;
183
	}
184
185
	public function getLeader() {
186
		return SmrPlayer::getPlayer($this->getLeaderID(), $this->getGameID());
187
	}
188
189
	public function setLeaderID($leaderID) {
190
		$this->leaderID = $leaderID;
191
	}
192
193
	public function getDiscordServer() {
194
		return $this->discordServer;
195
	}
196
197
	public function setDiscordServer($serverId) {
198
		$this->discordServer = $serverId;
199
	}
200
201
	public function getDiscordChannel() {
202
		return $this->discordChannel;
203
	}
204
205
	public function setDiscordChannel($channelId) {
206
		$this->discordChannel = $channelId;
207
	}
208
209
	public function getIrcChannel() {
210
		if (!isset($this->ircChannel)) {
211
			$this->db->query('SELECT channel FROM irc_alliance_has_channel WHERE ' . $this->SQL);
212
			if ($this->db->nextRecord()) {
213
				$this->ircChannel = $this->db->getField('channel');
214
			} else {
215
				$this->ircChannel = '';
216
			}
217
		}
218
		return $this->ircChannel;
219
	}
220
221
	public function setIrcChannel($ircChannel) {
222
		if ($this->ircChannel == $ircChannel) {
223
			return;
224
		}
225
		if (strlen($ircChannel) > 0 && $ircChannel != '#') {
226
			if ($ircChannel[0] != '#') {
227
				$ircChannel = '#' . $ircChannel;
228
			}
229
			if ($ircChannel == '#smr' || $ircChannel == '#smr-bar') {
230
				create_error('Please enter a valid irc channel for your alliance.');
231
			}
232
233
			$this->db->query('REPLACE INTO irc_alliance_has_channel (channel,alliance_id,game_id) values (' . $this->db->escapeString($ircChannel) . ',' . $this->db->escapeNumber($this->getAllianceID()) . ',' . $this->db->escapeNumber($this->getGameID()) . ');');
234
		} else {
235
			$this->db->query('DELETE FROM irc_alliance_has_channel WHERE ' . $this->SQL);
236
		}
237
		$this->ircChannel = $ircChannel;
238
	}
239
240
	public function hasImageURL() {
241
		return strlen($this->imgSrc) && $this->imgSrc != 'http://';
242
	}
243
244
	public function getImageURL() {
245
		return $this->imgSrc;
246
	}
247
248
	public function setImageURL($url) {
249
		if (preg_match('/"/', $url)) {
250
			throw new Exception('Tried to set an image url with ": ' . $url);
251
		}
252
		$this->imgSrc = htmlspecialchars($url);
253
	}
254
255
	/**
256
	 * Get the total credits in the alliance bank account.
257
	 */
258
	public function getBank() {
259
		return $this->bank;
260
	}
261
262
	public function setBank($credits) {
263
		$this->bank = $credits;
264
	}
265
266
	/**
267
	 * Get (HTML-safe) alliance Message of the Day for display.
268
	 */
269
	public function getMotD() {
270
		return htmlentities($this->motd);
271
	}
272
273
	public function setMotD($motd) {
274
		$this->motd = $motd;
275
	}
276
277
	public function getPassword() {
278
		return $this->password;
279
	}
280
281
	public function isRecruiting() : bool {
282
		return $this->recruiting;
283
	}
284
285
	/**
286
	 * Set the password and recruiting attributes.
287
	 * The input $password is ignored except for the "password" $type.
288
	 */
289
	public function setRecruitType(string $type, string $password) : void {
290
		if ($type == self::RECRUIT_CLOSED) {
291
			$this->recruiting = false;
292
			$this->password = '';
293
		} elseif ($type == self::RECRUIT_OPEN) {
294
			$this->recruiting = true;
295
			$this->password = '';
296
		} elseif ($type == self::RECRUIT_PASSWORD) {
297
			if (empty($password)) {
298
				throw new Exception('Password must not be empty here');
299
			}
300
			$this->recruiting = true;
301
			$this->password = $password;
302
		} else {
303
			throw new Exception('Unknown recruit type: ' . $type);
304
		}
305
	}
306
307
	public function getRecruitType() : string {
308
		if (!$this->isRecruiting()) {
309
			return self::RECRUIT_CLOSED;
310
		} elseif (empty($this->getPassword())) {
311
			return self::RECRUIT_OPEN;
312
		} else {
313
			return self::RECRUIT_PASSWORD;
314
		}
315
	}
316
317
	/**
318
	 * List of all recruitment types and their descriptions.
319
	 * Do not change the order of elements in the list!
320
	 */
321
	public static function allRecruitTypes() : array {
322
		// The first type is the default option when creating new alliances
323
		return [
324
			self::RECRUIT_PASSWORD => "Players can join by password or invitation",
325
			self::RECRUIT_CLOSED => "Players can join by invitation only",
326
			self::RECRUIT_OPEN => "Anyone can join (no password needed)",
327
		];
328
	}
329
330
	public function getKills() {
331
		return $this->kills;
332
	}
333
334
	public function getDeaths() {
335
		return $this->deaths;
336
	}
337
338
	/**
339
	 * Get (HTML-safe) alliance description for display.
340
	 */
341
	public function getDescription() {
342
		if (empty($this->description)) {
343
			return '';
344
		} else {
345
			return htmlentities($this->description);
346
		}
347
	}
348
349
	public function setAllianceDescription($description) {
350
		$description = word_filter($description);
351
		if ($description == $this->description) {
352
			return;
353
		}
354
		global $player, $account;
355
		$boxDescription = 'Alliance ' . $this->getAllianceBBLink() . ' had their description changed to:' . EOL . EOL . $description;
356
		if (is_object($player)) {
357
			$player->sendMessageToBox(BOX_ALLIANCE_DESCRIPTIONS, $boxDescription);
358
		} else {
359
			$account->sendMessageToBox(BOX_ALLIANCE_DESCRIPTIONS, $boxDescription);
360
		}
361
		$this->description = $description;
362
	}
363
364
	public function hasFlagship() {
365
		return $this->flagshipID != 0;
366
	}
367
368
	/**
369
	 * Get account ID of the player designated as the alliance flagship.
370
	 * Returns 0 if no flagship.
371
	 */
372
	public function getFlagshipID() {
373
		return $this->flagshipID;
374
	}
375
376
	/**
377
	 * Designate a player as the alliance flagship by their account ID.
378
	 */
379
	public function setFlagshipID($accountID) {
380
		if ($this->flagshipID == $accountID) {
381
			return;
382
		}
383
		$this->flagshipID = $accountID;
384
	}
385
386
	public function canJoinAlliance(SmrPlayer $player, $doAllianceCheck = true) {
387
		if (!$player->getAccount()->isValidated()) {
388
			return 'You cannot join an alliance until you validate your account.';
389
		}
390
		if ($this->hasDisbanded()) {
391
			return 'This alliance has disbanded!';
392
		}
393
		if ($doAllianceCheck && $player->hasAlliance()) {
394
			return 'You are already in an alliance!';
395
		}
396
		if (!$this->isRecruiting()) {
397
			return 'This alliance is not currently accepting new recruits.';
398
		}
399
		if ($player->getAllianceJoinable() > TIME) {
400
			return 'You cannot join another alliance for ' . format_time($player->getAllianceJoinable() - TIME) . '.';
401
		}
402
		if ($this->getNumMembers() < $this->getGame()->getAllianceMaxPlayers()) {
403
			if ($player->hasNewbieStatus()) {
404
				return true;
405
			}
406
			$maxVets = $this->getGame()->getAllianceMaxVets();
407
			if ($this->getNumMembers() < $maxVets) {
408
				return true;
409
			}
410
			$this->db->query('SELECT status FROM player_joined_alliance WHERE account_id=' . $this->db->escapeNumber($player->getAccountID()) . ' AND ' . $this->SQL);
411
			if ($this->db->nextRecord()) {
412
				if ($this->db->getField('status') == 'NEWBIE') {
413
					return true;
414
				}
415
			}
416
			$this->db->query('SELECT COUNT(*) AS num_orig_vets
417
							FROM player_joined_alliance
418
							JOIN player USING (account_id, alliance_id, game_id)
419
							WHERE ' . $this->SQL . ' AND status=\'VETERAN\'');
420
			if (!$this->db->nextRecord() || $this->db->getInt('num_orig_vets') < $maxVets) {
421
				return true;
422
			}
423
		}
424
		return 'There is not currently enough room for you in this alliance.';
425
	}
426
427
	public function getNumVeterans() {
428
		$numVeterans = 0;
429
		foreach ($this->getMembers() as $player) {
430
			if (!$player->hasNewbieStatus()) {
431
				$numVeterans++;
432
			}
433
		}
434
		return $numVeterans;
435
	}
436
437
	public function getNumMembers() {
438
		return count($this->getMemberIDs());
439
	}
440
441
	public function update() {
442
		$this->db->query('UPDATE alliance SET
443
								alliance_password = ' . $this->db->escapeString($this->password) . ',
444
								recruiting = ' . $this->db->escapeBoolean($this->recruiting) . ',
445
								alliance_account = ' . $this->db->escapeNumber($this->bank) . ',
446
								alliance_description = ' . $this->db->escapeString($this->description, true, true) . ',
447
								`mod` = ' . $this->db->escapeString($this->motd) . ',
448
								img_src = ' . $this->db->escapeString($this->imgSrc) . ',
449
								alliance_kills = ' . $this->db->escapeNumber($this->kills) . ',
450
								alliance_deaths = ' . $this->db->escapeNumber($this->deaths) . ',
451
								discord_server = ' . $this->db->escapeString($this->discordServer, true, true) . ',
452
								discord_channel = ' . $this->db->escapeString($this->discordChannel, true, true) . ',
453
								flagship_id = ' . $this->db->escapeNumber($this->flagshipID) . ',
454
								leader_id = ' . $this->db->escapeNumber($this->leaderID) . '
455
							WHERE ' . $this->SQL);
456
	}
457
458
	/**
459
	 * Returns the members of this alliance as an array of SmrPlayer objects.
460
	 */
461
	public function getMembers() {
462
		return SmrPlayer::getAlliancePlayers($this->getGameID(), $this->getAllianceID());
463
	}
464
465
	public function getMemberIDs() {
466
		if (!isset($this->memberList)) {
467
			$this->db->query('SELECT account_id FROM player WHERE ' . $this->SQL);
468
469
			//we have the list of players put them in an array now
470
			$this->memberList = array();
471
			while ($this->db->nextRecord()) {
472
				$this->memberList[] = $this->db->getInt('account_id');
473
			}
474
		}
475
		return $this->memberList;
476
	}
477
	
478
	public function getActiveIDs() {
479
		$activeIDs = array();
480
		
481
		$this->db->query('SELECT account_id
482
						FROM active_session
483
						JOIN player USING(account_id, game_id)
484
						WHERE '.$this->SQL . ' AND last_accessed >= ' . $this->db->escapeNumber(TIME - 600));
485
		
486
		while ($this->db->nextRecord()) {
487
			$activeIDs[] = $this->db->getInt('account_id');
488
		}
489
		
490
		return $activeIDs;
491
	}
492
493
	/**
494
	 * Return all planets owned by members of this alliance.
495
	 */
496
	public function getPlanets() {
497
		$this->db->query('SELECT planet.*
498
			FROM player
499
			JOIN planet ON player.game_id = planet.game_id AND player.account_id = planet.owner_id
500
			WHERE player.game_id=' . $this->db->escapeNumber($this->gameID) . '
501
			AND player.alliance_id=' . $this->db->escapeNumber($this->allianceID) . '
502
			ORDER BY planet.sector_id
503
		');
504
		$planets = array();
505
		while ($this->db->nextRecord()) {
506
			$planets[] = SmrPlanet::getPlanet($this->gameID, $this->db->getInt('sector_id'), false, $this->db);
507
		}
508
		return $planets;
509
	}
510
511
	/**
512
	 * Return array of sector_id for sectors in the alliance seedlist.
513
	 */
514
	public function getSeedlist() {
515
		if (!isset($this->seedlist)) {
516
			$this->db->query('SELECT sector_id FROM alliance_has_seedlist WHERE ' . $this->SQL);
517
			$this->seedlist = array();
518
			while ($this->db->nextRecord()) {
519
				$this->seedlist[] = $this->db->getInt('sector_id');
520
			}
521
		}
522
		return $this->seedlist;
523
	}
524
525
	/**
526
	 * Is the given sector in the alliance seedlist?
527
	 */
528
	public function isInSeedlist(SmrSector $sector) {
529
		return in_array($sector->getSectorID(), $this->getSeedlist());
530
	}
531
532
	/**
533
	 * Create the default roles for this alliance.
534
	 * This should only be called once after the alliance is created.
535
	 */
536
	public function createDefaultRoles($newMemberPermission = 'basic') {
537
		$db = $this->db; //for convenience
538
539
		$withPerDay = ALLIANCE_BANK_UNLIMITED;
540
		$removeMember = TRUE;
541
		$changePass = TRUE;
542
		$changeMOD = TRUE;
543
		$changeRoles = TRUE;
544
		$planetAccess = TRUE;
545
		$exemptWith = TRUE;
546
		$mbMessages = TRUE;
547
		$sendAllMsg = TRUE;
548
		$opLeader = TRUE;
549
		$viewBonds = TRUE;
550
		$db->query('INSERT INTO alliance_has_roles (alliance_id, game_id, role_id, role, with_per_day, remove_member, change_pass, change_mod, change_roles, planet_access, exempt_with, mb_messages, send_alliance_msg, op_leader, view_bonds) ' .
551
			'VALUES (' . $db->escapeNumber($this->getAllianceID()) . ', ' . $db->escapeNumber($this->getGameID()) . ', ' . $db->escapeNumber(ALLIANCE_ROLE_LEADER) . ', \'Leader\', ' . $db->escapeNumber($withPerDay) . ', ' . $db->escapeBoolean($removeMember) . ', ' . $db->escapeBoolean($changePass) . ', ' . $db->escapeBoolean($changeMOD) . ', ' . $db->escapeBoolean($changeRoles) . ', ' . $db->escapeBoolean($planetAccess) . ', ' . $db->escapeBoolean($exemptWith) . ', ' . $db->escapeBoolean($mbMessages) . ', ' . $db->escapeString($sendAllMsg) . ', ' . $db->escapeBoolean($opLeader) . ', ' . $db->escapeBoolean($viewBonds) . ')');
552
553
		switch ($newMemberPermission) {
554
			case 'full':
555
				//do nothing, perms already set above.
556
			break;
557
			case 'none':
558
				$withPerDay = 0;
559
				$removeMember = FALSE;
560
				$changePass = FALSE;
561
				$changeMOD = FALSE;
562
				$changeRoles = FALSE;
563
				$planetAccess = FALSE;
564
				$exemptWith = FALSE;
565
				$mbMessages = FALSE;
566
				$sendAllMsg = FALSE;
567
				$opLeader = FALSE;
568
				$viewBonds = FALSE;
569
			break;
570
			case 'basic':
571
				$withPerDay = ALLIANCE_BANK_UNLIMITED;
572
				$removeMember = FALSE;
573
				$changePass = FALSE;
574
				$changeMOD = FALSE;
575
				$changeRoles = FALSE;
576
				$planetAccess = TRUE;
577
				$exemptWith = FALSE;
578
				$mbMessages = FALSE;
579
				$sendAllMsg = FALSE;
580
				$opLeader = FALSE;
581
				$viewBonds = FALSE;
582
			break;
583
		}
584
		$db->query('INSERT INTO alliance_has_roles (alliance_id, game_id, role_id, role, with_per_day, remove_member, change_pass, change_mod, change_roles, planet_access, exempt_with, mb_messages, send_alliance_msg, op_leader, view_bonds) ' .
585
					'VALUES (' . $db->escapeNumber($this->getAllianceID()) . ', ' . $db->escapeNumber($this->getGameID()) . ', ' . $db->escapeNumber(ALLIANCE_ROLE_NEW_MEMBER) . ', \'New Member\', ' . $db->escapeNumber($withPerDay) . ', ' . $db->escapeBoolean($removeMember) . ', ' . $db->escapeBoolean($changePass) . ', ' . $db->escapeBoolean($changeMOD) . ', ' . $db->escapeBoolean($changeRoles) . ', ' . $db->escapeBoolean($planetAccess) . ', ' . $db->escapeBoolean($exemptWith) . ', ' . $db->escapeBoolean($mbMessages) . ', ' . $db->escapeString($sendAllMsg) . ', ' . $db->escapeBoolean($opLeader) . ', ' . $db->escapeBoolean($viewBonds) . ')');
586
587
	}
588
589
}
590