/** * Returns catched error/warning message. * @param \ErrorException catched error * @return bool */ public static function catchError(&$error) { if (!self::$enabled && self::$lastError !== FALSE) { restore_error_handler(); } $error = self::$lastError; self::$lastError = FALSE; return (bool) $error; }
/** * Enables displaying or logging errors and exceptions. * @param mixed production, development mode, autodetection or IP address(es). * @param string error log directory; enables logging in production mode * @param string administrator email; enables email sending in production mode * @return void */ public static function enable($mode = NULL, $logDirectory = NULL, $email = NULL) { error_reporting(E_ALL | E_STRICT); // production/development mode detection if (is_bool($mode)) { self::$productionMode = $mode; } elseif (is_string($mode)) { // IP adresses $mode = preg_split('#[,\s]+#', $mode); } if (is_array($mode)) { // IP adresses self::$productionMode = !isset($_SERVER['REMOTE_ADDR']) || !in_array($_SERVER['REMOTE_ADDR'], $mode, TRUE); } if (self::$productionMode === self::DETECT) { if (class_exists('Nette\Environment')) { self::$productionMode = Environment::isProduction(); } elseif (isset($_SERVER['SERVER_ADDR']) || isset($_SERVER['LOCAL_ADDR'])) { // IP address based detection $addr = isset($_SERVER['SERVER_ADDR']) ? $_SERVER['SERVER_ADDR'] : $_SERVER['LOCAL_ADDR']; $oct = explode('.', $addr); self::$productionMode = $addr !== '::1' && (count($oct) !== 4 || ($oct[0] !== '10' && $oct[0] !== '127' && ($oct[0] !== '172' || $oct[1] < 16 || $oct[1] > 31) && ($oct[0] !== '169' || $oct[1] !== '254') && ($oct[0] !== '192' || $oct[1] !== '168'))); } else { self::$productionMode = !self::$consoleMode; } } // logging configuration if (self::$productionMode && $logDirectory !== FALSE) { if (is_string($logDirectory)) { self::$logDirectory = $logDirectory; } else { self::$logDirectory = defined('APP_DIR') ? APP_DIR . '/../log/' : getcwd() . '/log'; } ini_set('error_log', self::$logDirectory . '/php_error.log'); } // php configuration if (function_exists('ini_set')) { ini_set('display_errors', !self::$productionMode); // or 'stderr' ini_set('html_errors', FALSE); ini_set('log_errors', FALSE); } elseif (ini_get('display_errors') != !self::$productionMode && ini_get('display_errors') !== (self::$productionMode ? 'stderr' : 'stdout')) { // intentionally == throw new \NotSupportedException('Function ini_set() must be enabled.'); } if ($email) { if (!is_string($email)) { throw new \InvalidArgumentException('E-mail address must be a string.'); } self::$email = $email; } if (!defined('E_DEPRECATED')) { define('E_DEPRECATED', 8192); } if (!defined('E_USER_DEPRECATED')) { define('E_USER_DEPRECATED', 16384); } if (!self::$enabled) { register_shutdown_function(array(__CLASS__, '_shutdownHandler')); set_exception_handler(array(__CLASS__, '_exceptionHandler')); set_error_handler(array(__CLASS__, '_errorHandler')); self::$enabled = TRUE; } }
/** * Logs or displays exception. * @param \Exception * @param bool is writing to standard output buffer allowed? * @return void */ public static function processException(\Exception $exception, $outputAllowed = FALSE) { if (!self::$enabled) { return; } elseif (self::$logFile) { try { $hash = md5($exception); self::log("PHP Fatal error: Uncaught " . str_replace("Stack trace:\n" . $exception->getTraceAsString(), '', $exception)); foreach (new \DirectoryIterator(dirname(self::$logFile)) as $entry) { if (strpos($entry, $hash)) { $skip = TRUE; break; } } $file = dirname(self::$logFile) . "/exception " . @date('Y-m-d H-i-s') . " {$hash}.html"; if (empty($skip) && (self::$logHandle = @fopen($file, 'w'))) { ob_start(); // double buffer prevents sending HTTP headers in some PHP ob_start(array(__CLASS__, '_writeFile'), 1); self::_paintBlueScreen($exception); ob_end_flush(); ob_end_clean(); fclose(self::$logHandle); } if (self::$sendEmails) { self::sendEmail((string) $exception); } } catch (\Exception $e) { if (!headers_sent()) { header('HTTP/1.1 500 Internal Server Error'); } echo 'Nette\\Debug fatal error: ', get_class($e), ': ', ($e->getCode() ? '#' . $e->getCode() . ' ' : '') . $e->getMessage(), "\n"; exit; } } elseif (self::$productionMode) { // be quiet } elseif (self::$consoleMode) { // dump to console if ($outputAllowed) { echo "{$exception}\n"; } } elseif (self::$firebugDetected && self::$ajaxDetected && !headers_sent()) { // AJAX mode self::fireLog($exception, self::EXCEPTION); } elseif ($outputAllowed) { // dump to browser if (!headers_sent()) { @ob_end_clean(); while (ob_get_level() && @ob_end_clean()) { } header_remove('Content-Encoding'); } self::_paintBlueScreen($exception); } elseif (self::$firebugDetected && !headers_sent()) { self::fireLog($exception, self::EXCEPTION); } foreach (self::$onFatalError as $handler) { call_user_func($handler, $exception); } }
/** * Starts catching potential errors/warnings. * @return void */ public static function tryError() { error_reporting(0); $old = self::$scream; self::$scream = FALSE; trigger_error(''); // "reset" error_get_last self::$scream = $old; }