\n
';
$caller = Debug::caller();
echo "Line $caller[line] of " . basename($caller['file']) . ":\n";
if (is_string($val)) print_r(wordwrap($val, 100));
else print_r($val);
echo '
';
}
/**
* ??
*
* @param unknown_type $val
* @return unknown
*/
static function text($val) {
if(is_object($val)) {
if(method_exists($val, 'hasMethod')) {
$hasDebugMethod = $val->hasMethod('debug');
} else {
$hasDebugMethod = method_exists($val, 'debug');
}
if($hasDebugMethod) {
return $val->debug();
}
}
if(is_array($val)) {
$result = "" . htmlentities($val) . "\n"; } } return $val; } /** * Show a debugging message */ static function message($message, $showHeader = true) { if(!Director::isLive()) { $caller = Debug::caller(); $file = basename($caller['file']); if(Director::is_cli()) { if($showHeader) echo "Debug (line $caller[line] of $file):\n "; echo trim($message) . "\n"; } else { echo "
\n"; if($showHeader) echo "Debug (line $caller[line] of $file):\n "; echo Convert::raw2xml(trim($message)) . "
\n"; } } } // Keep track of how many headers have been sent static $headerCount = 0; /** * Send a debug message in an HTTP header. Only works if you are * on Dev, and headers have not yet been sent. * * @param string $msg * @param string $prefix (optional) * @return void */ static function header($msg, $prefix = null) { if (Director::isDev() && !headers_sent()) { self::$headerCount++; header('SS-'.self::$headerCount.($prefix?'-'.$prefix:'').': '.$msg); } } /** * Log to a standard text file output. * * @param $message string to output */ static function log($message) { $file = dirname(__FILE__).'/../../debug.log'; $now = date('r'); $oldcontent = (file_exists($file)) ? file_get_contents($file) : ''; $content = $oldcontent . "\n\n== $now ==\n$message\n"; file_put_contents($file, $content); } /** * Load error handlers into environment. * Caution: The error levels default to E_ALL is the site is in dev-mode (set in main.php). */ static function loadErrorHandlers() { set_error_handler('errorHandler', error_reporting()); set_exception_handler('exceptionHandler'); } static function noticeHandler($errno, $errstr, $errfile, $errline, $errcontext) { if(error_reporting() == 0) return; // Send out the error details to the logger for writing SSLog::log( array( 'errno' => $errno, 'errstr' => $errstr, 'errfile' => $errfile, 'errline' => $errline, 'errcontext' => $errcontext ), SSLog::NOTICE ); if(Director::isDev()) { self::showError($errno, $errstr, $errfile, $errline, $errcontext, "Notice"); } } /** * Handle a non-fatal warning error thrown by PHP interpreter. * * @param unknown_type $errno * @param unknown_type $errstr * @param unknown_type $errfile * @param unknown_type $errline * @param unknown_type $errcontext */ static function warningHandler($errno, $errstr, $errfile, $errline, $errcontext) { if(error_reporting() == 0) return; if(self::$send_warnings_to) self::emailError(self::$send_warnings_to, $errno, $errstr, $errfile, $errline, $errcontext, "Warning"); // Send out the error details to the logger for writing SSLog::log( array( 'errno' => $errno, 'errstr' => $errstr, 'errfile' => $errfile, 'errline' => $errline, 'errcontext' => $errcontext ), SSLog::WARN ); self::log_error_if_necessary( $errno, $errstr, $errfile, $errline, $errcontext, "Warning"); if(Director::isDev()) { self::showError($errno, $errstr, $errfile, $errline, $errcontext, "Warning"); } } /** * Handle a fatal error, depending on the mode of the site (ie: Dev, Test, or Live). * * Runtime execution dies immediately once the error is generated. * * @param unknown_type $errno * @param unknown_type $errstr * @param unknown_type $errfile * @param unknown_type $errline * @param unknown_type $errcontext */ static function fatalHandler($errno, $errstr, $errfile, $errline, $errcontext) { if(self::$send_errors_to) self::emailError(self::$send_errors_to, $errno, $errstr, $errfile, $errline, $errcontext, "Error"); // Send out the error details to the logger for writing SSLog::log( array( 'errno' => $errno, 'errstr' => $errstr, 'errfile' => $errfile, 'errline' => $errline, 'errcontext' => $errcontext ), SSLog::ERR ); self::log_error_if_necessary( $errno, $errstr, $errfile, $errline, $errcontext, "Error"); if(Director::isDev() || Director::is_cli()) { self::showError($errno, $errstr, $errfile, $errline, $errcontext, "Error"); } else { self::friendlyError(); } exit(1); } /** * Render a user-facing error page, using the default HTML error template * rendered by {@link ErrorPage} if it exists. Doesn't use the standard {@link HTTPResponse} class * the keep dependencies minimal. * * @uses ErrorPage * * @param int $statusCode HTTP Status Code (Default: 500) * @param string $friendlyErrorMessage User-focused error message. Should not contain code pointers or "tech-speak". * Used in the HTTP Header and ajax responses. * @param string $friendlyErrorDetail Detailed user-focused message. Is just used if no {@link ErrorPage} is found * for this specific status code. * @return string HTML error message for non-ajax requests, plaintext for ajax-request. */ static function friendlyError($statusCode = 500, $friendlyErrorMessage = null, $friendlyErrorDetail = null) { if(!$friendlyErrorMessage) $friendlyErrorMessage = 'There has been an error'; if(!$friendlyErrorDetail) $friendlyErrorDetail = 'The website server has not been able to respond to your request.'; if(!headers_sent()) header($_SERVER['SERVER_PROTOCOL'] . " $statusCode $friendlyErrorMessage"); if(Director::is_ajax()) { echo $friendlyErrorMessage; } else { $errorFilePath = ErrorPage::get_filepath_for_errorcode($statusCode, Translatable::get_current_locale()); if(file_exists($errorFilePath)) { echo file_get_contents($errorFilePath); } else { $renderer = new DebugView(); $renderer->writeHeader(); $renderer->writeInfo("Website Error", $friendlyErrorMessage, $friendlyErrorDetail); if(Email::getAdminEmail()) { $mailto = Email::obfuscate(Email::getAdminEmail()); $renderer->writeParagraph('Contact an administrator: ' . $mailto . ''); } $renderer->writeFooter(); } } } /** * Create an instance of an appropriate DebugView object. */ static function create_debug_view() { if(Director::is_cli() || Director::is_ajax()) return new CliDebugView(); else return new DebugView(); } /** * Render a developer facing error page, showing the stack trace and details * of the code where the error occured. * * @param unknown_type $errno * @param unknown_type $errstr * @param unknown_type $errfile * @param unknown_type $errline * @param unknown_type $errcontext */ static function showError($errno, $errstr, $errfile, $errline, $errcontext, $errtype) { if(!headers_sent()) { $errText = "$errtype: \"$errstr\" at line $errline of $errfile"; $errText = str_replace(array("\n","\r")," ",$errText); if(!headers_sent()) header($_SERVER['SERVER_PROTOCOL'] . " 500 $errText"); // if error is displayed through ajax with CliDebugView, use plaintext output if(Director::is_ajax()) header('Content-Type: text/plain'); } // Legacy error handling for customized prototype.js Ajax.Base.responseIsSuccess() // if(Director::is_ajax()) echo "ERROR:\n"; $reporter = self::create_debug_view(); // Coupling alert: This relies on knowledge of how the director gets its URL, it could be improved. $httpRequest = isset($_SERVER['REQUEST_URI']) ? $_SERVER['REQUEST_URI'] : $_REQUEST['url']; if(isset($_SERVER['REQUEST_METHOD'])) $httpRequest = $_SERVER['REQUEST_METHOD'] . ' ' . $httpRequest; $reporter->writeHeader($httpRequest); $reporter->writeError($httpRequest, $errno, $errstr, $errfile, $errline, $errcontext); $lines = file($errfile); // Make the array 1-based array_unshift($lines,""); unset($lines[0]); $offset = $errline-10; $lines = array_slice($lines, $offset, 16, true); $reporter->writeSourceFragment($lines, $errline); $reporter->writeTrace(($errcontext ? $errcontext : debug_backtrace())); $reporter->writeFooter(); exit(1); } /** * Utility method to render a snippet of PHP source code, from selected file * and highlighting the given line number. * * @param string $errfile * @param int $errline */ static function showLines($errfile, $errline) { $lines = file($errfile); $offset = $errline-10; $lines = array_slice($lines, $offset, 16); echo ''; $offset++; foreach($lines as $line) { $line = htmlentities($line); if ($offset == $errline) { echo "$offset $line"; } else { echo "$offset $line"; } $offset++; } echo ''; } /** * Dispatch an email notification message when an error is triggered. * @deprecated 2.5 * To create error logs by email, use this code instead: *
* $emailWriter = new SSLogEmailWriter('my@email.com');
* SSLog::add_writer($emailWriter, SSLog::ERR);
*
*
* @param string $emailAddress
* @param string $errno
* @param string $errstr
* @param string $errfile
* @param int $errline
* @param string $errcontext
* @param string $errorType "warning" or "error"
* @return boolean
*/
static function emailError($emailAddress, $errno, $errstr, $errfile, $errline, $errcontext, $errorType = "Error") {
user_error('Debug::send_errors_to() and Debug::emailError() is deprecated. Please use SSLog instead.
See the class documentation for SSLog for more information.', E_USER_NOTICE);
$priority = ($errorType == 'Error') ? SSLog::ERR : SSLog::WARN;
$writer = new SSLogEmailWriter($emailAddress);
SSLog::add_writer($writer, $priority);
SSLog::log(
array(
'errno' => $errno,
'errstr' => $errstr,
'errfile' => $errfile,
'errline' => $errline,
'errcontext' => $errcontext
),
$priority
);
SSLog::remove_writer($writer);
}
/**
* Log the given error, if self::$log_errors is set.
* Uses the native error_log() funtion in PHP.
*
* Format: [d-M-Y h:i:s]