2007-07-19 12:40:28 +02:00
|
|
|
<?php
|
2015-07-24 00:53:41 +02:00
|
|
|
|
2008-02-25 03:10:37 +01:00
|
|
|
/**
|
2008-03-16 23:13:31 +01:00
|
|
|
* Supports debugging and core error handling.
|
2014-08-15 08:53:05 +02:00
|
|
|
*
|
2009-08-19 07:41:58 +02:00
|
|
|
* Attaches custom methods to the default error handling hooks
|
|
|
|
* in PHP. Currently, two levels of error are supported:
|
2014-08-15 08:53:05 +02:00
|
|
|
*
|
2009-08-19 08:03:57 +02:00
|
|
|
* - Notice
|
2008-03-16 23:13:31 +01:00
|
|
|
* - Warning
|
|
|
|
* - Error
|
2014-08-15 08:53:05 +02:00
|
|
|
*
|
2008-03-16 23:13:31 +01:00
|
|
|
* Uncaught exceptions are currently passed to the debug
|
|
|
|
* reporter as standard PHP errors.
|
2014-08-15 08:53:05 +02:00
|
|
|
*
|
API CHANGE: Renamed conflicting classes to have an "SS_" namespace, and renamed existing "SS" namespace to "SS_". The affected classes are: HTTPRequest, HTTPResponse, Query, Database, SSBacktrace, SSCli, SSDatetime, SSDatetimeTest, SSLog, SSLogTest, SSLogEmailWriter, SSLogErrorEmailFormatter, SSLogErrorFileFormatter, SSLogFileWriter and SSZendLog.
MINOR: Replaced usage of renamed classes with the new namespaced name.
From: Andrew Short <andrewjshort@gmail.com>
git-svn-id: svn://svn.silverstripe.com/silverstripe/open/modules/sapphire/trunk@90075 467b73ca-7a2a-4603-9d3b-597d59a354a9
2009-10-26 04:06:31 +01:00
|
|
|
* Errors handled by this class are passed along to {@link SS_Log}.
|
|
|
|
* For configuration information, see the {@link SS_Log}
|
2009-08-19 07:41:58 +02:00
|
|
|
* class documentation.
|
2014-08-15 08:53:05 +02:00
|
|
|
*
|
2008-03-16 23:13:31 +01:00
|
|
|
* @todo add support for user defined config: Debug::die_on_notice(true | false)
|
|
|
|
* @todo better way of figuring out the error context to display in highlighted source
|
2014-08-15 08:53:05 +02:00
|
|
|
*
|
2012-04-12 08:02:46 +02:00
|
|
|
* @package framework
|
2009-08-19 07:41:58 +02:00
|
|
|
* @subpackage dev
|
2007-07-19 12:40:28 +02:00
|
|
|
*/
|
|
|
|
class Debug {
|
2014-08-15 08:53:05 +02:00
|
|
|
|
2007-07-19 12:40:28 +02:00
|
|
|
/**
|
|
|
|
* Show the contents of val in a debug-friendly way.
|
|
|
|
* Debug::show() is intended to be equivalent to dprintr()
|
|
|
|
*/
|
2012-09-19 12:07:39 +02:00
|
|
|
public static function show($val, $showHeader = true) {
|
2007-07-19 12:40:28 +02:00
|
|
|
if(!Director::isLive()) {
|
|
|
|
if($showHeader) {
|
|
|
|
$caller = Debug::caller();
|
2008-08-13 03:47:05 +02:00
|
|
|
if(Director::is_ajax() || Director::is_cli())
|
2012-09-26 23:34:00 +02:00
|
|
|
echo "Debug ($caller[class]$caller[type]$caller[function]() in " . basename($caller['file'])
|
|
|
|
. ":$caller[line])\n";
|
2014-08-15 08:53:05 +02:00
|
|
|
else
|
2012-09-26 23:34:00 +02:00
|
|
|
echo "<div style=\"background-color: white; text-align: left;\">\n<hr>\n"
|
|
|
|
. "<h3>Debug <span style=\"font-size: 65%\">($caller[class]$caller[type]$caller[function]()"
|
|
|
|
. " \nin " . basename($caller['file']) . ":$caller[line])</span>\n</h3>\n";
|
2007-07-19 12:40:28 +02:00
|
|
|
}
|
2014-08-15 08:53:05 +02:00
|
|
|
|
2007-07-19 12:40:28 +02:00
|
|
|
echo Debug::text($val);
|
2014-08-15 08:53:05 +02:00
|
|
|
|
2008-08-13 03:47:05 +02:00
|
|
|
if(!Director::is_ajax() && !Director::is_cli()) echo "</div>";
|
|
|
|
else echo "\n\n";
|
2007-07-19 12:40:28 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
}
|
2012-11-15 02:56:43 +01:00
|
|
|
|
2014-07-05 04:37:06 +02:00
|
|
|
/**
|
|
|
|
* Returns the caller for a specific method
|
2014-08-15 08:53:05 +02:00
|
|
|
*
|
2014-07-05 04:37:06 +02:00
|
|
|
* @return array
|
|
|
|
*/
|
2012-11-15 02:56:43 +01:00
|
|
|
public static function caller() {
|
|
|
|
$bt = debug_backtrace();
|
|
|
|
$caller = $bt[2];
|
|
|
|
$caller['line'] = $bt[1]['line'];
|
|
|
|
$caller['file'] = $bt[1]['file'];
|
|
|
|
if(!isset($caller['class'])) $caller['class'] = '';
|
|
|
|
if(!isset($caller['type'])) $caller['type'] = '';
|
|
|
|
return $caller;
|
|
|
|
}
|
|
|
|
|
2008-08-09 08:24:30 +02:00
|
|
|
/**
|
|
|
|
* Close out the show dumper
|
|
|
|
*
|
|
|
|
* @param mixed $val
|
|
|
|
*/
|
2012-09-19 12:07:39 +02:00
|
|
|
public static function endshow($val) {
|
2007-07-19 12:40:28 +02:00
|
|
|
if(!Director::isLive()) {
|
|
|
|
$caller = Debug::caller();
|
2012-09-26 23:34:00 +02:00
|
|
|
echo "<hr>\n<h3>Debug \n<span style=\"font-size: 65%\">($caller[class]$caller[type]$caller[function]()"
|
|
|
|
. " \nin " . basename($caller['file']) . ":$caller[line])</span>\n</h3>\n";
|
2007-07-19 12:40:28 +02:00
|
|
|
echo Debug::text($val);
|
|
|
|
die();
|
|
|
|
}
|
|
|
|
}
|
2014-08-15 08:53:05 +02:00
|
|
|
|
2008-08-09 08:24:30 +02:00
|
|
|
/**
|
|
|
|
* Quick dump of a variable.
|
|
|
|
*
|
|
|
|
* @param mixed $val
|
|
|
|
*/
|
2012-09-19 12:07:39 +02:00
|
|
|
public static function dump($val) {
|
2014-07-05 04:37:06 +02:00
|
|
|
self::create_debug_view()->writeVariable($val, self::caller());
|
2008-03-16 23:13:31 +01:00
|
|
|
}
|
2007-07-19 12:40:28 +02:00
|
|
|
|
2008-08-09 08:24:30 +02:00
|
|
|
/**
|
2016-05-25 07:30:01 +02:00
|
|
|
* @param mixed $val
|
|
|
|
* @return string
|
2008-08-09 08:24:30 +02:00
|
|
|
*/
|
2012-09-19 12:07:39 +02:00
|
|
|
public static function text($val) {
|
2008-02-25 03:10:37 +01:00
|
|
|
if(is_object($val)) {
|
|
|
|
if(method_exists($val, 'hasMethod')) {
|
|
|
|
$hasDebugMethod = $val->hasMethod('debug');
|
2008-02-25 02:06:39 +01:00
|
|
|
} else {
|
2008-02-25 03:10:37 +01:00
|
|
|
$hasDebugMethod = method_exists($val, 'debug');
|
|
|
|
}
|
2014-08-15 08:53:05 +02:00
|
|
|
|
2008-02-25 03:10:37 +01:00
|
|
|
if($hasDebugMethod) {
|
|
|
|
return $val->debug();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if(is_array($val)) {
|
|
|
|
$result = "<ul>\n";
|
|
|
|
foreach($val as $k => $v) {
|
|
|
|
$result .= "<li>$k = " . Debug::text($v) . "</li>\n";
|
2007-07-19 12:40:28 +02:00
|
|
|
}
|
2008-02-25 03:10:37 +01:00
|
|
|
$val = $result . "</ul>\n";
|
2007-07-19 12:40:28 +02:00
|
|
|
|
2008-02-25 03:10:37 +01:00
|
|
|
} else if (is_object($val)) {
|
|
|
|
$val = var_export($val, true);
|
2010-10-19 06:52:33 +02:00
|
|
|
} else if (is_bool($val)) {
|
|
|
|
$val = $val ? 'true' : 'false';
|
|
|
|
$val = '(bool) ' . $val;
|
2008-02-25 03:10:37 +01:00
|
|
|
} else {
|
2008-08-13 03:47:05 +02:00
|
|
|
if(!Director::is_cli() && !Director::is_ajax()) {
|
2012-09-26 23:34:00 +02:00
|
|
|
$val = "<pre style=\"font-family: Courier new\">" . htmlentities($val, ENT_COMPAT, 'UTF-8')
|
|
|
|
. "</pre>\n";
|
2008-02-25 03:10:37 +01:00
|
|
|
}
|
2007-07-19 12:40:28 +02:00
|
|
|
}
|
2008-02-25 03:10:37 +01:00
|
|
|
|
|
|
|
return $val;
|
2007-07-19 12:40:28 +02:00
|
|
|
}
|
2007-09-14 05:19:34 +02:00
|
|
|
|
2007-07-19 12:40:28 +02:00
|
|
|
/**
|
|
|
|
* Show a debugging message
|
|
|
|
*/
|
2012-09-19 12:07:39 +02:00
|
|
|
public static function message($message, $showHeader = true) {
|
2007-07-19 12:40:28 +02:00
|
|
|
if(!Director::isLive()) {
|
|
|
|
$caller = Debug::caller();
|
|
|
|
$file = basename($caller['file']);
|
2008-08-09 08:18:32 +02:00
|
|
|
if(Director::is_cli()) {
|
|
|
|
if($showHeader) echo "Debug (line $caller[line] of $file):\n ";
|
2009-09-14 07:41:28 +02:00
|
|
|
echo $message . "\n";
|
2008-08-09 08:18:32 +02:00
|
|
|
} else {
|
2012-09-01 01:58:52 +02:00
|
|
|
echo "<p class=\"message warning\">\n";
|
2008-08-09 08:18:32 +02:00
|
|
|
if($showHeader) echo "<b>Debug (line $caller[line] of $file):</b>\n ";
|
2009-09-14 07:41:28 +02:00
|
|
|
echo Convert::raw2xml($message) . "</p>\n";
|
2008-08-09 08:18:32 +02:00
|
|
|
}
|
2007-07-19 12:40:28 +02:00
|
|
|
}
|
|
|
|
}
|
2014-08-15 08:53:05 +02:00
|
|
|
|
2008-08-11 06:02:32 +02:00
|
|
|
/**
|
|
|
|
* Create an instance of an appropriate DebugView object.
|
2014-08-15 08:53:05 +02:00
|
|
|
*
|
2014-07-05 04:37:06 +02:00
|
|
|
* @return DebugView
|
2008-08-11 06:02:32 +02:00
|
|
|
*/
|
2012-09-19 12:07:39 +02:00
|
|
|
public static function create_debug_view() {
|
2014-07-05 04:37:06 +02:00
|
|
|
$service = Director::is_cli() || Director::is_ajax()
|
|
|
|
? 'CliDebugView'
|
|
|
|
: 'DebugView';
|
|
|
|
return Injector::inst()->get($service);
|
2008-08-11 06:02:32 +02:00
|
|
|
}
|
2007-07-19 12:40:28 +02:00
|
|
|
|
2007-11-08 00:46:00 +01:00
|
|
|
/**
|
|
|
|
* Check if the user has permissions to run URL debug tools,
|
|
|
|
* else redirect them to log in.
|
|
|
|
*/
|
2012-09-19 12:07:39 +02:00
|
|
|
public static function require_developer_login() {
|
2007-11-08 00:46:00 +01:00
|
|
|
if(Director::isDev()) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if(isset($_SESSION['loggedInAs'])) {
|
|
|
|
// We have to do some raw SQL here, because this method is called in Object::defineMethods().
|
|
|
|
// This means we have to be careful about what objects we create, as we don't want Object::defineMethods()
|
|
|
|
// being called again.
|
|
|
|
// This basically calls Permission::checkMember($_SESSION['loggedInAs'], 'ADMIN');
|
2014-08-15 08:53:05 +02:00
|
|
|
|
2013-06-21 00:32:08 +02:00
|
|
|
// @TODO - Rewrite safely using DataList::filter
|
2007-11-08 00:46:00 +01:00
|
|
|
$memberID = $_SESSION['loggedInAs'];
|
2013-06-21 00:32:08 +02:00
|
|
|
$permission = DB::prepared_query('
|
|
|
|
SELECT "ID" FROM "Permission"
|
|
|
|
INNER JOIN "Group_Members" ON "Permission"."GroupID" = "Group_Members"."GroupID"
|
2014-08-15 08:53:05 +02:00
|
|
|
WHERE "Permission"."Code" = ?
|
|
|
|
AND "Permission"."Type" = ?
|
2013-06-21 00:32:08 +02:00
|
|
|
AND "Group_Members"."MemberID" = ?',
|
|
|
|
array(
|
|
|
|
'ADMIN', // Code
|
|
|
|
Permission::GRANT_PERMISSION, // Type
|
|
|
|
$memberID // MemberID
|
2007-11-08 00:46:00 +01:00
|
|
|
)
|
2013-06-21 00:32:08 +02:00
|
|
|
)->value();
|
2014-08-15 08:53:05 +02:00
|
|
|
|
2013-06-21 00:32:08 +02:00
|
|
|
if($permission) return;
|
2007-11-08 00:46:00 +01:00
|
|
|
}
|
2014-08-15 08:53:05 +02:00
|
|
|
|
2007-11-08 00:46:00 +01:00
|
|
|
// This basically does the same as
|
2012-09-26 23:34:00 +02:00
|
|
|
// Security::permissionFailure(null, "You need to login with developer access to make use of debugging tools.")
|
2007-11-08 00:46:00 +01:00
|
|
|
// We have to do this because of how early this method is called in execution.
|
2012-09-26 23:34:00 +02:00
|
|
|
$_SESSION['Security']['Message']['message']
|
|
|
|
= "You need to login with developer access to make use of debugging tools.";
|
2007-11-08 00:46:00 +01:00
|
|
|
$_SESSION['Security']['Message']['type'] = 'warning';
|
|
|
|
$_SESSION['BackURL'] = $_SERVER['REQUEST_URI'];
|
2008-10-01 16:43:43 +02:00
|
|
|
header($_SERVER['SERVER_PROTOCOL'] . " 302 Found");
|
2011-03-16 04:13:14 +01:00
|
|
|
header("Location: " . Director::baseURL() . Security::login_url());
|
2007-11-08 00:46:00 +01:00
|
|
|
die();
|
|
|
|
}
|
2007-07-19 12:40:28 +02:00
|
|
|
}
|