Issues (1369)

classes/debug.php (22 issues)

1
<?php /** @noinspection PhpUnnecessaryCurlyVarSyntaxInspection */
2
3
/*
4
 * debug.php ::  Clase Debug, maneja reporte de eventos
5
 *
6
 * V4.0 copyright 2010-2011 by Gorlum for http://supernova.ws
7
 *  [!] Merged `errors` to `logs`
8
 *  [+] Now debugger can work with database detached. All messages would be dumped to page
9
 *  [+] Now `logs` has both human-readable and machine-readable fields
10
 *
11
 * V3.0 copyright 2010 by Gorlum for http://supernova.ws
12
 *  [+] Full rewrtie & optimize
13
 *  [*] Now there is fallback procedure if no link to db detected
14
 *
15
 * V2.0 copyright 2010 by Gorlum for http://supernova.ws
16
 *  [*] Now error also contains backtrace - to see exact way problem comes
17
 *  [*] New method 'warning' sends message to dedicated SQL-table for non-errors
18
 *
19
 * V1.0 Created by Perberos. All rights reversed (C) 2006
20
 *
21
 *  Experiment code!!!
22
 *
23
 * vamos a experimentar >:)
24
 * le veo futuro a las classes, ayudaria mucho a tener un codigo mas ordenado...
25
 * que esperabas!!! soy newbie!!! D':<
26
*/
27
28
use DBAL\db_mysql;
29
30
if (!defined('INSIDE')) {
31
  die("attemp hacking");
32
}
33
34
class debug {
35
  protected $log;
36
  protected $numqueries;
37
  protected $log_array;
38
39
  public function log_file($message, $ident_change = 0) {
40
    if (!defined('SN_DEBUG_LOG') || !SN_DEBUG_LOG) {
0 ignored issues
show
The constant SN_DEBUG_LOG was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
41
      return;
42
    }
43
44
    static $ident = 0;
45
    static $logFileName;
46
47
    if (!$logFileName) {
48
      $logFileName = SN_ROOT_PHYSICAL . '/.logs/supernova.log';
49
      file_put_contents($logFileName, "\r\n\r\n", FILE_APPEND);
50
    }
51
    if ($ident_change < 0) {
52
      $ident += $ident_change * 2;
53
    }
54
    file_put_contents($logFileName, date(FMT_DATE_TIME_SQL, time()) . str_repeat(' ', $ident + 1) . $message . "\r\n", FILE_APPEND);
55
    if ($ident_change > 0) {
56
      $ident += $ident_change * 2;
57
    }
58
  }
59
60
  public function log_sql($message, $ident_change = 0) {
61
    static $ident = 0;
62
    static $logFileName;
63
    static $mt_rand;
64
65
    if (!$mt_rand) {
66
      $mt_rand = mt_rand();
67
    }
68
69
    if (!$logFileName) {
70
      $dbName      = SN::$db->dbName;
71
      $logFileName = SN_ROOT_PHYSICAL . "/.logs/{$dbName}.mysql." . date('Y-m-d-H-i-s.') . sprintf("%06d", gettimeofday()["usec"]) . ".log";
72
    }
73
    if ($ident_change < 0) {
74
      $ident += $ident_change * 2;
75
    }
76
    file_put_contents($logFileName, str_repeat(' ', $ident) . $message . "\n\n", FILE_APPEND);
77
    if ($ident_change > 0) {
78
      $ident += $ident_change * 2;
79
    }
80
  }
81
82
  public function __construct() {
83
    $this->log        = '';
84
    $this->numqueries = 0;
85
  }
86
87
  function add($mes) {
0 ignored issues
show
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
88
    $this->log .= $mes;
89
    $this->numqueries++;
90
  }
91
92
  function add_to_array($mes) {
0 ignored issues
show
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
93
    $this->log_array[] = $mes;
94
  }
95
96
  function echo_log() {
0 ignored issues
show
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
97
    echo '<br><table><tr><td class=k colspan=4><a href="' . SN_ROOT_PHYSICAL . "admin/settings.php\">Debug Log</a>:</td></tr>{$this->log}</table>";
98
    die();
0 ignored issues
show
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
99
  }
100
101
  public function compact_backtrace($backtrace, $long_comment = false, $onlyLastX = null) {
102
    static $exclude_functions = array(
103
      // Caller not needed
104
      'comment_query',
105
      // Excluding includes/requires
106
      'include', 'include_once', 'require_once', 'require',
107
      // Excluding query calls/DB wrap functions
108
      'doquery',
109
      'db_get_record_list', // 'db_user_by_id', 'db_get_user_by_id',
110
      'doSelect', 'doSelectFetch',
111
      'db_query_update',
112
      'selectValue',
113
      // classPersistent
114
      '__get', 'db_loadItem', '__set', 'db_saveItem',
115
      // Constructors ?! Why not...
116
      '__construct',
117
      // Hook handlers
118
      'sn_function_call',
119
      // Chat
120
      'db_chat_player_list_online',
121
      // Transaction-related functions
122
      'db_transaction_commit', 'transactionCommit', 'transactionStart', 'db_transaction_start', 'db_transaction_rollback', 'transactionRollback',
123
    );
124
125
    $raw      = [];
126
    $filtered = [];
127
    foreach ($backtrace as $a_trace) {
128
      $function =
129
        (!empty($a_trace['type'])
130
          ? ($a_trace['type'] == '->'
131
            ? "({$a_trace['class']})" . get_class($a_trace['object'])
132
            : $a_trace['class']
133
          ) . $a_trace['type']
134
          : ''
135
        ) . $a_trace['function'] . '()';
136
137
      $file = str_replace(SN_ROOT_PHYSICAL, '', str_replace('\\', '/', !empty($a_trace['file']) ? $a_trace['file'] : ''));
138
139
      $line  = !empty($a_trace['line']) ? '@' . $a_trace['line'] : '';
140
      $raw[] = "{$function} - '{$file}'{$line}";
141
142
      if (!in_array($a_trace['function'], $exclude_functions)) {
143
        $filtered[] = &$raw[count($raw) - 1];
144
      }
145
146
      if (!$long_comment) {
147
        break;
148
      }
149
    }
150
151
    $raw      = array_reverse($raw);
152
    $filtered = array_reverse($filtered);
153
154
    if ($onlyLastX) {
155
      $raw      = array_slice($raw, -$onlyLastX);
156
      $filtered = array_slice($filtered, -$onlyLastX);
157
    }
158
159
    return [$raw, $filtered,];
160
  }
161
162
  /**
163
   * @param array  $backtrace
164
   * @param string $sql
165
   *
166
   * @return string
167
   */
168
  public function comment_query($backtrace, $sql) {
169
    list($raw, $filtered,) = $this->compact_backtrace($backtrace, defined('DEBUG_SQL_COMMENT_LONG'));
170
171
    $sql_commented = [
172
      "/* ",
173
      'date' => date("s.") . sprintf("%06d", gettimeofday()["usec"]),
174
      !empty($filtered) ? "\n" . implode("\n", $filtered) . " \n" : '',
175
      "*/\n",
176
      // SQL itself with removed double spaces
177
      preg_replace("/\s+/", ' ', $sql),
178
    ];
179
180
    if (defined('DEBUG_SQL_FILE_LOG') && !empty(DEBUG_SQL_FILE_LOG)) {
0 ignored issues
show
The constant DEBUG_SQL_FILE_LOG was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
181
      $this->log_sql(implode('', $sql_commented));
182
    }
183
184
//      $sql_commented = '/* ' . implode("<br />", $sql_comment) . '<br /> */ ' . preg_replace("/\s+/", ' ', $sql);
185
//      $isSelect = strpos(strtoupper($query), 'SELECT') !== false ? 'true' : 'false';
186
    $sql_commented['date'] = date('Y-m-d H:i:') . $sql_commented['date'];
187
188
//      if(strpos($sql_comment, 'compact_backtrace') === false) {
189
//        $transaction_id = SN::db_transaction_check(false) ? SN::$transaction_id : SN::$transaction_id++;
190
//        $result[] = "tID {$transaction_id}";
191
//      }
192
193
    if (defined('DEBUG_SQL_ERROR')) {
194
      array_unshift($raw, preg_replace("/\s+/", ' ', $sql));
195
      array_unshift($raw, $sql_commented['date']);
196
      $this->add_to_array($raw);
197
    }
198
199
    $sql = implode('', $sql_commented);
200
201
    return $sql;
202
  }
203
204
205
  function dump($dump = false, $force_base = false, $deadlock = false) {
0 ignored issues
show
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
206
    if ($dump === false) {
207
      return [];
208
    }
209
210
    $error_backtrace = array();
211
    $base_dump       = false;
212
213
    if ($force_base === true) {
214
      $base_dump = true;
215
    }
216
217
    if ($dump === true) {
218
      $base_dump = true;
219
    } else {
220
      if (!is_array($dump)) {
221
        $dump = array('var' => $dump);
222
      }
223
224
      foreach ($dump as $dump_var_name => $dump_var) {
225
        if ($dump_var_name == 'base_dump') {
226
          $base_dump = $dump_var;
227
        } else {
228
          $error_backtrace[$dump_var_name] = $dump_var;
229
        }
230
      }
231
    }
232
233
    if ($deadlock && ($q = SN::$db->mysql_get_innodb_status())) {
234
      $error_backtrace['deadlock'] = explode("\n", $q['Status']);
235
      foreach ($error_backtrace['cSN_data'] as &$location) {
236
        foreach ($location as $location_id => &$location_data) //          $location_data = $location_id;
237
        {
238
          $location_data = isset($location_data['username']) ? $location_data['username'] :
239
            (isset($location_data['name']) ? $location_data['name'] : $location_id);
240
        }
241
      }
242
    }
243
244
    if ($base_dump) {
245
      if (!is_array($this->log_array) || empty($this->log_array)) {
246
        $this->log_array = [];
247
      } else {
248
        foreach ($this->log_array as $log) {
249
          $error_backtrace['queries'][] = $log;
250
        }
251
      }
252
253
      $error_backtrace['backtrace'] = debug_backtrace();
254
      unset($error_backtrace['backtrace'][1]);
255
      unset($error_backtrace['backtrace'][0]);
256
257
      // Converting object instances to object names
258
259
      foreach ($error_backtrace['backtrace'] as &$backtrace) {
260
        if (!empty($backtrace['object']) && is_object($backtrace['object'])) {
261
          $backtrace['object'] = get_class($backtrace['object']);
262
        }
263
264
        if (empty($backtrace['args'])) {
265
          continue;
266
        }
267
268
        // Doing same conversion for backtrace params
269
        foreach ($backtrace['args'] as &$arg) {
270
          if (is_object($arg)) {
271
            $arg = 'object::' . get_class($arg);
272
          }
273
        }
274
      }
275
276
      // $error_backtrace['query_log'] = "\r\n\r\nQuery log\r\n<table><tr><th>Number</th><th>Query</th><th>Page</th><th>Table</th><th>Rows</th></tr>{$this->log}</table>\r\n";
277
      $error_backtrace['$_GET']     = $_GET;
278
      $error_backtrace['$_POST']    = $_POST;
279
      $error_backtrace['$_REQUEST'] = $_REQUEST;
280
      $error_backtrace['$_COOKIE']  = $_COOKIE;
281
      $error_backtrace['$_SESSION'] = empty($_SESSION) ? [] : $_SESSION;
282
      $error_backtrace['$_SERVER']  = $_SERVER;
283
      global $user, $planetrow;
284
      $error_backtrace['user']      = $user;
285
      $error_backtrace['planetrow'] = $planetrow;
286
    }
287
288
    return $error_backtrace;
289
  }
290
291
  function error_fatal($die_message, $details = 'There is a fatal error on page') {
0 ignored issues
show
The parameter $details is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

291
  function error_fatal($die_message, /** @scrutinizer ignore-unused */ $details = 'There is a fatal error on page') {

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

Loading history...
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
292
    // TODO - Записывать детали ошибки в лог-файл
293
    die($die_message);
0 ignored issues
show
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
294
  }
295
296
  public function error($message = 'There is a error on page', $title = 'Internal Error', $httpCode = 500, $dump = true) {
297
    global $config, $sys_stop_log_hit, $lang, $sys_log_disabled, $user;
298
299
    if (empty(SN::$db->connected)) {
300
      // TODO - писать ошибку в файл
301
      die('SQL server currently unavailable. Please contact Administration...');
0 ignored issues
show
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
302
    }
303
304
    db_mysql::db_transaction_rollback();
305
306
    if (SN::$config->debug == 1) {
307
      /** @noinspection HtmlDeprecatedTag */
308
      /** @noinspection XmlDeprecatedElement */
309
      /** @noinspection HtmlDeprecatedAttribute */
310
      echo "<h2>{$title}</h2><br><font color=red>" . htmlspecialchars($message) . "</font><br><hr>";
311
      echo "<table>{$this->log}</table>";
312
    }
313
314
    $fatal_error = 'Fatal error: cannot write to `logs` table. Please contact Administration...';
315
316
    $error_text      = SN::$db->db_escape($message);
317
    $error_backtrace = $this->dump($dump, true, strpos($message, 'Deadlock') !== false);
318
319
    if (!$sys_log_disabled) {
320
      $this->_writeLogMessage($httpCode, $user, $title, $message, $error_backtrace, $fatal_error);
321
322
      $message = "Пожалуйста, свяжитесь с админом, если ошибка повторится. Ошибка №: <b>" . SN::$db->db_insert_id() . "</b>";
323
324
      $sys_stop_log_hit = true;
325
      $sys_log_disabled = true;
326
      !function_exists('messageBox') ? die($message) : SnTemplate::messageBox($message, 'Ошибка', '', 0, false);
0 ignored issues
show
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
327
    } else {
328
//        // TODO Здесь надо писать в файло
329
      ob_start();
330
      print("<hr>User ID {$user['id']} raised error code {$httpCode} titled '{$title}' with text '{$error_text}' on page {$_SERVER['SCRIPT_NAME']}");
331
332
      foreach ($error_backtrace as $name => $value) {
333
        print('<hr>');
334
        pdump($value, $name);
335
      }
336
      ob_end_flush();
337
      die();
0 ignored issues
show
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
338
    }
339
  }
340
341
  function warning($message, $title = 'System Message', $httpCode = 300, $dump = false) {
0 ignored issues
show
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
342
    global $user, $lang, $sys_log_disabled;
343
344
    if (empty(SN::$db->connected)) {
345
      // TODO - писать ошибку в файл
346
      die('SQL server currently unavailable. Please contact Administration...');
0 ignored issues
show
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
347
    }
348
349
    $fatal_error = 'Fatal error: cannot write to `logs` table. Please contact Administration...';
350
351
    $error_backtrace = $this->dump($dump, false);
352
353
    if (empty($sys_log_disabled)) {
354
      $this->_writeLogMessage($httpCode, $user, $title, $message, $error_backtrace, $fatal_error);
355
    } else {
356
//        // TODO Здесь надо писать в файло
357
      $id = !empty($user['id']) ? $user['id'] : 0;
358
      print("<hr>User ID {$id} made log entry with code {$httpCode} titled '{$title}' with text '{$message}' on page {$_SERVER['SCRIPT_NAME']}");
359
    }
360
  }
361
362
  /**
363
   * @param       $httpCode
364
   * @param       $user
365
   * @param       $title
366
   * @param       $message
367
   * @param array $error_backtrace
368
   * @param       $fatal_error
369
   *
370
   * @return void
371
   */
372
  function _writeLogMessage($httpCode, $user, $title, $message, array $error_backtrace, $fatal_error) {
0 ignored issues
show
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
373
    /** @noinspection SqlResolve */
374
    $query = "INSERT INTO `{{logs}}` SET
375
        `log_time` = '" . time() . "', `log_code` = '" . SN::$db->db_escape($httpCode) . "', " .
376
      "`log_sender` = '" . (!empty($user['id']) ? SN::$db->db_escape($user['id']) : 0) . "', " .
377
      "`log_username` = '" . SN::$db->db_escape(!empty($user['user_name']) ? $user['user_name'] : '') . "', " .
378
      "`log_title` = '" . SN::$db->db_escape($title) . "',  `log_text` = '" . SN::$db->db_escape($message) . "', " .
379
      "`log_page` = '" . SN::$db->db_escape(strpos($_SERVER['SCRIPT_NAME'], SN_ROOT_RELATIVE) === false ? $_SERVER['SCRIPT_NAME'] : substr($_SERVER['SCRIPT_NAME'], strlen(SN_ROOT_RELATIVE))) . "'" . ", " .
380
      "`log_dump` = '" . ($error_backtrace ? SN::$db->db_escape(json_encode($error_backtrace)) : '') . "'" . ";";
381
382
    doquery($query, '', false, true) or die($fatal_error . SN::$db->db_error());
0 ignored issues
show
Deprecated Code introduced by
The function doquery() has been deprecated. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

382
    /** @scrutinizer ignore-deprecated */ doquery($query, '', false, true) or die($fatal_error . SN::$db->db_error());
Loading history...
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
383
  }
384
}
385
386
// Copyright (c) 2009-2010 Gorlum for http://supernova.ws
387
// Dump variables nicer then var_dump()
388
389
function dump($value, $varname = null, $level = 0, $dumper = '') {
390
  if (isset($varname)) {
391
    $varname .= " = ";
392
  }
393
394
  if ($level == -1) {
395
    $trans[' ']  = '&there4;';
0 ignored issues
show
Comprehensibility Best Practice introduced by
$trans was never initialized. Although not strictly required by PHP, it is generally a good practice to add $trans = array(); before regardless.
Loading history...
396
    $trans["\t"] = '&rArr;';
397
    $trans["\n"] = '&para;;';
398
    $trans["\r"] = '&lArr;';
399
    $trans["\0"] = '&oplus;';
400
401
    return strtr(htmlspecialchars($value), $trans);
402
  }
403
  if ($level == 0) {
404
//    $dumper = '<pre>' . mt_rand(10, 99) . '|' . $varname;
405
    $dumper = mt_rand(10, 99) . '|' . $varname;
406
  }
407
408
  $type   = gettype($value);
409
  $dumper .= $type;
410
411
  if ($type == 'string') {
412
    $dumper .= '(' . strlen($value) . ')';
413
    $value  = dump($value, '', -1);
414
  } elseif ($type == 'boolean') {
415
    $value = ($value ? 'true' : 'false');
416
  } elseif ($type == 'object') {
417
    $props  = get_class_vars(get_class($value));
418
    $dumper .= '(' . count($props) . ') <u>' . get_class($value) . '</u>';
419
    foreach ($props as $key => $val) {
420
      $dumper .= "\n" . str_repeat("\t", $level + 1) . $key . ' => ';
421
      $dumper .= dump($value->$key, '', $level + 1);
422
    }
423
    $value = '';
424
  } elseif ($type == 'array') {
425
    $dumper .= '(' . count($value) . ')';
426
    foreach ($value as $key => $val) {
427
      $dumper .= "\n" . str_repeat("\t", $level + 1) . dump($key, '', -1) . ' => ';
428
      $dumper .= dump($val, '', $level + 1);
429
    }
430
    $value = '';
431
  }
432
  $dumper .= " <b>$value</b>";
433
//  if($level == 0) {
434
//    $dumper .= '</pre>';
435
//  }
436
437
  return $dumper;
438
}
439
440
function pdump($value, $varname = null) {
441
  $backtrace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS);
442
//  print_rr($backtrace);
443
//  $backtrace = $backtrace[1];
444
445
  $caller = '';
446
  if (defined('SN_DEBUG_PDUMP_CALLER') && SN_DEBUG_PDUMP_CALLER) {
0 ignored issues
show
The constant SN_DEBUG_PDUMP_CALLER was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
447
    $caller = (!empty($backtrace[1]['class']) ? $backtrace[1]['class'] : '') .
448
      (!empty($backtrace[1]['type']) ? $backtrace[1]['type'] : '') .
449
      $backtrace[1]['function'] .
450
      (!empty($backtrace[0]['file'])
451
        ? (
452
          ' (' . substr($backtrace[0]['file'], SN_ROOT_PHYSICAL_STR_LEN) .
453
          (!empty($backtrace[0]['line']) ? ':' . $backtrace[0]['line'] : '') .
454
          ')'
455
        )
456
        : ''
457
      );
458
    $caller = "\r\n" . $caller;
459
  }
460
461
  if (php_sapi_name() == "cli") {
462
    print("\n" .
463
      dump($value, $varname) .
464
      $caller .
465
      "\n\n"
466
    );
467
  } else {
468
    print('<pre style="text-align: left; background-color: #111111; color: #0A0; font-family: Courier, monospace !important; padding: 1em 0; font-weight: 800; font-size: 14px;">' .
469
      dump($value, $varname) .
470
      $caller .
471
      '</pre>'
472
    );
473
  }
474
}
475
476
function debug($value, $varname = null) {
477
  pdump($value, $varname);
478
}
479
480
function pr($prePrint = false) {
481
  if ($prePrint) {
482
    print("<br>");
483
  }
484
  print(mt_rand() . "<br>");
485
}
486
487
function pc($prePrint = false) {
488
  global $_PRINT_COUNT_VALUE;
489
  $_PRINT_COUNT_VALUE++;
490
491
  if ($prePrint) {
492
    print("<br>");
493
  }
494
  print($_PRINT_COUNT_VALUE . "<br>");
495
}
496
497
function prep($message) {
498
  print('<pre>' . $message . '</pre>');
499
}
500
501
function backtrace_no_arg() {
502
  $trace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS);
503
  array_shift($trace);
504
505
  return $trace;
506
}
507
508
if (!function_exists('pre')) {
509
  define('START', microtime(true)); // SHOULD NEVER BE REMOVED!
510
511
  /**
512
   * @param mixed $value     <p>
513
   *                         The variable you want to export.
514
   *                         </p>
515
   * @param mixed ...$values [optional]
516
   *
517
   * @return void
518
   */
519
  function pre() {
520
    if (func_num_args() <= 0) {
521
      return;
522
    }
523
524
    foreach (func_get_args() ?: [] as $var) {
525
      print "<pre>";
526
      print_r(
527
        $var === null ? 'null' :
528
          (($type = gettype($var)) == 'object' || $type == 'array'
529
            ? $var :
530
            ($type === 'string'
531
              ? $type . '(' . strlen($var) . ') `' . $var . '`' :
532
              ($type == 'boolean'
533
                ? ($var ? 'true' : 'false')
534
                : $type . ' ' . print_r($var, true)
0 ignored issues
show
Are you sure print_r($var, true) of type string|true can be used in concatenation? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

534
                : $type . ' ' . /** @scrutinizer ignore-type */ print_r($var, true)
Loading history...
535
              )
536
            )
537
          )
538
      );
539
      print "</pre>";
540
    }
541
542
    $trace = debug_backtrace();
543
544
    $p     = $trace[1]['function'] == 'pred' ? $trace[1] : $trace[0];
545
//            print("\n{$p['file']}@{$p['line']}<br />\n" . (is_string($die) ? 'Die message: ' . $die . "<br />\n" : ''));
546
    print("\n{$p['file']}@{$p['line']}<br />\n");
547
  }
548
549
  function pred() {
550
    call_user_func_array('pre', func_get_args());
551
    die();
0 ignored issues
show
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
552
  }
553
}
554