function _fp_error_handler

7.x misc.inc _fp_error_handler($error_level, $message, $filename, $line, $context = array())
6.x misc.inc _fp_error_handler($error_level, $message, $filename, $line, $context = array())
5.x misc.inc _fp_error_handler($error_level, $message, $filename, $line, $context = array())

This is our custom error handler, which will intercept PHP warnings, notices, etc, and let us display them, log them, etc.

See https://www.php.net/manual/en/function.set-error-handler.php

1 string reference to '_fp_error_handler'
bootstrap.inc in ./bootstrap.inc
This file should be included by every public-facing page of FlightPath. It will include all the classes, as well as settings and function files, and modules.

File

includes/misc.inc, line 488
This file contains misc functions for FlightPath

Code

function _fp_error_handler($error_level, $message, $filename, $line, $context = array()) {
  global $user;

  // In case we have not loaded bootstrap.inc yet.  
  @define('WATCHDOG_NOTICE', 5);
  @define('WATCHDOG_ALERT', 1);
  @define('WATCHDOG_ERROR', 3);
  @define('WATCHDOG_DEBUG', 7);

  $PHP_8_0_SUPPRESSED_ERROR = E_ERROR | E_CORE_ERROR | E_COMPILE_ERROR | E_USER_ERROR | E_RECOVERABLE_ERROR | E_PARSE;
  $er = error_reporting();
  if ($er === 0 || $er === $PHP_8_0_SUPPRESSED_ERROR) {
    return false;
  } // suppressed with @-operator  (0 for pre-php8, the variable for 8.0)



  $err_name = _fp_map_php_error_code($error_level);
  if (is_string($err_name) && stristr($err_name, 'notice')) {
    return FALSE; // don't care about Notices. 
  }

  $watchdog_type = "php_error";
  $watchdog_severity = WATCHDOG_ERROR;


  if (is_string($err_name) && stristr($err_name, 'warning')) {
    $watchdog_type = "php_warning";
    $watchdog_severity = WATCHDOG_ALERT;
  }

  if (is_string($err_name) && stristr($err_name, 'recoverable error')) {
    $watchdog_type = "php_warning";
    $watchdog_severity = WATCHDOG_ALERT;
  }

  $arr = debug_backtrace(DEBUG_BACKTRACE_PROVIDE_OBJECT, 10); // limit of 10 levels deep so as not to eat up all the memory.

  // fpm() only displays for privileged users

  // We don't want to bother repeating the same message more than once for errors.  The following code
  // will prevent that.
  // TODO: Make this a setting?
  $errmsg = $err_name . ": $message<br>... ($line) $filename";
  $errmsg_hash = hash('sha256', $errmsg);

  if (!isset($GLOBALS ['fp_error_handler__already_shown_error'][$errmsg_hash])) {
    fpm($errmsg);
    fpm($arr);
    $GLOBALS ['fp_error_handler__already_shown_error'][$errmsg_hash] = TRUE;
  }
  else {
    return; // we've already displayed this error message; we can harmlessly return.
  }



  // Before we watchdog or mail this backtrace, make sure no field called "password" is in plain text.
  foreach ($arr as $c => $trace) {
    if (is_array($trace) && isset($trace ['args'])) {
      foreach ($trace ['args'] as $k => $details) {
        if (is_array($details)) {
          foreach ($details as $j => $val) {
            if (stristr($j, 'password')) {
              $arr [$c]['args'][$k][$j] = "--PASSWORD HIDDEN IN LOG--";
            }
          }
        }
      }
    }
  }


  $hostname = php_uname('n') . ' - ' . $GLOBALS ['fp_system_settings']['base_url'];

  $msg = "";
  $msg .= "USER:   $user->name ($user->id) \n";
  $msg .= "SERVER:   $hostname \n";
  $msg .= "DATE:     " . format_date(convert_time(time())) . "\n";
  $msg .= "SEVERITY: $err_name \n";
  $msg .= "--------------------------\n\n";
  $msg .= "$err_name: $message \n\n";
  $msg .= "... ($line) $filename\n\n";
  $msg .= "Backtrace: <pre>\n";
  $msg .= print_r($arr, TRUE);
  $msg .= "\n\n</pre>";


  // Because we can have EXTREMELY long $msg due to the backtrace, limit it to a reasonable number.
  if (strlen($msg) > 10000) {
    $msg = substr($msg, 0, 10000) . "\n\n\n... truncated to 10,000 characters to save space.  Full length was: " . strlen($msg);
  }

  watchdog($watchdog_type, $msg, array(), $watchdog_severity);

  if (@intval($user->id) !== 0) {
    // We are NOT the admin user.  (No need to email, since it would appear on screen with the fpm() calls earlier.

    // Should we email someone, as with mysql errors?
    $tomail = trim(variable_get("notify_php_error_email_address", ""));

    if ($tomail != "") {
      fp_mail($tomail, "PHP Error in FlightPath", $msg);
    }

  }

}