Completed
Push — work-fleets ( abbbcf...8b8b7f )
by SuperNova.WS
05:13
created

UnitList::_dump()   B

Complexity

Conditions 2
Paths 2

Size

Total Lines 99
Code Lines 71

Duplication

Lines 0
Ratio 0 %

Importance

Changes 5
Bugs 0 Features 0
Metric Value
c 5
b 0
f 0
dl 0
loc 99
rs 8.3103
cc 2
eloc 71
nc 2
nop 0

How to fix   Long Method   

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
 * Class UnitList
5
 * Indexed by DB_ID - as it should be!
6
 *
7
 *
8
 *
9
 * Hints for IDE - inherited from ArrayAccessV2
10
 *
11
 * @method Unit offsetGet($offset)
12
 * @property Unit[] $_container
13
 *
14
 */
15
class UnitList extends ArrayAccessV2 implements IDbRow, ILocation {
16
17
18
  // Properties ********************************************************************************************************
19
20
  // ILocation implementation ==========================================================================================
21
22
  /**
23
   * Type of this location
24
   *
25
   * @var int $locationType
26
   */
27
  protected static $locationType = LOC_UNIT_LIST;
28
  /**
29
   * @var ILocation $locatedAt
30
   */
31
  protected $locatedAt = null;
32
33
34
  // New properties ====================================================================================================
35
36
  /**
37
   * @var Unit[] $mapUnitIdToDb
38
   */
39
  // Нужно для корректного сохранения новых юнитов. Их db_id = 0, поэтому при добавлении в контейнер они будут перезаписывать друг друга
40
  // Соответственно - при сохраненнии флота надо проходить dbSave именно по $mapUnitIdToDb
41
  protected $mapUnitIdToDb = array();
42
43
44
  // Methods ***********************************************************************************************************
45
46
  // ILocation implementation ==========================================================================================
47
48
  public function getPlayerOwnerId() {
49
    return is_object($this->locatedAt) ? $this->locatedAt->getPlayerOwnerId() : null;
50
  }
51
52
  public function getLocationType() {
53
    return is_object($this->locatedAt) ? $this->locatedAt->getLocationType() : LOC_NONE;
54
  }
55
56
  public function getLocationDbId() {
57
    return is_object($this->locatedAt) ? $this->locatedAt->getLocationDbId() : null;
58
  }
59
60
  // TODO - достаточно установить один раз Unit::LocatedAt на UnitList, что бы затем все юниты автоматически брали наиболее актуальный locatedAt
61
  public function setLocatedAt($location) {
62
    $this->locatedAt = $location;
63
    // TODO - по факту не нужно - достточно один раз поставить на $this
64
//    foreach($this->_container as $unit) {
65
//      $unit->setLocatedAt($this->locatedAt);
66
//    }
67
  }
68
69
  public function getLocatedAt() {
70
    return $this->locatedAt;
71
  }
72
73
  public function getLocatedAtType() {
74
    return is_object($this->locatedAt) ? $this->locatedAt->getLocationType() : LOC_NONE;
75
  }
76
77
  public function getLocatedAtDbId() {
78
    return is_object($this->locatedAt) ? $this->locatedAt->getLocationDbId() : 0;
79
  }
80
81
82
  // ArrayAccessV2 inheritance =========================================================================================
83
84
  /**
85
   * Adds link to unit object also to mapUnitIdToDb
86
   *
87
   * @param mixed $offset
88
   * @param Unit  $value
89
   */
90
  public function offsetSet($offset, $value) {
91
    if(isset($this->mapUnitIdToDb[$value->unitId])) {
92
      classSupernova::$debug->error('UnitList::offsetSet: Unit with UnitId ' . $value->unitId . ' already exists');
93
    }
94
    $this->mapUnitIdToDb[$value->unitId] = $value;
95
    parent::offsetSet($offset, $value);
96
  }
97
98
  public function offsetUnset($offset) {
99
    if(!empty($this[$offset]->unitId)) {
100
//      $unit_id = $this[$offset]->unitId;
0 ignored issues
show
Unused Code Comprehensibility introduced by
63% 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...
101
//      $this->mapUnitIdToDb[$unit_id] = null;
102
//      unset($this->mapUnitIdToDb[$unit_id]);
103
      unset($this->mapUnitIdToDb[$this[$offset]->unitId]);
104
    }
105
    parent::offsetUnset($offset);
106
  }
107
108
109
  // IDbRow implementation =============================================================================================
110
111
  /**
112
   * Loading object from DB by primary ID
113
   * Real location should be set before calling this method
114
   *
115
   * @param int $dbId - dbId is generally unused here. However it works as flag: 0 - just reset; (negative) - just reset; (positive) - proceed with loading
116
   */
117
  // TODO: Implement dbLoad() method.
118
  public function dbLoad($dbId) {
119
//    $this->_reset();
0 ignored issues
show
Unused Code Comprehensibility introduced by
72% 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...
120
121
    if($dbId <= 0) {
122
      return;
123
    }
124
125
    if(!is_object($this->locatedAt)) {
126
      classSupernova::$debug->error('UnitList::dbLoad have no locatedAt field set');
127
    }
128
129
    $unit_array = classSupernova::db_get_unit_list_by_location(0, $this->getLocationType(), $this->getLocationDbId());
130
    if(!is_array($unit_array)) {
131
      return;
132
    }
133
134
    foreach($unit_array as $unit_db_row) {
135
      $unit = $this->_createElement();
136
      $unit->setLocatedAt($this);
137
      $unit->dbRowParse($unit_db_row);
138
139
      // TODO - сюда вставить разборку бонусов данного юнитлиста - тех бонусов, которые Grants данный юнит добавить в список бонусов юнит-листа
140
141
      $this[$unit->dbId] = $unit;
142
    }
143
144
    // TODO - Применить бонусы от location
145
    // Точнее - опустить бонусы с юнитлиста (те, которые Grants) на каждый юнит (те, которые receives)
146
    // Вообще-то Receives это будут параметры каждого юнита
147
  }
148
149
  public function dbSave() {
150
    if(!is_object($this->locatedAt)) {
151
      classSupernova::$debug->error('UnitList::dbSave have no locatedAt field set');
152
    }
153
154
    foreach($this->mapUnitIdToDb as $unit) {
155
      $unit_db_id = $unit->dbId;
156
      $unit->dbSave();
157
158
      if($unit->isEmpty()) {
159
        // Removing unit object
160
        // TODO - change when there will be common bus for all objects
161
        // ...or should I? If COUNT is empty - it means that object does not exists in DB. So it should be deleted from PHP memory and cache too
162
        unset($this[$unit_db_id]);
163
      } else {
164
        if($unit->dbId <= 0) {
165
          classSupernova::$debug->error('Error writing unit to DB');
166
        }
167
        // If unit is new then putting unit object to container
168
        if(empty($this->_container[$unit->dbId])) {
169
          $this->_container[$unit->dbId] = $unit;
170
        }
171
      }
172
    }
173
  }
174
175
176
177
178
179
  // Other =============================================================================================================
180
181
  /**
182
   * @return Unit
183
   *
184
   * @version 41a6.30
185
   */
186
  // TODO - Factory
187
  public function _createElement() {
188
    return new Unit();
0 ignored issues
show
Bug Best Practice introduced by
The return type of return new \Unit(); (Unit) is incompatible with the return type of the parent method ArrayAccessV2::_createElement of type stdClass.

If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.

Let’s take a look at an example:

class Author {
    private $name;

    public function __construct($name) {
        $this->name = $name;
    }

    public function getName() {
        return $this->name;
    }
}

abstract class Post {
    public function getAuthor() {
        return 'Johannes';
    }
}

class BlogPost extends Post {
    public function getAuthor() {
        return new Author('Johannes');
    }
}

class ForumPost extends Post { /* ... */ }

function my_function(Post $post) {
    echo strtoupper($post->getAuthor());
}

Our function my_function expects a Post object, and outputs the author of the post. The base class Post returns a simple string and outputting a simple string will work just fine. However, the child class BlogPost which is a sub-type of Post instead decided to return an object, and is therefore violating the SOLID principles. If a BlogPost were passed to my_function, PHP would not complain, but ultimately fail when executing the strtoupper call in its body.

Loading history...
189
  }
190
191
  /**
192
   * Set unit count of $unit_id to $unit_count
193
   * If there is no $unit_id - it will be created and saved to DB on dbSave
194
   *
195
   * @param int $unit_id
196
   * @param int $unit_count
197
   */
198
  public function unitSetCount($unit_id, $unit_count = 0) {
199
    $this->unitAdjustCount($unit_id, $unit_count, true);
200
  }
201
202
  public function unitGetCount($unit_id) {
203
    if(empty($this->mapUnitIdToDb[$unit_id])) {
204
      throw new Exception('Unit [' . $unit_id . '] is not exists in UnitList');
205
    }
206
    return $this->mapUnitIdToDb[$unit_id]->count;
207
  }
208
209
  public function unitsCountApplyLossMultiplier($ships_lost_multiplier) {
210
    foreach($this->mapUnitIdToDb as $unit_id => $unit) {
211
      $unit->count = floor($unit->count * $ships_lost_multiplier);
212
    }
213
  }
214
215
  /**
216
   * Adjust unit count of $unit_id by $unit_count - or just replace value
217
   * If there is no $unit_id - it will be created and saved to DB on dbSave
218
   *
219
   * @param int  $unit_id
220
   * @param int  $unit_count
221
   * @param bool $replace_value
222
   */
223
  public function unitAdjustCount($unit_id, $unit_count = 0, $replace_value = false) {
224
    if(empty($this->mapUnitIdToDb[$unit_id])) {
225
      // If unit not exists - creating one and setting all attributes
226
      $this->mapUnitIdToDb[$unit_id] = $this->_createElement();
227
      $this->mapUnitIdToDb[$unit_id]->setUnitId($unit_id);
228
      $this->mapUnitIdToDb[$unit_id]->setLocatedAt($this);
229
    }
230
231
    if($replace_value) {
232
      $this->mapUnitIdToDb[$unit_id]->count = $unit_count;
233
    } else {
234
      $this->mapUnitIdToDb[$unit_id]->adjustCount($unit_count);
235
    }
236
  }
237
238
  /**
239
   * Get unit list in array as $unit_id => $unit_count
240
   *
241
   * @return array
242
   */
243
  public function unitsGetArray() {
244
    $result = array();
245
    foreach($this->mapUnitIdToDb as $unit) {
246
      $result[$unit->unitId] = $unit->count;
247
    }
248
249
    return $result;
250
  }
251
252
  public function unitsCount() {
253
    return $this->getSumProperty('count');
254
  }
255
256
  public function unitsCapacity() {
257
    return $this->getSumProperty('capacity');
258
  }
259
260
  /**
261
   * Get count of units in UnitList by unit_id (or all units if unit_id == 0)
262
   *
263
   * @param int $unit_id - 0 - all units
264
   *
265
   * @return int
266
   */
267
  public function unitsCountById($unit_id = 0) {
268
    $result = 0;
269
    foreach($this->mapUnitIdToDb as $unit) {
270
      if(!$unit_id || $unit->unitId == $unit_id) {
271
        $result += $unit->count;
272
      }
273
    }
274
275
    return $result;
276
  }
277
278
279
//  // TODO - revise it later
0 ignored issues
show
Unused Code Comprehensibility introduced by
39% 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...
280
//  public function _reset() {
281
//    //if(!empty($this->mapUnitIdToDb)) {
282
//    //  foreach($this->mapUnitIdToDb as $unit_id => $object) {
283
//    //    unset($this->mapUnitIdToDb[$unit_id]);
284
//    //  }
285
//    //}
286
//    unset($this->mapUnitIdToDb);
287
//    $this->mapUnitIdToDb = array();
288
//
289
//    //if(!empty($this->_container)) {
290
//    //  foreach($this->_container as $unit_db_id => $object) {
291
//    //    unset($this->_container[$unit_db_id]);
292
//    //  }
293
//    //}
294
//    unset($this->_container);
295
//    $this->_container = array();
296
//  }
297
298
299
  // TODO - DEBUG - REMOVE =============================================================================================
300
  public function _dump() {
301
    global $lang;
302
303
    print(__FILE__ . ':' . __LINE__ . "<br />");
304
    print("Located at " . $this->getLocationDbId() . " type " . $this->getLocationType() . "<br />");
305
306
    print('<table border="1">');
307
    print('<tr>');
308
309
    print('<th>');
310
    print('dbId');
311
    print('</th>');
312
313
    print('<th>');
314
    print('type');
315
    print('</th>');
316
317
    print('<th>');
318
    print('unitId');
319
    print('</th>');
320
321
    print('<th>');
322
    print('count');
323
    print('</th>');
324
325
    print('<th>');
326
    print('playerOwnerId');
327
    print('</th>');
328
329
    print('<th>');
330
    print('location');
331
    print('</th>');
332
333
    print('<th>');
334
    print('locationType');
335
    print('</th>');
336
337
    print('<th>');
338
    print('locationDbId');
339
    print('</th>');
340
341
    print('<th>');
342
    print('timeStart');
343
    print('</th>');
344
345
    print('<th>');
346
    print('timeFinish');
347
    print('</th>');
348
349
    print('</tr>');
350
351
    foreach($this->mapUnitIdToDb as $unit) {
352
      print('<tr>');
353
354
      print('<td>');
355
      print($unit->dbId);
356
      print('</td>');
357
358
      print('<td>');
359
      $type = $unit->getType();
360
      print("[{$type}] {$lang['tech'][$type]}");
361
      print('</td>');
362
363
      print('<td>');
364
      print("[{$unit->unitId}] {$lang['tech'][$unit->unitId]}");
365
      print('</td>');
366
367
      print('<td>');
368
      print($unit->count);
369
      print('</td>');
370
371
      print('<td>');
372
      print($unit->getPlayerOwnerId());
373
      print('</td>');
374
375
      print('<td>');
376
//      print($unit->location);
0 ignored issues
show
Unused Code Comprehensibility introduced by
75% 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...
377
      print('</td>');
378
379
      print('<td>');
380
      print($unit->getLocationType());
381
      print('</td>');
382
383
      print('<td>');
384
      print($unit->getLocationDbId());
385
      print('</td>');
386
387
      print('<td>');
388
      print($unit->getTimeStart());
389
      print('</td>');
390
391
      print('<td>');
392
      print($unit->getTimeFinish());
393
      print('</td>');
394
395
      print('</tr>');
396
    }
397
    print('</table>');
398
  }
399
400
401
  public function unitZeroDbId() {
402
    foreach($this->mapUnitIdToDb as $unit) {
403
      $unit->zeroDbId();
404
    }
405
  }
406
407
408
  public function unitZeroCount() {
409
    foreach($this->mapUnitIdToDb as $unit) {
410
      $unit->count = 0;
411
    }
412
  }
413
414
}
415