Completed
Push — work-fleets ( fff2b6...e0e753 )
by SuperNova.WS
06:54
created

general.php ➔ sn_player_nick_render_current_to_array()   F

Complexity

Conditions 31
Paths 600

Size

Total Lines 34
Code Lines 18

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 31
eloc 18
nc 600
nop 3
dl 0
loc 34
rs 2.6656
c 1
b 0
f 0

How to fix   Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

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);
248
}
249
250
/**
251
 * @param        $param_name
252
 * @param string $default
253
 *
254
 * @return string|array
255
 */
256
function sys_get_param($param_name, $default = '') {
257
  return $_POST[$param_name] !== null ? $_POST[$param_name] : ($_GET[$param_name] !== null ? $_GET[$param_name] : $default);
258
}
259
260
function sys_get_param_array($param_name, $default = array()) {
261
  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...
262
}
263
264
function sys_get_param_id($param_name, $default = 0) {
265
  return is_id($value = sys_get_param($param_name, $default)) ? $value : $default;
266
}
267
268
function sys_get_param_int($param_name, $default = 0) {
269
  $value = sys_get_param($param_name, $default);
270
271
  return $value === 'on' ? 1 : ($value === 'off' ? $default : intval($value));
272
}
273
274
function sys_get_param_float($param_name, $default = 0) {
275
  return floatval(sys_get_param($param_name, $default));
276
}
277
278
function sys_get_param_escaped($param_name, $default = '') {
279
  return db_escape(sys_get_param($param_name, $default));
280
}
281
282
function sys_get_param_date_sql($param_name, $default = '2000-01-01') {
283
  $val = sys_get_param($param_name, $default);
284
285
  return preg_match(PREG_DATE_SQL_RELAXED, $val) ? $val : $default;
286
}
287
288
function sys_get_param_str_unsafe($param_name, $default = '') {
289
  return str_raw2unsafe(sys_get_param($param_name, $default));
290
}
291
292
function sys_get_param_str($param_name, $default = '') {
293
  return db_escape(sys_get_param_str_unsafe($param_name, $default));
294
}
295
296
function sys_get_param_str_both($param_name, $default = '') {
297
  $param = sys_get_param($param_name, $default);
298
  $param_unsafe = str_raw2unsafe($param);
299
300
  return array(
301
    'raw'    => $param,
302
    'unsafe' => $param_unsafe,
303
    'safe'   => db_escape($param_unsafe),
304
  );
305
}
306
307
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...
308
  $phone_raw = sys_get_param_str_unsafe($param_name, $default = '');
309
  if ($phone_raw) {
310
    $phone = $phone_raw[0] == '+' ? '+' : '';
311
    for ($i = 0; $i < strlen($phone_raw); $i++) {
312
      $ord = ord($phone_raw[$i]);
313
      if ($ord >= 48 && $ord <= 57) {
314
        $phone .= $phone_raw[$i];
315
      }
316
    }
317
    $phone = strlen($phone) < 11 ? '' : $phone;
318
  } else {
319
    $phone = '';
320
  }
321
322
  return array('raw' => $phone_raw, 'phone' => $phone);
323
}
324
325
function GetPhalanxRange($phalanx_level) {
326
  return $phalanx_level > 1 ? pow($phalanx_level, 2) - 1 : 0;
327
}
328
329
function CheckAbandonPlanetState(&$planet) {
330
  if ($planet['destruyed'] && $planet['destruyed'] <= SN_TIME_NOW) {
331
    db_planet_delete_by_id($planet['id']);
332
  }
333
}
334
335
function eco_get_total_cost($unit_id, $unit_level) {
336
  static $rate, $sn_group_resources_all, $sn_group_resources_loot;
337
  if (!$rate) {
338
    $sn_group_resources_all = sn_get_groups('resources_all');
339
    $sn_group_resources_loot = sn_get_groups('resources_loot');
340
341
    $rate[RES_METAL] = classSupernova::$config->rpg_exchange_metal;
342
    $rate[RES_CRYSTAL] = classSupernova::$config->rpg_exchange_crystal / classSupernova::$config->rpg_exchange_metal;
343
    $rate[RES_DEUTERIUM] = classSupernova::$config->rpg_exchange_deuterium / classSupernova::$config->rpg_exchange_metal;
344
  }
345
346
  $unit_cost_data = get_unit_param($unit_id, 'cost');
347
  if (!is_array($unit_cost_data)) {
348
    return array('total' => 0);
349
  }
350
  $factor = isset($unit_cost_data['factor']) ? $unit_cost_data['factor'] : 1;
351
  $cost_array = array(BUILD_CREATE => array(), 'total' => 0);
352
  $unit_level = $unit_level > 0 ? $unit_level : 0;
353
  foreach ($unit_cost_data as $resource_id => $resource_amount) {
354
    if (!in_array($resource_id, $sn_group_resources_all)) {
355
      continue;
356
    }
357
    $cost_array[BUILD_CREATE][$resource_id] = round($resource_amount * ($factor == 1 ? $unit_level : ((1 - pow($factor, $unit_level)) / (1 - $factor))));
358
    if (in_array($resource_id, $sn_group_resources_loot)) {
359
      $cost_array['total'] += $cost_array[BUILD_CREATE][$resource_id] * $rate[$resource_id];
360
    }
361
  }
362
363
  return $cost_array;
364
}
365
366
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...
367
368
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...
369
370
/**
371
 * @param array|bool|null $user
372
 * @param array|null      $planet
373
 * @param int             $unit_id
374
 * @param bool            $for_update
375
 * @param bool            $plain
376
 *
377
 * @return mixed
378
 */
379
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)); }
380
381
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...
382
  $mercenary_level = 0;
383
  $unit_db_name = pname_resource_name($unit_id);
384
385
  if (in_array($unit_id, sn_get_groups(array('plans', 'mercenaries', 'tech', 'artifacts')))) {
386
    $unit = classSupernova::db_get_unit_by_location($user['id'], LOC_USER, $user['id'], $unit_id);
387
    $mercenary_level = is_array($unit) && $unit['unit_level'] ? $unit['unit_level'] : 0;
388
  } elseif (in_array($unit_id, sn_get_groups(array('structures', 'fleet', 'defense')))) {
389
    $unit = classSupernova::db_get_unit_by_location(isset($user['id']) ? $user['id'] : $planet['id_owner'], LOC_PLANET, $planet['id'], $unit_id);
390
    $mercenary_level = is_array($unit) && $unit['unit_level'] ? $unit['unit_level'] : 0;
391
  } elseif (in_array($unit_id, sn_get_groups('governors'))) {
392
    $mercenary_level = $unit_id == $planet['PLANET_GOVERNOR_ID'] ? $planet['PLANET_GOVERNOR_LEVEL'] : 0;
393
  } elseif ($unit_id == RES_DARK_MATTER) {
394
    $mercenary_level = $user[$unit_db_name] + ($plain || $user['user_as_ally'] ? 0 : classSupernova::$auth->account->account_metamatter);
395
  } elseif ($unit_id == RES_METAMATTER) {
396
    $mercenary_level = classSupernova::$auth->account->account_metamatter; //$user[$unit_db_name];
397
  } elseif (in_array($unit_id, sn_get_groups(array('resources_loot'))) || $unit_id == UNIT_SECTOR) {
398
    $mercenary_level = !empty($planet) ? $planet[$unit_db_name] : $user[$unit_db_name];
399
  }
400
401
  return $result = $mercenary_level;
402
}
403
404
function mrc_modify_value(&$user, $planet = array(), $mercenaries, $value) { return sn_function_call(__FUNCTION__, array(&$user, $planet, $mercenaries, $value)); }
405
406
function sn_mrc_modify_value(&$user, $planet = array(), $mercenaries, $value, $base_value = null) {
407
  if (!is_array($mercenaries)) {
408
    $mercenaries = array($mercenaries);
409
  }
410
411
  $base_value = isset($base_value) ? $base_value : $value;
412
413
  foreach ($mercenaries as $mercenary_id) {
414
    $mercenary_level = mrc_get_level($user, $planet, $mercenary_id);
415
416
    $mercenary = get_unit_param($mercenary_id);
417
    $mercenary_bonus = $mercenary['bonus'];
418
419
    switch ($mercenary['bonus_type']) {
420
      case BONUS_PERCENT_CUMULATIVE:
421
        $value *= 1 + $mercenary_level * $mercenary_bonus / 100;
422
      break;
423
424
      case BONUS_PERCENT:
425
        $mercenary_level = $mercenary_bonus < 0 && $mercenary_level * $mercenary_bonus < -90 ? -90 / $mercenary_bonus : $mercenary_level;
426
        $value += $base_value * $mercenary_level * $mercenary_bonus / 100;
427
      break;
428
429
      case BONUS_ADD:
430
        $value += $mercenary_level * $mercenary_bonus;
431
      break;
432
433
      case BONUS_ABILITY:
434
        $value = $mercenary_level ? $mercenary_level : 0;
435
      break;
436
437
      default:
438
      break;
439
    }
440
  }
441
442
  return $value;
443
}
444
445
// Generates random string of $length symbols from $allowed_chars charset
446
function sys_random_string($length = 16, $allowed_chars = SN_SYS_SEC_CHARS_ALLOWED) {
447
  $allowed_length = strlen($allowed_chars);
448
449
  $random_string = '';
450
  for ($i = 0; $i < $length; $i++) {
451
    $random_string .= $allowed_chars[mt_rand(0, $allowed_length - 1)];
452
  }
453
454
  return $random_string;
455
}
456
457
function js_safe_string($string) {
458
  return str_replace(array("\r", "\n"), array('\r', '\n'), addslashes($string));
459
}
460
461
function sys_safe_output($string) {
462
  return str_replace(array("&", "\"", "<", ">", "'"), array("&amp;", "&quot;", "&lt;", "&gt;", "&apos;"), $string);
463
}
464
465
function sys_user_options_pack(&$user) {
466
  global $user_option_list;
467
468
  $options = '';
469
  $option_list = array();
470
  foreach ($user_option_list as $option_group_id => $option_group) {
471
    $option_list[$option_group_id] = array();
472
    foreach ($option_group as $option_name => $option_value) {
473
      if (!isset($user[$option_name])) {
474
        $user[$option_name] = $option_value;
475
      } elseif ($user[$option_name] == '') {
476
        $user[$option_name] = 0;
477
      }
478
      $options .= "{$option_name}^{$user[$option_name]}|";
479
      $option_list[$option_group_id][$option_name] = $user[$option_name];
480
    }
481
  }
482
483
  $user['options'] = $options;
484
  $user['option_list'] = $option_list;
485
486
  return $options;
487
}
488
489
function sys_user_options_unpack(&$user) {
490
  global $user_option_list;
491
492
  $option_list = array();
493
  $option_string_list = explode('|', $user['options']);
494
495
  foreach ($option_string_list as $option_string) {
496
    list($option_name, $option_value) = explode('^', $option_string);
497
    $option_list[$option_name] = $option_value;
498
  }
499
500
  $final_list = array();
501
  foreach ($user_option_list as $option_group_id => $option_group) {
502
    $final_list[$option_group_id] = array();
503
    foreach ($option_group as $option_name => $option_value) {
504
      if (!isset($option_list[$option_name])) {
505
        $option_list[$option_name] = $option_value;
506
      }
507
      $user[$option_name] = $final_list[$option_group_id][$option_name] = $option_list[$option_name];
508
    }
509
  }
510
511
  $user['option_list'] = $final_list;
512
513
  return $final_list;
514
}
515
516
function sys_unit_str2arr($fleet_string) {
517
  $fleet_array = array();
518
  if (!empty($fleet_string)) {
519
    $arrTemp = explode(';', $fleet_string);
520
    foreach ($arrTemp as $temp) {
521
      if ($temp) {
522
        $temp = explode(',', $temp);
523
        if (!empty($temp[0]) && !empty($temp[1])) {
524
          $fleet_array[$temp[0]] += $temp[1];
525
        }
526
      }
527
    }
528
  }
529
530
  return $fleet_array;
531
}
532
533
function sys_unit_arr2str($unit_list) {
534
  $fleet_string = array();
535
  if (isset($unit_list)) {
536
    if (!is_array($unit_list)) {
537
      $unit_list = array($unit_list => 1);
538
    }
539
540
    foreach ($unit_list as $unit_id => $unit_count) {
541
      if ($unit_id && $unit_count) {
542
        $fleet_string[] = "{$unit_id},{$unit_count}";
543
      }
544
    }
545
  }
546
547
  return implode(';', $fleet_string);
548
}
549
550
function mymail($email_unsafe, $title, $body, $from = '', $html = false) {
551
  $from = trim($from ? $from : classSupernova::$config->game_adminEmail);
552
553
  $head = '';
554
  $head .= "Content-Type: text/" . ($html ? 'html' : 'plain') . "; charset=utf-8 \r\n";
555
  $head .= "Date: " . date('r') . " \r\n";
556
  $classConfig = classSupernova::$config;
557
  $head .= "Return-Path: {$classConfig->game_adminEmail} \r\n";
558
  $head .= "From: {$from} \r\n";
559
  $head .= "Sender: {$from} \r\n";
560
  $head .= "Reply-To: {$from} \r\n";
561
  // $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...
562
  $head .= "X-Sender: {$from} \r\n";
563
  $head .= "X-Priority: 3 \r\n";
564
  $body = str_replace("\r\n", "\n", $body);
565
  $body = str_replace("\n", "\r\n", $body);
566
567
  if ($html) {
568
    $body = '<html><head><base href="' . SN_ROOT_VIRTUAL . '"></head><body>' . nl2br($body) . '</body></html>';
569
  }
570
571
  $title = '=?UTF-8?B?' . base64_encode($title) . '?=';
572
573
  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.

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...
574
}
575
576
function sys_time_human($time, $full = false) {
577
  $seconds = $time % 60;
578
  $time = floor($time / 60);
579
  $minutes = $time % 60;
580
  $time = floor($time / 60);
581
  $hours = $time % 24;
582
  $time = floor($time / 24);
583
584
  $classLocale = classLocale::$lang;
585
586
  return
587
    ($full || $time ? "{$time} {$classLocale['sys_day']}&nbsp;" : '') .
588
    ($full || $hours ? "{$hours} {$classLocale['sys_hrs']}&nbsp;" : '') .
589
    ($full || $minutes ? "{$minutes} {$classLocale['sys_min']}&nbsp;" : '') .
590
    ($full || !$time || $seconds ? "{$seconds} {$classLocale['sys_sec']}" : '');
591
}
592
593
function sys_time_human_system($time) {
594
  return $time ? date(FMT_DATE_TIME_SQL, $time) . " ({$time}), " . sys_time_human(SN_TIME_NOW - $time) : '{NEVER}';
595
}
596
597
function sys_redirect($url) {
598
  header("Location: {$url}");
599
  ob_end_flush();
600
  die();
601
}
602
603
// TODO Для полноценного функионирования апдейтера пакет функций, включая эту должен быть вынесен раньше - или грузить general.php до апдейтера
604
function sys_get_unit_location($user, $planet, $unit_id) { return sn_function_call(__FUNCTION__, array($user, $planet, $unit_id)); }
605
606
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...
607
  return get_unit_param($unit_id, 'location');
608
}
609
610
function sn_ali_fill_user_ally(&$user) {
611
  if (!$user['ally_id']) {
612
    return;
613
  }
614
615
  if (!isset($user['ally'])) {
616
    $user['ally'] = db_ally_get_by_id($user['ally_id']);
617
  }
618
619
  if (!isset($user['ally']['player'])) {
620
    $user['ally']['player'] = db_user_by_id($user['ally']['ally_user_id'], true, '*', false);
621
  }
622
}
623
624
function sn_get_url_contents($url) {
625
  if (function_exists('curl_init')) {
626
    $crl = curl_init();
627
    $timeout = 5;
628
    curl_setopt($crl, CURLOPT_URL, $url);
629
    curl_setopt($crl, CURLOPT_RETURNTRANSFER, 1);
630
    curl_setopt($crl, CURLOPT_CONNECTTIMEOUT, $timeout);
631
    $return = curl_exec($crl);
632
    curl_close($crl);
633
  } else {
634
    $return = @file_get_contents($url);
635
  }
636
637
  return $return;
638
}
639
640
function get_engine_data($user, $engine_info) {
641
  $sn_data_tech_bonus = get_unit_param($engine_info['tech'], 'bonus');
642
643
  $user_tech_level = intval(mrc_get_level($user, null, $engine_info['tech']));
644
645
  $engine_info['speed_base'] = $engine_info['speed'];
646
  $tech_bonus = ($user_tech_level - $engine_info['min_level']) * $sn_data_tech_bonus / 100;
647
  $tech_bonus = $tech_bonus < -0.9 ? -0.95 : $tech_bonus;
648
  $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...
649
650
  $engine_info['consumption_base'] = $engine_info['consumption'];
651
  $tech_bonus = ($user_tech_level - $engine_info['min_level']) * $sn_data_tech_bonus / 1000;
652
  $tech_bonus = $tech_bonus > 0.5 ? 0.5 : ($tech_bonus < 0 ? $tech_bonus * 2 : $tech_bonus);
653
  $engine_info['consumption'] = ceil($engine_info['consumption'] * (1 - $tech_bonus));
654
655
  return $engine_info;
656
}
657
658
function get_ship_data($ship_id, $user) {
659
  $ship_data = array();
660
  if (in_array($ship_id, sn_get_groups(array('fleet', 'missile')))) {
661
    foreach (get_unit_param($ship_id, 'engine') as $engine_info) {
662
      $tech_level = intval(mrc_get_level($user, null, $engine_info['tech']));
663
      if (empty($ship_data) || $tech_level >= $engine_info['min_level']) {
664
        $ship_data = $engine_info;
665
        $ship_data['tech_level'] = $tech_level;
666
      }
667
    }
668
    $ship_data = get_engine_data($user, $ship_data);
669
    $ship_data['capacity'] = get_unit_param($ship_id, 'capacity');
670
  }
671
672
  return $ship_data;
673
}
674
675
if (!function_exists('strptime')) {
676
  function strptime($date, $format) {
677
    $masks = array(
678
      '%d' => '(?P<d>[0-9]{2})',
679
      '%m' => '(?P<m>[0-9]{2})',
680
      '%Y' => '(?P<Y>[0-9]{4})',
681
      '%H' => '(?P<H>[0-9]{2})',
682
      '%M' => '(?P<M>[0-9]{2})',
683
      '%S' => '(?P<S>[0-9]{2})',
684
      // usw..
685
    );
686
687
    $rexep = "#" . strtr(preg_quote($format), $masks) . "#";
688
    if (preg_match($rexep, $date, $out)) {
689
      $ret = array(
690
        "tm_sec"  => (int)$out['S'],
691
        "tm_min"  => (int)$out['M'],
692
        "tm_hour" => (int)$out['H'],
693
        "tm_mday" => (int)$out['d'],
694
        "tm_mon"  => $out['m'] ? $out['m'] - 1 : 0,
695
        "tm_year" => $out['Y'] > 1900 ? $out['Y'] - 1900 : 0,
696
      );
697
    } else {
698
      $ret = false;
699
    }
700
701
    return $ret;
702
  }
703
}
704
705
function sn_sys_sector_buy($redirect = 'overview.php') {
706
  global $user, $planetrow;
707
708
  if (!sys_get_param_str('sector_buy') || $planetrow['planet_type'] != PT_PLANET) {
709
    return;
710
  }
711
712
  sn_db_transaction_start();
713
  $user = db_user_by_id($user['id'], true, '*');
714
  $planetrow = db_planet_by_id($planetrow['id'], true, '*');
715
  // Тут не надо делать обсчет - ресурсы мы уже посчитали, очередь (и количество зданий) - тоже
716
  $sector_cost = eco_get_build_data($user, $planetrow, UNIT_SECTOR, mrc_get_level($user, $planetrow, UNIT_SECTOR), true);
717
  $sector_cost = $sector_cost[BUILD_CREATE][RES_DARK_MATTER];
718
  if ($sector_cost <= mrc_get_level($user, null, RES_DARK_MATTER)) {
719
    $planet_name_text = uni_render_planet($planetrow);
720
    if (rpg_points_change($user['id'], RPG_SECTOR, -$sector_cost, sprintf(classLocale::$lang['sys_sector_purchase_log'],
721
        $user['username'], $user['id'], $planet_name_text, classLocale::$lang['sys_planet_type'][$planetrow['planet_type']], $planetrow['id'], $sector_cost)
722
    )) {
723
      $sector_db_name = pname_resource_name(UNIT_SECTOR);
724
      db_planet_set_by_id($planetrow['id'], "{$sector_db_name} = {$sector_db_name} + 1");
725
    } else {
726
      sn_db_transaction_rollback();
727
    }
728
  }
729
  sn_db_transaction_commit();
730
731
  sys_redirect($redirect);
732
}
733
734
function sn_sys_handler_add(&$functions, $handler_list, $class_module_name = '', $sub_type = '') {
735
  if (isset($handler_list) && is_array($handler_list) && !empty($handler_list)) {
736
    foreach ($handler_list as $function_name => $function_data) {
737
      $override_with = '';
738
      if (is_string($function_data)) {
739
        $override_with = &$function_data;
740
      } elseif (isset($function_data['callable'])) {
741
        $override_with = &$function_data['callable'];
742
      }
743
744
      $overwrite = $override_with[0] == '*';
745
      if ($overwrite) {
746
        $override_with = substr($override_with, 1);
747
      }
748
749
      if (($point_position = strpos($override_with, '.')) === false && $class_module_name) {
750
        $override_with = array($class_module_name, $override_with);
751
      } elseif ($point_position == 0) {
752
        $override_with = substr($override_with, 1);
753
      } elseif ($point_position > 0) {
754
        $override_with = array(substr($override_with, 0, $point_position), substr($override_with, $point_position + 1));
755
      }
756
757
      if ($overwrite) {
758
        $functions[$function_name] = array();
759
      } elseif (!isset($functions[$function_name])) {
760
        $functions[$function_name] = array();
761
        $sn_function_name = 'sn_' . $function_name . ($sub_type ? '_' . $sub_type : '');
762
        $functions[$function_name][] = $sn_function_name;
763
      }
764
765
      $functions[$function_name][] = $function_data;
766
    }
767
  }
768
}
769
770
// TODO - поменять название
771
// Может принимать: (array)$user, $nick_render_array, $nick_render_array_html, $nick_render_string_compact
772
function player_nick_render_to_html($result, $options = false) {
773
  // TODO - обрабатывать разные случаи: $user, $render_nick_array, $string
774
775
  if (is_string($result) && strpos($result, ':{i:')) {
776
    $result = player_nick_uncompact($result);
777
  }
778
779
  if (is_array($result)) {
780
    if (isset($result['id'])) {
781
      $result = player_nick_render_current_to_array($result, $options);
782
    }
783
    if (!isset($result[NICK_HTML])) {
784
      $result = player_nick_render_array_to_html($result);
785
    }
786
    unset($result[NICK_HTML]);
787
    ksort($result);
788
    $result = implode('', $result);
789
  }
790
791
  return $result;
792
}
793
794
795
function player_nick_compact($nick_array) {
796
  ksort($nick_array);
797
798
  return serialize($nick_array);
799
}
800
801
function player_nick_uncompact($nick_string) {
802
  try {
803
    $result = unserialize($nick_string);
804
  } catch (exception $e) {
805
    $result = strpos($nick_string, ':{i:') ? null : $nick_string; // fallback if it is already string - for old chat strings, for example
806
  }
807
808
  return $result;
809
}
810
811
function player_nick_render_array_to_html($nick_array) { return sn_function_call(__FUNCTION__, array($nick_array, &$result)); }
812
813
function sn_player_nick_render_array_to_html($nick_array, &$result) {
814
  global $user;
815
816
  // ALL STRING ARE UNSAFE!!!
817
  if (isset($nick_array[NICK_BIRTHSDAY])) {
818
    $result[NICK_BIRTHSDAY] = '<img src="design/images/birthday.png" />';
819
  }
820
821
  if (isset($nick_array[NICK_VACATION])) {
822
    $result[NICK_VACATION] = '<img src="design/images/icon_vacation.png" />';
823
  }
824
825
  if (isset($nick_array[NICK_GENDER])) {
826
    $result[NICK_GENDER] = '<img src="' . ($user['dpath'] ? $user['dpath'] : DEFAULT_SKINPATH) . 'images/gender_' . $nick_array[NICK_GENDER] . '.png" />';
827
  }
828
829
  if (isset($nick_array[NICK_AUTH_LEVEL]) || isset($nick_array[NICK_PREMIUM])) {
830
    switch ($nick_array[NICK_AUTH_LEVEL]) {
831
      case 4:
832
        $highlight = classSupernova::$config->chat_highlight_developer;
833
      break;
834
835
      case 3:
836
        $highlight = classSupernova::$config->chat_highlight_admin;
837
      break;
838
839
      case 2:
840
        $highlight = classSupernova::$config->chat_highlight_operator;
841
      break;
842
843
      case 1:
844
        $highlight = classSupernova::$config->chat_highlight_moderator;
845
      break;
846
847
      default:
848
        $highlight = isset($nick_array[NICK_PREMIUM]) ? classSupernova::$config->chat_highlight_premium : '';
849
    }
850
851
    if ($highlight) {
852
      list($result[NICK_HIGHLIGHT], $result[NICK_HIGHLIGHT_END]) = explode('$1', $highlight);
853
    }
854
  }
855
856 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...
857
    $result[NICK_CLASS] = '<span ' . $nick_array[NICK_CLASS] . '>';
858
    $result[NICK_CLASS_END] = '</span>';
859
  }
860
861
  $result[NICK_NICK] = sys_safe_output($nick_array[NICK_NICK]);
862
863 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...
864
    $result[NICK_ALLY] = '[' . sys_safe_output($nick_array[NICK_ALLY]) . ']';
865
  }
866
867
  $result[NICK_HTML] = true;
868
869
  return $result;
870
}
871
872
function player_nick_render_current_to_array($render_user, $options = false) { return sn_function_call(__FUNCTION__, array($render_user, $options, &$result)); }
873
874
function sn_player_nick_render_current_to_array($render_user, $options = false, &$result) {
875
  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))) {
876
    $result[NICK_BIRTHSDAY] = '';
877
  }
878
879
  if ($options === true || (isset($options['icons']) && $options['icons']) || (isset($options['gender']) && $options['gender'])) {
880
    $result[NICK_GENDER] = $render_user['gender'] == GENDER_UNKNOWN ? 'unknown' : ($render_user['gender'] == GENDER_FEMALE ? 'female' : 'male');
881
  }
882
883
  if (($options === true || (isset($options['icons']) && $options['icons']) || (isset($options['vacancy']) && $options['vacancy'])) && $render_user['vacation']) {
884
    $result[NICK_VACATION] = $render_user['vacation'];
885
  }
886
887
  if ($options === true || (isset($options['color']) && $options['color'])) {
888
    if ($user_auth_level = $render_user['authlevel']) {
889
      $result[NICK_AUTH_LEVEL] = $user_auth_level;
890
    }
891
    if ($user_premium = mrc_get_level($render_user, null, UNIT_PREMIUM)) {
892
      $result[NICK_PREMIUM] = $user_premium;
893
    }
894
  }
895
896
  if ((isset($options['class']) && $options['class'])) {
897
    $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...
898
  }
899
900
  if ($render_user['ally_tag'] && ($options === true || (isset($options['ally']) && $options['ally']))) {
901
    $result[NICK_ALLY] = $render_user['ally_tag'];
902
  }
903
904
  $result[NICK_NICK] = $render_user['username'];
905
906
  return $result;
907
}
908
909
910
// TODO sys_stat_get_user_skip_list() ПЕРЕДЕЛАТЬ!
911
function sys_stat_get_user_skip_list() {
912
  $result = array();
913
914
  $user_skip_list = array();
915
916
  if (classSupernova::$config->stats_hide_admins) {
917
    $user_skip_list[] = '`authlevel` > 0';
918
  }
919
920
  if (classSupernova::$config->stats_hide_player_list) {
921
    $temp = explode(',', classSupernova::$config->stats_hide_player_list);
922
    foreach ($temp as $user_id) {
923
      $user_id = floatval($user_id);
924
      if ($user_id) {
925
        $user_skip_list[] = '`id` = ' . $user_id;
926
      }
927
    }
928
  }
929
930
  if (!empty($user_skip_list)) {
931
    $user_skip_list = implode(' OR ', $user_skip_list);
932
    $user_skip_query = db_user_list($user_skip_list);
933
    if (!empty($user_skip_query)) {
934
      foreach ($user_skip_query as $user_skip_row) {
935
        $result[$user_skip_row['id']] = $user_skip_row['id'];
936
      }
937
    }
938
  }
939
940
  return $result;
941
}
942
943
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)); }
944
945
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...
946
  global $sn_data;
947
948
  $result = isset($sn_data[$unit_id])
949
    ? ($param_name === null
950
      ? $sn_data[$unit_id]
951
      : (isset($sn_data[$unit_id][$param_name]) ? $sn_data[$unit_id][$param_name] : $result)
952
    )
953
    : $result;
954
955
  return $result;
956
}
957
958
/**
959
 * @param $groups
960
 *
961
 * @return array
962
 */
963
function sn_get_groups($groups) { return sn_function_call(__FUNCTION__, array($groups, &$result)); }
964
965
/**
966
 * @param $groups
967
 * @param $result
968
 *
969
 * @return array
970
 */
971
function sn_sn_get_groups($groups, &$result) {
972
  $result = is_array($result) ? $result : array();
973
  foreach ($groups = is_array($groups) ? $groups : array($groups) as $group_name) {
974
    $result += is_array($a_group = get_unit_param(UNIT_GROUP, $group_name)) ? $a_group : array();
975
  }
976
977
  return $result;
978
}
979
980
// Format $value to ID
981
/**
982
 * @param     $value
983
 * @param int $default
984
 *
985
 * @return float|int
986
 */
987
function idval($value, $default = 0) {
988
  $value = floatval($value);
989
990
  return preg_match('#^(\d*)#', $value, $matches) && $matches[1] ? floatval($matches[1]) : $default;
991
}
992
993
function unit_requirements_render($user, $planetrow, $unit_id, $field = 'require') { return sn_function_call(__FUNCTION__, array($user, $planetrow, $unit_id, $field, &$result)); }
994
995
function sn_unit_requirements_render($user, $planetrow, $unit_id, $field = 'require', &$result) {
996
  $sn_data_unit = get_unit_param($unit_id);
997
998
  $result = is_array($result) ? $result : array();
999
  if ($sn_data_unit[$field] && !($sn_data_unit[P_UNIT_TYPE] == UNIT_MERCENARIES && classSupernova::$config->empire_mercenary_temporary)) {
1000
    foreach ($sn_data_unit[$field] as $require_id => $require_level) {
1001
      $level_got = mrc_get_level($user, $planetrow, $require_id);
1002
      $level_basic = mrc_get_level($user, $planetrow, $require_id, false, true);
1003
      $result[] = array(
1004
        'NAME'             => classLocale::$lang['tech'][$require_id],
1005
        //'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...
1006
        'REQUEREMENTS_MET' => intval($require_level <= $level_got ? REQUIRE_MET : REQUIRE_MET_NOT),
1007
        'LEVEL_REQUIRE'    => $require_level,
1008
        'LEVEL'            => $level_got,
1009
        'LEVEL_BASIC'      => $level_basic,
1010
        'LEVEL_BONUS'      => max(0, $level_got - $level_basic),
1011
        'ID'               => $require_id,
1012
      );
1013
    }
1014
  }
1015
1016
  return $result;
1017
}
1018
1019
function ally_get_ranks(&$ally) {
1020
  global $ally_rights;
1021
1022
  $ranks = array();
1023
1024
  if ($ally['ranklist']) {
1025
    $str_ranks = explode(';', $ally['ranklist']);
1026
    foreach ($str_ranks as $str_rank) {
1027
      if (!$str_rank) {
1028
        continue;
1029
      }
1030
1031
      $tmp = explode(',', $str_rank);
1032
      $rank_id = count($ranks);
1033
      foreach ($ally_rights as $key => $value) {
1034
        $ranks[$rank_id][$value] = $tmp[$key];
1035
      }
1036
    }
1037
  }
1038
1039
  return $ranks;
1040
}
1041
1042
function sys_player_new_adjust($user_id, $planet_id) { return sn_function_call(__FUNCTION__, array($user_id, $planet_id, &$result)); }
1043
1044
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...
1045
  return $result;
1046
}
1047
1048
function array_merge_recursive_numeric($array1, $array2) {
1049
  if (!empty($array2) && is_array($array2)) {
1050
    foreach ($array2 as $key => $value) {
1051
      $array1[$key] = !isset($array1[$key]) || !is_array($array1[$key]) ? $value : array_merge_recursive_numeric($array1[$key], $value);
1052
    }
1053
  }
1054
1055
  return $array1;
1056
}
1057
1058
function sn_sys_array_cumulative_sum(&$array) {
1059
  $accum = 0;
1060
  foreach ($array as &$value) {
1061
    $accum += $value;
1062
    $value = $accum;
1063
  }
1064
}
1065
1066
function planet_density_price_chart($planet_row) {
1067
  $sn_data_density = sn_get_groups('planet_density');
1068
  $density_price_chart = array();
1069
1070
  foreach ($sn_data_density as $density_id => $density_data) {
1071
    // Отсекаем записи с RARITY = 0 - служебные записи и супер-ядра
1072
    $density_data[UNIT_PLANET_DENSITY_RARITY] ? $density_price_chart[$density_id] = $density_data[UNIT_PLANET_DENSITY_RARITY] : false;
1073
  }
1074
  unset($density_price_chart[PLANET_DENSITY_NONE]);
1075
1076
  $total_rarity = array_sum($density_price_chart);
1077
1078
  foreach ($density_price_chart as &$density_data) {
1079
    $density_data = ceil($total_rarity / $density_data * $planet_row['field_max'] * PLANET_DENSITY_TO_DARK_MATTER_RATE);
1080
  }
1081
1082
  return $density_price_chart;
1083
}
1084
1085
function sn_sys_planet_core_transmute(&$user, &$planetrow) {
1086
  if (!sys_get_param_str('transmute')) {
1087
    return array();
1088
  }
1089
1090
  try {
1091 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...
1092
      throw new exception(classLocale::$lang['ov_core_err_not_a_planet'], ERR_ERROR);
1093
    }
1094
1095
    if ($planetrow['density_index'] == ($new_density_index = sys_get_param_id('density_type'))) {
1096
      throw new exception(classLocale::$lang['ov_core_err_same_density'], ERR_WARNING);
1097
    }
1098
1099
    sn_db_transaction_start();
1100
    $user = db_user_by_id($user['id'], true, '*');
1101
    $planetrow = db_planet_by_id($planetrow['id'], true, '*');
1102
1103
    $planet_density_index = $planetrow['density_index'];
1104
1105
    $density_price_chart = planet_density_price_chart($planetrow);
1106
    if (!isset($density_price_chart[$new_density_index])) {
1107
      // Hack attempt
1108
      throw new exception(classLocale::$lang['ov_core_err_denisty_type_wrong'], ERR_ERROR);
1109
    }
1110
1111
    $user_dark_matter = mrc_get_level($user, null, RES_DARK_MATTER);
1112
    $transmute_cost = $density_price_chart[$new_density_index];
1113
    if ($user_dark_matter < $transmute_cost) {
1114
      throw new exception(classLocale::$lang['ov_core_err_no_dark_matter'], ERR_ERROR);
1115
    }
1116
1117
    $sn_data_planet_density = sn_get_groups('planet_density');
1118
    $prev_density_index = PLANET_DENSITY_NONE;
1119
    foreach ($sn_data_planet_density as $key => $value) {
1120
      if ($key == $new_density_index) {
1121
        break;
1122
      }
1123
      $prev_density_index = $key;
1124
    }
1125
1126
    $new_density = round(($sn_data_planet_density[$new_density_index][UNIT_PLANET_DENSITY] + $sn_data_planet_density[$prev_density_index][UNIT_PLANET_DENSITY]) / 2);
1127
1128
    rpg_points_change($user['id'], RPG_PLANET_DENSITY_CHANGE, -$transmute_cost,
1129
      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...
1130
        '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',
1131
        $planetrow['name'],
1132
        $planetrow['id'],
1133
        uni_render_coordinates($planetrow),
1134
        $planet_density_index,
1135
        classLocale::$lang['uni_planet_density_types'][$planet_density_index],
1136
        $new_density_index,
1137
        classLocale::$lang['uni_planet_density_types'][$new_density_index],
1138
        $new_density
1139
      )
1140
    );
1141
1142
    db_planet_set_by_id($planetrow['id'], "`density` = {$new_density}, `density_index` = {$new_density_index}");
1143
    sn_db_transaction_commit();
1144
1145
    $planetrow['density'] = $new_density;
1146
    $planetrow['density_index'] = $new_density_index;
1147
    $result = array(
1148
      'STATUS'  => ERR_NONE,
1149
      '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),
1150
    );
1151
  } catch (exception $e) {
1152
    sn_db_transaction_rollback();
1153
    $result = array(
1154
      'STATUS'  => $e->getCode(),
1155
      'MESSAGE' => $e->getMessage(),
1156
    );
1157
  }
1158
1159
  return $result;
1160
}
1161
1162
function sn_module_get_active_count($group = '*') {
1163
  $active_modules = 0;
1164
  if (isset(sn_module::$sn_module_list[$group]) && is_array(sn_module::$sn_module_list[$group])) {
1165
    foreach (sn_module::$sn_module_list[$group] as $payment_module) {
1166
      $active_modules += $payment_module->manifest['active'];
1167
    }
1168
  }
1169
1170
  return $active_modules;
1171
}
1172
1173
function get_resource_exchange() {
1174
  static $rates;
1175
1176
  if (!$rates) {
1177
    $rates = array(
1178
      RES_METAL       => 'rpg_exchange_metal',
1179
      RES_CRYSTAL     => 'rpg_exchange_crystal',
1180
      RES_DEUTERIUM   => 'rpg_exchange_deuterium',
1181
      RES_DARK_MATTER => 'rpg_exchange_darkMatter',
1182
    );
1183
1184
    foreach ($rates as &$rate) {
1185
      $rate = classSupernova::$config->$rate;
1186
    }
1187
  }
1188
1189
  return $rates;
1190
}
1191
1192
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...
1193
  static $rates;
1194
1195
  if (!$rates) {
1196
    $rates = get_resource_exchange();
1197
  }
1198
1199
  $metal_cost = 0;
1200
  foreach ($cost as $resource_id => $resource_value) {
1201
    $metal_cost += $rates[$resource_id] * $resource_value;
1202
  }
1203
1204
  return $metal_cost;
1205
}
1206
1207
/**
1208
 * @param array $user
1209
 * @param int   $astrotech
1210
 *
1211
 * @return int
1212
 */
1213
function get_player_max_expeditons(&$user, $astrotech = -1) { return sn_function_call(__FUNCTION__, array(&$user, $astrotech, &$result)); }
1214
1215
/**
1216
 * @param     $user
1217
 * @param int $astrotech
1218
 * @param int $result
1219
 *
1220
 * @return float|int
1221
 */
1222
function sn_get_player_max_expeditons(&$user, $astrotech = -1, &$result = 0) {
1223
  if ($astrotech == -1) {
1224
    if (!isset($user[UNIT_PLAYER_EXPEDITIONS_MAX])) {
1225
      $astrotech = mrc_get_level($user, null, TECH_ASTROTECH);
1226
      $user[UNIT_PLAYER_EXPEDITIONS_MAX] = $astrotech >= 1 ? floor(sqrt($astrotech - 1)) : 0;
1227
    }
1228
1229
    return $result += $user[UNIT_PLAYER_EXPEDITIONS_MAX];
1230
  } else {
1231
    return $result += $astrotech >= 1 ? floor(sqrt($astrotech - 1)) : 0;
1232
  }
1233
}
1234
1235
function get_player_max_expedition_duration(&$user, $astrotech = -1) {
1236
  return $astrotech == -1 ? mrc_get_level($user, null, TECH_ASTROTECH) : $astrotech;
1237
}
1238
1239
function get_player_max_colonies(&$user, $astrotech = -1) {
1240
  if ($astrotech == -1) {
1241
    if (!isset($user[UNIT_PLAYER_COLONIES_MAX])) {
1242
1243
      $expeditions = get_player_max_expeditons($user);
1244
      $astrotech = mrc_get_level($user, null, TECH_ASTROTECH);
1245
      $colonies = $astrotech - $expeditions;
1246
1247
      $user[UNIT_PLAYER_COLONIES_MAX] = classSupernova::$config->player_max_colonies < 0 ? $colonies : min(classSupernova::$config->player_max_colonies, $colonies);
1248
    }
1249
1250
    return $user[UNIT_PLAYER_COLONIES_MAX];
1251 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...
1252
    $expeditions = get_player_max_expeditons($user, $astrotech);
1253
    // $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...
1254
    $colonies = $astrotech - $expeditions;
1255
1256
    return classSupernova::$config->player_max_colonies < 0 ? $colonies : min(classSupernova::$config->player_max_colonies, $colonies);
1257
  }
1258
}
1259
1260
function get_player_current_colonies(&$user) {
1261
  return $user[UNIT_PLAYER_COLONIES_CURRENT] = isset($user[UNIT_PLAYER_COLONIES_CURRENT]) ? $user[UNIT_PLAYER_COLONIES_CURRENT] : max(0, db_planet_count_by_type($user['id']) - 1);
1262
}
1263
1264
function str_raw2unsafe($raw) {
1265
  return trim(strip_tags($raw));
1266
}
1267
1268
function ip2longu($ip) {
1269
  return sprintf('%u', floatval(ip2long($ip)));
1270
}
1271
1272
1273
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)); }
1274
1275
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...
1276
  global $sn_powerup_buy_discounts;
1277
1278
  $result = array();
1279
1280
  $powerup_data = get_unit_param($powerup_id);
1281
  $is_upgrade = !empty($powerup_unit) && $powerup_unit;
1282
1283
  $level_current = $term_original = $time_left = 0;
1284
  if ($is_upgrade) {
1285
    $time_finish = strtotime($powerup_unit['unit_time_finish']);
1286
    $time_left = max(0, $time_finish - SN_TIME_NOW);
1287
    if ($time_left > 0) {
1288
      $term_original = $time_finish - strtotime($powerup_unit['unit_time_start']);
1289
      $level_current = $powerup_unit['unit_level'];
1290
    }
1291
  }
1292
1293
  $level_max = $level_max > $powerup_data[P_MAX_STACK] ? $level_max : $powerup_data[P_MAX_STACK];
1294
  $original_cost = 0;
1295
  for ($i = 1; $i <= $level_max; $i++) {
1296
    $base_cost = eco_get_total_cost($powerup_id, $i);
1297
    $base_cost = $base_cost[BUILD_CREATE][RES_DARK_MATTER];
1298
    foreach ($sn_powerup_buy_discounts as $period => $discount) {
1299
      $upgrade_price = floor($base_cost * $discount * $period / PERIOD_MONTH);
1300
      $result[$i][$period] = $upgrade_price;
1301
      $original_cost = $is_upgrade && $i == $level_current && $period <= $term_original ? $upgrade_price : $original_cost;
1302
    }
1303
  }
1304
1305
  if ($is_upgrade && $time_left) {
1306
    $term_original = round($term_original / PERIOD_DAY);
1307
    $time_left = min(floor($time_left / PERIOD_DAY), $term_original);
1308
    $cost_left = $term_original > 0 ? ceil($time_left / $term_original * $original_cost) : 0;
1309
1310
    array_walk_recursive($result, function (&$value) use ($cost_left) {
1311
      $value -= $cost_left;
1312
    });
1313
  }
1314
1315
  return $result;
1316
}
1317
1318
/**
1319
 * @param template $template
1320
 * @param array    $note_row
1321
 */
1322
function note_assign(&$template, $note_row) {
1323
  global $note_priority_classes;
1324
1325
  $template->assign_block_vars('note', array(
1326
    'ID'                     => $note_row['id'],
1327
    'TIME'                   => $note_row['time'],
1328
    'TIME_TEXT'              => date(FMT_DATE_TIME, $note_row['time']),
1329
    'PRIORITY'               => $note_row['priority'],
1330
    'PRIORITY_CLASS'         => $note_priority_classes[$note_row['priority']],
1331
    'PRIORITY_TEXT'          => classLocale::$lang['sys_notes_priorities'][$note_row['priority']],
1332
    'TITLE'                  => htmlentities($note_row['title'], ENT_COMPAT, 'UTF-8'),
1333
    'GALAXY'                 => intval($note_row['galaxy']),
1334
    'SYSTEM'                 => intval($note_row['system']),
1335
    'PLANET'                 => intval($note_row['planet']),
1336
    'PLANET_TYPE'            => intval($note_row['planet_type']),
1337
    'PLANET_TYPE_TEXT'       => classLocale::$lang['sys_planet_type'][$note_row['planet_type']],
1338
    'PLANET_TYPE_TEXT_SHORT' => classLocale::$lang['sys_planet_type_sh'][$note_row['planet_type']],
1339
    'TEXT'                   => sys_bbcodeParse(htmlentities($note_row['text'], ENT_COMPAT, 'UTF-8')),
1340
    'TEXT_EDIT'              => htmlentities($note_row['text'], ENT_COMPAT, 'UTF-8'),
1341
    'STICKY'                 => intval($note_row['sticky']),
1342
  ));
1343
}
1344
1345
function sn_version_compare_extra($version) {
1346
  static $version_regexp = '#(\d+)([a-f])(\d+)(?:\.(\d+))*#';
1347
  preg_match($version_regexp, $version, $version);
1348
  unset($version[0]);
1349
  $version[2] = ord($version[2]) - ord('a');
1350
1351
  return implode('.', $version);
1352
}
1353
1354
function sn_version_compare($ver1, $ver2) {
1355
  return version_compare(sn_version_compare_extra($ver1), sn_version_compare_extra($ver2));
1356
}
1357
1358
function sn_setcookie($name, $value = null, $expire = null, $path = SN_ROOT_RELATIVE, $domain = null, $secure = null, $httponly = null) {
1359
  $_COOKIE[$name] = $value;
1360
1361
  return setcookie($name, $value, $expire, $path, $domain, $secure, $httponly);
1362
}
1363
1364
function market_get_autoconvert_cost() {
1365
  return classSupernova::$config->rpg_cost_exchange ? classSupernova::$config->rpg_cost_exchange * 3 : 3000;
1366
}
1367
1368
function print_rr($var, $capture = false) {
1369
  $print = '<pre>' . htmlspecialchars(print_r($var, true)) . '</pre>';
1370
  if ($capture) {
1371
    return $print;
1372
  } else {
1373
    print($print);
1374
  }
1375
}
1376
1377
function can_capture_planet() { return sn_function_call(__FUNCTION__, array(&$result)); }
1378
1379
function sn_can_capture_planet(&$result) {
1380
  return $result = false;
1381
}
1382
1383
/**
1384
 * Возвращает информацию об IPv4 адресах пользователя
1385
 *
1386
 * НЕ ПОДДЕРЖИВАЕТ IPv6!
1387
 *
1388
 * @return array
1389
 */
1390
// OK v4
1391
function sec_player_ip() {
1392
  // TODO - IPv6 support
1393
  $ip = array(
1394
    'ip'          => $_SERVER["REMOTE_ADDR"],
1395
    'proxy_chain' => $_SERVER["HTTP_X_FORWARDED_FOR"]
1396
      ? $_SERVER["HTTP_X_FORWARDED_FOR"]
1397
      : ($_SERVER["HTTP_CLIENT_IP"]
1398
        ? $_SERVER["HTTP_CLIENT_IP"]
1399
        : '' // $_SERVER["REMOTE_ADDR"]
1400
      ),
1401
  );
1402
1403
  return array_map('db_escape', $ip);
1404
}
1405
1406
/**
1407
 * Converts unix timestamp to SQL DateTime
1408
 *
1409
 * @param int $value
1410
 *
1411
 * @return string|null
1412
 */
1413
function unixTimeStampToSqlString($value) {
1414
  $result = !empty($value) ? date(FMT_DATE_TIME_SQL, $value) : null;
1415
1416
  return $result ? $result : null;
1417
}
1418
1419
/**
1420
 * Converts SQL DateTime to unix timestamp
1421
 *
1422
 * @param $value
1423
 *
1424
 * @return int
1425
 */
1426
function sqlStringToUnixTimeStamp($value) {
1427
  $result = !empty($value) ? strtotime($value) : 0;
1428
1429
  return $result ? $result : 0;
1430
}
1431
1432
/**
1433
 * @param mixed $value
1434
 *
1435
 * @return mixed|null
1436
 */
1437
function nullIfEmpty($value) {
1438
  return !empty($value) ? $value : null;
1439
}
1440
1441
1442
/**
1443
 * @param $sort_option
1444
 * @param $sort_option_inverse
1445
 *
1446
 * @return mixed
1447
 */
1448
function sortUnitRenderedList(&$ListToSort, $sort_option, $sort_option_inverse) {
1449
  if ($sort_option || $sort_option_inverse != PLAYER_OPTION_SORT_ORDER_PLAIN) {
1450
    switch ($sort_option) {
1451
      case PLAYER_OPTION_SORT_NAME:
1452
        $sort_option_field = 'NAME';
1453
      break;
1454
      case PLAYER_OPTION_SORT_SPEED:
1455
        $sort_option_field = 'SPEED';
1456
      break;
1457
      case PLAYER_OPTION_SORT_COUNT:
1458
        $sort_option_field = 'AMOUNT';
1459
      break;
1460
      case PLAYER_OPTION_SORT_ID:
1461
        $sort_option_field = 'ID';
1462
      break;
1463
      case PLAYER_OPTION_SORT_CREATE_TIME_LENGTH:
1464
        $sort_option_field = 'TIME_SECONDS';
1465
      break;
1466
      default:
1467
        $sort_option_field = '__INDEX';
1468
      break;
1469
    }
1470
    $sort_option_inverse_closure = $sort_option_inverse ? -1 : 1;
1471
    usort($ListToSort, function ($a, $b) use ($sort_option_field, $sort_option_inverse_closure) {
1472
      return $a[$sort_option_field] < $b[$sort_option_field] ? -1 * $sort_option_inverse_closure : (
1473
      $a[$sort_option_field] > $b[$sort_option_field] ? 1 * $sort_option_inverse_closure : 0
1474
      );
1475
    });
1476
  }
1477
1478
}
1479