Completed
Push — new-committers ( 29cb6f...bcba16 )
by Sam
12:18 queued 33s
created

Debug::show()   B

Complexity

Conditions 7
Paths 7

Size

Total Lines 20
Code Lines 14

Duplication

Lines 0
Ratio 0 %
Metric Value
dl 0
loc 20
rs 8.2222
cc 7
eloc 14
nc 7
nop 2
1
<?php
2
/**
3
 * Supports debugging and core error handling.
4
 *
5
 * Attaches custom methods to the default error handling hooks
6
 * in PHP. Currently, two levels of error are supported:
7
 *
8
 * - Notice
9
 * - Warning
10
 * - Error
11
 *
12
 * Uncaught exceptions are currently passed to the debug
13
 * reporter as standard PHP errors.
14
 *
15
 * Errors handled by this class are passed along to {@link SS_Log}.
16
 * For configuration information, see the {@link SS_Log}
17
 * class documentation.
18
 *
19
 * @todo add support for user defined config: Debug::die_on_notice(true | false)
20
 * @todo better way of figuring out the error context to display in highlighted source
21
 *
22
 * @package framework
23
 * @subpackage dev
24
 */
25
class Debug {
26
27
	/**
28
	 * @config
29
	 * @var String indicating the file where errors are logged.
30
	 * Filename is relative to the site root.
31
	 * The named file will have a terse log sent to it, and the full log (an
32
	 * encoded file containing backtraces and things) will go to a file of a similar
33
	 * name, but with the suffix ".full" added.
34
	 */
35
	private static $log_errors_to = null;
36
37
	/**
38
	 * @config
39
	 * @var string The header of the message shown to users on the live site when a fatal error occurs.
40
	 */
41
	private static $friendly_error_header = 'There has been an error';
42
43
	/**
44
	 * @config
45
	 * @var string The body of the message shown to users on the live site when a fatal error occurs.
46
	 */
47
	private static $friendly_error_detail = 'The website server has not been able to respond to your request.';
48
49
	/**
50
	 * Show the contents of val in a debug-friendly way.
51
	 * Debug::show() is intended to be equivalent to dprintr()
52
	 */
53
	public static function show($val, $showHeader = true) {
54
		if(!Director::isLive()) {
55
			if($showHeader) {
56
				$caller = Debug::caller();
57
				if(Director::is_ajax() || Director::is_cli())
58
					echo "Debug ($caller[class]$caller[type]$caller[function]() in " . basename($caller['file'])
59
						. ":$caller[line])\n";
60
				else
61
					echo "<div style=\"background-color: white; text-align: left;\">\n<hr>\n"
62
						. "<h3>Debug <span style=\"font-size: 65%\">($caller[class]$caller[type]$caller[function]()"
63
						. " \nin " . basename($caller['file']) . ":$caller[line])</span>\n</h3>\n";
64
			}
65
66
			echo Debug::text($val);
67
68
			if(!Director::is_ajax() && !Director::is_cli()) echo "</div>";
69
			else echo "\n\n";
70
		}
71
72
	}
73
74
	/**
75
	 * Returns the caller for a specific method
76
	 *
77
	 * @return array
78
	 */
79
	public static function caller() {
80
		$bt = debug_backtrace();
81
		$caller = $bt[2];
82
		$caller['line'] = $bt[1]['line'];
83
		$caller['file'] = $bt[1]['file'];
84
		if(!isset($caller['class'])) $caller['class'] = '';
85
		if(!isset($caller['type'])) $caller['type'] = '';
86
		return $caller;
87
	}
88
89
	/**
90
	 * Close out the show dumper
91
	 *
92
	 * @param mixed $val
93
	 */
94
	public static function endshow($val) {
95
		if(!Director::isLive()) {
96
			$caller = Debug::caller();
97
			echo "<hr>\n<h3>Debug \n<span style=\"font-size: 65%\">($caller[class]$caller[type]$caller[function]()"
98
				. " \nin " . basename($caller['file']) . ":$caller[line])</span>\n</h3>\n";
99
			echo Debug::text($val);
100
			die();
101
		}
102
	}
103
104
	/**
105
	 * Quick dump of a variable.
106
	 *
107
	 * @param mixed $val
108
	 */
109
	public static function dump($val) {
110
		self::create_debug_view()->writeVariable($val, self::caller());
111
	}
112
113
	/**
114
	 * ??
115
	 *
116
	 * @param unknown_type $val
117
	 * @return unknown
118
	 */
119
	public static function text($val) {
120
		if(is_object($val)) {
121
			if(method_exists($val, 'hasMethod')) {
122
				$hasDebugMethod = $val->hasMethod('debug');
123
			} else {
124
				$hasDebugMethod = method_exists($val, 'debug');
125
			}
126
127
			if($hasDebugMethod) {
128
				return $val->debug();
129
			}
130
		}
131
132
		if(is_array($val)) {
133
			$result = "<ul>\n";
134
			foreach($val as $k => $v) {
135
				$result .= "<li>$k = " . Debug::text($v) . "</li>\n";
136
			}
137
			$val = $result . "</ul>\n";
138
139
		} else if (is_object($val)) {
140
			$val = var_export($val, true);
141
		} else if (is_bool($val)) {
142
			$val = $val ? 'true' : 'false';
143
			$val = '(bool) ' . $val;
144
		} else {
145
			if(!Director::is_cli() && !Director::is_ajax()) {
146
				$val = "<pre style=\"font-family: Courier new\">" . htmlentities($val, ENT_COMPAT, 'UTF-8')
147
					. "</pre>\n";
148
			}
149
		}
150
151
		return $val;
0 ignored issues
show
Bug Best Practice introduced by
The return type of return $val; (string) is incompatible with the return type documented by Debug::text of type unknown.

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...
152
	}
153
154
	/**
155
	 * Show a debugging message
156
	 */
157
	public static function message($message, $showHeader = true) {
158
		if(!Director::isLive()) {
159
			$caller = Debug::caller();
160
			$file = basename($caller['file']);
161
			if(Director::is_cli()) {
162
				if($showHeader) echo "Debug (line $caller[line] of $file):\n ";
163
				echo $message . "\n";
164
			} else {
165
				echo "<p class=\"message warning\">\n";
166
				if($showHeader) echo "<b>Debug (line $caller[line] of $file):</b>\n ";
167
				echo Convert::raw2xml($message) . "</p>\n";
168
			}
169
		}
170
	}
171
172
	// Keep track of how many headers have been sent
173
	private static $headerCount = 0;
174
175
	/**
176
	 * Send a debug message in an HTTP header. Only works if you are
177
	 * on Dev, and headers have not yet been sent.
178
	 *
179
	 * @param string $msg
180
	 * @param string $prefix (optional)
181
	 * @return void
182
	 */
183
	public static function header($msg, $prefix = null) {
184
		if (Director::isDev() && !headers_sent()) {
185
			self::$headerCount++;
186
			header('SS-'.self::$headerCount.($prefix?'-'.$prefix:'').': '.$msg);
187
		}
188
	}
189
190
	/**
191
	 * Log to a standard text file output.
192
	 *
193
	 * @param $message string to output
194
	 */
195
	public static function log($message) {
196
		if (defined('BASE_PATH')) {
197
			$path = BASE_PATH;
198
		}
199
		else {
200
			$path = dirname(__FILE__) . '/../..';
201
		}
202
		$file = $path . '/debug.log';
203
		$now = date('r');
204
		$content = "\n\n== $now ==\n$message\n";
205
		file_put_contents($file, $content, FILE_APPEND);
206
	}
207
208
	/**
209
	 * Load error handlers into environment.
210
	 * Caution: The error levels default to E_ALL is the site is in dev-mode (set in main.php).
211
	 */
212
	public static function loadErrorHandlers() {
213
		set_error_handler('errorHandler', error_reporting());
214
		set_exception_handler('exceptionHandler');
215
	}
216
217 View Code Duplication
	public static function noticeHandler($errno, $errstr, $errfile, $errline, $errcontext) {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in 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...
218
		if(error_reporting() == 0) return;
219
		ini_set('display_errors', 0);
220
221
		// Send out the error details to the logger for writing
222
		SS_Log::log(
223
			array(
224
				'errno' => $errno,
225
				'errstr' => $errstr,
226
				'errfile' => $errfile,
227
				'errline' => $errline,
228
				'errcontext' => $errcontext
229
			),
230
			SS_Log::NOTICE
231
		);
232
233
		if(Director::isDev()) {
234
			return self::showError($errno, $errstr, $errfile, $errline, $errcontext, "Notice");
235
		} else {
236
			return false;
237
		}
238
	}
239
240
	/**
241
	 * Handle a non-fatal warning error thrown by PHP interpreter.
242
	 *
243
	 * @param unknown_type $errno
244
	 * @param unknown_type $errstr
245
	 * @param unknown_type $errfile
246
	 * @param unknown_type $errline
247
	 * @param unknown_type $errcontext
248
	 */
249 View Code Duplication
	public static function warningHandler($errno, $errstr, $errfile, $errline, $errcontext) {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in 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...
250
		if(error_reporting() == 0) return;
251
		ini_set('display_errors', 0);
252
253
		// Send out the error details to the logger for writing
254
		SS_Log::log(
255
			array(
256
				'errno' => $errno,
257
				'errstr' => $errstr,
258
				'errfile' => $errfile,
259
				'errline' => $errline,
260
				'errcontext' => $errcontext
261
			),
262
			SS_Log::WARN
263
		);
264
265
		if(Director::isDev()) {
266
			return self::showError($errno, $errstr, $errfile, $errline, $errcontext, "Warning");
267
		} else {
268
			return false;
269
		}
270
	}
271
272
	/**
273
	 * Handle a fatal error, depending on the mode of the site (ie: Dev, Test, or Live).
274
	 *
275
	 * Runtime execution dies immediately once the error is generated.
276
	 *
277
	 * @param unknown_type $errno
278
	 * @param unknown_type $errstr
279
	 * @param unknown_type $errfile
280
	 * @param unknown_type $errline
281
	 * @param unknown_type $errcontext
282
	 */
283
	public static function fatalHandler($errno, $errstr, $errfile, $errline, $errcontext) {
284
		ini_set('display_errors', 0);
285
286
		// Send out the error details to the logger for writing
287
		SS_Log::log(
288
			array(
289
				'errno' => $errno,
290
				'errstr' => $errstr,
291
				'errfile' => $errfile,
292
				'errline' => $errline,
293
				'errcontext' => $errcontext
294
			),
295
			SS_Log::ERR
296
		);
297
298
		if(Director::isDev() || Director::is_cli()) {
299
			self::showError($errno, $errstr, $errfile, $errline, $errcontext, "Error");
300
		} else {
301
			self::friendlyError();
302
		}
303
		return false;
304
	}
305
306
	/**
307
	 * Render a user-facing error page, using the default HTML error template
308
	 * rendered by {@link ErrorPage} if it exists. Doesn't use the standard {@link SS_HTTPResponse} class
309
	 * the keep dependencies minimal.
310
	 *
311
	 * @uses ErrorPage
312
	 *
313
	 * @param int $statusCode HTTP Status Code (Default: 500)
314
	 * @param string $friendlyErrorMessage User-focused error message. Should not contain code pointers
315
	 *                                     or "tech-speak". Used in the HTTP Header and ajax responses.
316
	 * @param string $friendlyErrorDetail Detailed user-focused message. Is just used if no {@link ErrorPage} is found
317
	 *                                    for this specific status code.
318
	 * @return string HTML error message for non-ajax requests, plaintext for ajax-request.
319
	 */
320
	public static function friendlyError($statusCode=500, $friendlyErrorMessage=null, $friendlyErrorDetail=null) {
321
		if(!$friendlyErrorMessage) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $friendlyErrorMessage of type string|null is loosely compared to false; this is ambiguous if the string can be empty. You might want to explicitly use === null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
322
			$friendlyErrorMessage = Config::inst()->get('Debug', 'friendly_error_header');
323
		}
324
325
		if(!$friendlyErrorDetail) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $friendlyErrorDetail of type string|null is loosely compared to false; this is ambiguous if the string can be empty. You might want to explicitly use === null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
326
			$friendlyErrorDetail = Config::inst()->get('Debug', 'friendly_error_detail');
327
		}
328
329
		if(!headers_sent()) {
330
			// Ensure the error message complies with the HTTP 1.1 spec
331
			$msg = strip_tags(str_replace(array("\n", "\r"), '', $friendlyErrorMessage));
332
			if(Controller::has_curr()) {
333
				$response = Controller::curr()->getResponse();
334
				$response->setStatusCode($statusCode, $msg);
335
			} else {
336
				header($_SERVER['SERVER_PROTOCOL'] . " $statusCode $msg");
337
			}
338
		}
339
340
		if(Director::is_ajax()) {
341
			echo $friendlyErrorMessage;
342
		} else {
343
			if(class_exists('ErrorPage')){
344
				$errorFilePath = ErrorPage::get_filepath_for_errorcode(
345
					$statusCode,
346
					class_exists('Translatable') ? Translatable::get_current_locale() : null
347
				);
348
				if(file_exists($errorFilePath)) {
349
					$content = file_get_contents($errorFilePath);
350
					if(!headers_sent()) header('Content-Type: text/html');
351
					// $BaseURL is left dynamic in error-###.html, so that multi-domain sites don't get broken
352
					echo str_replace('$BaseURL', Director::absoluteBaseURL(), $content);
353
				}
354
			} else {
355
				$renderer = new DebugView();
356
				$renderer->writeHeader();
357
				$renderer->writeInfo("Website Error", $friendlyErrorMessage, $friendlyErrorDetail);
358
359
				if(Email::config()->admin_email) {
360
					$mailto = Email::obfuscate(Email::config()->admin_email);
361
					$renderer->writeParagraph('Contact an administrator: ' . $mailto . '');
362
				}
363
364
				$renderer->writeFooter();
365
			}
366
		}
367
		return false;
368
	}
369
370
	/**
371
	 * Create an instance of an appropriate DebugView object.
372
	 *
373
	 * @return DebugView
374
	 */
375
	public static function create_debug_view() {
376
		$service = Director::is_cli() || Director::is_ajax()
377
			? 'CliDebugView'
378
			: 'DebugView';
379
		return Injector::inst()->get($service);
380
	}
381
382
	/**
383
	 * Render a developer facing error page, showing the stack trace and details
384
	 * of the code where the error occured.
385
	 *
386
	 * @param unknown_type $errno
387
	 * @param unknown_type $errstr
388
	 * @param unknown_type $errfile
389
	 * @param unknown_type $errline
390
	 * @param unknown_type $errcontext
391
	 */
392
	public static function showError($errno, $errstr, $errfile, $errline, $errcontext, $errtype) {
393
		if(!headers_sent()) {
394
			$errText = "$errtype at line $errline of $errfile";
395
			$errText = str_replace(array("\n","\r")," ",$errText);
396
397
			if(!headers_sent()) header($_SERVER['SERVER_PROTOCOL'] . " 500 $errText");
398
399
			// if error is displayed through ajax with CliDebugView, use plaintext output
400
			if(Director::is_ajax()) {
401
				header('Content-Type: text/plain');
402
			}
403
		}
404
405
		$reporter = self::create_debug_view();
406
407
		// Coupling alert: This relies on knowledge of how the director gets its URL, it could be improved.
408
		$httpRequest = null;
409
		if(isset($_SERVER['REQUEST_URI'])) {
410
			$httpRequest = $_SERVER['REQUEST_URI'];
411
		} elseif(isset($_REQUEST['url'])) {
412
			$httpRequest = $_REQUEST['url'];
413
		}
414
		if(isset($_SERVER['REQUEST_METHOD'])) $httpRequest = $_SERVER['REQUEST_METHOD'] . ' ' . $httpRequest;
415
416
		$reporter->writeHeader($httpRequest);
0 ignored issues
show
Unused Code introduced by
The call to DebugView::writeHeader() has too many arguments starting with $httpRequest.

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.

In this case you can add the @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

Loading history...
417
		$reporter->writeError($httpRequest, $errno, $errstr, $errfile, $errline, $errcontext);
418
419
		if(file_exists($errfile)) {
420
			$lines = file($errfile);
421
422
			// Make the array 1-based
423
			array_unshift($lines,"");
424
			unset($lines[0]);
425
426
			$offset = $errline-10;
427
			$lines = array_slice($lines, $offset, 16, true);
428
			$reporter->writeSourceFragment($lines, $errline);
429
		}
430
		$reporter->writeTrace(($errcontext ? $errcontext : debug_backtrace()));
431
		$reporter->writeFooter();
432
		return false;
433
	}
434
435
	/**
436
	 * Utility method to render a snippet of PHP source code, from selected file
437
	 * and highlighting the given line number.
438
	 *
439
	 * @param string $errfile
440
	 * @param int $errline
441
	 */
442
	public static function showLines($errfile, $errline) {
443
		$lines = file($errfile);
444
		$offset = $errline-10;
445
		$lines = array_slice($lines, $offset, 16);
446
		echo '<pre>';
447
		$offset++;
448 View Code Duplication
		foreach($lines as $line) {
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...
449
			$line = htmlentities($line, ENT_COMPAT, 'UTF-8');
450
			if ($offset == $errline) {
451
				echo "<span>$offset</span> <span class=\"error\">$line</span>";
452
			} else {
453
				echo "<span>$offset</span> $line";
454
			}
455
			$offset++;
456
		}
457
		echo '</pre>';
458
	}
459
460
	/**
461
	 * Check if the user has permissions to run URL debug tools,
462
	 * else redirect them to log in.
463
	 */
464
	public static function require_developer_login() {
465
		if(Director::isDev())	{
466
			return;
467
		}
468
		if(isset($_SESSION['loggedInAs'])) {
469
			// We have to do some raw SQL here, because this method is called in Object::defineMethods().
470
			// This means we have to be careful about what objects we create, as we don't want Object::defineMethods()
471
			// being called again.
472
			// This basically calls Permission::checkMember($_SESSION['loggedInAs'], 'ADMIN');
473
474
			// @TODO - Rewrite safely using DataList::filter
475
			$memberID = $_SESSION['loggedInAs'];
476
			$permission = DB::prepared_query('
477
				SELECT "ID" FROM "Permission"
478
				INNER JOIN "Group_Members" ON "Permission"."GroupID" = "Group_Members"."GroupID"
479
				WHERE "Permission"."Code" = ?
480
				AND "Permission"."Type" = ?
481
				AND "Group_Members"."MemberID" = ?',
482
				array(
483
					'ADMIN', // Code
484
					Permission::GRANT_PERMISSION, // Type
485
					$memberID // MemberID
486
				)
487
			)->value();
488
489
			if($permission) return;
490
		}
491
492
		// This basically does the same as
493
		// Security::permissionFailure(null, "You need to login with developer access to make use of debugging tools.")
494
		// We have to do this because of how early this method is called in execution.
495
		$_SESSION['Security']['Message']['message']
496
			= "You need to login with developer access to make use of debugging tools.";
497
		$_SESSION['Security']['Message']['type'] =  'warning';
498
		$_SESSION['BackURL'] = $_SERVER['REQUEST_URI'];
499
		header($_SERVER['SERVER_PROTOCOL'] . " 302 Found");
500
		header("Location: " . Director::baseURL() . Security::login_url());
501
		die();
502
	}
503
}
504
505
506
507
508
509
510
511
512
513
514
/**
515
 * Generic callback, to catch uncaught exceptions when they bubble up to the top of the call chain.
516
 *
517
 * @ignore
518
 * @param Exception $exception
519
 */
520
function exceptionHandler($exception) {
521
	$errno = E_USER_ERROR;
522
	$type = get_class($exception);
523
	$message = "Uncaught " . $type . ": " . $exception->getMessage();
524
	$file = $exception->getFile();
525
	$line = $exception->getLine();
526
	$context = $exception->getTrace();
527
	Debug::fatalHandler($errno, $message, $file, $line, $context);
0 ignored issues
show
Documentation introduced by
$errno is of type integer, but the function expects a object<unknown_type>.

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...
Documentation introduced by
$message is of type string, but the function expects a object<unknown_type>.

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...
528
	exit(1);
529
}
530
531
/**
532
 * Generic callback to catch standard PHP runtime errors thrown by the interpreter
533
 * or manually triggered with the user_error function. Any unknown error codes are treated as
534
 * fatal errors.
535
 * Caution: The error levels default to E_ALL if the site is in dev-mode (set in main.php).
536
 *
537
 * @ignore
538
 * @param int $errno
539
 * @param string $errstr
540
 * @param string $errfile
541
 * @param int $errline
542
 */
543
function errorHandler($errno, $errstr, $errfile, $errline) {
544
	switch($errno) {
545
		case E_NOTICE:
546
		case E_USER_NOTICE:
547
		case E_DEPRECATED:
548
		case E_USER_DEPRECATED:
549
		case E_STRICT:
550
			return Debug::noticeHandler($errno, $errstr, $errfile, $errline, debug_backtrace());
551
552
		case E_WARNING:
553
		case E_CORE_WARNING:
554
		case E_USER_WARNING:
555
		case E_RECOVERABLE_ERROR:
556
			return Debug::warningHandler($errno, $errstr, $errfile, $errline, debug_backtrace());
0 ignored issues
show
Documentation introduced by
$errno is of type integer, but the function expects a object<unknown_type>.

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...
Documentation introduced by
$errstr is of type string, but the function expects a object<unknown_type>.

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...
Documentation introduced by
$errfile is of type string, but the function expects a object<unknown_type>.

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...
Documentation introduced by
$errline is of type integer, but the function expects a object<unknown_type>.

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...
Documentation introduced by
debug_backtrace() is of type array, but the function expects a object<unknown_type>.

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...
557
558
		case E_ERROR:
559
		case E_CORE_ERROR:
560
		case E_USER_ERROR:
561
		default:
562
			Debug::fatalHandler($errno, $errstr, $errfile, $errline, debug_backtrace());
0 ignored issues
show
Documentation introduced by
$errno is of type integer, but the function expects a object<unknown_type>.

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...
Documentation introduced by
$errstr is of type string, but the function expects a object<unknown_type>.

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...
Documentation introduced by
$errfile is of type string, but the function expects a object<unknown_type>.

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...
Documentation introduced by
$errline is of type integer, but the function expects a object<unknown_type>.

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...
Documentation introduced by
debug_backtrace() is of type array, but the function expects a object<unknown_type>.

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...
563
			exit(1);
564
	}
565
}
566