Completed
Push — work-fleets ( d1f99e...fc0000 )
by SuperNova.WS
06:40
created

flotenajax.php ➔ fleet_ajax()   D

Complexity

Conditions 15
Paths 122

Size

Total Lines 141
Code Lines 94

Duplication

Lines 0
Ratio 0 %

Importance

Changes 3
Bugs 0 Features 0
Metric Value
cc 15
eloc 94
c 3
b 0
f 0
nc 122
nop 0
dl 0
loc 141
rs 4.597

How to fix   Long Method    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
 * flotenajax.php
5
 *
6
 * Fleet manager on Ajax (to work in Galaxy view)
7
 *
8
 * @version 2.0 Security checks by Gorlum for http://supernova.ws
9
 *  [!] Full rewrite
10
 *  [+] Added missile attack launch sequience
11
 *  [-] Moved almost all check code to flt_can_attack
12
 * @version 1.1 Security checks by Gorlum for http://supernova.ws
13
 * @version 1
14
 * @copyright 2008 By Chlorel for XNova
15
 **/
16
17
use DBStatic\DBStaticFleetMissile;
18
use DBStatic\DBStaticPlanet;
19
use DBStatic\DBStaticUnit;
20
use DBStatic\DBStaticUser;
21
22
include('common.' . substr(strrchr(__FILE__, '.'), 1));
23
24
define('IN_AJAX', true);
25
26
require_once('includes/includes/flt_functions.php');
27
28
/**
29
 * @throws Exception
30
 */
31
function fleet_ajax() {
32
  global $user;
33
34
  classLocale::$lang->lng_include('universe');
35
  classLocale::$lang->lng_include('fleet');
36
37
  $classLocale = classLocale::$lang;
38
39
  $travel_data = array();
40
41
  // TODO - change to JSON. Message can be sent in JSON-encoded field
42
  header("Content-type: text/html; charset=utf-8");
43
44
  $target_mission = sys_get_param_int('mission');
45
  $sn_group_missions = sn_get_groups('missions');
46
  if (empty($sn_group_missions[$target_mission]['AJAX'])) {
47
    die(classLocale::$lang['gs_c00']);
48
  }
49
50
  // Checking target coordinates validity
51
  $target_coord = array(
52
    'id'          => null,
53
    'id_owner'    => 0,
54
    'galaxy'      => sys_get_param_int('galaxy'),
55
    'system'      => sys_get_param_int('system'),
56
    'planet'      => sys_get_param_int('planet'),
57
    'planet_type' => sys_get_param_int('planet_type'),
58
  );
59
  // fleet_ajax now can send fleets only to existing planets/moons
60
  // TODO - sending colonization and expeditions in 1 click
61
  if (!uni_coordinates_valid($target_coord)) {
62
    die(classLocale::$lang['gs_c02']);
63
  }
64
65
  sn_db_transaction_start();
66
67
  $user = DBStaticUser::db_user_by_id($user['id'], true);
68
  $planetrow = DBStaticPlanet::db_planet_by_id($user['current_planet'], true);
69
70
  // TODO - DEADLOCK CAN BE HERE!!!! We should lock SOURCE and TARGET owners in one query
71
  $target_row = DBStaticPlanet::db_planet_by_vector($target_coord);
72
  if (empty($target_row)) {
73
    $target_row = $target_coord;
74
    $target_row['id_owner'] = 0;
75
    // If fleet destination is PT_DEBRIS - then it's actually destination is PT_PLANET // TODO - REMOVE! Debris should be valid DESTINATION planet_type!
76
    $target_row['planet_type'] = $target_row['planet_type'] == PT_DEBRIS ? PT_PLANET : $target_row['planet_type'];
77
  } else {
78
    $target_coord['id'] = $target_row['id'];
79
    $target_coord['id_owner'] = $target_row['id_owner'];
80
  }
81
82
  $unit_group = '';
83
  $fleet_array = array();
84
  switch ($target_mission) {
85
    case MT_SPY:
86
      $fleet_array[SHIP_SPY] = min(mrc_get_level($user, $planetrow, SHIP_SPY), abs(classSupernova::$user_options[PLAYER_OPTION_FLEET_SPY_DEFAULT]));
87
      $unit_group = 'flt_spies';
88
    break;
89
90
    case MT_RECYCLE:
91
      foreach (classSupernova::$gc->groupRecyclers as $unit_id) {
0 ignored issues
show
Bug introduced by
The expression \classSupernova::$gc->groupRecyclers of type array|object<Closure> is not guaranteed to be traversable. How about adding an additional type check?

There are different options of fixing this problem.

  1. If you want to be on the safe side, you can add an additional type-check:

    $collection = json_decode($data, true);
    if ( ! is_array($collection)) {
        throw new \RuntimeException('$collection must be an array.');
    }
    
    foreach ($collection as $item) { /** ... */ }
    
  2. If you are sure that the expression is traversable, you might want to add a doc comment cast to improve IDE auto-completion and static analysis:

    /** @var array $collection */
    $collection = json_decode($data, true);
    
    foreach ($collection as $item) { /** .. */ }
    
  3. Mark the issue as a false-positive: Just hover the remove button, in the top-right corner of this issue for more options.

Loading history...
92
        if ($unit_count = mrc_get_level($user, $planetrow, $unit_id)) {
93
          $fleet_array[$unit_id] = $unit_count;
94
        }
95
      }
96
      $transport_data = flt_calculate_fleet_to_transport($fleet_array, $target_row['debris_metal'] + $target_row['debris_crystal'], $planetrow, $target_row);
97
      $fleet_array = $transport_data['fleet'];
98
      $unit_group = 'flt_recyclers';
99
    break;
100
101
    case MT_MISSILE:
102
      $fleet_array[UNIT_DEF_MISSILE_INTERPLANET] = min(mrc_get_level($user, $planetrow, UNIT_DEF_MISSILE_INTERPLANET), abs(sys_get_param_float('missiles')));
103
      $unit_group = GROUP_STR_MISSILES;
104
    break;
105
106
  }
107
108
  $isAttackAllowed = flt_can_attack(
109
    $planetrow,
110
    $target_row,
111
    $fleet_array,
112
    $target_mission,
113
    array(
0 ignored issues
show
Documentation introduced by
array('target_structure'...aram_int('structures')) is of type array<string,integer,{"t..._structure":"integer"}>, but the function expects a boolean.

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...
114
      'target_structure' => $target_structure = sys_get_param_int('structures'),
115
    )
116
  );
117
  if ($isAttackAllowed != FLIGHT_ALLOWED) {
118
    die(classLocale::$lang['fl_attack_error'][$isAttackAllowed]);
119
  }
120
121
  if ($target_mission == MT_MISSILE) {
122
    $distance = abs($target_coord['system'] - $planetrow['system']);
123
    $duration = round((30 + (60 * $distance)) / flt_server_flight_speed_multiplier());
124
    $arrival = SN_TIME_NOW + $duration;
125
    $travel_data['consumption'] = 0;
126
127
    DBStaticFleetMissile::db_missile_insert($target_coord, $user, $planetrow, $arrival, array_sum($fleet_array), $target_structure);
128
  } else {
129
    $objFleet = new Fleet();
130
    $objFleet->set_start_planet($planetrow);
131
    $objFleet->set_end_planet($target_coord);
132
    $objFleet->playerOwnerId = $user['id'];
133
    $objFleet->group_id = 0;
134
    $objFleet->unitsSetFromArray($fleet_array);
135
    $objFleet->mission_type = $target_mission;
136
137
    $travel_data = flt_travel_data($user, $planetrow, $target_coord, $fleet_array, 10);
138
139
    if ($planetrow['deuterium'] < $travel_data['consumption']) {
140
      die(classLocale::$lang['gs_c13']);
141
    }
142
143
    $objFleet->set_times($travel_data['duration']);
144
    $objFleet->dbInsert();
145
  }
146
147
  DBStaticPlanet::db_planet_update_adjust_by_id(
148
    $planetrow['id'],
149
    array(
150
      'deuterium' => -$travel_data['consumption'],
151
    )
152
  );
153
154
  foreach ($fleet_array as $unit_id => $unit_count) {
155
    DBStaticUnit::dbUpdateOrInsertUnit($unit_id, -$unit_count, $user, $planetrow);
156
  }
157
  sn_db_transaction_commit();
158
159
  $ships_sent = array();
160
  $ships_sent_js = 0;
161
  foreach ($fleet_array as $unit_id => $unit_count) {
162
    $ships_sent[] = "{$unit_count} {$classLocale['tech'][$unit_id]}";
163
    $ships_sent_js += mrc_get_level($user, $planetrow, $unit_id, false, true);
164
  }
165
  $ships_sent = implode(', ', $ships_sent);
166
  $ships_sent_js = "{$unit_group}={$ships_sent_js}";
167
168
  $ResultMessage = "{$classLocale['gs_sending']} {$ships_sent} {$classLocale['gs_to']} {$target_coord['galaxy']}:{$target_coord['system']}:{$target_coord['planet']}|{$ships_sent_js}";
169
170
  die($ResultMessage);
171
}
172
173
fleet_ajax();
174