Completed
Push — work-fleets ( c94fa6...bf14b2 )
by SuperNova.WS
06:23
created

DBStaticMessages   C

Complexity

Total Complexity 76

Size/Duplication

Total Lines 520
Duplicated Lines 1.15 %

Coupling/Cohesion

Components 1
Dependencies 8

Test Coverage

Coverage 0%

Importance

Changes 14
Bugs 0 Features 0
Metric Value
c 14
b 0
f 0
dl 6
loc 520
rs 5.488
ccs 0
cts 313
cp 0
wmc 76
lcom 1
cbo 8

20 Methods

Rating   Name   Duplication   Size   Complexity  
F messageWrite() 6 72 13
A db_message_count_by_type() 0 5 2
A db_message_list_delete_set() 0 3 1
B messageShow() 0 44 6
B messageRenderList() 0 19 5
D msg_send_simple_message() 0 81 17
A msg_ali_send() 0 19 4
A msgSendFromAdmin() 0 3 1
A msgSendFromPlayer() 0 5 1
A msgSendFromPlayerBuddy() 0 9 1
C messageDelete() 0 38 13
A db_message_list_get_last_20() 0 9 1
A db_message_list_outbox_by_user_id() 0 12 2
A db_message_list_by_owner_and_string() 0 3 1
A db_message_count_by_owner_and_type() 0 3 1
A db_message_count_outbox() 0 5 1
A db_message_list_admin_by_type() 0 17 2
A db_message_insert_all() 0 9 1
A db_message_delete_by_id() 0 3 1
A db_message_list_delete_by_date() 0 7 2

How to fix   Duplicated Code    Complexity   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

Complex Class

 Tip:   Before tackling complexity, make sure that you eliminate any duplication first. This often can reduce the size of classes significantly.

Complex classes like DBStaticMessages often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use DBStaticMessages, and based on these observations, apply Extract Interface, too.

1
<?php
2
3
class DBStaticMessages {
4
  public static $snMessageClassList = array(
5
    MSG_TYPE_NEW       => array(
6
      'name'       => 'new_message',
7
      'switchable' => false,
8
      'email'      => false,
9
    ),
10
    MSG_TYPE_ADMIN     => array(
11
      'name'       => 'msg_admin',
12
      'switchable' => false,
13
      'email'      => true,
14
    ),
15
    MSG_TYPE_PLAYER    => array(
16
      'name'       => 'mnl_joueur',
17
      'switchable' => false,
18
      'email'      => true,
19
    ),
20
    MSG_TYPE_ALLIANCE  => array(
21
      'name'       => 'mnl_alliance',
22
      'switchable' => false,
23
      'email'      => true,
24
    ),
25
    MSG_TYPE_SPY       => array(
26
      'name'       => 'mnl_spy',
27
      'switchable' => true,
28
      'email'      => true,
29
    ),
30
    MSG_TYPE_COMBAT    => array(
31
      'name'       => 'mnl_attaque',
32
      'switchable' => true,
33
      'email'      => true,
34
    ),
35
    MSG_TYPE_TRANSPORT => array(
36
      'name'       => 'mnl_transport',
37
      'switchable' => true,
38
      'email'      => true,
39
    ),
40
    MSG_TYPE_RECYCLE   => array(
41
      'name'       => 'mnl_exploit',
42
      'switchable' => true,
43
      'email'      => true,
44
    ),
45
    MSG_TYPE_EXPLORE   => array(
46
      'name'       => 'mnl_expedition',
47
      'switchable' => true,
48
      'email'      => true,
49
    ),
50
    //     97 => 'mnl_general',
0 ignored issues
show
Unused Code Comprehensibility introduced by
58% 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...
51
    MSG_TYPE_QUE       => array(
52
      'name'       => 'mnl_buildlist',
53
      'switchable' => true,
54
      'email'      => true,
55
    ),
56
    MSG_TYPE_OUTBOX    => array(
57
      'name'       => 'mnl_outbox',
58
      'switchable' => false,
59
      'email'      => false,
60
    ),
61
  );
62
  public static $snMessageGroup = array(
63
    'switchable' => array(MSG_TYPE_SPY, MSG_TYPE_COMBAT, MSG_TYPE_RECYCLE, MSG_TYPE_TRANSPORT, MSG_TYPE_EXPLORE, MSG_TYPE_QUE),
64
    'email'      => array(MSG_TYPE_SPY, MSG_TYPE_PLAYER, MSG_TYPE_ALLIANCE, MSG_TYPE_COMBAT, MSG_TYPE_RECYCLE, MSG_TYPE_TRANSPORT,
65
      MSG_TYPE_ADMIN, MSG_TYPE_EXPLORE, MSG_TYPE_QUE),
66
  );
67
68
  /**
69
   * @param mixed|array $owners
70
   * @param integer     $sender
71
   * @param integer     $timestamp
72
   * @param integer     $message_type
73
   * @param string      $from_unsafe
74
   * @param string      $subject_unsafe
75
   * @param string      $text_unsafe
76
   * @param bool        $force
77
   */
78
  public static function msg_send_simple_message($owners, $sender, $timestamp, $message_type, $from_unsafe, $subject_unsafe, $text_unsafe, $force = false) {
79
    global $user;
80
81
    if (!$owners) {
82
      return;
83
    }
84
85
    $timestamp = $timestamp ? $timestamp : SN_TIME_NOW;
86
    $sender = intval($sender);
87
    if (!is_array($owners)) {
88
      $owners = array($owners);
89
    }
90
91
    // TODO - check for valid message_type ?
92
    $message_class = static::$snMessageClassList[$message_type];
93
    $message_class_name = $message_class['name'];
94
95
    $text_safe = db_escape($text_unsafe);
0 ignored issues
show
Unused Code introduced by
$text_safe is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
96
97
    $message_class_name_total = static::$snMessageClassList[MSG_TYPE_NEW]['name'];
98
99
    if ($owners[0] == '*') {
100
      if ($user['authlevel'] < 3) {
101
        return false;
102
      }
103
      // TODO Добавить $timestamp - рассылка может быть и отсроченной
104
      // TODO Добавить $sender - рассылка может быть и от кого-то
105
      static::db_message_insert_all($message_type, $from_unsafe, $subject_unsafe, $text_unsafe);
106
      $owners = array();
107
    } else {
108
      $insert_values = array();
109
      foreach ($owners as $owner) {
110
        if ($user['id'] != $owner) {
111
          $owner_row = DBStaticUser::db_user_by_id($owner);
112
        } else {
113
          $owner_row = $user;
114
        }
115
        sys_user_options_unpack($owner_row);
116
117
        if ($force || !$message_class['switchable'] || $owner_row["opt_{$message_class_name}"]) {
118
          $insert_values[] = "('" . idval($owner) . "', '{$sender}', '{$timestamp}', '{$message_type}', '" . db_escape($from_unsafe) . "', '" . db_escape($subject_unsafe) . "', '" . db_escape($text_unsafe) . "')";
119
        }
120
121
        // TODO - allow sending HTML email only from admin
122
        if ($message_class['email'] && classSupernova::$config->game_email_pm && $owner_row["opt_email_{$message_class_name}"]) {
123
          $text_unescaped = str_replace(array('\\r\\n', '\\n', "\r\n", "\n"), "<br />", $text_unsafe);
124
          @$result = mymail($owner_row['email'], $subject_unsafe, $text_unescaped, '', true);
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
125
        }
126
      }
127
128
      if (empty($insert_values)) {
129
        return;
130
      }
131
132
      classSupernova::$db->doInsertValuesDeprecated(
0 ignored issues
show
Deprecated Code introduced by
The method db_mysql::doInsertValuesDeprecated() has been deprecated.

This method has been deprecated.

Loading history...
133
        TABLE_MESSAGES,
134
        array(
135
          'message_owner',
136
          'message_sender',
137
          'message_time',
138
          'message_type',
139
          'message_from',
140
          'message_subject',
141
          'message_text',
142
        ),
143
        $insert_values
144
      );
145
    }
146
    DBStaticUser::db_user_list_set_mass_mail(
147
      $owners,
148
      array(
149
        $message_class_name       => +1,
150
        $message_class_name_total => +1,
151
      )
152
    );
153
154
    if (in_array($user['id'], $owners) || $owners[0] == '*') {
155
      $user[$message_class_name]++;
156
      $user[$message_class_name_total]++;
157
    }
158
  }
159
160
  public static function msg_ali_send($message, $subject, $ally_rank_id = 0, $ally_id = 0) {
161
    global $user;
162
163
    $ally_id = $ally_id ? $ally_id : $user['ally_id'];
164
165
    $sendList = array();
166
    $list = '';
167
    $query = DBStaticUser::db_user_list(
168
      "ally_id = '{$ally_id}'" . ($ally_rank_id >= 0 ? " AND ally_rank_id = {$ally_rank_id}" : ''),
169
      false, 'id, username');
170
    foreach ($query as $u) {
171
      $sendList[] = $u['id'];
172
      $list .= "<br>{$u['username']} ";
173
    }
174
175
    static::msg_send_simple_message($sendList, $user['id'], SN_TIME_NOW, MSG_TYPE_ALLIANCE, $user['username'], $subject, $message);
176
177
    return $list;
178
  }
179
180
181
  /**
182
   * @param mixed|array $owners
183
   * @param string      $subject
184
   * @param string      $text
185
   * @param bool        $force
186
   */
187
  public static function msgSendFromAdmin($owners, $subject, $text, $force = false) {
188
    static::msg_send_simple_message($owners, 0, SN_TIME_NOW, MSG_TYPE_ADMIN, classLocale::$lang['sys_administration'], $subject, $text, $force);
189
  }
190
191
  /**
192
   * @param        $senderPlayerId
193
   * @param        $senderPlayerNameAndCoordinates
194
   * @param mixed  $recipientId
195
   * @param string $subject
196
   * @param string $text
197
   */
198
  public static function msgSendFromPlayer($senderPlayerId, $senderPlayerNameAndCoordinates, $recipientId, $subject, $text) {
199
    static::msg_send_simple_message(
200
      $recipientId, $senderPlayerId, SN_TIME_NOW, MSG_TYPE_PLAYER, $senderPlayerNameAndCoordinates, $subject, $text
201
    );
202
  }
203
204
  /**
205
   * @param \Buddy\BuddyRoutingParams $cBuddy
206
   * @param string                    $localeSubjectId
207
   * @param string                    $localeTextId
208
   */
209
  public static function msgSendFromPlayerBuddy($cBuddy, $localeSubjectId, $localeTextId) {
210
    static::msgSendFromPlayer(
211
      $cBuddy->playerId,
212
      $cBuddy->playerNameAndCoordinates,
213
      $cBuddy->newFriendIdSafe,
214
      classLocale::$lang[$localeSubjectId],
215
      sprintf(classLocale::$lang[$localeTextId], $cBuddy->playerName)
216
    );
217
  }
218
219
220
  /**
221
   * @param array $player
222
   *
223
   * @return template
224
   */
225
  public static function messageWrite($player) {
226
    $error_list = array();
227
228
    $recipientId = sys_get_param_id('id');
229
    $recipient_name_unescaped = sys_get_param_str_unsafe('recipient_name');
230
    $subject_unsafe = sys_get_param_str_unsafe('subject');
231
232
    if (!empty($recipientId)) {
233
      $recipient_row = DBStaticUser::db_user_by_id($recipientId);
234
    }
235
236
    if (empty($recipient_row)) {
237
      $recipient_row = DBStaticUser::db_user_by_username($recipient_name_unescaped);
238
    }
239
240
    if (!empty($recipient_row)) {
241
      $recipientId = $recipient_row['id'];
242
      $recipient_name_unescaped = $recipient_row['username'];
243
    } else {
244
      $recipientId = 0;
245
      $recipient_name_unescaped = '';
246
    }
247
248 View Code Duplication
    if ($recipientId == $player['id']) {
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...
249
      $error_list[] = array('MESSAGE' => classLocale::$lang['msg_err_self_send'], 'STATUS' => ERR_ERROR);
250
    }
251
252
    $re = 0;
253
    while (strpos($subject_unsafe, classLocale::$lang['msg_answer_prefix']) !== false) {
254
      $subject_unsafe = substr($subject_unsafe, strlen(classLocale::$lang['msg_answer_prefix']));
255
      $re++;
256
    }
257
    $re ? $subject_unsafe = classLocale::$lang['msg_answer_prefix'] . $subject_unsafe : false;
258
259
    $subject_unsafe = $subject_unsafe ? $subject_unsafe : classLocale::$lang['msg_subject_default'];
260
261
    $textUnsafe = sys_get_param_str_unsafe('text');
262
    if (sys_get_param_str('msg_send')) {
263 View Code Duplication
      if (!$recipientId) {
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...
264
        $error_list[] = array('MESSAGE' => classLocale::$lang['msg_err_player_not_found'], 'STATUS' => ERR_ERROR);
265
      }
266
267
      if (empty($textUnsafe)) {
268
        $error_list[] = array('MESSAGE' => classLocale::$lang['msg_err_no_text'], 'STATUS' => ERR_ERROR);
269
      }
270
271
      if (empty($error_list)) {
272
        $error_list[] = array('MESSAGE' => classLocale::$lang['msg_not_message_sent'], 'STATUS' => ERR_NONE);
273
274
        static::msgSendFromPlayer($player['id'], DBStaticUser::renderNameAndCoordinates($player), $recipientId, $subject_unsafe, $textUnsafe);
275
276
        $textUnsafe = '';
277
      }
278
    }
279
280
    $template = gettemplate('msg_message_compose', true);
281
    $template->assign_vars(array(
282
      'RECIPIENT_ID'   => $recipientId,
283
      'RECIPIENT_NAME' => htmlspecialchars($recipient_name_unescaped),
284
      'SUBJECT'        => htmlspecialchars($subject_unsafe),
285
      'TEXT'           => htmlspecialchars($textUnsafe),
286
    ));
287
288
    foreach ($error_list as $error_message) {
289
      $template->assign_block_vars('result', $error_message);
290
    }
291
292
    $message_query = static::db_message_list_get_last_20($player, $recipientId);
293
    static::messageRenderList(MSG_TYPE_OUTBOX, $template, $message_query);
294
295
    return $template;
296
  }
297
298
299
  /**
300
   * @param array  $player
301
   * @param string $current_class
302
   */
303
  public static function messageDelete($player, $current_class) {
304
    $message_range = sys_get_param_str('message_range');
305
    $marked_message_list = sys_get_param('mark', array());
0 ignored issues
show
Documentation introduced by
array() 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...
306
307
    $deleteAll = false;
308
    $where = array();
309
    $not = '';
310
    switch ($message_range) {
311
      case 'unchecked':
312
        $not = 'NOT';
313
      case 'checked':
314
        if ($message_range == 'checked' && empty($marked_message_list)) {
315
          break;
316
        }
317
318
        foreach ($marked_message_list as &$messageId) {
0 ignored issues
show
Bug introduced by
The expression $marked_message_list of type string|array 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...
319
          $messageId = idval($messageId);
320
        }
321
322
        if ($query_add = implode(',', $marked_message_list)) {
323
          $where[] = "`message_id` {$not} IN ({$query_add})";
324
        }
325
326
      case 'class':
327
        if ($current_class != MSG_TYPE_OUTBOX && $current_class != MSG_TYPE_NEW) {
328
          $where['message_type'] = $current_class;
329
        }
330
      case 'all':
331
        $deleteAll = true;
332
      break;
333
    }
334
335
    if ($deleteAll || !empty($where)) {
336
      $where['message_owner'] = $player['id'];
337
      // Mallformed $where
338
      classSupernova::$gc->db->doDeleteDeprecated(TABLE_MESSAGES, $where);
0 ignored issues
show
Bug introduced by
The method doDeleteDeprecated does only exist in db_mysql, but not in Closure.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
339
    }
340
  }
341
342
  /**
343
   * @param array $player
344
   * @param int   $current_class
345
   *
346
   * @return template
347
   */
348
  public static function messageShow(&$player, $current_class) {
349
    if ($current_class == MSG_TYPE_OUTBOX) {
350
      $message_query = static::db_message_list_outbox_by_user_id($player['id']);
351
    } else {
352
      if ($current_class == MSG_TYPE_NEW) {
353
        $SubUpdateQry = array();
354
        foreach (static::$snMessageClassList as $message_class_id => $message_class) {
355
          if ($message_class_id != MSG_TYPE_OUTBOX) {
356
            $SubUpdateQry[] = "`{$message_class['name']}` = '0'";
357
            $player[$message_class['name']] = 0;
358
          }
359
        }
360
        $SubUpdateQry = implode(',', $SubUpdateQry);
361
      } else {
362
        $classFieldNameCurrent = static::$snMessageClassList[$current_class]['name'];
363
        $classFieldNameNew = static::$snMessageClassList[MSG_TYPE_NEW]['name'];
364
        $SubUpdateQry = "`{$classFieldNameCurrent}` = '0', `{$classFieldNameNew}` = `{$classFieldNameNew}` - '{$player[$classFieldNameCurrent]}'";
365
        $SubSelectQry = "AND `message_type` = '{$current_class}'";
366
367
        $player[static::$snMessageClassList[MSG_TYPE_NEW]['name']] -= $player[static::$snMessageClassList[$current_class]['name']];
368
        $player[static::$snMessageClassList[$current_class]['name']] = 0;
369
      }
370
371
      DBStaticUser::db_user_set_by_id_DEPRECATED($player['id'], $SubUpdateQry);
0 ignored issues
show
Deprecated Code introduced by
The method DBStaticUser::db_user_set_by_id_DEPRECATED() has been deprecated.

This method has been deprecated.

Loading history...
372
      $message_query = static::db_message_list_by_owner_and_string($player, $SubSelectQry);
0 ignored issues
show
Bug introduced by
The variable $SubSelectQry does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
373
    }
374
375
    if (sys_get_param_int('return')) {
376
      header('Location: messages.php');
377
      die();
378
    }
379
380
    $template = gettemplate('msg_message_list', true);
381
    static::messageRenderList($current_class, $template, $message_query);
382
383
    $current_class_text = classLocale::$lang['msg_class'][$current_class];
384
385
    $template->assign_vars(array(
386
      "MESSAGE_CLASS"      => $current_class,
387
      "MESSAGE_CLASS_TEXT" => $current_class_text,
388
    ));
389
390
    return $template;
391
  }
392
393
394
  /**
395
   * @param int      $current_class
396
   * @param template $template
397
   * @param          $message_query
398
   */
399
  public function messageRenderList($current_class, $template, $message_query) {
400
    while ($message_row = db_fetch($message_query)) {
401
      $template->assign_block_vars('messages', array(
402
        'ID'   => $message_row['message_id'],
403
        'DATE' => date(FMT_DATE_TIME, $message_row['message_time'] + SN_CLIENT_TIME_DIFF),
404
        'FROM' => htmlspecialchars($message_row['message_from']),
405
        'SUBJ' => htmlspecialchars($message_row['message_subject']),
406
        'TEXT' => in_array($message_row['message_type'], array(MSG_TYPE_PLAYER, MSG_TYPE_ALLIANCE)) && $message_row['message_sender']
407
          ? nl2br(htmlspecialchars($message_row['message_text']))
408
          : nl2br($message_row['message_text']),
409
410
        'FROM_ID'        => $message_row['message_sender'],
411
        'SUBJ_SANITIZED' => htmlspecialchars($message_row['message_subject']),
412
        'STYLE'          => $current_class == MSG_TYPE_OUTBOX
413
          ? static::$snMessageClassList[MSG_TYPE_OUTBOX]['name']
414
          : static::$snMessageClassList[$message_row['message_type']]['name'],
415
      ));
416
    }
417
  }
418
419
420
// Messages *************************************************************************************************************
421
  public static function db_message_list_get_last_20($user, $recipient_id) {
422
    return classSupernova::$db->doSelect(
423
      "SELECT * FROM {{messages}}
424
        WHERE
425
          `message_type` = '" . MSG_TYPE_PLAYER . "' AND
426
          ((`message_owner` = '{$user['id']}' AND `message_sender` = '{$recipient_id}')
427
          OR
428
          (`message_sender` = '{$user['id']}' AND `message_owner` = '{$recipient_id}')) ORDER BY `message_time` DESC LIMIT 20;");
429
  }
430
431
  public static function db_message_list_outbox_by_user_id($user_id) {
432
    $user_id = idval($user_id);
433
    if (empty($user_id)) {
434
      return false;
435
    }
436
437
    return classSupernova::$db->doSelect("SELECT {{messages}}.message_id, {{messages}}.message_owner, {{users}}.id AS message_sender, {{messages}}.message_time,
438
          {{messages}}.message_type, {{users}}.username AS message_from, {{messages}}.message_subject, {{messages}}.message_text
439
       FROM
440
         {{messages}} LEFT JOIN {{users}} ON {{users}}.id = {{messages}}.message_owner WHERE `message_sender` = '{$user_id}' AND `message_type` = 1
441
       ORDER BY `message_time` DESC;");
442
  }
443
444
  public static function db_message_list_by_owner_and_string($user, $SubSelectQry) {
445
    return classSupernova::$db->doSelect("SELECT * FROM {{messages}} WHERE `message_owner` = '{$user['id']}' {$SubSelectQry} ORDER BY `message_time` DESC;");
446
  }
447
448
  public static function db_message_count_by_owner_and_type($user) {
449
    return classSupernova::$db->doSelect("SELECT message_owner, message_type, COUNT(message_owner) AS message_count FROM {{messages}} WHERE `message_owner` = {$user['id']} GROUP BY message_owner, message_type ORDER BY message_owner ASC, message_type;");
450
  }
451
452
  public static function db_message_count_outbox($user) {
453
    $row = classSupernova::$db->doSelectFetch("SELECT COUNT(message_sender) AS message_count FROM {{messages}} WHERE `message_sender` = '{$user['id']}' AND message_type = 1 GROUP BY message_sender;");
454
455
    return intval($row['message_count']);
456
  }
457
458
  public static function db_message_list_admin_by_type($int_type_selected, $StartRec) {
459
    return classSupernova::$db->doSelect("SELECT
460
  message_id as `ID`,
461
  message_from as `FROM`,
462
  message_owner as `OWNER_ID`,
463
  u.username as `OWNER_NAME`,
464
  message_text as `TEXT`,
465
  FROM_UNIXTIME(message_time) as `TIME`
466
FROM
467
  {{messages}} AS m
468
  LEFT JOIN {{users}} AS u ON u.id = m.message_owner " .
469
      ($int_type_selected >= 0 ? "WHERE `message_type` = {$int_type_selected} " : '') .
470
      "ORDER BY
471
  `message_id` DESC
472
LIMIT
473
  {$StartRec}, 25;");
474
  }
475
476
  public static function db_message_insert_all($message_type, $from_unsafe, $subject_unsafe, $text_unsafe) {
477
    $message_type_safe = intval($message_type);
478
    $from_safe = db_escape($from_unsafe);
479
    $subject_safe = db_escape($subject_unsafe);
480
    $text_safe = db_escape($text_unsafe);
481
482
    return classSupernova::$db->doInsertComplex('INSERT INTO {{messages}} (`message_owner`, `message_sender`, `message_time`, `message_type`, `message_from`, `message_subject`, `message_text`) ' .
483
      "SELECT `id`, 0, unix_timestamp(now()), {$message_type_safe}, '{$from_safe}', '{$subject_safe}', '{$text_safe}' FROM {{users}}");
484
  }
485
486
  /**
487
   * @param $int_type_selected
488
   *
489
   * @return array|bool|mysqli_result|null
490
   */
491
  public static function db_message_count_by_type($int_type_selected) {
492
    $page_max = classSupernova::$db->doSelectFetch('SELECT COUNT(*) AS `max` FROM `{{messages}}`' . ($int_type_selected >= 0 ? " WHERE `message_type` = {$int_type_selected};" : ''));
493
494
    return $page_max;
495
  }
496
497
  /**
498
   * @param string $message_delete
499
   */
500
  public static function db_message_list_delete_set($message_delete) {
501
    classSupernova::$db->doDeleteDeprecated(TABLE_MESSAGES, array(0 => "`message_id` in ({$message_delete})",));
0 ignored issues
show
Deprecated Code introduced by
The method db_mysql::doDeleteDeprecated() has been deprecated.

This method has been deprecated.

Loading history...
502
  }
503
504
  public static function db_message_delete_by_id($messageId) {
505
    classSupernova::$gc->db->doDeleteRowWhere(TABLE_MESSAGES, array('message_id' => $messageId));
0 ignored issues
show
Bug introduced by
The method doDeleteRowWhere does only exist in db_mysql, but not in Closure.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
506
  }
507
508
509
510
  /**
511
   * @param $delete_date
512
   * @param $int_type_selected
513
   */
514
  public static function db_message_list_delete_by_date($delete_date, $int_type_selected) {
515
    $where[] = "message_time <= UNIX_TIMESTAMP('{$delete_date}')";
0 ignored issues
show
Coding Style Comprehensibility introduced by
$where was never initialized. Although not strictly required by PHP, it is generally a good practice to add $where = array(); before regardless.

Adding an explicit array definition is generally preferable to implicit array definition as it guarantees a stable state of the code.

Let’s take a look at an example:

foreach ($collection as $item) {
    $myArray['foo'] = $item->getFoo();

    if ($item->hasBar()) {
        $myArray['bar'] = $item->getBar();
    }

    // do something with $myArray
}

As you can see in this example, the array $myArray is initialized the first time when the foreach loop is entered. You can also see that the value of the bar key is only written conditionally; thus, its value might result from a previous iteration.

This might or might not be intended. To make your intention clear, your code more readible and to avoid accidental bugs, we recommend to add an explicit initialization $myArray = array() either outside or inside the foreach loop.

Loading history...
516
    if($int_type_selected >= 0) {
517
      $where['message_type'] = $int_type_selected;
518
    }
519
    classSupernova::$db->doDeleteDeprecated(TABLE_MESSAGES, $where);
0 ignored issues
show
Deprecated Code introduced by
The method db_mysql::doDeleteDeprecated() has been deprecated.

This method has been deprecated.

Loading history...
520
  }
521
522
}
523