Completed
Push — work-fleets ( 33857b...22a48f )
by SuperNova.WS
05:55
created

general.php ➔ isInGroup()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 3
c 1
b 0
f 0
nc 1
nop 2
dl 0
loc 4
rs 10
1
<?php
2
3
/*
4
Function wrapping
5
6
Due glitch in PHP 5.3.1 SuperNova is incompatible with this version
7
Reference: https://bugs.php.net/bug.php?id=50394
8
9
*/
10
11
require_once('general/math.php');
12
require_once('general_pname.php');
13
14
/**
15
 * @param       $func_name
16
 * @param array $func_arg
17
 *
18
 * @return mixed
19
 */
20
function sn_function_call($func_name, $func_arg = array()) {
21
  // All data in classSupernova::$functions should be normalized to valid 'callable' state: '<function_name>'|array('<object_name>', '<method_name>')
22
  $result = null;
23
24
  if (is_array(classSupernova::$functions[$func_name]) && !is_callable(classSupernova::$functions[$func_name])) {
25
    // Chain-callable functions should be made as following:
26
    // 1. Never use incomplete calls with parameters "by default"
27
    // 2. Reserve last parameter for cumulative result
28
    // 3. Use same format for original value and cumulative result (if there is original value)
29
    // 4. Honor cumulative result
30
    // 5. Return cumulative result
31
    foreach (classSupernova::$functions[$func_name] as $func_chain_name) {
32
      // По идее - это уже тут не нужно, потому что оно все должно быть callable к этому моменту
33
      // Но для старых модулей...
34
      if (is_callable($func_chain_name)) {
35
        $result = call_user_func_array($func_chain_name, $func_arg);
36
      }
37
    }
38
  } else {
39
    // TODO: This is left for backward compatibility. Appropriate code should be rewrote!
40
    $func_name = isset(classSupernova::$functions[$func_name]) && is_callable(classSupernova::$functions[$func_name]) ? classSupernova::$functions[$func_name] : ('sn_' . $func_name);
41
    if (is_callable($func_name)) {
42
      $result = call_user_func_array($func_name, $func_arg);
43
    }
44
  }
45
46
  return $result;
47
}
48
49
/**
50
 * @param        $hook_list
51
 * @param        $template
52
 * @param string $hook_type - тип хука 'model' или 'view'
53
 * @param string $page_name - имя страницы, для которого должен был быть выполнен хук
54
 */
55
function execute_hooks(&$hook_list, &$template, $hook_type = null, $page_name = null) {
56
  if (!empty($hook_list)) {
57
    foreach ($hook_list as $hook) {
58
      if (is_callable($hook_call = (is_string($hook) ? $hook : (is_array($hook) ? $hook['callable'] : $hook->callable)))) {
59
        $template = call_user_func($hook_call, $template, $hook_type, $page_name);
60
      }
61
    }
62
  }
63
}
64
65
// ----------------------------------------------------------------------------------------------------------------
66
function sys_file_read($filename) {
67
  return @file_get_contents($filename);
68
}
69
70
function sys_file_write($filename, $content) {
71
  return @file_put_contents($filename, $content, FILE_APPEND);
72
}
73
74
function get_game_speed($plain = false) { return sn_function_call(__FUNCTION__, array($plain, &$result)); }
75
76
function sn_get_game_speed($plain = false, &$result) {
0 ignored issues
show
Unused Code introduced by
The parameter $plain is not used and could be removed.

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

Loading history...
77
  return $result = classSupernova::$config->game_speed ? classSupernova::$config->game_speed : 1;
78
}
79
80
function flt_server_flight_speed_multiplier($plain = false) { return sn_function_call(__FUNCTION__, array($plain, &$result)); }
81
82
function sn_flt_server_flight_speed_multiplier($plain = false, &$result) {
0 ignored issues
show
Unused Code introduced by
The parameter $plain is not used and could be removed.

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

Loading history...
83
  return $result = classSupernova::$config->fleet_speed;
84
}
85
86
function game_resource_multiplier($plain = false) { return sn_function_call(__FUNCTION__, array($plain, &$result)); }
87
88
function sn_game_resource_multiplier($plain = false, &$result) {
0 ignored issues
show
Unused Code introduced by
The parameter $plain is not used and could be removed.

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

Loading history...
89
  return $result = classSupernova::$config->resource_multiplier;
90
}
91
92
/**
93
 * Получение стоимости ММ в валюте сервера
94
 *
95
 * @param bool|false $plain
96
 *
97
 * @return mixed
98
 */
99
function get_mm_cost($plain = false) { return sn_function_call(__FUNCTION__, array($plain, &$result)); }
100
101
function sn_get_mm_cost($plain = false, &$result) {
0 ignored issues
show
Unused Code introduced by
The parameter $plain is not used and could be removed.

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

Loading history...
102
  return $result = classSupernova::$config->payment_currency_exchange_mm_ ? classSupernova::$config->payment_currency_exchange_mm_ : METAMATTER_DEFAULT_LOT_SIZE;
103
}
104
105
/**
106
 * Получение курса обмены валюты в серверную валюту
107
 *
108
 * @param $currency_symbol
109
 *
110
 * @return float
111
 */
112
function get_exchange_rate($currency_symbol) {
113
  $currency_symbol = strtolower($currency_symbol);
114
  $config_field = 'payment_currency_exchange_' . $currency_symbol;
115
116
  // Заворачиваем получение стоимости ММ через перекрываемую процедуру
117
  $exchange_rate = floatval($currency_symbol == 'mm_' ? get_mm_cost() : classSupernova::$config->$config_field);
118
119
  return $exchange_rate;
120
}
121
122
/**
123
 * pretty_number implementation for SuperNova
124
 *
125
 * $n - number to format
126
 * $floor: (ignored if $limit set)
127
 * integer   - floors to $floor numbers after decimal points
128
 * true      - floors number before format
129
 * otherwise - floors to 2 numbers after decimal points
130
 * $color:
131
 * true    - colors number to green if positive or zero; red if negative
132
 * 0
133
 * numeric - colors number to green if less then $color; red if greater
134
 * $limit:
135
 * 0/false - proceed with $floor
136
 * numeric - divides number to segments by power of $limit and adds 'k' for each segment
137
 * makes sense for 1000, but works with any number
138
 * generally converts "15000" to "15k", "2000000" to "2kk" etc
139
 * $style
140
 * null  - standard result
141
 * true  - return only style class for current params
142
 * false - return array('text' => $ret, 'class' => $class), where $ret - unstyled
143
 */
144
145
/**
146
 * @param float     $n
147
 * @param int|bool  $floor
148
 * @param int|bool  $color
149
 * @param int|bool  $limit
150
 * @param bool|null $style
151
 *
152
 * @return array|float|string
153
 */
154
function pretty_number($n, $floor = true, $color = false, $limit = false, $style = null) {
155
  $n = floatval($n);
156
  if (is_int($floor)) {
157
    $n = round($n, $floor); // , PHP_ROUND_HALF_DOWN
158
  } elseif ($floor === true) {
159
    $n = floor($n);
160
    $floor = 0;
161
  } else {
162
    $floor = 2;
163
  }
164
165
  $ret = $n;
166
167
  $suffix = '';
168
  if ($limit) {
169
    if ($ret > 0) {
170
      while ($ret > $limit) {
171
        $suffix .= 'k';
172
        $ret = round($ret / 1000);
173
      }
174
    } else {
175
      while ($ret < -$limit) {
176
        $suffix .= 'k';
177
        $ret = round($ret / 1000);
178
      }
179
    }
180
  }
181
182
  $ret = number_format($ret, $floor, ',', '.');
183
  $ret .= $suffix;
184
185
  if ($color !== false) {
186
    if ($color === true) {
187
      $class = $n == 0 ? 'zero' : ($n > 0 ? 'positive' : 'negative');
188
    } elseif ($color >= 0) {
189
      $class = $n == $color ? 'zero' : ($n < $color ? 'positive' : 'negative');
190
    } else {
191
      $class = ($n == -$color) ? 'zero' : ($n < -$color ? 'negative' : 'positive');
192
    }
193
194
    if (!isset($style)) {
195
      $ret = "<span class='{$class}'>{$ret}</span>";
196
    } else {
197
      $ret = $style ? $ret = $class : $ret = array('text' => $ret, 'class' => $class);
198
    }
199
  }
200
201
  return $ret;
202
}
203
204
// ----------------------------------------------------------------------------------------------------------------
205
function pretty_time($seconds) {
206
  $day = floor($seconds / (24 * 3600));
207
208
  $sys_day_short = classLocale::$lang['sys_day_short'];
209
210
  return sprintf("%s%02d:%02d:%02d", $day ? "{$day}{$sys_day_short} " : '', floor($seconds / 3600 % 24), floor($seconds / 60 % 60), floor($seconds / 1 % 60));
211
}
212
213
// ----------------------------------------------------------------------------------------------------------------
214
function eco_planet_fields_max($planet) {
215
  return $planet['field_max'] + ($planet['planet_type'] == PT_PLANET ? mrc_get_level($user, $planet, STRUC_TERRAFORMER) * 5 : (mrc_get_level($user, $planet, STRUC_MOON_STATION) * 3));
216
}
217
218
// ----------------------------------------------------------------------------------------------------------------
219
function flt_get_missile_range($user) {
220
  return max(0, mrc_get_level($user, false, TECH_ENGINE_ION) * 5 - 1);
0 ignored issues
show
Documentation introduced by
false is of type boolean, but the function expects a array|null.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
221
}
222
223
// ----------------------------------------------------------------------------------------------------------------
224
function GetSpyLevel(&$user) {
225
  return mrc_modify_value($user, false, array(MRC_SPY, TECH_SPY), 0);
0 ignored issues
show
Documentation introduced by
false is of type boolean, but the function expects a array.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
226
}
227
228
// ----------------------------------------------------------------------------------------------------------------
229
function GetMaxFleets(&$user) {
230
  return mrc_modify_value($user, false, array(MRC_COORDINATOR, TECH_COMPUTER), 1);
0 ignored issues
show
Documentation introduced by
false is of type boolean, but the function expects a array.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
231
}
232
233
// ----------------------------------------------------------------------------------------------------------------
234
// Check input string for forbidden words
235
//
236
function CheckInputStrings($String) {
237
  global $ListCensure;
238
239
  return preg_replace($ListCensure, '*', $String);
240
}
241
242
function is_email($email) {
243
  return (preg_match("/^[-_.[:alnum:]]+@((([[:alnum:]]|[[:alnum:]][[:alnum:]-]*[[:alnum:]])\.)+(ad|ae|aero|af|ag|ai|al|am|an|ao|aq|ar|arpa|as|at|au|aw|az|ba|bb|bd|be|bf|bg|bh|bi|biz|bj|bm|bn|bo|br|bs|bt|bv|bw|by|bz|ca|cc|cd|cf|cg|ch|ci|ck|cl|cm|cn|co|com|coop|cr|cs|cu|cv|cx|cy|cz|de|dj|dk|dm|do|dz|ec|edu|ee|eg|eh|er|es|et|eu|fi|fj|fk|fm|fo|fr|ga|gb|gd|ge|gf|gh|gi|gl|gm|gn|gov|gp|gq|gr|gs|gt|gu|gw|gy|hk|hm|hn|hr|ht|hu|id|ie|il|in|info|int|io|iq|ir|is|it|jm|jo|jp|ke|kg|kh|ki|km|kn|kp|kr|kw|ky|kz|la|lb|lc|li|lk|lr|ls|lt|lu|lv|ly|ma|mc|md|mg|mh|mil|mk|ml|mm|mn|mo|mp|mq|mr|ms|mt|mu|museum|mv|mw|mx|my|mz|na|name|nc|ne|net|nf|ng|ni|nl|no|np|nr|nt|nu|nz|om|org|pa|pe|pf|pg|ph|pk|pl|pm|pn|pr|pro|ps|pt|pw|py|qa|re|ro|ru|rw|sa|sb|sc|sd|se|sg|sh|si|sj|sk|sl|sm|sn|so|sr|st|su|sv|sy|sz|tc|td|tf|tg|th|tj|tk|tm|tn|to|tp|tr|tt|tv|tw|tz|ua|ug|uk|um|us|uy|uz|va|vc|ve|vg|vi|vn|vu|wf|ws|ye|yt|yu|za|zm|zw)$|(([0-9][0-9]?|[0-1][0-9][0-9]|[2][0-4][0-9]|[2][5][0-5])\.){3}([0-9][0-9]?|[0-1][0-9][0-9]|[2][0-4][0-9]|[2][5][0-5]))$/i", $email));
244
}
245
246
function is_id($value) {
247
//  return preg_match('/^\d+$/', $value) && ($value >= 0);
0 ignored issues
show
Unused Code Comprehensibility introduced by
55% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
248
  return is_numeric($value) && ($value + 0 >= 0);
249
}
250
251
/**
252
 * @param        $param_name
253
 * @param string $default
254
 *
255
 * @return string|array
256
 */
257
function sys_get_param($param_name, $default = '') {
258
  return $_POST[$param_name] !== null ? $_POST[$param_name] : ($_GET[$param_name] !== null ? $_GET[$param_name] : $default);
259
}
260
261
function sys_get_param_array($param_name, $default = array()) {
262
  return is_array($result = sys_get_param($param_name, $default)) ? $result : array();
0 ignored issues
show
Documentation introduced by
$default is of type array, but the function expects a string.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
263
}
264
265
function sys_get_param_id($param_name, $default = 0) {
266
  return is_id($value = sys_get_param($param_name, $default)) ? $value : $default;
267
}
268
269
function sys_get_param_int($param_name, $default = 0) {
270
  $value = sys_get_param($param_name, $default);
271
272
  return $value === 'on' ? 1 : ($value === 'off' ? $default : intval($value));
273
}
274
275
function sys_get_param_float($param_name, $default = 0) {
276
  return floatval(sys_get_param($param_name, $default));
277
}
278
279
function sys_get_param_escaped($param_name, $default = '') {
280
  return db_escape(sys_get_param($param_name, $default));
281
}
282
283
function sys_get_param_date_sql($param_name, $default = '2000-01-01') {
284
  $val = sys_get_param($param_name, $default);
285
286
  return preg_match(PREG_DATE_SQL_RELAXED, $val) ? $val : $default;
287
}
288
289
function sys_get_param_str_unsafe($param_name, $default = '') {
290
  return str_raw2unsafe(sys_get_param($param_name, $default));
291
}
292
293
function sys_get_param_str($param_name, $default = '') {
294
  return db_escape(sys_get_param_str_unsafe($param_name, $default));
295
}
296
297
function sys_get_param_str_both($param_name, $default = '') {
298
  $param = sys_get_param($param_name, $default);
299
  $param_unsafe = str_raw2unsafe($param);
300
301
  return array(
302
    'raw'    => $param,
303
    'unsafe' => $param_unsafe,
304
    'safe'   => db_escape($param_unsafe),
305
  );
306
}
307
308
function sys_get_param_phone($param_name, $default = '') {
0 ignored issues
show
Unused Code introduced by
The parameter $default is not used and could be removed.

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

Loading history...
309
  $phone_raw = sys_get_param_str_unsafe($param_name, $default = '');
310
  if ($phone_raw) {
311
    $phone = $phone_raw[0] == '+' ? '+' : '';
312
    for ($i = 0; $i < strlen($phone_raw); $i++) {
313
      $ord = ord($phone_raw[$i]);
314
      if ($ord >= 48 && $ord <= 57) {
315
        $phone .= $phone_raw[$i];
316
      }
317
    }
318
    $phone = strlen($phone) < 11 ? '' : $phone;
319
  } else {
320
    $phone = '';
321
  }
322
323
  return array('raw' => $phone_raw, 'phone' => $phone);
324
}
325
326
function GetPhalanxRange($phalanx_level) {
327
  return $phalanx_level > 1 ? pow($phalanx_level, 2) - 1 : 0;
328
}
329
330
function CheckAbandonPlanetState(&$planet) {
331
  if ($planet['destruyed'] && $planet['destruyed'] <= SN_TIME_NOW) {
332
    DBStaticPlanet::db_planet_delete_by_id($planet['id']);
333
  }
334
}
335
336
function eco_get_total_cost($unit_id, $unit_level) {
337
  static $rate, $sn_group_resources_all, $sn_group_resources_loot;
338
  if (!$rate) {
339
    $sn_group_resources_all = sn_get_groups('resources_all');
340
    $sn_group_resources_loot = sn_get_groups('resources_loot');
341
342
    $rate[RES_METAL] = classSupernova::$config->rpg_exchange_metal;
343
    $rate[RES_CRYSTAL] = classSupernova::$config->rpg_exchange_crystal / classSupernova::$config->rpg_exchange_metal;
344
    $rate[RES_DEUTERIUM] = classSupernova::$config->rpg_exchange_deuterium / classSupernova::$config->rpg_exchange_metal;
345
  }
346
347
  $unit_cost_data = get_unit_param($unit_id, 'cost');
348
  if (!is_array($unit_cost_data)) {
349
    return array('total' => 0);
350
  }
351
  $factor = isset($unit_cost_data['factor']) ? $unit_cost_data['factor'] : 1;
352
  $cost_array = array(BUILD_CREATE => array(), 'total' => 0);
353
  $unit_level = $unit_level > 0 ? $unit_level : 0;
354
  foreach ($unit_cost_data as $resource_id => $resource_amount) {
355
    if (!in_array($resource_id, $sn_group_resources_all)) {
356
      continue;
357
    }
358
    $cost_array[BUILD_CREATE][$resource_id] = round($resource_amount * ($factor == 1 ? $unit_level : ((1 - pow($factor, $unit_level)) / (1 - $factor))));
359
    if (in_array($resource_id, $sn_group_resources_loot)) {
360
      $cost_array['total'] += $cost_array[BUILD_CREATE][$resource_id] * $rate[$resource_id];
361
    }
362
  }
363
364
  return $cost_array;
365
}
366
367
function sn_unit_purchase($unit_id) { }
0 ignored issues
show
Unused Code introduced by
The parameter $unit_id is not used and could be removed.

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

Loading history...
368
369
function sn_unit_relocate($unit_id, $from, $to) { }
0 ignored issues
show
Unused Code introduced by
The parameter $unit_id is not used and could be removed.

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

Loading history...
Unused Code introduced by
The parameter $from is not used and could be removed.

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

Loading history...
Unused Code introduced by
The parameter $to is not used and could be removed.

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

Loading history...
370
371
/**
372
 * @param array|bool|null $user
373
 * @param array|null      $planet
374
 * @param int             $unit_id
375
 * @param bool            $for_update
376
 * @param bool            $plain
377
 *
378
 * @return mixed
379
 */
380
function mrc_get_level(&$user, $planet = array(), $unit_id, $for_update = false, $plain = false) { return sn_function_call(__FUNCTION__, array(&$user, $planet, $unit_id, $for_update, $plain, &$result)); }
381
382
function sn_mrc_get_level(&$user, $planet = array(), $unit_id, $for_update = false, $plain = false, &$result) {
0 ignored issues
show
Unused Code introduced by
The parameter $for_update is not used and could be removed.

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

Loading history...
383
  $mercenary_level = 0;
384
  $unit_db_name = pname_resource_name($unit_id);
385
386
  if (in_array($unit_id, sn_get_groups(array('plans', 'mercenaries', 'tech', 'artifacts')))) {
387
    $unit = classSupernova::db_get_unit_by_location($user['id'], LOC_USER, $user['id'], $unit_id);
388
    $mercenary_level = is_array($unit) && $unit['unit_level'] ? $unit['unit_level'] : 0;
389
  } elseif (in_array($unit_id, sn_get_groups(array('structures', 'fleet', 'defense')))) {
390
    $unit = classSupernova::db_get_unit_by_location(isset($user['id']) ? $user['id'] : $planet['id_owner'], LOC_PLANET, $planet['id'], $unit_id);
391
    $mercenary_level = is_array($unit) && $unit['unit_level'] ? $unit['unit_level'] : 0;
392
  } elseif (in_array($unit_id, sn_get_groups('governors'))) {
393
    $mercenary_level = $unit_id == $planet['PLANET_GOVERNOR_ID'] ? $planet['PLANET_GOVERNOR_LEVEL'] : 0;
394
  } elseif ($unit_id == RES_DARK_MATTER) {
395
    $mercenary_level = $user[$unit_db_name] + ($plain || $user['user_as_ally'] ? 0 : classSupernova::$auth->account->account_metamatter);
396
  } elseif ($unit_id == RES_METAMATTER) {
397
    $mercenary_level = classSupernova::$auth->account->account_metamatter; //$user[$unit_db_name];
398
  } elseif (in_array($unit_id, sn_get_groups(array('resources_loot'))) || $unit_id == UNIT_SECTOR) {
399
    $mercenary_level = !empty($planet) ? $planet[$unit_db_name] : $user[$unit_db_name];
400
  }
401
402
  return $result = $mercenary_level;
403
}
404
405
function mrc_modify_value(&$user, $planet = array(), $mercenaries, $value) { return sn_function_call(__FUNCTION__, array(&$user, $planet, $mercenaries, $value)); }
406
407
function sn_mrc_modify_value(&$user, $planet = array(), $mercenaries, $value, $base_value = null) {
408
  if (!is_array($mercenaries)) {
409
    $mercenaries = array($mercenaries);
410
  }
411
412
  $base_value = isset($base_value) ? $base_value : $value;
413
414
  foreach ($mercenaries as $mercenary_id) {
415
    $mercenary_level = mrc_get_level($user, $planet, $mercenary_id);
416
417
    $mercenary = get_unit_param($mercenary_id);
418
    $mercenary_bonus = $mercenary['bonus'];
419
420
    switch ($mercenary['bonus_type']) {
421
      case BONUS_PERCENT_CUMULATIVE:
422
        $value *= 1 + $mercenary_level * $mercenary_bonus / 100;
423
      break;
424
425
      case BONUS_PERCENT:
426
        $mercenary_level = $mercenary_bonus < 0 && $mercenary_level * $mercenary_bonus < -90 ? -90 / $mercenary_bonus : $mercenary_level;
427
        $value += $base_value * $mercenary_level * $mercenary_bonus / 100;
428
      break;
429
430
      case BONUS_ADD:
431
        $value += $mercenary_level * $mercenary_bonus;
432
      break;
433
434
      case BONUS_ABILITY:
435
        $value = $mercenary_level ? $mercenary_level : 0;
436
      break;
437
438
      default:
439
      break;
440
    }
441
  }
442
443
  return $value;
444
}
445
446
// Generates random string of $length symbols from $allowed_chars charset
447
function sys_random_string($length = 16, $allowed_chars = SN_SYS_SEC_CHARS_ALLOWED) {
448
  $allowed_length = strlen($allowed_chars);
449
450
  $random_string = '';
451
  for ($i = 0; $i < $length; $i++) {
452
    $random_string .= $allowed_chars[mt_rand(0, $allowed_length - 1)];
453
  }
454
455
  return $random_string;
456
}
457
458
function js_safe_string($string) {
459
  return str_replace(array("\r", "\n"), array('\r', '\n'), addslashes($string));
460
}
461
462
function sys_safe_output($string) {
463
  return str_replace(array("&", "\"", "<", ">", "'"), array("&amp;", "&quot;", "&lt;", "&gt;", "&apos;"), $string);
464
}
465
466
function sys_user_options_pack(&$user) {
467
  global $user_option_list;
468
469
  $options = '';
470
  $option_list = array();
471
  foreach ($user_option_list as $option_group_id => $option_group) {
472
    $option_list[$option_group_id] = array();
473
    foreach ($option_group as $option_name => $option_value) {
474
      if (!isset($user[$option_name])) {
475
        $user[$option_name] = $option_value;
476
      } elseif ($user[$option_name] == '') {
477
        $user[$option_name] = 0;
478
      }
479
      $options .= "{$option_name}^{$user[$option_name]}|";
480
      $option_list[$option_group_id][$option_name] = $user[$option_name];
481
    }
482
  }
483
484
  $user['options'] = $options;
485
  $user['option_list'] = $option_list;
486
487
  return $options;
488
}
489
490
function sys_user_options_unpack(&$user) {
491
  global $user_option_list;
492
493
  $option_list = array();
494
  $option_string_list = explode('|', $user['options']);
495
496
  foreach ($option_string_list as $option_string) {
497
    list($option_name, $option_value) = explode('^', $option_string);
498
    $option_list[$option_name] = $option_value;
499
  }
500
501
  $final_list = array();
502
  foreach ($user_option_list as $option_group_id => $option_group) {
503
    $final_list[$option_group_id] = array();
504
    foreach ($option_group as $option_name => $option_value) {
505
      if (!isset($option_list[$option_name])) {
506
        $option_list[$option_name] = $option_value;
507
      }
508
      $user[$option_name] = $final_list[$option_group_id][$option_name] = $option_list[$option_name];
509
    }
510
  }
511
512
  $user['option_list'] = $final_list;
513
514
  return $final_list;
515
}
516
517
function sys_unit_str2arr($fleet_string) {
518
  $fleet_array = array();
519
  if (!empty($fleet_string)) {
520
    $arrTemp = explode(';', $fleet_string);
521
    foreach ($arrTemp as $temp) {
522
      if ($temp) {
523
        $temp = explode(',', $temp);
524
        if (!empty($temp[0]) && !empty($temp[1])) {
525
          $fleet_array[$temp[0]] += $temp[1];
526
        }
527
      }
528
    }
529
  }
530
531
  return $fleet_array;
532
}
533
534
function sys_unit_arr2str($unit_list) {
535
  $fleet_string = array();
536
  if (isset($unit_list)) {
537
    if (!is_array($unit_list)) {
538
      $unit_list = array($unit_list => 1);
539
    }
540
541
    foreach ($unit_list as $unit_id => $unit_count) {
542
      if ($unit_id && $unit_count) {
543
        $fleet_string[] = "{$unit_id},{$unit_count}";
544
      }
545
    }
546
  }
547
548
  return implode(';', $fleet_string);
549
}
550
551
function mymail($email_unsafe, $title, $body, $from = '', $html = false) {
552
  $from = trim($from ? $from : classSupernova::$config->game_adminEmail);
553
554
  $head = '';
555
  $head .= "Content-Type: text/" . ($html ? 'html' : 'plain') . "; charset=utf-8 \r\n";
556
  $head .= "Date: " . date('r') . " \r\n";
557
  $classConfig = classSupernova::$config;
558
  $head .= "Return-Path: {$classConfig->game_adminEmail} \r\n";
559
  $head .= "From: {$from} \r\n";
560
  $head .= "Sender: {$from} \r\n";
561
  $head .= "Reply-To: {$from} \r\n";
562
  // $head .= "Organization: {$org} \r\n";
0 ignored issues
show
Unused Code Comprehensibility introduced by
38% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
563
  $head .= "X-Sender: {$from} \r\n";
564
  $head .= "X-Priority: 3 \r\n";
565
  $body = str_replace("\r\n", "\n", $body);
566
  $body = str_replace("\n", "\r\n", $body);
567
568
  if ($html) {
569
    $body = '<html><head><base href="' . SN_ROOT_VIRTUAL . '"></head><body>' . nl2br($body) . '</body></html>';
570
  }
571
572
  $title = '=?UTF-8?B?' . base64_encode($title) . '?=';
573
574
  return @mail($email_unsafe, $title, $body, $head);
0 ignored issues
show
Security Header Injection introduced by
$email_unsafe can contain request data and is used in request header context(s) leading to a potential security vulnerability.

1 path for user data to reach this point

  1. Read from $_POST
    in includes/general.php on line 258
  2. sys_get_param() returns tainted data
    in includes/general.php on line 290
  3. Data is passed through strip_tags(), and Data is passed through trim()
    in vendor/includes/general.php on line 1280
  4. sys_get_param_str_unsafe() returns tainted data, and auth_local::$input_email_unsafe is assigned
    in includes/classes/auth_local.php on line 364
  5. Tainted property auth_local::$input_email_unsafe is read, and $email_unsafe is assigned
    in includes/classes/auth_local.php on line 207
  6. $email_unsafe is passed to mymail()
    in includes/classes/auth_local.php on line 240

General Strategies to prevent injection

In general, it is advisable to prevent any user-data to reach this point. This can be done by white-listing certain values:

if ( ! in_array($value, array('this-is-allowed', 'and-this-too'), true)) {
    throw new \InvalidArgumentException('This input is not allowed.');
}

For numeric data, we recommend to explicitly cast the data:

$sanitized = (integer) $tainted;
Loading history...
575
}
576
577
function sys_time_human($time, $full = false) {
578
  $seconds = $time % 60;
579
  $time = floor($time / 60);
580
  $minutes = $time % 60;
581
  $time = floor($time / 60);
582
  $hours = $time % 24;
583
  $time = floor($time / 24);
584
585
  $classLocale = classLocale::$lang;
586
587
  return
588
    ($full || $time ? "{$time} {$classLocale['sys_day']}&nbsp;" : '') .
589
    ($full || $hours ? "{$hours} {$classLocale['sys_hrs']}&nbsp;" : '') .
590
    ($full || $minutes ? "{$minutes} {$classLocale['sys_min']}&nbsp;" : '') .
591
    ($full || !$time || $seconds ? "{$seconds} {$classLocale['sys_sec']}" : '');
592
}
593
594
function sys_time_human_system($time) {
595
  return $time ? date(FMT_DATE_TIME_SQL, $time) . " ({$time}), " . sys_time_human(SN_TIME_NOW - $time) : '{NEVER}';
596
}
597
598
function sys_redirect($url) {
599
  header("Location: {$url}");
600
  ob_end_flush();
601
  die();
602
}
603
604
// TODO Для полноценного функионирования апдейтера пакет функций, включая эту должен быть вынесен раньше - или грузить general.php до апдейтера
605
function sys_get_unit_location($user, $planet, $unit_id) { return sn_function_call(__FUNCTION__, array($user, $planet, $unit_id)); }
606
607
function sn_sys_get_unit_location($user, $planet, $unit_id) {
0 ignored issues
show
Unused Code introduced by
The parameter $user is not used and could be removed.

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

Loading history...
Unused Code introduced by
The parameter $planet is not used and could be removed.

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

Loading history...
608
  return get_unit_param($unit_id, 'location');
609
}
610
611
function sn_ali_fill_user_ally(&$user) {
612
  if (!$user['ally_id']) {
613
    return;
614
  }
615
616
  if (!isset($user['ally'])) {
617
    $user['ally'] = DBStaticAlly::db_ally_get_by_id($user['ally_id']);
618
  }
619
620
  if (!isset($user['ally']['player'])) {
621
    $user['ally']['player'] = DBStaticUser::db_user_by_id($user['ally']['ally_user_id'], true, '*', false);
622
  }
623
}
624
625
function sn_get_url_contents($url) {
626
  if (function_exists('curl_init')) {
627
    $crl = curl_init();
628
    $timeout = 5;
629
    curl_setopt($crl, CURLOPT_URL, $url);
630
    curl_setopt($crl, CURLOPT_RETURNTRANSFER, 1);
631
    curl_setopt($crl, CURLOPT_CONNECTTIMEOUT, $timeout);
632
    $return = curl_exec($crl);
633
    curl_close($crl);
634
  } else {
635
    $return = @file_get_contents($url);
636
  }
637
638
  return $return;
639
}
640
641
function get_engine_data($user, $engine_info) {
642
  $sn_data_tech_bonus = get_unit_param($engine_info['tech'], 'bonus');
643
644
  $user_tech_level = intval(mrc_get_level($user, null, $engine_info['tech']));
645
646
  $engine_info['speed_base'] = $engine_info['speed'];
647
  $tech_bonus = ($user_tech_level - $engine_info['min_level']) * $sn_data_tech_bonus / 100;
648
  $tech_bonus = $tech_bonus < -0.9 ? -0.95 : $tech_bonus;
649
  $engine_info['speed'] = floor(mrc_modify_value($user, false, array(MRC_NAVIGATOR), $engine_info['speed']) * (1 + $tech_bonus));
0 ignored issues
show
Documentation introduced by
false is of type boolean, but the function expects a array.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
650
651
  $engine_info['consumption_base'] = $engine_info['consumption'];
652
  $tech_bonus = ($user_tech_level - $engine_info['min_level']) * $sn_data_tech_bonus / 1000;
653
  $tech_bonus = $tech_bonus > 0.5 ? 0.5 : ($tech_bonus < 0 ? $tech_bonus * 2 : $tech_bonus);
654
  $engine_info['consumption'] = ceil($engine_info['consumption'] * (1 - $tech_bonus));
655
656
  return $engine_info;
657
}
658
659
function get_ship_data($ship_id, $user) {
660
  $ship_data = array();
661
  if (in_array($ship_id, Fleet::$snGroupFleetAndMissiles)) {
662
    $engines = get_unit_param($ship_id, 'engine');
663
    empty($engines) ? $engines = array() : false;
664
    foreach ($engines as $engine_info) {
665
      $tech_level = intval(mrc_get_level($user, null, $engine_info['tech']));
666
      if (empty($ship_data) || $tech_level >= $engine_info['min_level']) {
667
        $ship_data = $engine_info;
668
        $ship_data['tech_level'] = $tech_level;
669
      }
670
    }
671
    $ship_data = get_engine_data($user, $ship_data);
672
    $ship_data['capacity'] = get_unit_param($ship_id, 'capacity');
673
  }
674
675
  return $ship_data;
676
}
677
678
if (!function_exists('strptime')) {
679
  function strptime($date, $format) {
680
    $masks = array(
681
      '%d' => '(?P<d>[0-9]{2})',
682
      '%m' => '(?P<m>[0-9]{2})',
683
      '%Y' => '(?P<Y>[0-9]{4})',
684
      '%H' => '(?P<H>[0-9]{2})',
685
      '%M' => '(?P<M>[0-9]{2})',
686
      '%S' => '(?P<S>[0-9]{2})',
687
      // usw..
688
    );
689
690
    $rexep = "#" . strtr(preg_quote($format), $masks) . "#";
691
    if (preg_match($rexep, $date, $out)) {
692
      $ret = array(
693
        "tm_sec"  => (int)$out['S'],
694
        "tm_min"  => (int)$out['M'],
695
        "tm_hour" => (int)$out['H'],
696
        "tm_mday" => (int)$out['d'],
697
        "tm_mon"  => $out['m'] ? $out['m'] - 1 : 0,
698
        "tm_year" => $out['Y'] > 1900 ? $out['Y'] - 1900 : 0,
699
      );
700
    } else {
701
      $ret = false;
702
    }
703
704
    return $ret;
705
  }
706
}
707
708
function sn_sys_sector_buy($redirect = 'overview.php') {
709
  global $user, $planetrow;
710
711
  if (!sys_get_param_str('sector_buy') || $planetrow['planet_type'] != PT_PLANET) {
712
    return;
713
  }
714
715
  sn_db_transaction_start();
716
  $user = DBStaticUser::db_user_by_id($user['id'], true, '*');
717
  $planetrow = DBStaticPlanet::db_planet_by_id($planetrow['id'], true, '*');
718
  // Тут не надо делать обсчет - ресурсы мы уже посчитали, очередь (и количество зданий) - тоже
719
  $sector_cost = eco_get_build_data($user, $planetrow, UNIT_SECTOR, mrc_get_level($user, $planetrow, UNIT_SECTOR), true);
720
  $sector_cost = $sector_cost[BUILD_CREATE][RES_DARK_MATTER];
721
  if ($sector_cost <= mrc_get_level($user, null, RES_DARK_MATTER)) {
722
    $planet_name_text = uni_render_planet($planetrow);
723
    if (rpg_points_change($user['id'], RPG_SECTOR, -$sector_cost, sprintf(classLocale::$lang['sys_sector_purchase_log'],
724
        $user['username'], $user['id'], $planet_name_text, classLocale::$lang['sys_planet_type'][$planetrow['planet_type']], $planetrow['id'], $sector_cost)
725
    )) {
726
      $sector_db_name = pname_resource_name(UNIT_SECTOR);
727
      DBStaticPlanet::db_planet_set_by_id($planetrow['id'], "{$sector_db_name} = {$sector_db_name} + 1");
728
    } else {
729
      sn_db_transaction_rollback();
730
    }
731
  }
732
  sn_db_transaction_commit();
733
734
  sys_redirect($redirect);
735
}
736
737
/**
738
 * @param           $functions
739
 * @param           $handler_list
740
 * @param sn_module $class_module_name
741
 * @param string    $sub_type
742
 */
743
function sn_sys_handler_add(&$functions, $handler_list, $class_module_name = '', $sub_type = '') {
744
  if (isset($handler_list) && is_array($handler_list) && !empty($handler_list)) {
745
    foreach ($handler_list as $function_name => $function_data) {
746
      $override_with = '';
747
      if (is_string($function_data)) {
748
        $override_with = &$function_data;
749
      } elseif (isset($function_data['callable'])) {
750
        $override_with = &$function_data['callable'];
751
      }
752
753
      $overwrite = $override_with[0] == '*';
754
      if ($overwrite) {
755
        $override_with = substr($override_with, 1);
756
      }
757
758
      if (($point_position = strpos($override_with, '.')) === false && $class_module_name) {
759
        $override_with = array($class_module_name, $override_with);
760
      } elseif ($point_position == 0) {
761
        $override_with = substr($override_with, 1);
762
      } elseif ($point_position > 0) {
763
        $override_with = array(substr($override_with, 0, $point_position), substr($override_with, $point_position + 1));
764
      }
765
766
      if ($overwrite) {
767
        $functions[$function_name] = array();
768
        $function_data = array('callable' => $override_with);
769
      } elseif (!isset($functions[$function_name])) {
770
        $functions[$function_name] = array();
771
        $sn_function_name = 'sn_' . $function_name . ($sub_type ? '_' . $sub_type : '');
772
        $functions[$function_name][] = $sn_function_name;
773
      }
774
775
      $functions[$function_name][] = $function_data;
776
    }
777
  }
778
}
779
780
// TODO - поменять название
781
// Может принимать: (array)$user, $nick_render_array, $nick_render_array_html, $nick_render_string_compact
782
function player_nick_render_to_html($result, $options = false) {
783
  // TODO - обрабатывать разные случаи: $user, $render_nick_array, $string
784
785
  if (is_string($result) && strpos($result, ':{i:')) {
786
    $result = player_nick_uncompact($result);
787
  }
788
789
  if (is_array($result)) {
790
    if (isset($result['id'])) {
791
      $result = player_nick_render_current_to_array($result, $options);
792
    }
793
    if (!isset($result[NICK_HTML])) {
794
      $result = player_nick_render_array_to_html($result);
795
    }
796
    unset($result[NICK_HTML]);
797
    ksort($result);
798
    $result = implode('', $result);
799
  }
800
801
  return $result;
802
}
803
804
805
function player_nick_compact($nick_array) {
806
  ksort($nick_array);
807
808
  return serialize($nick_array);
809
}
810
811
function player_nick_uncompact($nick_string) {
812
  try {
813
    $result = unserialize($nick_string);
814
  } catch (exception $e) {
815
    $result = strpos($nick_string, ':{i:') ? null : $nick_string; // fallback if it is already string - for old chat strings, for example
816
  }
817
818
  return $result;
819
}
820
821
function player_nick_render_array_to_html($nick_array) { return sn_function_call(__FUNCTION__, array($nick_array, &$result)); }
822
823
function sn_player_nick_render_array_to_html($nick_array, &$result) {
824
  global $user;
825
826
  // ALL STRING ARE UNSAFE!!!
827
  if (isset($nick_array[NICK_BIRTHSDAY])) {
828
    $result[NICK_BIRTHSDAY] = '<img src="design/images/birthday.png" />';
829
  }
830
831
  if (isset($nick_array[NICK_VACATION])) {
832
    $result[NICK_VACATION] = '<img src="design/images/icon_vacation.png" />';
833
  }
834
835
  if (isset($nick_array[NICK_GENDER])) {
836
    $result[NICK_GENDER] = '<img src="' . ($user['dpath'] ? $user['dpath'] : DEFAULT_SKINPATH) . 'images/gender_' . $nick_array[NICK_GENDER] . '.png" />';
837
  }
838
839
  if (isset($nick_array[NICK_AUTH_LEVEL]) || isset($nick_array[NICK_PREMIUM])) {
840
    switch ($nick_array[NICK_AUTH_LEVEL]) {
841
      case 4:
842
        $highlight = classSupernova::$config->chat_highlight_developer;
843
      break;
844
845
      case 3:
846
        $highlight = classSupernova::$config->chat_highlight_admin;
847
      break;
848
849
      case 2:
850
        $highlight = classSupernova::$config->chat_highlight_operator;
851
      break;
852
853
      case 1:
854
        $highlight = classSupernova::$config->chat_highlight_moderator;
855
      break;
856
857
      default:
858
        $highlight = isset($nick_array[NICK_PREMIUM]) ? classSupernova::$config->chat_highlight_premium : '';
859
    }
860
861
    if ($highlight) {
862
      list($result[NICK_HIGHLIGHT], $result[NICK_HIGHLIGHT_END]) = explode('$1', $highlight);
863
    }
864
  }
865
866 View Code Duplication
  if (isset($nick_array[NICK_CLASS])) {
1 ignored issue
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
867
    $result[NICK_CLASS] = '<span ' . $nick_array[NICK_CLASS] . '>';
868
    $result[NICK_CLASS_END] = '</span>';
869
  }
870
871
  $result[NICK_NICK] = sys_safe_output($nick_array[NICK_NICK]);
872
873 View Code Duplication
  if (isset($nick_array[NICK_ALLY])) {
1 ignored issue
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
874
    $result[NICK_ALLY] = '[' . sys_safe_output($nick_array[NICK_ALLY]) . ']';
875
  }
876
877
  $result[NICK_HTML] = true;
878
879
  return $result;
880
}
881
882
function player_nick_render_current_to_array($render_user, $options = false) { return sn_function_call(__FUNCTION__, array($render_user, $options, &$result)); }
883
884
function sn_player_nick_render_current_to_array($render_user, $options = false, &$result) {
885
  if ($render_user['user_birthday'] && ($options === true || isset($options['icons']) || isset($options['birthday'])) && (date('Y', SN_TIME_NOW) . date('-m-d', strtotime($render_user['user_birthday'])) == date('Y-m-d', SN_TIME_NOW))) {
886
    $result[NICK_BIRTHSDAY] = '';
887
  }
888
889
  if ($options === true || (isset($options['icons']) && $options['icons']) || (isset($options['gender']) && $options['gender'])) {
890
    $result[NICK_GENDER] = $render_user['gender'] == GENDER_UNKNOWN ? 'unknown' : ($render_user['gender'] == GENDER_FEMALE ? 'female' : 'male');
891
  }
892
893
  if (($options === true || (isset($options['icons']) && $options['icons']) || (isset($options['vacancy']) && $options['vacancy'])) && $render_user['vacation']) {
894
    $result[NICK_VACATION] = $render_user['vacation'];
895
  }
896
897
  if ($options === true || (isset($options['color']) && $options['color'])) {
898
    if ($user_auth_level = $render_user['authlevel']) {
899
      $result[NICK_AUTH_LEVEL] = $user_auth_level;
900
    }
901
    if ($user_premium = mrc_get_level($render_user, null, UNIT_PREMIUM)) {
902
      $result[NICK_PREMIUM] = $user_premium;
903
    }
904
  }
905
906
  if ((isset($options['class']) && $options['class'])) {
907
    $result[NICK_CLASS] = (isset($result_options[NICK_CLASS]) ? ' ' . $result_options[NICK_CLASS] : '') . $options['class'];
0 ignored issues
show
Bug introduced by
The variable $result_options does not exist. Did you mean $options?

This check looks for variables that are accessed but have not been defined. It raises an issue if it finds another variable that has a similar name.

The variable may have been renamed without also renaming all references.

Loading history...
908
  }
909
910
  if ($render_user['ally_tag'] && ($options === true || (isset($options['ally']) && $options['ally']))) {
911
    $result[NICK_ALLY] = $render_user['ally_tag'];
912
  }
913
914
  $result[NICK_NICK] = $render_user['username'];
915
916
  return $result;
917
}
918
919
920
// TODO sys_stat_get_user_skip_list() ПЕРЕДЕЛАТЬ!
921
function sys_stat_get_user_skip_list() {
922
  $result = array();
923
924
  $user_skip_list = array();
925
926
  if (classSupernova::$config->stats_hide_admins) {
927
    $user_skip_list[] = '`authlevel` > 0';
928
  }
929
930
  if (classSupernova::$config->stats_hide_player_list) {
931
    $temp = explode(',', classSupernova::$config->stats_hide_player_list);
932
    foreach ($temp as $user_id) {
933
      $user_id = floatval($user_id);
934
      if ($user_id) {
935
        $user_skip_list[] = '`id` = ' . $user_id;
936
      }
937
    }
938
  }
939
940
  if (!empty($user_skip_list)) {
941
    $user_skip_list = implode(' OR ', $user_skip_list);
942
    $user_skip_query = DBStaticUser::db_user_list($user_skip_list);
943
    if (!empty($user_skip_query)) {
944
      foreach ($user_skip_query as $user_skip_row) {
945
        $result[$user_skip_row['id']] = $user_skip_row['id'];
946
      }
947
    }
948
  }
949
950
  return $result;
951
}
952
953
function get_unit_param($unit_id, $param_name = null, $user = null, $planet = null) { return sn_function_call(__FUNCTION__, array($unit_id, $param_name, $user, $planet, &$result)); }
954
955
function sn_get_unit_param($unit_id, $param_name = null, $user = null, $planet = null, &$result) {
0 ignored issues
show
Unused Code introduced by
The parameter $user is not used and could be removed.

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

Loading history...
Unused Code introduced by
The parameter $planet is not used and could be removed.

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

Loading history...
956
  global $sn_data;
957
958
  $result = isset($sn_data[$unit_id])
959
    ? ($param_name === null
960
      ? $sn_data[$unit_id]
961
      : (isset($sn_data[$unit_id][$param_name]) ? $sn_data[$unit_id][$param_name] : $result)
962
    )
963
    : $result;
964
965
  return $result;
966
}
967
968
/**
969
 * @param $groups
970
 *
971
 * @return array
972
 */
973
function sn_get_groups($groups) { return sn_function_call(__FUNCTION__, array($groups, &$result)); }
974
975
/**
976
 * @param $groups
977
 * @param $result
978
 *
979
 * @return array
980
 */
981
function sn_sn_get_groups($groups, &$result) {
982
  $result = is_array($result) ? $result : array();
983
  foreach ($groups = is_array($groups) ? $groups : array($groups) as $group_name) {
984
    $result += is_array($a_group = get_unit_param(UNIT_GROUP, $group_name)) ? $a_group : array();
985
  }
986
987
  return $result;
988
}
989
990
function isInGroup($groups, $unitId) {
991
  $group = sn_get_groups($groups);
992
  return !empty($group[$unitId]);
993
}
994
995
// Format $value to ID
996
/**
997
 * @param     $value
998
 * @param int $default
999
 *
1000
 * @return float|int
1001
 */
1002
function idval($value, $default = 0) {
1003
  $value = floatval($value);
1004
1005
  return preg_match('#^(\d*)#', $value, $matches) && $matches[1] ? floatval($matches[1]) : $default;
1006
}
1007
1008
function unit_requirements_render($user, $planetrow, $unit_id, $field = 'require') { return sn_function_call(__FUNCTION__, array($user, $planetrow, $unit_id, $field, &$result)); }
1009
1010
function sn_unit_requirements_render($user, $planetrow, $unit_id, $field = 'require', &$result) {
1011
  $sn_data_unit = get_unit_param($unit_id);
1012
1013
  $result = is_array($result) ? $result : array();
1014
  if ($sn_data_unit[$field] && !($sn_data_unit[P_UNIT_TYPE] == UNIT_MERCENARIES && classSupernova::$config->empire_mercenary_temporary)) {
1015
    foreach ($sn_data_unit[$field] as $require_id => $require_level) {
1016
      $level_got = mrc_get_level($user, $planetrow, $require_id);
1017
      $level_basic = mrc_get_level($user, $planetrow, $require_id, false, true);
1018
      $result[] = array(
1019
        'NAME'             => classLocale::$lang['tech'][$require_id],
1020
        //'CLASS' => $require_level > $level_got ? 'negative' : ($require_level == $level_got ? 'zero' : 'positive'),
0 ignored issues
show
Unused Code Comprehensibility introduced by
50% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
1021
        'REQUEREMENTS_MET' => intval($require_level <= $level_got ? REQUIRE_MET : REQUIRE_MET_NOT),
1022
        'LEVEL_REQUIRE'    => $require_level,
1023
        'LEVEL'            => $level_got,
1024
        'LEVEL_BASIC'      => $level_basic,
1025
        'LEVEL_BONUS'      => max(0, $level_got - $level_basic),
1026
        'ID'               => $require_id,
1027
      );
1028
    }
1029
  }
1030
1031
  return $result;
1032
}
1033
1034
function ally_get_ranks(&$ally) {
1035
  global $ally_rights;
1036
1037
  $ranks = array();
1038
1039
  if ($ally['ranklist']) {
1040
    $str_ranks = explode(';', $ally['ranklist']);
1041
    foreach ($str_ranks as $str_rank) {
1042
      if (!$str_rank) {
1043
        continue;
1044
      }
1045
1046
      $tmp = explode(',', $str_rank);
1047
      $rank_id = count($ranks);
1048
      foreach ($ally_rights as $key => $value) {
1049
        $ranks[$rank_id][$value] = $tmp[$key];
1050
      }
1051
    }
1052
  }
1053
1054
  return $ranks;
1055
}
1056
1057
function sys_player_new_adjust($user_id, $planet_id) { return sn_function_call(__FUNCTION__, array($user_id, $planet_id, &$result)); }
1058
1059
function sn_sys_player_new_adjust($user_id, $planet_id, &$result) {
0 ignored issues
show
Unused Code introduced by
The parameter $user_id is not used and could be removed.

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

Loading history...
Unused Code introduced by
The parameter $planet_id is not used and could be removed.

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

Loading history...
1060
  return $result;
1061
}
1062
1063
function array_merge_recursive_numeric($array1, $array2) {
1064
  if (!empty($array2) && is_array($array2)) {
1065
    foreach ($array2 as $key => $value) {
1066
      $array1[$key] = !isset($array1[$key]) || !is_array($array1[$key]) ? $value : array_merge_recursive_numeric($array1[$key], $value);
1067
    }
1068
  }
1069
1070
  return $array1;
1071
}
1072
1073
function sn_sys_array_cumulative_sum(&$array) {
1074
  $accum = 0;
1075
  foreach ($array as &$value) {
1076
    $accum += $value;
1077
    $value = $accum;
1078
  }
1079
}
1080
1081
function planet_density_price_chart($planet_row) {
1082
  $sn_data_density = sn_get_groups('planet_density');
1083
  $density_price_chart = array();
1084
1085
  foreach ($sn_data_density as $density_id => $density_data) {
1086
    // Отсекаем записи с RARITY = 0 - служебные записи и супер-ядра
1087
    $density_data[UNIT_PLANET_DENSITY_RARITY] ? $density_price_chart[$density_id] = $density_data[UNIT_PLANET_DENSITY_RARITY] : false;
1088
  }
1089
  unset($density_price_chart[PLANET_DENSITY_NONE]);
1090
1091
  $total_rarity = array_sum($density_price_chart);
1092
1093
  foreach ($density_price_chart as &$density_data) {
1094
    $density_data = ceil($total_rarity / $density_data * $planet_row['field_max'] * PLANET_DENSITY_TO_DARK_MATTER_RATE);
1095
  }
1096
1097
  return $density_price_chart;
1098
}
1099
1100
function sn_sys_planet_core_transmute(&$user, &$planetrow) {
1101
  if (!sys_get_param_str('transmute')) {
1102
    return array();
1103
  }
1104
1105
  try {
1106 View Code Duplication
    if ($planetrow['planet_type'] != PT_PLANET) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
1107
      throw new exception(classLocale::$lang['ov_core_err_not_a_planet'], ERR_ERROR);
1108
    }
1109
1110
    if ($planetrow['density_index'] == ($new_density_index = sys_get_param_id('density_type'))) {
1111
      throw new exception(classLocale::$lang['ov_core_err_same_density'], ERR_WARNING);
1112
    }
1113
1114
    sn_db_transaction_start();
1115
    $user = DBStaticUser::db_user_by_id($user['id'], true, '*');
1116
    $planetrow = DBStaticPlanet::db_planet_by_id($planetrow['id'], true, '*');
1117
1118
    $planet_density_index = $planetrow['density_index'];
1119
1120
    $density_price_chart = planet_density_price_chart($planetrow);
1121
    if (!isset($density_price_chart[$new_density_index])) {
1122
      // Hack attempt
1123
      throw new exception(classLocale::$lang['ov_core_err_denisty_type_wrong'], ERR_ERROR);
1124
    }
1125
1126
    $user_dark_matter = mrc_get_level($user, null, RES_DARK_MATTER);
1127
    $transmute_cost = $density_price_chart[$new_density_index];
1128
    if ($user_dark_matter < $transmute_cost) {
1129
      throw new exception(classLocale::$lang['ov_core_err_no_dark_matter'], ERR_ERROR);
1130
    }
1131
1132
    $sn_data_planet_density = sn_get_groups('planet_density');
1133
    $prev_density_index = PLANET_DENSITY_NONE;
1134
    foreach ($sn_data_planet_density as $key => $value) {
1135
      if ($key == $new_density_index) {
1136
        break;
1137
      }
1138
      $prev_density_index = $key;
1139
    }
1140
1141
    $new_density = round(($sn_data_planet_density[$new_density_index][UNIT_PLANET_DENSITY] + $sn_data_planet_density[$prev_density_index][UNIT_PLANET_DENSITY]) / 2);
1142
1143
    rpg_points_change($user['id'], RPG_PLANET_DENSITY_CHANGE, -$transmute_cost,
1144
      array(
0 ignored issues
show
Documentation introduced by
array('Planet %1$s ID %2...y_index], $new_density) is of type array<integer,?,{"0":"st...,"7":"?","8":"double"}>, but the function expects a string.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
1145
        'Planet %1$s ID %2$d at coordinates %3$s changed density type from %4$d "%5$s" to %6$d "%7$s". New density is %8$d kg/m3',
1146
        $planetrow['name'],
1147
        $planetrow['id'],
1148
        uni_render_coordinates($planetrow),
1149
        $planet_density_index,
1150
        classLocale::$lang['uni_planet_density_types'][$planet_density_index],
1151
        $new_density_index,
1152
        classLocale::$lang['uni_planet_density_types'][$new_density_index],
1153
        $new_density
1154
      )
1155
    );
1156
1157
    DBStaticPlanet::db_planet_set_by_id($planetrow['id'], "`density` = {$new_density}, `density_index` = {$new_density_index}");
1158
    sn_db_transaction_commit();
1159
1160
    $planetrow['density'] = $new_density;
1161
    $planetrow['density_index'] = $new_density_index;
1162
    $result = array(
1163
      'STATUS'  => ERR_NONE,
1164
      'MESSAGE' => sprintf(classLocale::$lang['ov_core_err_none'], classLocale::$lang['uni_planet_density_types'][$planet_density_index], classLocale::$lang['uni_planet_density_types'][$new_density_index], $new_density),
1165
    );
1166
  } catch (exception $e) {
1167
    sn_db_transaction_rollback();
1168
    $result = array(
1169
      'STATUS'  => $e->getCode(),
1170
      'MESSAGE' => $e->getMessage(),
1171
    );
1172
  }
1173
1174
  return $result;
1175
}
1176
1177
function sn_module_get_active_count($group = '*') {
1178
  $active_modules = 0;
1179
  if (isset(sn_module::$sn_module_list[$group]) && is_array(sn_module::$sn_module_list[$group])) {
1180
    foreach (sn_module::$sn_module_list[$group] as $payment_module) {
1181
      $active_modules += $payment_module->manifest['active'];
1182
    }
1183
  }
1184
1185
  return $active_modules;
1186
}
1187
1188
function get_resource_exchange() {
1189
  static $rates;
1190
1191
  if (!$rates) {
1192
    $rates = array(
1193
      RES_METAL       => 'rpg_exchange_metal',
1194
      RES_CRYSTAL     => 'rpg_exchange_crystal',
1195
      RES_DEUTERIUM   => 'rpg_exchange_deuterium',
1196
      RES_DARK_MATTER => 'rpg_exchange_darkMatter',
1197
    );
1198
1199
    foreach ($rates as &$rate) {
1200
      $rate = classSupernova::$config->$rate;
1201
    }
1202
  }
1203
1204
  return $rates;
1205
}
1206
1207
function get_unit_cost_in(&$cost, $in_resource = RES_METAL) {
0 ignored issues
show
Unused Code introduced by
The parameter $in_resource is not used and could be removed.

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

Loading history...
1208
  static $rates;
1209
1210
  if (!$rates) {
1211
    $rates = get_resource_exchange();
1212
  }
1213
1214
  $metal_cost = 0;
1215
  foreach ($cost as $resource_id => $resource_value) {
1216
    $metal_cost += $rates[$resource_id] * $resource_value;
1217
  }
1218
1219
  return $metal_cost;
1220
}
1221
1222
/**
1223
 * @param array $user
1224
 * @param int   $astrotech
1225
 *
1226
 * @return int
1227
 */
1228
function get_player_max_expeditons(&$user, $astrotech = -1) { return sn_function_call(__FUNCTION__, array(&$user, $astrotech, &$result)); }
1229
1230
/**
1231
 * @param     $user
1232
 * @param int $astrotech
1233
 * @param int $result
1234
 *
1235
 * @return float|int
1236
 */
1237
function sn_get_player_max_expeditons(&$user, $astrotech = -1, &$result = 0) {
1238
  if ($astrotech == -1) {
1239
    if (!isset($user[UNIT_PLAYER_EXPEDITIONS_MAX])) {
1240
      $astrotech = mrc_get_level($user, null, TECH_ASTROTECH);
1241
      $user[UNIT_PLAYER_EXPEDITIONS_MAX] = $astrotech >= 1 ? floor(sqrt($astrotech - 1)) : 0;
1242
    }
1243
1244
    return $result += $user[UNIT_PLAYER_EXPEDITIONS_MAX];
1245
  } else {
1246
    return $result += $astrotech >= 1 ? floor(sqrt($astrotech - 1)) : 0;
1247
  }
1248
}
1249
1250
function get_player_max_expedition_duration(&$user, $astrotech = -1) {
1251
  return $astrotech == -1 ? mrc_get_level($user, null, TECH_ASTROTECH) : $astrotech;
1252
}
1253
1254
function get_player_max_colonies(&$user, $astrotech = -1) {
1255
  if ($astrotech == -1) {
1256
    if (!isset($user[UNIT_PLAYER_COLONIES_MAX])) {
1257
1258
      $expeditions = get_player_max_expeditons($user);
1259
      $astrotech = mrc_get_level($user, null, TECH_ASTROTECH);
1260
      $colonies = $astrotech - $expeditions;
1261
1262
      $user[UNIT_PLAYER_COLONIES_MAX] = classSupernova::$config->player_max_colonies < 0 ? $colonies : min(classSupernova::$config->player_max_colonies, $colonies);
1263
    }
1264
1265
    return $user[UNIT_PLAYER_COLONIES_MAX];
1266 View Code Duplication
  } else {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
1267
    $expeditions = get_player_max_expeditons($user, $astrotech);
1268
    // $astrotech = mrc_get_level($user, false, TECH_ASTROTECH);
0 ignored issues
show
Unused Code Comprehensibility introduced by
50% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
1269
    $colonies = $astrotech - $expeditions;
1270
1271
    return classSupernova::$config->player_max_colonies < 0 ? $colonies : min(classSupernova::$config->player_max_colonies, $colonies);
1272
  }
1273
}
1274
1275
function get_player_current_colonies(&$user) {
1276
  return $user[UNIT_PLAYER_COLONIES_CURRENT] = isset($user[UNIT_PLAYER_COLONIES_CURRENT]) ? $user[UNIT_PLAYER_COLONIES_CURRENT] : max(0, DBStaticPlanet::db_planet_count_by_type($user['id']) - 1);
1277
}
1278
1279
function str_raw2unsafe($raw) {
1280
  return trim(strip_tags($raw));
1281
}
1282
1283
function ip2longu($ip) {
1284
  return sprintf('%u', floatval(ip2long($ip)));
1285
}
1286
1287
1288
function sn_powerup_get_price_matrix($powerup_id, $powerup_unit = false, $level_max = null, $plain = false) { return sn_function_call(__FUNCTION__, array($powerup_id, $powerup_unit, $level_max, $plain, &$result)); }
1289
1290
function sn_sn_powerup_get_price_matrix($powerup_id, $powerup_unit = false, $level_max = null, $plain = false, &$result) {
0 ignored issues
show
Unused Code introduced by
The parameter $plain is not used and could be removed.

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

Loading history...
1291
  global $sn_powerup_buy_discounts;
1292
1293
  $result = array();
1294
1295
  $powerup_data = get_unit_param($powerup_id);
1296
  $is_upgrade = !empty($powerup_unit) && $powerup_unit;
1297
1298
  $level_current = $term_original = $time_left = 0;
1299
  if ($is_upgrade) {
1300
    $time_finish = strtotime($powerup_unit['unit_time_finish']);
1301
    $time_left = max(0, $time_finish - SN_TIME_NOW);
1302
    if ($time_left > 0) {
1303
      $term_original = $time_finish - strtotime($powerup_unit['unit_time_start']);
1304
      $level_current = $powerup_unit['unit_level'];
1305
    }
1306
  }
1307
1308
  $level_max = $level_max > $powerup_data[P_MAX_STACK] ? $level_max : $powerup_data[P_MAX_STACK];
1309
  $original_cost = 0;
1310
  for ($i = 1; $i <= $level_max; $i++) {
1311
    $base_cost = eco_get_total_cost($powerup_id, $i);
1312
    $base_cost = $base_cost[BUILD_CREATE][RES_DARK_MATTER];
1313
    foreach ($sn_powerup_buy_discounts as $period => $discount) {
1314
      $upgrade_price = floor($base_cost * $discount * $period / PERIOD_MONTH);
1315
      $result[$i][$period] = $upgrade_price;
1316
      $original_cost = $is_upgrade && $i == $level_current && $period <= $term_original ? $upgrade_price : $original_cost;
1317
    }
1318
  }
1319
1320
  if ($is_upgrade && $time_left) {
1321
    $term_original = round($term_original / PERIOD_DAY);
1322
    $time_left = min(floor($time_left / PERIOD_DAY), $term_original);
1323
    $cost_left = $term_original > 0 ? ceil($time_left / $term_original * $original_cost) : 0;
1324
1325
    array_walk_recursive($result, function (&$value) use ($cost_left) {
1326
      $value -= $cost_left;
1327
    });
1328
  }
1329
1330
  return $result;
1331
}
1332
1333
/**
1334
 * @param template $template
1335
 * @param array    $note_row
1336
 */
1337
function note_assign(&$template, $note_row) {
1338
  global $note_priority_classes;
1339
1340
  $template->assign_block_vars('note', array(
1341
    'ID'                     => $note_row['id'],
1342
    'TIME'                   => $note_row['time'],
1343
    'TIME_TEXT'              => date(FMT_DATE_TIME, $note_row['time']),
1344
    'PRIORITY'               => $note_row['priority'],
1345
    'PRIORITY_CLASS'         => $note_priority_classes[$note_row['priority']],
1346
    'PRIORITY_TEXT'          => classLocale::$lang['sys_notes_priorities'][$note_row['priority']],
1347
    'TITLE'                  => htmlentities($note_row['title'], ENT_COMPAT, 'UTF-8'),
1348
    'GALAXY'                 => intval($note_row['galaxy']),
1349
    'SYSTEM'                 => intval($note_row['system']),
1350
    'PLANET'                 => intval($note_row['planet']),
1351
    'PLANET_TYPE'            => intval($note_row['planet_type']),
1352
    'PLANET_TYPE_TEXT'       => classLocale::$lang['sys_planet_type'][$note_row['planet_type']],
1353
    'PLANET_TYPE_TEXT_SHORT' => classLocale::$lang['sys_planet_type_sh'][$note_row['planet_type']],
1354
    'TEXT'                   => sys_bbcodeParse(htmlentities($note_row['text'], ENT_COMPAT, 'UTF-8')),
1355
    'TEXT_EDIT'              => htmlentities($note_row['text'], ENT_COMPAT, 'UTF-8'),
1356
    'STICKY'                 => intval($note_row['sticky']),
1357
  ));
1358
}
1359
1360
function sn_version_compare_extra($version) {
1361
  static $version_regexp = '#(\d+)([a-f])(\d+)(?:\.(\d+))*#';
1362
  preg_match($version_regexp, $version, $version);
1363
  unset($version[0]);
1364
  $version[2] = ord($version[2]) - ord('a');
1365
1366
  return implode('.', $version);
1367
}
1368
1369
function sn_version_compare($ver1, $ver2) {
1370
  return version_compare(sn_version_compare_extra($ver1), sn_version_compare_extra($ver2));
1371
}
1372
1373
function sn_setcookie($name, $value = null, $expire = null, $path = SN_ROOT_RELATIVE, $domain = null, $secure = null, $httponly = null) {
1374
  $_COOKIE[$name] = $value;
1375
1376
  return setcookie($name, $value, $expire, $path, $domain, $secure, $httponly);
1377
}
1378
1379
function market_get_autoconvert_cost() {
1380
  return classSupernova::$config->rpg_cost_exchange ? classSupernova::$config->rpg_cost_exchange * 3 : 3000;
1381
}
1382
1383
function print_rr($var, $capture = false) {
1384
  $print = '<pre>' . htmlspecialchars(print_r($var, true)) . '</pre>';
1385
  if ($capture) {
1386
    return $print;
1387
  } else {
1388
    print($print);
1389
  }
1390
}
1391
1392
function can_capture_planet() { return sn_function_call(__FUNCTION__, array(&$result)); }
1393
1394
function sn_can_capture_planet(&$result) {
1395
  return $result = false;
1396
}
1397
1398
/**
1399
 * Возвращает информацию об IPv4 адресах пользователя
1400
 *
1401
 * НЕ ПОДДЕРЖИВАЕТ IPv6!
1402
 *
1403
 * @return array
1404
 */
1405
// OK v4
1406
function sec_player_ip() {
1407
  // TODO - IPv6 support
1408
  $ip = array(
1409
    'ip'          => $_SERVER["REMOTE_ADDR"],
1410
    'proxy_chain' => $_SERVER["HTTP_X_FORWARDED_FOR"]
1411
      ? $_SERVER["HTTP_X_FORWARDED_FOR"]
1412
      : ($_SERVER["HTTP_CLIENT_IP"]
1413
        ? $_SERVER["HTTP_CLIENT_IP"]
1414
        : '' // $_SERVER["REMOTE_ADDR"]
1415
      ),
1416
  );
1417
1418
  return array_map('db_escape', $ip);
1419
}
1420
1421
/**
1422
 * Converts unix timestamp to SQL DateTime
1423
 *
1424
 * @param int $value
1425
 *
1426
 * @return string|null
1427
 */
1428
function unixTimeStampToSqlString($value) {
1429
  $result = !empty($value) ? date(FMT_DATE_TIME_SQL, $value) : null;
1430
1431
  return $result ? $result : null;
1432
}
1433
1434
/**
1435
 * Converts SQL DateTime to unix timestamp
1436
 *
1437
 * @param $value
1438
 *
1439
 * @return int
1440
 */
1441
function sqlStringToUnixTimeStamp($value) {
1442
  $result = !empty($value) ? strtotime($value) : 0;
1443
1444
  return $result ? $result : 0;
1445
}
1446
1447
/**
1448
 * @param mixed $value
1449
 *
1450
 * @return mixed|null
1451
 */
1452
function nullIfEmpty($value) {
1453
  return !empty($value) ? $value : null;
1454
}
1455
1456
1457
/**
1458
 * @param $sort_option
1459
 * @param $sort_option_inverse
1460
 *
1461
 * @return mixed
1462
 */
1463
function sortUnitRenderedList(&$ListToSort, $sort_option, $sort_option_inverse) {
1464
  if ($sort_option || $sort_option_inverse != PLAYER_OPTION_SORT_ORDER_PLAIN) {
1465
    switch ($sort_option) {
1466
      case PLAYER_OPTION_SORT_NAME:
1467
        $sort_option_field = 'NAME';
1468
      break;
1469
      case PLAYER_OPTION_SORT_SPEED:
1470
        $sort_option_field = 'SPEED';
1471
      break;
1472
      case PLAYER_OPTION_SORT_COUNT:
1473
        $sort_option_field = 'AMOUNT';
1474
      break;
1475
      case PLAYER_OPTION_SORT_ID:
1476
        $sort_option_field = 'ID';
1477
      break;
1478
      case PLAYER_OPTION_SORT_CREATE_TIME_LENGTH:
1479
        $sort_option_field = 'TIME_SECONDS';
1480
      break;
1481
      default:
1482
        $sort_option_field = '__INDEX';
1483
      break;
1484
    }
1485
    $sort_option_inverse_closure = $sort_option_inverse ? -1 : 1;
1486
    usort($ListToSort, function ($a, $b) use ($sort_option_field, $sort_option_inverse_closure) {
1487
      return $a[$sort_option_field] < $b[$sort_option_field] ? -1 * $sort_option_inverse_closure : (
1488
      $a[$sort_option_field] > $b[$sort_option_field] ? 1 * $sort_option_inverse_closure : 0
1489
      );
1490
    });
1491
  }
1492
1493
}
1494