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

Failed Conditions
Pull Request — master (#1031)
by Dan
04:16
created

create_submit_link()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 2
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 1
dl 0
loc 2
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 2
1
<?php declare(strict_types=1);
2
3
function htmliseMessage($message) {
4
	$message = htmlentities($message, ENT_COMPAT, 'utf-8');
5
	$message = str_replace('&lt;br /&gt;', '<br />', $message);
6
	return $message;
7
}
8
9
function parseBoolean($check) {
10
	// Only negative strings are not implicitly converted to the correct bool
11
	if (is_string($check) && (strcasecmp($check, 'NO') == 0 || strcasecmp($check, 'FALSE') == 0)) {
12
		return false;
13
	}
14
	return (bool)$check;
15
}
16
17
function linkCombatLog($logID) {
18
	$container = Page::create('combat_log_viewer_verify.php');
19
	$container['log_id'] = $logID;
20
	return '<a href="' . $container->href() . '"><img src="images/notify.gif" width="14" height="11" border="0" title="View the combat log" /></a>';
21
}
22
23
/**
24
 * Converts a BBCode tag into some other text depending on the tag and value.
25
 * This is called in two stages: first with action BBCODE_CHECK (where the
26
 * returned value must be a boolean) and second, if the first check passes,
27
 * with action BBCODE_OUTPUT.
28
 */
29
function smrBBCode($bbParser, $action, $tagName, $default, $tagParams, $tagContent) {
0 ignored issues
show
Unused Code introduced by
The parameter $bbParser is not used and could be removed. ( Ignorable by Annotation )

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

29
function smrBBCode(/** @scrutinizer ignore-unused */ $bbParser, $action, $tagName, $default, $tagParams, $tagContent) {

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
30
	global $overrideGameID, $disableBBLinks, $player, $account, $var;
31
	try {
32
		switch ($tagName) {
33
			case 'combatlog':
34
				if ($action == \Nbbc\BBCode::BBCODE_CHECK) {
35
					return is_numeric($default);
36
				}
37
				$logID = (int)$default;
38
				return linkCombatLog($logID);
39
			break;
0 ignored issues
show
Unused Code introduced by
break is not strictly necessary here and could be removed.

The break statement is not necessary if it is preceded for example by a return statement:

switch ($x) {
    case 1:
        return 'foo';
        break; // This break is not necessary and can be left off.
}

If you would like to keep this construct to be consistent with other case statements, you can safely mark this issue as a false-positive.

Loading history...
40
			case 'player':
41
				if ($action == \Nbbc\BBCode::BBCODE_CHECK) {
42
					return is_numeric($default);
43
				}
44
				$playerID = (int)$default;
45
				$bbPlayer = SmrPlayer::getPlayerByPlayerID($playerID, $overrideGameID);
46
				$showAlliance = isset($tagParams['showalliance']) ? parseBoolean($tagParams['showalliance']) : false;
47
				if ($disableBBLinks === false && $overrideGameID == SmrSession::getGameID()) {
48
					return $bbPlayer->getLinkedDisplayName($showAlliance);
49
				}
50
				return $bbPlayer->getDisplayName($showAlliance);
51
			break;
52
			case 'alliance':
53
				if ($action == \Nbbc\BBCode::BBCODE_CHECK) {
54
					return is_numeric($default);
55
				}
56
				$allianceID = (int)$default;
57
				$alliance = SmrAlliance::getAlliance($allianceID, $overrideGameID);
58
				if ($disableBBLinks === false && $overrideGameID == SmrSession::getGameID()) {
59
					$container = Page::create('skeleton.php');
60
					$container['alliance_id'] = $alliance->getAllianceID();
61
					if (is_object($player) && $alliance->getAllianceID() == $player->getAllianceID()) {
62
						$container['body'] = 'alliance_mod.php';
63
					} else {
64
						$container['body'] = 'alliance_roster.php';
65
					}
66
					return create_link($container, $alliance->getAllianceDisplayName());
67
				}
68
				return $alliance->getAllianceDisplayName();
69
			break;
70
			case 'race':
71
				$raceNameID = $default;
72
				foreach (Globals::getRaces() as $raceID => $raceInfo) {
73
					if ((is_numeric($raceNameID) && $raceNameID == $raceID)
74
						|| $raceNameID == $raceInfo['Race Name']) {
75
						if ($action == \Nbbc\BBCode::BBCODE_CHECK) {
76
							return true;
77
						}
78
						$linked = $disableBBLinks === false && $overrideGameID == SmrSession::getGameID();
79
						return AbstractSmrPlayer::getColouredRaceNameOrDefault($raceID, $player, $linked);
80
					}
81
				}
82
			break;
83
			case 'servertimetouser':
84
				if ($action == \Nbbc\BBCode::BBCODE_CHECK) {
85
					return true;
86
				}
87
				$timeString = $default;
88
				if ($timeString != '' && ($time = strtotime($timeString)) !== false) {
89
					if (is_object($account)) {
90
						$time += $account->getOffset() * 3600;
91
					}
92
					return date(DATE_FULL_SHORT, $time);
93
				}
94
			break;
95
			case 'chess':
96
				if ($action == \Nbbc\BBCode::BBCODE_CHECK) {
97
					return is_numeric($default);
98
				}
99
				$chessGameID = (int)$default;
100
				$chessGame = ChessGame::getChessGame($chessGameID);
101
				return '<a href="' . $chessGame->getPlayGameHREF() . '">chess game (' . $chessGame->getChessGameID() . ')</a>';
102
			break;
103
104
			case 'sector':
105
				if ($action == \Nbbc\BBCode::BBCODE_CHECK) {
106
					return is_numeric($default);
107
				}
108
109
				$sectorID = (int)$default;
110
				$sectorTag = '<span class="sectorColour">#' . $sectorID . '</span>';
111
112
				// The use of $var here is for a corner case where an admin can check reported messages whilst being in-game.
113
				// Ugly but working, probably want a better mechanism to check if more BBCode tags get added
114
				if ($disableBBLinks === false
115
					&& SmrSession::hasGame()
116
					&& SmrSession::getGameID() == $overrideGameID
117
					&& SmrSector::sectorExists($overrideGameID, $sectorID)) {
118
					return '<a href="' . Globals::getPlotCourseHREF($player->getSectorID(), $sectorID) . '">' . $sectorTag . '</a>';
119
				}
120
121
				return $sectorTag;
122
			break;
123
			case 'join_alliance':
124
				if ($action == \Nbbc\BBCode::BBCODE_CHECK) {
125
					return is_numeric($default);
126
				}
127
				$allianceID = (int)$default;
128
				$alliance = SmrAlliance::getAlliance($allianceID, $overrideGameID);
129
				$container = Page::create('alliance_invite_accept_processing.php');
130
				$container['alliance_id'] = $alliance->getAllianceID();
131
				return '<div class="buttonA"><a class="buttonA" href="' . $container->href() . '">Join ' . $alliance->getAllianceDisplayName() . '</a></div>';
132
			break;
133
		}
134
	} catch (Throwable $e) {
135
		// If there's an error, we will silently display the original text
136
	}
137
	if ($action == \Nbbc\BBCode::BBCODE_CHECK) {
138
		return false;
139
	}
140
	return htmlspecialchars($tagParams['_tag']) . $tagContent . htmlspecialchars($tagParams['_endtag']);
141
}
142
143
function xmlify($str) {
144
	$xml = htmlspecialchars($str, ENT_XML1, 'utf-8');
145
	return $xml;
146
}
147
148
function inify($text) {
149
	return str_replace(',', '', html_entity_decode($text));
150
}
151
152
function bbifyMessage($message, $noLinks = false) {
153
	static $bbParser;
154
	if (!isset($bbParser)) {
155
		$bbParser = new \Nbbc\BBCode();
156
		$bbParser->SetEnableSmileys(false);
157
		$bbParser->RemoveRule('wiki');
158
		$bbParser->RemoveRule('img');
159
		$bbParser->SetURLTarget('_blank');
160
		$bbParser->SetURLTargetable('override');
161
		$bbParser->setEscapeContent(false); // don't escape HTML, needed for News etc.
162
		$smrRule = array(
163
				'mode' => \Nbbc\BBCode::BBCODE_MODE_CALLBACK,
164
				'method' => 'smrBBCode',
165
				'class' => 'link',
166
				'allow_in' => Array('listitem', 'block', 'columns', 'inline'),
167
				'end_tag' => \Nbbc\BBCode::BBCODE_PROHIBIT,
168
				'content' => \Nbbc\BBCode::BBCODE_PROHIBIT,
169
			);
170
		$bbParser->AddRule('combatlog', $smrRule);
171
		$bbParser->AddRule('player', $smrRule);
172
		$bbParser->AddRule('alliance', $smrRule);
173
		$bbParser->AddRule('race', $smrRule);
174
		$bbParser->AddRule('servertimetouser', $smrRule);
175
		$bbParser->AddRule('chess', $smrRule);
176
		$bbParser->AddRule('sector', $smrRule);
177
		$bbParser->addRule('join_alliance', $smrRule);
178
	}
179
	global $disableBBLinks;
180
	if ($noLinks === true) {
181
		$disableBBLinks = true;
182
	} else {
183
		$disableBBLinks = false;
184
	}
185
	if (strpos($message, '[') !== false) { //We have BBCode so let's do a full parse.
186
		$message = $bbParser->parse($message);
187
		$message = str_replace('&lt;br /&gt;', '<br />', $message);
188
	} else { //Otherwise just convert newlines
189
		$message = nl2br($message, true);
190
	}
191
	return $message;
192
}
193
194
function create_error($message) {
195
	$container = Page::create('skeleton.php', 'error.php');
196
	$container['message'] = $message;
197
	if (USING_AJAX) {
198
		// To avoid the page just not refreshing when an error is encountered
199
		// during ajax updates, use javascript to auto-redirect to the
200
		// appropriate error page.
201
		global $template;
202
		if (is_object($template) && method_exists($template, 'addJavascriptForAjax')) {
203
			$errorHREF = $container->href();
204
			// json_encode the HREF as a safety precaution
205
			$template->addJavascriptForAjax('EVAL', 'location.href = ' . json_encode($errorHREF));
206
		}
207
	}
208
	$container->go();
209
}
210
211
function create_link(Page|string $container, $text, $class = null) {
212
	return '<a' . ($class == null ? '' : ' class="' . $class . '"') . ' href="' . (is_string($container) ? $container : $container->href()) . '">' . $text . '</a>';
213
}
214
215
function create_submit_link(Page $container, $text) {
216
	return '<a href="' . $container->href() . '" class="submitStyle">' . $text . '</a>';
217
}
218
219
function get_colored_text_range($value, $maxValue, $text = null, $minValue = 0, $type = 'Game', $return_type = 'Normal') {
220
	if ($text == null) {
221
		$text = number_format($value);
222
	}
223
	if ($maxValue - $minValue == 0) {
224
		return $text;
225
	} else {
226
		$normalisedValue = IRound(510 * max(0, min($maxValue, $value) - $minValue) / ($maxValue - $minValue)) - 255;
227
	}
228
	if ($type == 'Game') {
229
		if ($normalisedValue < 0) {
230
			$r_component = 'ff';
231
			$g_component = dechex(255 + $normalisedValue);
232
			if (strlen($g_component) == 1) {
233
				$g_component = '0' . $g_component;
234
			}
235
		} else if ($normalisedValue > 0) {
236
			$g_component = 'ff';
237
			$r_component = dechex(255 - $normalisedValue);
238
			if (strlen($r_component) == 1) {
239
				$r_component = '0' . $r_component;
240
			}
241
		} else {
242
			$r_component = 'ff';
243
			$g_component = 'ff';
244
		}
245
		$colour = $r_component . $g_component . '00';
246
		if ($return_type == 'Colour') {
247
			return $colour;
248
		}
249
		return '<span style="color:#' . $colour . '">' . $text . '</span>';
250
	} elseif ($type == 'IRC') {
251
		//IRC color codes
252
		if ($normalisedValue == 255) {
253
			$colour = '[k03]';
254
		} elseif ($normalisedValue == -255) {
255
			$colour = '[k04]';
256
		} else {
257
			$colour = '[k08]';
258
		}
259
		if ($return_type == 'Colour') {
260
			return $colour;
261
		}
262
		return $colour . $text;
263
	}
264
}
265
266
function get_colored_text($value, $text = null, $type = 'Game', $return_type = 'Normal') {
267
	return get_colored_text_range($value, 300, $text, -300, $type, $return_type);
268
}
269
270
function word_filter($string) {
271
	static $words;
272
273
	if (!is_array($words)) {
274
		$db = MySqlDatabase::getInstance();
275
		$db->query('SELECT word_value, word_replacement FROM word_filter');
276
		$words = array();
277
		while ($db->nextRecord()) {
278
			$row = $db->getRow();
279
			$words[] = array('word_value' => '/' . str_replace('/', '\/', $row['word_value']) . '/i', 'word_replacement'=> $row['word_replacement']);
280
		}
281
	}
282
283
	foreach ($words as $word) {
284
		$string = preg_replace($word['word_value'], $word['word_replacement'], $string);
285
	}
286
287
	return $string;
288
}
289
290
// choose correct pluralization based on amount
291
function pluralise($word, $count = 0) {
292
	if ($count == 1) {
293
		return $word;
294
	}
295
	if (strtolower($word) == 'is') {
296
		return 'are';
297
	}
298
	return $word . 's';
299
}
300
301
/**
302
 * This function is a hack around the old style http forward mechanism.
303
 * It is also responsible for setting most of the global variables
304
 * (see loader.php for the initialization of the globals).
305
 */
306
function do_voodoo() {
307
	global $lock, $var, $player, $ship, $sector, $account, $db, $template;
308
309
	if (!defined('AJAX_CONTAINER')) {
310
		define('AJAX_CONTAINER', isset($var['AJAX']) && $var['AJAX'] === true);
311
	}
312
	if (!AJAX_CONTAINER && USING_AJAX && SmrSession::hasChangedSN()) {
313
		exit;
0 ignored issues
show
Best Practice introduced by
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
314
	}
315
//	ob_clean();
316
317
	// create account object
318
	$account = SmrSession::getAccount();
319
320
	if (!defined('DATE_DATE_SHORT')) {
321
		define('DATE_DATE_SHORT', $account->getShortDateFormat());
322
	}
323
	if (!defined('DATE_TIME_SHORT')) {
324
		define('DATE_TIME_SHORT', $account->getShortTimeFormat());
325
	}
326
	if (!defined('DATE_FULL_SHORT')) {
327
		define('DATE_FULL_SHORT', DATE_DATE_SHORT . ' ' . DATE_TIME_SHORT);
328
	}
329
	if (!defined('DATE_FULL_SHORT_SPLIT')) {
330
		define('DATE_FULL_SHORT_SPLIT', DATE_DATE_SHORT . '\<b\r /\>' . DATE_TIME_SHORT);
331
	}
332
333
	// initialize objects we usually need, like player, ship
334
	if (SmrSession::hasGame()) {
335
		if (SmrGame::getGame(SmrSession::getGameID())->hasEnded()) {
336
			Page::create('game_leave_processing.php', 'game_play.php', array('errorMsg' => 'The game has ended.'))->go();
337
		}
338
		// We need to acquire locks BEFORE getting the player information
339
		// Otherwise we could be working on stale information
340
		$db->query('SELECT sector_id FROM player WHERE account_id=' . $db->escapeNumber($account->getAccountID()) . ' AND game_id=' . $db->escapeNumber(SmrSession::getGameID()) . ' LIMIT 1');
341
		$db->requireRecord();
342
		$sector_id = $db->getInt('sector_id');
343
344
		global $locksFailed;
345
		if (!USING_AJAX //AJAX should never do anything that requires a lock.
346
//			&& !isset($var['url']) && ($var['body'] == 'current_sector.php' || $var['body'] == 'map_local.php') //Neither should CS or LM and they gets loaded a lot so should reduce lag issues with big groups.
347
			) {
348
			if (!$lock && !isset($locksFailed[$sector_id])) {
349
				if (!acquire_lock($sector_id)) {
350
					create_error('Failed to acquire sector lock');
351
				}
352
				//Refetch var info in case it changed between grabbing lock.
353
				SmrSession::fetchVarInfo();
354
				if (!($var = SmrSession::retrieveVar())) {
355
					if (ENABLE_DEBUG) {
356
						$db->query('INSERT INTO debug VALUES (\'SPAM\',' . $db->escapeNumber($account->getAccountID()) . ',0,0)');
357
					}
358
					create_error('Please do not spam click!');
359
				}
360
			}
361
		}
362
363
		// Now that they've acquire a lock we can move on
364
		$player = SmrPlayer::getPlayer($account->getAccountID(), SmrSession::getGameID());
365
366
		if ($player->isDead() && $var['url'] != 'death_processing.php' && !isset($var['override_death'])) {
367
			Page::create('death_processing.php')->go();
368
		}
369
370
		$ship = $player->getShip();
371
		$sector = $player->getSector();
372
373
		// update turns on that player
374
		$player->updateTurns();
375
376
		if (!$player->isDead() && $player->getNewbieTurns() <= NEWBIE_TURNS_WARNING_LIMIT &&
377
			$player->getNewbieWarning() &&
378
			$var['url'] != 'newbie_warning_processing.php')
379
			Page::create('newbie_warning_processing.php')->go();
380
	}
381
382
	// Initialize the template
383
	$template = new Template();
384
385
	if ($var['url'] != 'skeleton.php') {
386
		require(get_file_loc($var['url']));
387
	}
388
	if ($var['body']) {
389
		if ($var['body'] == 'error.php') { // infinite includes for error pages
390
			require(get_file_loc($var['body']));
391
		} else {
392
			require_once(get_file_loc($var['body']));
393
		}
394
	}
395
396
	if (SmrSession::hasGame()) {
397
		$template->assign('UnderAttack', $player->removeUnderAttack());
398
	}
399
400
	if ($lock) { //Only save if we have the lock.
401
		SmrSector::saveSectors();
402
		SmrShip::saveShips();
403
		SmrPlayer::savePlayers();
404
		SmrForce::saveForces();
405
		SmrPort::savePorts();
406
		SmrPlanet::savePlanets();
407
		if (class_exists('WeightedRandom', false)) {
408
			WeightedRandom::saveWeightedRandoms();
409
		}
410
		//Update session here to make sure current page $var is up to date before releasing lock.
411
		SmrSession::update();
412
		release_lock();
413
	}
414
415
	//Nothing below this point should require the lock.
416
417
	$template->assign('TemplateBody', $var['body']);
418
	if (SmrSession::hasGame()) {
419
		$template->assign('ThisSector', $sector);
420
		$template->assign('ThisPlayer', $player);
421
		$template->assign('ThisShip', $ship);
422
	}
423
	$template->assign('ThisAccount', $account);
424
	if ($account->getCssLink() != null) {
0 ignored issues
show
Bug introduced by
It seems like you are loosely comparing $account->getCssLink() of type null|string against null; this is ambiguous if the string can be empty. Consider using a strict comparison !== instead.
Loading history...
425
		$template->assign('ExtraCSSLink', $account->getCssLink());
426
	}
427
	doSkeletonAssigns($template, $player, $ship, $sector, $db, $account, $var);
428
429
	// Set ajax refresh time
430
	$ajaxRefresh = $var['AllowAjax'] ?? true; // hack for bar_gambling_processing.php
431
	if (!$account->isUseAJAX()) {
432
		$ajaxRefresh = false;
433
	}
434
	if ($ajaxRefresh) {
435
		// If we can refresh, specify the refresh interval in millisecs
436
		if (SmrSession::hasGame() && $player->canFight()) {
437
			$ajaxRefresh = AJAX_UNPROTECTED_REFRESH_TIME;
438
		} else {
439
			$ajaxRefresh = AJAX_DEFAULT_REFRESH_TIME;
440
		}
441
	}
442
	$template->assign('AJAX_ENABLE_REFRESH', $ajaxRefresh);
443
444
	$template->display($var['url'], USING_AJAX || AJAX_CONTAINER);
445
446
	SmrSession::update();
447
448
	exit;
0 ignored issues
show
Best Practice introduced by
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
449
}
450
451
//xdebug_dump_function_profile(2);
452
453
// This is hackish, but without row level locking it's the best we can do
454
function acquire_lock($sector) {
455
	global $db, $lock, $locksFailed;
456
457
	if ($lock) {
458
		return true;
459
	}
460
461
	// Insert ourselves into the queue.
462
	$db->query('INSERT INTO locks_queue (game_id,account_id,sector_id,timestamp) VALUES(' . $db->escapeNumber(SmrSession::getGameID()) . ',' . $db->escapeNumber(SmrSession::getAccountID()) . ',' . $db->escapeNumber($sector) . ',' . $db->escapeNumber(SmrSession::getTime()) . ')');
463
	$lock = $db->getInsertID();
464
465
	for ($i = 0; $i < 250; ++$i) {
466
		if (time() - SmrSession::getTime() >= LOCK_DURATION - LOCK_BUFFER) {
467
			break;
468
		}
469
		// If there is someone else before us in the queue we sleep for a while
470
		$db->query('SELECT COUNT(*) FROM locks_queue WHERE lock_id<' . $db->escapeNumber($lock) . ' AND sector_id=' . $db->escapeNumber($sector) . ' AND game_id=' . $db->escapeNumber(SmrSession::getGameID()) . ' AND timestamp > ' . $db->escapeNumber(SmrSession::getTime() - LOCK_DURATION));
471
		$locksInQueue = -1;
0 ignored issues
show
Unused Code introduced by
The assignment to $locksInQueue is dead and can be removed.
Loading history...
472
		if ($db->nextRecord() && ($locksInQueue = $db->getInt('COUNT(*)')) > 0) {
473
			//usleep(100000 + mt_rand(0,50000));
474
475
			// We can only have one lock in the queue, anything more means someone is screwing around
476
			$db->query('SELECT COUNT(*) FROM locks_queue WHERE account_id=' . $db->escapeNumber(SmrSession::getAccountID()) . ' AND sector_id=' . $db->escapeNumber($sector) . ' AND timestamp > ' . $db->escapeNumber(SmrSession::getTime() - LOCK_DURATION));
477
			if ($db->nextRecord() && $db->getInt('COUNT(*)') > 1) {
478
				release_lock();
479
				$locksFailed[$sector] = true;
480
				create_error('Multiple actions cannot be performed at the same time!');
481
			}
482
483
			usleep(25000 * $locksInQueue);
484
			continue;
485
		} else {
486
			return true;
487
		}
488
	}
489
490
	release_lock();
491
	$locksFailed[$sector] = true;
492
	return false;
493
}
494
495
function release_lock() {
496
	global $db, $lock;
497
	if ($lock) {
498
		$db->query('DELETE from locks_queue WHERE lock_id=' . $db->escapeNumber($lock) . ' OR timestamp<' . $db->escapeNumber(SmrSession::getTime() - LOCK_DURATION));
499
	}
500
501
	$lock = false;
502
}
503
504
function doTickerAssigns($template, $player, $db) {
505
	//any ticker news?
506
	if ($player->hasTickers()) {
507
		$ticker = array();
508
		$max = SmrSession::getTime() - 60;
509
		if ($player->hasTicker('NEWS')) {
510
			//get recent news (5 mins)
511
			$db->query('SELECT time,news_message FROM news WHERE game_id = ' . $db->escapeNumber($player->getGameID()) . ' AND time >= ' . $max . ' ORDER BY time DESC LIMIT 4');
512
			while ($db->nextRecord()) {
513
				$ticker[] = array('Time' => date(DATE_FULL_SHORT, $db->getInt('time')),
514
								'Message'=>$db->getField('news_message'));
515
			}
516
		}
517
		if ($player->hasTicker('SCOUT')) {
518
			$db->query('SELECT message_text,send_time FROM message
519
						WHERE account_id=' . $db->escapeNumber($player->getAccountID()) . '
520
						AND game_id=' . $db->escapeNumber($player->getGameID()) . '
521
						AND message_type_id=' . $db->escapeNumber(MSG_SCOUT) . '
522
						AND send_time>=' . $db->escapeNumber($max) . '
523
						AND sender_id NOT IN (SELECT account_id FROM player_has_ticker WHERE type='.$db->escapeString('BLOCK') . ' AND expires > ' . $db->escapeNumber(SmrSession::getTime()) . ' AND game_id = ' . $db->escapeNumber($player->getGameID()) . ') AND receiver_delete = \'FALSE\'
524
						ORDER BY send_time DESC
525
						LIMIT 4');
526
			while ($db->nextRecord()) {
527
				$ticker[] = array('Time' => date(DATE_FULL_SHORT, $db->getInt('send_time')),
528
								'Message'=>$db->getField('message_text'));
529
			}
530
		}
531
		$template->assign('Ticker', $ticker);
532
	}
533
}
534
535
function doSkeletonAssigns($template, $player, $ship, $sector, $db, $account, $var) {
0 ignored issues
show
Unused Code introduced by
The parameter $sector is not used and could be removed. ( Ignorable by Annotation )

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

535
function doSkeletonAssigns($template, $player, $ship, /** @scrutinizer ignore-unused */ $sector, $db, $account, $var) {

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
536
	$template->assign('CSSLink', $account->getCssUrl());
537
	$template->assign('CSSColourLink', $account->getCssColourUrl());
538
539
	$template->assign('FontSize', $account->getFontSize() - 20);
540
	$template->assign('timeDisplay', date(DATE_FULL_SHORT_SPLIT, SmrSession::getTime()));
541
542
	$container = Page::create('skeleton.php');
543
544
545
	if (SmrSession::hasGame()) {
546
		$template->assign('GameName', SmrGame::getGame(SmrSession::getGameID())->getName());
547
		$template->assign('GameID', SmrSession::getGameID());
548
549
		$template->assign('PlotCourseLink', Globals::getPlotCourseHREF());
550
551
		$template->assign('TraderLink', Globals::getTraderStatusHREF());
552
553
		$template->assign('PoliticsLink', Globals::getPoliticsHREF());
554
555
		$container['body'] = 'combat_log_list.php';
556
		$template->assign('CombatLogsLink', $container->href());
557
558
		$template->assign('PlanetLink', Globals::getPlanetListHREF($player->getAllianceID()));
559
560
		$container['body'] = 'forces_list.php';
561
		$template->assign('ForcesLink', $container->href());
562
563
		$template->assign('MessagesLink', Globals::getViewMessageBoxesHREF());
564
565
		$container['body'] = 'news_read_current.php';
566
		$template->assign('ReadNewsLink', $container->href());
567
568
		$container['body'] = 'galactic_post_current.php';
569
		$template->assign('GalacticPostLink', $container->href());
570
571
		$container['body'] = 'trader_search.php';
572
		$template->assign('SearchForTraderLink', $container->href());
573
574
		$container['body'] = 'rankings_player_experience.php';
575
		$template->assign('RankingsLink', $container->href());
576
577
		$container['body'] = 'hall_of_fame_new.php';
578
		$container['game_id'] = $player->getGameID();
579
		$template->assign('CurrentHallOfFameLink', $container->href());
580
	}
581
582
	if (SmrSession::hasAccount()) {
583
		$container = Page::create('skeleton.php', 'hall_of_fame_new.php');
584
		$template->assign('HallOfFameLink', $container->href());
585
586
		$template->assign('AccountID', SmrSession::getAccountID());
587
		$template->assign('PlayGameLink', Page::create('game_leave_processing.php', 'game_play.php')->href());
588
589
		$template->assign('LogoutLink', Page::create('logoff.php')->href());
590
	}
591
592
	$container = Page::create('game_leave_processing.php', 'admin_tools.php');
593
	$template->assign('AdminToolsLink', $container->href());
594
595
	$container = Page::create('skeleton.php', 'preferences.php');
596
	$template->assign('PreferencesLink', $container->href());
597
598
	$container['body'] = 'album_edit.php';
599
	$template->assign('EditPhotoLink', $container->href());
600
601
	$container['body'] = 'bug_report.php';
602
	$template->assign('ReportABugLink', $container->href());
603
604
	$container['body'] = 'contact.php';
605
	$template->assign('ContactFormLink', $container->href());
606
607
	$container['body'] = 'chat_rules.php';
608
	$template->assign('IRCLink', $container->href());
609
610
	$container['body'] = 'donation.php';
611
	$template->assign('DonateLink', $container->href());
612
613
614
615
	if (SmrSession::hasGame()) {
616
		$db->query('SELECT message_type_id,COUNT(*) FROM player_has_unread_messages WHERE ' . $player->getSQL() . ' GROUP BY message_type_id');
617
618
		if ($db->getNumRows()) {
619
			$messages = array();
620
			while ($db->nextRecord()) {
621
				$messages[$db->getInt('message_type_id')] = $db->getInt('COUNT(*)');
622
			}
623
624
			$container = Page::create('skeleton.php', 'message_view.php');
625
626
			if (isset($messages[MSG_GLOBAL])) {
627
				$container['folder_id'] = MSG_GLOBAL;
628
				$template->assign('MessageGlobalLink', $container->href());
629
				$template->assign('MessageGlobalNum', $messages[MSG_GLOBAL]);
630
			}
631
632
			if (isset($messages[MSG_PLAYER])) {
633
				$container['folder_id'] = MSG_PLAYER;
634
				$template->assign('MessagePersonalLink', $container->href());
635
				$template->assign('MessagePersonalNum', $messages[MSG_PLAYER]);
636
			}
637
638
			if (isset($messages[MSG_SCOUT])) {
639
				$container['folder_id'] = MSG_SCOUT;
640
				$template->assign('MessageScoutLink', $container->href());
641
				$template->assign('MessageScoutNum', $messages[MSG_SCOUT]);
642
			}
643
644
			if (isset($messages[MSG_POLITICAL])) {
645
				$container['folder_id'] = MSG_POLITICAL;
646
				$template->assign('MessagePoliticalLink', $container->href());
647
				$template->assign('MessagePoliticalNum', $messages[MSG_POLITICAL]);
648
			}
649
650
			if (isset($messages[MSG_ALLIANCE])) {
651
				$container['folder_id'] = MSG_ALLIANCE;
652
				$template->assign('MessageAllianceLink', $container->href());
653
				$template->assign('MessageAllianceNum', $messages[MSG_ALLIANCE]);
654
			}
655
656
			if (isset($messages[MSG_ADMIN])) {
657
				$container['folder_id'] = MSG_ADMIN;
658
				$template->assign('MessageAdminLink', $container->href());
659
				$template->assign('MessageAdminNum', $messages[MSG_ADMIN]);
660
			}
661
662
			if (isset($messages[MSG_CASINO])) {
663
				$container['folder_id'] = MSG_CASINO;
664
				$template->assign('MessageCasinoLink', $container->href());
665
				$template->assign('MessageCasinoNum', $messages[MSG_CASINO]);
666
			}
667
668
			if (isset($messages[MSG_PLANET])) {
669
				$container = Page::create('planet_msg_processing.php');
670
				$template->assign('MessagePlanetLink', $container->href());
671
				$template->assign('MessagePlanetNum', $messages[MSG_PLANET]);
672
			}
673
		}
674
675
		$container = Page::create('skeleton.php', 'trader_search_result.php');
676
		$container['player_id'] = $player->getPlayerID();
677
		$template->assign('PlayerNameLink', $container->href());
678
679
		if (is_array(Globals::getHiddenPlayers()) && in_array($player->getAccountID(), Globals::getHiddenPlayers())) {
680
			$template->assign('PlayerInvisible', true);
681
		}
682
683
		// ******* Hardware *******
684
		$container = Page::create('skeleton.php', 'configure_hardware.php');
685
686
		$template->assign('HardwareLink', $container->href());
687
688
		// ******* Forces *******
689
		$template->assign('ForceDropLink', Page::create('skeleton.php', 'forces_drop.php')->href());
690
691
		if ($ship->hasMines()) {
692
			$container = Page::create('forces_drop_processing.php');
693
			$container['owner_id'] = $player->getAccountID();
694
			$container['drop_mines'] = 1;
695
			$container['referrer'] = $var['body'];
696
			$template->assign('DropMineLink', $container->href());
697
		}
698
		if ($ship->hasCDs()) {
699
			$container = Page::create('forces_drop_processing.php');
700
			$container['owner_id'] = $player->getAccountID();
701
			$container['drop_combat_drones'] = 1;
702
			$container['referrer'] = $var['body'];
703
			$template->assign('DropCDLink', $container->href());
704
		}
705
706
		if ($ship->hasSDs()) {
707
			$container = Page::create('forces_drop_processing.php');
708
			$container['owner_id'] = $player->getAccountID();
709
			$container['drop_scout_drones'] = 1;
710
			$container['referrer'] = $var['body'];
711
			$template->assign('DropSDLink', $container->href());
712
		}
713
714
		$template->assign('CargoJettisonLink', Page::create('skeleton.php', 'cargo_dump.php')->href());
715
716
		$template->assign('WeaponReorderLink', Page::create('skeleton.php', 'weapon_reorder.php')->href());
717
718
	}
719
720
	// ------- VOTING --------
721
	$voteSites = array();
722
	foreach (VoteSite::getAllSites() as $site) {
723
		$voteSites[] = array(
724
			'img' => $site->getLinkImg($account->getAccountID(), SmrSession::getGameID()),
725
			'url' => $site->getLinkUrl($account->getAccountID(), SmrSession::getGameID()),
726
			'sn' => $site->getSN($account->getAccountID(), SmrSession::getGameID()),
727
		);
728
	}
729
	$template->assign('VoteSites', $voteSites);
730
731
	// Determine the minimum time until the next vote across all sites
732
	$minVoteWait = VoteSite::getMinTimeUntilFreeTurns($account->getAccountID());
733
	if ($minVoteWait <= 0) {
734
		$template->assign('TimeToNextVote', 'now');
735
	} else {
736
		$template->assign('TimeToNextVote', 'in ' . format_time($minVoteWait, true));
737
	}
738
739
	// ------- VERSION --------
740
	$db->query('SELECT * FROM version ORDER BY went_live DESC LIMIT 1');
741
	$version = '';
742
	if ($db->nextRecord()) {
743
		$container = Page::create('skeleton.php', 'changelog_view.php');
744
		$version = create_link($container, 'v' . $db->getField('major_version') . '.' . $db->getField('minor_version') . '.' . $db->getField('patch_level'));
745
	}
746
747
	$template->assign('Version', $version);
748
	$template->assign('CurrentYear', date('Y', SmrSession::getTime()));
749
}
750
751
/**
752
 * Convert an integer number of seconds into a human-readable time.
753
 * Seconds are omitted to avoid frequent and disruptive ajax updates.
754
 * Use short=true to use 1-letter units (e.g. "1h and 3m").
755
 * If seconds is negative, will append "ago" to the result.
756
 * If seconds is zero, will return only "now".
757
 * If seconds is <60, will prefix "less than" or "<" (HTML-safe).
758
 */
759
function format_time($seconds, $short = false) {
760
	if ($seconds == 0) {
761
		return "now";
762
	}
763
764
	if ($seconds < 0) {
765
		$past = true;
766
		$seconds = abs($seconds);
767
	} else {
768
		$past = false;
769
	}
770
771
	$minutes = ceil($seconds / 60);
772
	$hours = 0;
773
	$days = 0;
774
	$weeks = 0;
775
	if ($minutes >= 60) {
776
		$hours = floor($minutes / 60);
777
		$minutes = $minutes % 60;
778
	}
779
	if ($hours >= 24) {
780
		$days = floor($hours / 24);
781
		$hours = $hours % 24;
782
	}
783
	if ($days >= 7) {
784
		$weeks = floor($days / 7);
785
		$days = $days % 7;
786
	}
787
	$times = [
788
		'week' => $weeks,
789
		'day' => $days,
790
		'hour' => $hours,
791
		'minute' => $minutes,
792
	];
793
	$parts = [];
794
	foreach ($times as $unit => $amount) {
795
		if ($amount > 0) {
796
			if ($short) {
797
				$parts[] = $amount . $unit[0];
798
			} else {
799
				$parts[] = $amount . ' ' . pluralise($unit, $amount);
800
			}
801
		}
802
	}
803
804
	if (count($parts) == 1) {
805
		$result = $parts[0];
806
	} else {
807
		// e.g. 5h, 10m and 30s
808
		$result = join(', ', array_slice($parts, 0, -1)) . ' and ' . end($parts);
809
	}
810
811
	if ($seconds < 60) {
812
		$result = ($short ? '&lt;' : 'less than ') . $result;
813
	}
814
815
	if ($past) {
816
		$result .= ' ago';
817
	}
818
	return $result;
819
}
820
821
function number_colour_format($number, $justSign = false) {
822
	$formatted = '<span';
823
	if ($number > 0) {
824
		$formatted .= ' class="green">+';
825
	} else if ($number < 0) {
826
		$formatted .= ' class="red">-';
827
	} else {
828
		$formatted .= '>';
829
	}
830
	if ($justSign === false) {
831
		$decimalPlaces = 0;
832
		if (($pos = strpos((string)$number, '.')) !== false) {
833
			$decimalPlaces = strlen(substr((string)$number, $pos + 1));
834
		}
835
		$formatted .= number_format(abs($number), $decimalPlaces);
836
	}
837
	$formatted .= '</span>';
838
	return $formatted;
839
}
840
841
842
/**
843
 * Randomly choose an array key weighted by the array values.
844
 * Probabilities are relative to the total weight. For example:
845
 *
846
 * array(
847
 *    'A' => 1, // 10% chance
848
 *    'B' => 3, // 30% chance
849
 *    'C' => 6, // 60% chance
850
 * );
851
 */
852
function getWeightedRandom(array $choices) : string|int {
853
	// Normalize the weights so that their sum is much larger than 1.
854
	$maxWeight = max($choices);
855
	foreach ($choices as $key => $weight) {
856
		$choices[$key] = IRound($weight * 1000 / $maxWeight);
857
	}
858
859
	// Generate a random number that is lower than the sum of the weights.
860
	$rand = rand(1, array_sum($choices));
0 ignored issues
show
Bug introduced by
It seems like array_sum($choices) can also be of type double; however, parameter $max of rand() does only seem to accept integer, maybe add an additional type check? ( Ignorable by Annotation )

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

860
	$rand = rand(1, /** @scrutinizer ignore-type */ array_sum($choices));
Loading history...
861
862
	// Subtract weights from the random number until it is negative,
863
	// then return the key associated with that weight.
864
	foreach ($choices as $key => $weight) {
865
		$rand -= $weight;
866
		if ($rand <= 0) {
867
			return $key;
868
		}
869
	}
870
	throw new Exception('Internal error computing weights');
871
}
872