function is_oop_on($trace = false) { static $s_oopIsEnabled; if (isset($s_oopIsEnabled)) { // Return the cached value. return $s_oopIsEnabled; } if (CConfiguration::isInitialized()) { $s_oopIsEnabled = CConfiguration::appOption("enableOop"); return $s_oopIsEnabled; } else { return false; } }
public static function errorHandler($errorLevel, $errorDesc, $filePath, $line) { // If any error processing is enabled, this function is called by the PHP runtime on a failed assertion or // runtime error. settype($errorLevel, "int"); settype($line, "int"); $reportThisError = true; if (CConfiguration::isInitialized()) { $errorReportingLevel = constant(CConfiguration::option("debug.errorReportingLevel")); if ($errorLevel & $errorReportingLevel == 0) { $reportThisError = false; } } if ($reportThisError) { // Avoid double reporting of the same error if the method registered with `register_shutdown_function` is // called by the runtime after an error occurred. $errorFileAndLine = []; $errorFileAndLine["file"] = $filePath; $errorFileAndLine["line"] = $line; self::$ms_processedErrors[] = $errorFileAndLine; $strErrorLevel; switch ($errorLevel) { case E_ERROR: // 1 $strErrorLevel = "E_ERROR"; break; case E_WARNING: // 2 $strErrorLevel = "E_WARNING"; break; case E_PARSE: // 4 $strErrorLevel = "E_PARSE"; break; case E_NOTICE: // 8 $strErrorLevel = "E_NOTICE"; break; case E_CORE_ERROR: // 16 $strErrorLevel = "E_CORE_ERROR"; break; case E_CORE_WARNING: // 32 $strErrorLevel = "E_CORE_WARNING"; break; case E_COMPILE_ERROR: // 64 $strErrorLevel = "E_COMPILE_ERROR"; break; case E_COMPILE_WARNING: // 128 $strErrorLevel = "E_COMPILE_WARNING"; break; case E_USER_ERROR: // 256 $strErrorLevel = "E_USER_ERROR"; break; case E_USER_WARNING: // 512 $strErrorLevel = "E_USER_WARNING"; break; case E_USER_NOTICE: // 1024 $strErrorLevel = "E_USER_NOTICE"; break; case E_STRICT: // 2048 $strErrorLevel = "E_STRICT"; break; case E_RECOVERABLE_ERROR: // 4096 $strErrorLevel = "E_RECOVERABLE_ERROR"; break; case E_DEPRECATED: // 8192 $strErrorLevel = "E_DEPRECATED"; break; case E_USER_DEPRECATED: // 16384 $strErrorLevel = "E_USER_DEPRECATED"; break; default: $strErrorLevel = (string) $errorLevel; break; } $time = gmdate(self::$ms_logRecordDateTimePattern, time()); $fileRelPath = str_replace(realpath($GLOBALS["PHRED_PATH_TO_FRAMEWORK_ROOT"]) . "/", "", $filePath); $isAssertWithVars = is_int(strpos($errorDesc, self::$ms_assertVarsMarker)); $errorDesc = preg_replace("/\\n{2,}/", "\n", $errorDesc); if (!$isAssertWithVars) { // In case of an assert without vars. $errorDesc = preg_replace("/^assert\\(\\)\\s*:\\s*/", "", $errorDesc); } else { $errorDesc = preg_replace("/^[^\\n]*\\n(.*)" . self::$ms_assertVarsMarker . "\\s*:\\s*([\"'][^\\n]*)\\s*\\z/s", "\$2 ({$strErrorLevel})\n\$1", $errorDesc); if (preg_match("/^\\s*assert/i", $errorDesc) !== 1) { $errorDesc = "Assertion {$errorDesc}"; } } // Backtrace. ob_start(); debug_print_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS); $backtrace = ob_get_clean(); $backtrace = preg_replace("/\\n{2,}/", "\n", $backtrace); $backtrace = preg_replace("/^\\s*#.*?(?=#)/s", "", $backtrace); // remove the first line that is useless $backtrace = str_replace(realpath($GLOBALS["PHRED_PATH_TO_FRAMEWORK_ROOT"]) . "/", "", $backtrace); $backtrace = preg_replace("/\\s+\\z/", "", $backtrace); // Format the error message. if (!$isAssertWithVars) { $errorMessage = "[Time:] {$time}\n\n[Location:] {$fileRelPath}, line {$line}\n\n{$errorDesc} ({$strErrorLevel})\n\n" . "[Backtrace:]\n{$backtrace}\n"; } else { $errorMessage = "[Time:] {$time}\n\n[Location:] {$fileRelPath}, line {$line}\n\n{$errorDesc}\n\n" . "[Backtrace:]\n{$backtrace}\n"; } $logRecordSep = rtrim(str_repeat("- ", 60)); $leSep = "\n\n{$logRecordSep}\n\n"; if (self::$ms_logging) { // Log the record. $logRecord = "{$errorMessage}\n{$logRecordSep}\n\n"; if (file_exists(self::$ms_errorLogFp)) { // Check if log rotation needs to be performed for the error log. $log = file_get_contents(self::$ms_errorLogFp); $numRecords = substr_count($log, $leSep); if ($numRecords >= self::$ms_maxNumRecordsInLog) { $numDelFirstRecords = $numRecords - self::$ms_maxNumRecordsInLog + 1; $pos; for ($i = 0; $i < $numDelFirstRecords; $i++) { $pos = !isset($pos) ? 0 : $pos + 1; $pos = strpos($log, $leSep, $pos); } $log = substr($log, $pos); $log = "\n{$logRecordSep}\n\n" . preg_replace("/^{$leSep}/", "", $log); file_put_contents(self::$ms_errorLogFp, $log); } } else { file_put_contents(self::$ms_errorLogFp, "\n{$logRecordSep}\n\n"); } file_put_contents(self::$ms_errorLogFp, $logRecord, FILE_APPEND); } if (self::$ms_mailing) { $doMail = true; $destDp = sys_get_temp_dir(); $docRoot = isset($_SERVER["DOCUMENT_ROOT"]) ? $_SERVER["DOCUMENT_ROOT"] : ""; $docRootHash = hash("crc32", $docRoot, false); $lastMailTimeFp = $destDp . "/" . self::$ms_lastMailingTimeFnPrefix . $docRootHash; if (file_exists($lastMailTimeFp)) { $lastMailTime = (int) file_get_contents($lastMailTimeFp); $lastMailTimeDiffSeconds = time() - $lastMailTime; // If the difference is negative, which is wrong, the mailing should not be canceled. if ($lastMailTimeDiffSeconds >= 0) { if ($lastMailTimeDiffSeconds < self::$ms_minTimeBetweenSendMailHours * 3600) { // Too little time has passed since the last mailing, so cancel this one. $doMail = false; } } } if ($doMail) { // Notify about the error by mail. // Format the subject. $subject = "Something curious was encountered on "; // alternative: "" $serverName = isset($_SERVER["SERVER_NAME"]) ? $_SERVER["SERVER_NAME"] : ""; $serverIp = isset($_SERVER["SERVER_ADDR"]) ? $_SERVER["SERVER_ADDR"] : ""; $docRoot = isset($_SERVER["DOCUMENT_ROOT"]) ? basename($_SERVER["DOCUMENT_ROOT"]) : ""; if ($serverName !== "") { $subject .= $serverName; if ($serverIp !== "") { $subject .= " ({$serverIp})"; } if ($docRoot !== "") { $subject .= " in "; } else { $subject .= ""; // alternative: ": " } } if ($docRoot !== "") { $subject .= "'{$docRoot}'"; // alternative: "'$docRoot': " } // Alternative: // $subject .= "PHP Encountered a Problem"; // Compose the message. $mailMessage = "{$subject}\n\n{$errorMessage}"; if (self::$ms_logging && file_exists(self::$ms_errorLogFp)) { // Add the latest log records to the message. $log = file_get_contents(self::$ms_errorLogFp); $log .= "\n"; // to be able to use `-1` in `strrpos` below $logLength = strlen($log); $res = strrpos($log, $leSep, -1); if (is_int($res)) { for ($i = 0; $i < self::$ms_maxNumLatestLogRecordsInMailMessage; $i++) { $res = strrpos($log, $leSep, $res - $logLength - 1); if (!is_int($res)) { break; } } if (!is_int($res)) { $res = 0; } $latestRecords = substr($log, $res); $latestRecords = trim($latestRecords); $mailMessage .= "\n\n\n\n[Latest error log records, chronologically:]\n\n{$latestRecords}\n"; } } // Send. self::$ms_mail->setSubject($subject); self::$ms_mail->setBody($mailMessage); self::$ms_mail->disableWordWrapping(); $numMailsSent = self::$ms_mail->send(); if ($numMailsSent > 0) { file_put_contents($lastMailTimeFp, time()); } } } } // If a value other than `false` was returned, the error would not be shown in the output, regardless of // whether or not the PHP's "display_errors" option was enabled or disabled. return false; }