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 ( 2bbb94...dae5f6 )
by Dan
04:55 queued 11s
created

forwardURL()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 3
dl 0
loc 4
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 1
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 = create_container('combat_log_viewer_verify.php');
19
	$container['log_id'] = $logID;
20
	return '<a href="' . SmrSession::getNewHREF($container) . '"><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 = create_container('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 = create_container('alliance_invite_accept_processing.php');
130
				$container['alliance_id'] = $alliance->getAllianceID();
131
				return '<div class="buttonA"><a class="buttonA" href="' . SmrSession::getNewHREF($container) . '">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 = create_container('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 = SmrSession::getNewHREF($container);
204
			// json_encode the HREF as a safety precaution
205
			$template->addJavascriptForAjax('EVAL', 'location.href = ' . json_encode($errorHREF));
206
		}
207
	}
208
	forward($container);
209
}
210
211
function resetContainer($new_container, $sn = null) {
212
	global $container, $var;
213
214
	// this sn identifies our container later
215
	if (!is_null($sn)) {
216
		SmrSession::resetLink($new_container, $sn);
217
	}
218
219
	$var = $new_container;
220
	$container = $new_container;
221
}
222
223
function forward($new_container) {
224
	global $sn;
225
	if (defined('OVERRIDE_FORWARD') && OVERRIDE_FORWARD === true) {
226
		return overrideForward($new_container);
227
	}
228
	resetContainer($new_container, $sn);
229
	do_voodoo();
230
}
231
232
function transfer($what) {
233
	global $var, $container;
234
235
	// transfer this value to next container
236
	if (isset($var[$what])) {
237
		$container[$what] = $var[$what];
238
	}
239
}
240
241
function create_container($file, $body = '', array $extra = array(), $remainingPageLoads = null) {
242
	$container = $extra;
243
	$container['url'] = $file;
244
	$container['body'] = $body;
245
	if ($remainingPageLoads) {
246
		$container['RemainingPageLoads'] = $remainingPageLoads;
247
	}
248
	return $container;
249
}
250
251
function create_link($container, $text, $class = null) {
252
	return '<a' . ($class == null ? '' : ' class="' . $class . '"') . ' href="' . (is_array($container) ?SmrSession::getNewHREF($container) : $container) . '">' . $text . '</a>';
253
}
254
255
function create_submit_link($container, $text) {
256
	return '<a href="' . SmrSession::getNewHREF($container) . '" class="submitStyle">' . $text . '</a>';
257
}
258
259
function get_colored_text_range($value, $maxValue, $text = null, $minValue = 0, $type = 'Game', $return_type = 'Normal') {
260
	if ($text == null) {
261
		$text = number_format($value);
262
	}
263
	if ($maxValue - $minValue == 0) {
264
		return $text;
265
	} else {
266
		$normalisedValue = IRound(510 * max(0, min($maxValue, $value) - $minValue) / ($maxValue - $minValue)) - 255;
267
	}
268
	if ($type == 'Game') {
269
		if ($normalisedValue < 0) {
270
			$r_component = 'ff';
271
			$g_component = dechex(255 + $normalisedValue);
272
			if (strlen($g_component) == 1) {
273
				$g_component = '0' . $g_component;
274
			}
275
		} else if ($normalisedValue > 0) {
276
			$g_component = 'ff';
277
			$r_component = dechex(255 - $normalisedValue);
278
			if (strlen($r_component) == 1) {
279
				$r_component = '0' . $r_component;
280
			}
281
		} else {
282
			$r_component = 'ff';
283
			$g_component = 'ff';
284
		}
285
		$colour = $r_component . $g_component . '00';
286
		if ($return_type == 'Colour') {
287
			return $colour;
288
		}
289
		return '<span style="color:#' . $colour . '">' . $text . '</span>';
290
	} elseif ($type == 'IRC') {
291
		//IRC color codes
292
		if ($normalisedValue == 255) {
293
			$colour = '[k03]';
294
		} elseif ($normalisedValue == -255) {
295
			$colour = '[k04]';
296
		} else {
297
			$colour = '[k08]';
298
		}
299
		if ($return_type == 'Colour') {
300
			return $colour;
301
		}
302
		return $colour . $text;
303
	}
304
}
305
306
function get_colored_text($value, $text = null, $type = 'Game', $return_type = 'Normal') {
307
	return get_colored_text_range($value, 300, $text, -300, $type, $return_type);
308
}
309
310
function word_filter($string) {
311
	static $words;
312
313
	if (!is_array($words)) {
314
		$db = MySqlDatabase::getInstance();
315
		$db->query('SELECT word_value, word_replacement FROM word_filter');
316
		$words = array();
317
		while ($db->nextRecord()) {
318
			$row = $db->getRow();
319
			$words[] = array('word_value' => '/' . str_replace('/', '\/', $row['word_value']) . '/i', 'word_replacement'=> $row['word_replacement']);
320
		}
321
	}
322
323
	foreach ($words as $word) {
324
		$string = preg_replace($word['word_value'], $word['word_replacement'], $string);
325
	}
326
327
	return $string;
328
}
329
330
// choose correct pluralization based on amount
331
function pluralise($word, $count = 0) {
332
	if ($count == 1) {
333
		return $word;
334
	}
335
	if (strtolower($word) == 'is') {
336
		return 'are';
337
	}
338
	return $word . 's';
339
}
340
341
/**
342
 * This function is a hack around the old style http forward mechanism.
343
 * It is also responsible for setting most of the global variables
344
 * (see loader.php for the initialization of the globals).
345
 */
346
function do_voodoo() {
347
	global $lock, $var, $container, $player, $ship, $sector, $account, $db, $template;
348
349
	if (!defined('AJAX_CONTAINER')) {
350
		define('AJAX_CONTAINER', isset($var['AJAX']) && $var['AJAX'] === true);
351
	}
352
	if (!AJAX_CONTAINER && USING_AJAX && SmrSession::hasChangedSN()) {
353
		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...
354
	}
355
//	ob_clean();
356
357
	// create account object
358
	$account = SmrSession::getAccount();
359
360
	if (!defined('DATE_DATE_SHORT')) {
361
		define('DATE_DATE_SHORT', $account->getShortDateFormat());
362
	}
363
	if (!defined('DATE_TIME_SHORT')) {
364
		define('DATE_TIME_SHORT', $account->getShortTimeFormat());
365
	}
366
	if (!defined('DATE_FULL_SHORT')) {
367
		define('DATE_FULL_SHORT', DATE_DATE_SHORT . ' ' . DATE_TIME_SHORT);
368
	}
369
	if (!defined('DATE_FULL_SHORT_SPLIT')) {
370
		define('DATE_FULL_SHORT_SPLIT', DATE_DATE_SHORT . '\<b\r /\>' . DATE_TIME_SHORT);
371
	}
372
373
	// initialize objects we usually need, like player, ship
374
	if (SmrSession::hasGame()) {
375
		if (SmrGame::getGame(SmrSession::getGameID())->hasEnded()) {
376
			forward(create_container('game_leave_processing.php', 'game_play.php', array('errorMsg' => 'The game has ended.')));
377
		}
378
		// We need to acquire locks BEFORE getting the player information
379
		// Otherwise we could be working on stale information
380
		$db->query('SELECT sector_id FROM player WHERE account_id=' . $db->escapeNumber($account->getAccountID()) . ' AND game_id=' . $db->escapeNumber(SmrSession::getGameID()) . ' LIMIT 1');
381
		$db->requireRecord();
382
		$sector_id = $db->getInt('sector_id');
383
384
		global $locksFailed;
385
		if (!USING_AJAX //AJAX should never do anything that requires a lock.
386
//			&& !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.
387
			) {
388
			if (!$lock && !isset($locksFailed[$sector_id])) {
389
				if (!acquire_lock($sector_id)) {
390
					create_error('Failed to acquire sector lock');
391
				}
392
				//Refetch var info in case it changed between grabbing lock.
393
				SmrSession::fetchVarInfo();
394
				if (!($var = SmrSession::retrieveVar())) {
395
					if (ENABLE_DEBUG) {
396
						$db->query('INSERT INTO debug VALUES (\'SPAM\',' . $db->escapeNumber($account->getAccountID()) . ',0,0)');
397
					}
398
					create_error('Please do not spam click!');
399
				}
400
			}
401
		}
402
403
		// Now that they've acquire a lock we can move on
404
		$player = SmrPlayer::getPlayer($account->getAccountID(), SmrSession::getGameID());
405
406
		if ($player->isDead() && $var['url'] != 'death_processing.php' && !isset($var['override_death'])) {
407
			forward(create_container('death_processing.php'));
408
		}
409
410
		$ship = $player->getShip();
411
		$sector = $player->getSector();
412
413
		// update turns on that player
414
		$player->updateTurns();
415
416
		if (!$player->isDead() && $player->getNewbieTurns() <= NEWBIE_TURNS_WARNING_LIMIT &&
417
			$player->getNewbieWarning() &&
418
			$var['url'] != 'newbie_warning_processing.php')
419
			forward(create_container('newbie_warning_processing.php'));
420
	}
421
422
	// Initialize the template
423
	$template = new Template();
424
425
	if ($var['url'] != 'skeleton.php') {
426
		require(get_file_loc($var['url']));
427
	}
428
	if ($var['body']) {
429
		if ($var['body'] == 'error.php') { // infinite includes for error pages
430
			require(get_file_loc($var['body']));
431
		} else {
432
			require_once(get_file_loc($var['body']));
433
		}
434
	}
435
436
	if (SmrSession::hasGame()) {
437
		$template->assign('UnderAttack', $player->removeUnderAttack());
438
	}
439
440
	if ($lock) { //Only save if we have the lock.
441
		SmrSector::saveSectors();
442
		SmrShip::saveShips();
443
		SmrPlayer::savePlayers();
444
		SmrForce::saveForces();
445
		SmrPort::savePorts();
446
		SmrPlanet::savePlanets();
447
		if (class_exists('WeightedRandom', false)) {
448
			WeightedRandom::saveWeightedRandoms();
449
		}
450
		//Update session here to make sure current page $var is up to date before releasing lock.
451
		SmrSession::update();
452
		release_lock();
453
	}
454
455
	//Nothing below this point should require the lock.
456
457
	$template->assign('TemplateBody', $var['body']);
458
	if (SmrSession::hasGame()) {
459
		$template->assign('ThisSector', $sector);
460
		$template->assign('ThisPlayer', $player);
461
		$template->assign('ThisShip', $ship);
462
	}
463
	$template->assign('ThisAccount', $account);
464
	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...
465
		$template->assign('ExtraCSSLink', $account->getCssLink());
466
	}
467
	doSkeletonAssigns($template, $player, $ship, $sector, $db, $account, $var);
468
469
	// Set ajax refresh time
470
	$ajaxRefresh = $var['AllowAjax'] ?? true; // hack for bar_gambling_processing.php
471
	if (!$account->isUseAJAX()) {
472
		$ajaxRefresh = false;
473
	}
474
	if ($ajaxRefresh) {
475
		// If we can refresh, specify the refresh interval in millisecs
476
		if (SmrSession::hasGame() && $player->canFight()) {
477
			$ajaxRefresh = AJAX_UNPROTECTED_REFRESH_TIME;
478
		} else {
479
			$ajaxRefresh = AJAX_DEFAULT_REFRESH_TIME;
480
		}
481
	}
482
	$template->assign('AJAX_ENABLE_REFRESH', $ajaxRefresh);
483
484
	$template->display($var['url'], USING_AJAX || AJAX_CONTAINER);
485
486
	SmrSession::update();
487
488
	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...
489
}
490
491
//xdebug_dump_function_profile(2);
492
493
// This is hackish, but without row level locking it's the best we can do
494
function acquire_lock($sector) {
495
	global $db, $lock, $locksFailed;
496
497
	if ($lock) {
498
		return true;
499
	}
500
501
	// Insert ourselves into the queue.
502
	$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()) . ')');
503
	$lock = $db->getInsertID();
504
505
	for ($i = 0; $i < 250; ++$i) {
506
		if (time() - SmrSession::getTime() >= LOCK_DURATION - LOCK_BUFFER) {
507
			break;
508
		}
509
		// If there is someone else before us in the queue we sleep for a while
510
		$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));
511
		$locksInQueue = -1;
0 ignored issues
show
Unused Code introduced by
The assignment to $locksInQueue is dead and can be removed.
Loading history...
512
		if ($db->nextRecord() && ($locksInQueue = $db->getInt('COUNT(*)')) > 0) {
513
			//usleep(100000 + mt_rand(0,50000));
514
515
			// We can only have one lock in the queue, anything more means someone is screwing around
516
			$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));
517
			if ($db->nextRecord() && $db->getInt('COUNT(*)') > 1) {
518
				release_lock();
519
				$locksFailed[$sector] = true;
520
				create_error('Multiple actions cannot be performed at the same time!');
521
			}
522
523
			usleep(25000 * $locksInQueue);
524
			continue;
525
		} else {
526
			return true;
527
		}
528
	}
529
530
	release_lock();
531
	$locksFailed[$sector] = true;
532
	return false;
533
}
534
535
function release_lock() {
536
	global $db, $lock;
537
	if ($lock) {
538
		$db->query('DELETE from locks_queue WHERE lock_id=' . $db->escapeNumber($lock) . ' OR timestamp<' . $db->escapeNumber(SmrSession::getTime() - LOCK_DURATION));
539
	}
540
541
	$lock = false;
542
}
543
544
function doTickerAssigns($template, $player, $db) {
545
	//any ticker news?
546
	if ($player->hasTickers()) {
547
		$ticker = array();
548
		$max = SmrSession::getTime() - 60;
549
		if ($player->hasTicker('NEWS')) {
550
			//get recent news (5 mins)
551
			$db->query('SELECT time,news_message FROM news WHERE game_id = ' . $db->escapeNumber($player->getGameID()) . ' AND time >= ' . $max . ' ORDER BY time DESC LIMIT 4');
552
			while ($db->nextRecord()) {
553
				$ticker[] = array('Time' => date(DATE_FULL_SHORT, $db->getInt('time')),
554
								'Message'=>$db->getField('news_message'));
555
			}
556
		}
557
		if ($player->hasTicker('SCOUT')) {
558
			$db->query('SELECT message_text,send_time FROM message
559
						WHERE account_id=' . $db->escapeNumber($player->getAccountID()) . '
560
						AND game_id=' . $db->escapeNumber($player->getGameID()) . '
561
						AND message_type_id=' . $db->escapeNumber(MSG_SCOUT) . '
562
						AND send_time>=' . $db->escapeNumber($max) . '
563
						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\'
564
						ORDER BY send_time DESC
565
						LIMIT 4');
566
			while ($db->nextRecord()) {
567
				$ticker[] = array('Time' => date(DATE_FULL_SHORT, $db->getInt('send_time')),
568
								'Message'=>$db->getField('message_text'));
569
			}
570
		}
571
		$template->assign('Ticker', $ticker);
572
	}
573
}
574
575
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

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

900
	$rand = rand(1, /** @scrutinizer ignore-type */ array_sum($choices));
Loading history...
901
902
	// Subtract weights from the random number until it is negative,
903
	// then return the key associated with that weight.
904
	foreach ($choices as $key => $weight) {
905
		$rand -= $weight;
906
		if ($rand <= 0) {
907
			return $key;
908
		}
909
	}
910
	throw new Exception('Internal error computing weights');
911
}
912