diff --git a/dibi/Nette/IDebugPanel.php b/dibi/Nette/IDebugPanel.php
new file mode 100644
index 00000000..95755b28
--- /dev/null
+++ b/dibi/Nette/IDebugPanel.php
@@ -0,0 +1,44 @@
+' . $matches[4] . '';
}
-
-
- /**
- * Returns brief descriptions.
- * @return string
- * @return array
- */
- public static function getColophon($sender = NULL)
- {
- $arr = array(
- 'Number of SQL queries: ' . dibi::$numOfQueries
- . (dibi::$totalTime === NULL ? '' : ', elapsed time: ' . sprintf('%0.3f', dibi::$totalTime * 1000) . ' ms'),
- );
- if ($sender === 'bluescreen') {
- $arr[] = 'dibi ' . dibi::VERSION . ' (revision ' . dibi::REVISION . ')';
- }
- return $arr;
- }
-
}
diff --git a/dibi/libs/DibiConnection.php b/dibi/libs/DibiConnection.php
index 179876c5..1d7458d4 100644
--- a/dibi/libs/DibiConnection.php
+++ b/dibi/libs/DibiConnection.php
@@ -42,10 +42,6 @@ class DibiConnection extends DibiObject
*/
public function __construct($config, $name = NULL)
{
- if (class_exists(/*Nette\*/'Debug', FALSE)) {
- /*Nette\*/Debug::addColophon(array('dibi', 'getColophon'));
- }
-
// DSN string
if (is_string($config)) {
parse_str($config, $config);
diff --git a/dibi/libs/DibiException.php b/dibi/libs/DibiException.php
index ccdb3098..0e6491a9 100644
--- a/dibi/libs/DibiException.php
+++ b/dibi/libs/DibiException.php
@@ -18,7 +18,7 @@
* @copyright Copyright (c) 2005, 2010 David Grudl
* @package dibi
*/
-class DibiException extends Exception implements /*Nette\*/IDebuggable
+class DibiException extends Exception implements /*Nette\*/IDebugPanel
{
/** @var string */
private $sql;
@@ -59,23 +59,39 @@ class DibiException extends Exception implements /*Nette\*/IDebuggable
- /********************* interface Nette\IDebuggable ****************d*g**/
+ /********************* interface Nette\IDebugPanel ****************d*g**/
+
/**
- * Returns custom panels.
- * @return array
+ * Returns HTML code for custom tab.
+ * @return mixed
*/
- public function getPanels()
+ public function getTab()
+ {
+ return 'SQL';
+ }
+
+
+
+ /**
+ * Returns HTML code for custom panel.
+ * @return mixed
+ */
+ public function getPanel()
{
- $panels = array();
- if ($this->sql !== NULL) {
- $panels['SQL'] = array(
- 'expanded' => TRUE,
- 'content' => dibi::dump($this->sql, TRUE),
- );
- }
- return $panels;
+ return dibi::dump($this->sql, TRUE);
+ }
+
+
+
+ /**
+ * Returns panel ID.
+ * @return string
+ */
+ public function getId()
+ {
+ return __CLASS__;
}
}
diff --git a/dibi/libs/DibiProfiler.php b/dibi/libs/DibiProfiler.php
index 0caa34ec..3a3bb48f 100644
--- a/dibi/libs/DibiProfiler.php
+++ b/dibi/libs/DibiProfiler.php
@@ -18,13 +18,13 @@
* @copyright Copyright (c) 2005, 2010 David Grudl
* @package dibi
*/
-class DibiProfiler extends DibiObject implements IDibiProfiler
+class DibiProfiler extends DibiObject implements IDibiProfiler, /*Nette\*/IDebugPanel
{
/** maximum number of rows */
- const FIREBUG_MAX_ROWS = 30;
+ const MAX_ROWS = 30;
/** maximum SQL length */
- const FIREBUG_MAX_LENGTH = 500;
+ const MAX_LENGTH = 500;
/** @var string Name of the file where SQL errors should be logged */
private $file;
@@ -45,6 +45,10 @@ class DibiProfiler extends DibiObject implements IDibiProfiler
public function __construct()
{
+ if (class_exists(/*Nette\*/'Debug', FALSE) && is_callable('Debug::addPanel')) {
+ /*Nette\*/Debug::addPanel($this);
+ }
+
$this->useFirebug = isset($_SERVER['HTTP_USER_AGENT']) && strpos($_SERVER['HTTP_USER_AGENT'], 'FirePHP/');
}
@@ -114,28 +118,27 @@ class DibiProfiler extends DibiObject implements IDibiProfiler
$count = '?';
}
- if ($this->useFirebug && !headers_sent()) {
- if (count(self::$table) < self::FIREBUG_MAX_ROWS) {
- self::$table[] = array(
- sprintf('%0.3f', dibi::$elapsedTime * 1000),
- strlen($sql) > self::FIREBUG_MAX_LENGTH ? substr($sql, 0, self::FIREBUG_MAX_LENGTH) . '...' : $sql,
- $count,
- $connection->getConfig('driver') . '/' . $connection->getConfig('name')
- );
- }
+ if (count(self::$table) < self::MAX_ROWS) {
+ self::$table[] = array(
+ sprintf('%0.3f', dibi::$elapsedTime * 1000),
+ strlen($sql) > self::MAX_LENGTH ? substr($sql, 0, self::MAX_LENGTH) . '...' : $sql,
+ $count,
+ $connection->getConfig('driver') . '/' . $connection->getConfig('name')
+ );
+ }
+ if ($this->useFirebug && !headers_sent()) {
header('X-Wf-Protocol-dibi: http://meta.wildfirehq.org/Protocol/JsonStream/0.2');
header('X-Wf-dibi-Plugin-1: http://meta.firephp.org/Wildfire/Plugin/FirePHP/Library-FirePHPCore/0.2.0');
header('X-Wf-dibi-Structure-1: http://meta.firephp.org/Wildfire/Structure/FirePHP/FirebugConsole/0.1');
- $payload = array(
+ $payload = json_encode(array(
array(
'Type' => 'TABLE',
'Label' => 'dibi profiler (' . dibi::$numOfQueries . ' SQL queries took ' . sprintf('%0.3f', dibi::$totalTime * 1000) . ' ms)',
),
self::$table,
- );
- $payload = json_encode($payload);
+ ));
foreach (str_split($payload, 4990) as $num => $s) {
$num++;
header("X-Wf-dibi-1-1-d$num: |$s|\\"); // protocol-, structure-, plugin-, message-index
@@ -198,4 +201,58 @@ class DibiProfiler extends DibiObject implements IDibiProfiler
fclose($handle);
}
+
+
+ /********************* interface Nette\IDebugPanel ****************d*g**/
+
+
+
+ /**
+ * Returns HTML code for custom tab.
+ * @return mixed
+ */
+ public function getTab()
+ {
+ return '
'
+ . dibi::$numOfQueries . ' queries';
+ }
+
+
+
+ /**
+ * Returns HTML code for custom panel.
+ * @return mixed
+ */
+ public function getPanel()
+ {
+ if (!dibi::$numOfQueries) return;
+
+ $content = '
SQL queries: ' . dibi::$numOfQueries . (dibi::$totalTime === NULL ? '' : ', elapsed time: ' . sprintf('%0.3f', dibi::$totalTime * 1000) . ' ms') . '
';
+ if (self::$table) {
+ $content .= '';
+ foreach (self::$table as $i => $row) {
+ if ($i === 0) {
+ $content .= "$row[0] | $row[1] | $row[2] | $row[3] |
";
+ } else {
+ $content .= "$row[0] | $row[1] | $row[2] | $row[3] |
";
+ }
+ }
+ $content .= '
';
+ } else {
+ $content .= 'no query
';
+ }
+ return $content;
+ }
+
+
+
+ /**
+ * Returns panel ID.
+ * @return string
+ */
+ public function getId()
+ {
+ return get_class($this);
+ }
+
}
diff --git a/examples/Nette/Debug.php b/examples/Nette/Debug.php
index 71d62d04..e6515d11 100644
--- a/examples/Nette/Debug.php
+++ b/examples/Nette/Debug.php
@@ -23,8 +23,7 @@ static$productionMode;public
static$consoleMode;public
static$time;private
static$firebugDetected;private
-static$ajaxDetected;private
-static$consoleData;public
+static$ajaxDetected;public
static$maxDepth=3;public
static$maxLen=150;public
static$showLocation=FALSE;const
@@ -40,8 +39,10 @@ static$logFile;private
static$logHandle;private
static$sendEmails;private
static$emailHeaders=array('To'=>'','From'=>'noreply@%host%','X-Mailer'=>'Nette Framework','Subject'=>'PHP: An error occurred on the server %host%','Body'=>'[%date%] %message%');private
-static$colophons=array(array(__CLASS__,'getDefaultColophons'));private
-static$enabledProfiler=FALSE;public
+static$enabledBar=TRUE;private
+static$panels=array();private
+static$dumps;private
+static$errors;public
static$counters=array();const
LOG='LOG';const
INFO='INFO';const
@@ -58,316 +59,788 @@ new
LogicException("Cannot instantiate static class ".get_class($this));}public
static
function
-_init(){self::$time=microtime(TRUE);self::$consoleMode=PHP_SAPI==='cli';self::$productionMode=self::DETECT;self::$firebugDetected=isset($_SERVER['HTTP_USER_AGENT'])&&strpos($_SERVER['HTTP_USER_AGENT'],'FirePHP/');self::$ajaxDetected=isset($_SERVER['HTTP_X_REQUESTED_WITH'])&&$_SERVER['HTTP_X_REQUESTED_WITH']==='XMLHttpRequest';register_shutdown_function(array(__CLASS__,'_shutdownHandler'));}public
+_init(){self::$time=microtime(TRUE);self::$consoleMode=PHP_SAPI==='cli';self::$productionMode=self::DETECT;self::$firebugDetected=isset($_SERVER['HTTP_USER_AGENT'])&&strpos($_SERVER['HTTP_USER_AGENT'],'FirePHP/');self::$ajaxDetected=isset($_SERVER['HTTP_X_REQUESTED_WITH'])&&$_SERVER['HTTP_X_REQUESTED_WITH']==='XMLHttpRequest';self::addPanel(new
+DebugPanel('time',array(__CLASS__,'getDefaultPanel')));self::addPanel(new
+DebugPanel('memory',array(__CLASS__,'getDefaultPanel')));self::addPanel(new
+DebugPanel('errors',array(__CLASS__,'getDefaultPanel')));self::addPanel(new
+DebugPanel('dumps',array(__CLASS__,'getDefaultPanel')));register_shutdown_function(array(__CLASS__,'_shutdownHandler'));}public
static
function
-_shutdownHandler(){static$types=array(E_ERROR=>1,E_CORE_ERROR=>1,E_COMPILE_ERROR=>1,E_PARSE=>1);$error=error_get_last();if(self::$enabled&&isset($types[$error['type']])){if(!headers_sent()){header('HTTP/1.1 500 Internal Server Error');}if(ini_get('html_errors')){$error['message']=html_entity_decode(strip_tags($error['message']));}self::processException(new
-FatalErrorException($error['message'],0,$error['type'],$error['file'],$error['line'],NULL),TRUE);}if(self::$productionMode){return;}foreach(headers_list()as$header){if(strncasecmp($header,'Content-Type:',13)===0){if(substr($header,14,9)==='text/html'){break;}return;}}if(self::$enabledProfiler){if(self::$firebugDetected){self::fireLog('Nette profiler',self::GROUP_START);foreach(self::$colophons
-as$callback){foreach((array)call_user_func($callback,'profiler')as$line)self::fireLog(strip_tags($line));}self::fireLog(NULL,self::GROUP_END);}if(!self::$ajaxDetected){$colophons=self::$colophons;?>
+_shutdownHandler(){static$types=array(E_ERROR=>1,E_CORE_ERROR=>1,E_COMPILE_ERROR=>1,E_PARSE=>1);$error=error_get_last();if(self::$enabled&&isset($types[$error['type']])){if(!headers_sent()){header('HTTP/1.1 500 Internal Server Error');}if(ini_get('html_errors')){$error['message']=html_entity_decode(strip_tags($error['message']),ENT_QUOTES,'UTF-8');}self::processException(new
+FatalErrorException($error['message'],0,$error['type'],$error['file'],$error['line'],NULL),TRUE);}if(self::$enabledBar&&!self::$productionMode&&!self::$ajaxDetected){foreach(headers_list()as$header){if(strncasecmp($header,'Content-Type:',13)===0){if(substr($header,14,9)==='text/html'){break;}return;}}$panels=array();foreach(self::$panels
+as$panel){$panels[]=array('id'=>preg_replace('#[^a-z0-9]+#i','-',$panel->getId()),'tab'=>$tab=(string)$panel->getTab(),'panel'=>$tab?(string)$panel->getPanel():NULL);}?>
-
-
-
-
-$m[2]($m[3]) ".($m[3]<7?'▼ ':'► ');}}ob_start();?>
-
-
-
-
-
-
- Nette Debug Console
-
-
-
-
-
-
-
- Nette Debug Console
-
-
-
+
-
-
-
-
-
+
+
+
+
+ - ',trim($panel['tab']),'
';endif?>
+
+
+
-
-
- $dump):?>
-
- |
- |\s+)?(.*)\((\d+)\) #','_netteDumpCb2',$dump)?> |
-
-
-
+
+
+
+
+
+
+$panel):?>
+
-
+
-
".self::_dump($var,0)."\n";if(self::$showLocation){$trace=debug_backtrace();$i=isset($trace[1]['class'])&&$trace[1]['class']===__CLASS__?1:0;if(isset($trace[$i]['file'],$trace[$i]['line'])){$output=substr_replace($output,' '.htmlspecialchars("in file {$trace[$i]['file']} on line {$trace[$i]['line']}",ENT_NOQUOTES).'',-8,0);}}if(self::$consoleMode){$output=htmlspecialchars_decode(strip_tags($output),ENT_NOQUOTES);}if($return){return$output;}else{echo$output;return$var;}}public
static
function
-consoleDump($var,$title=NULL){if(!self::$productionMode){$dump=array();foreach((is_array($var)?$var:array(''=>$var))as$key=>$val){$dump[$key]=self::dump($val,TRUE);}self::$consoleData[]=array('title'=>$title,'dump'=>$dump);}return$var;}private
+barDump($var,$title=NULL){if(!self::$productionMode){$dump=array();foreach((is_array($var)?$var:array(''=>$var))as$key=>$val){$dump[$key]=self::dump($val,TRUE);}self::$dumps[]=array('title'=>$title,'dump'=>$dump);}return$var;}private
static
function
_dump(&$var,$level){static$tableUtf,$tableBin,$re='#[^\x09\x0A\x0D\x20-\x7E\xA0-\x{10FFFF}]#u';if($tableUtf===NULL){foreach(range("\x00","\xFF")as$ch){if(ord($ch)<32&&strpos("\r\n\t",$ch)===FALSE)$tableUtf[$ch]=$tableBin[$ch]='\\x'.str_pad(dechex(ord($ch)),2,'0',STR_PAD_LEFT);elseif(ord($ch)<127)$tableUtf[$ch]=$tableBin[$ch]=$ch;else{$tableUtf[$ch]=$ch;$tableBin[$ch]='\\x'.dechex(ord($ch));}}$tableUtf['\\x']=$tableBin['\\x']='\\\\x';}if(is_bool($var)){return"bool(".($var?'TRUE':'FALSE').")\n";}elseif($var===NULL){return"NULL\n";}elseif(is_int($var)){return"int($var)\n";}elseif(is_float($var)){return"float($var)\n";}elseif(is_string($var)){if(self::$maxLen&&strlen($var)>self::$maxLen){$s=htmlSpecialChars(substr($var,0,self::$maxLen),ENT_NOQUOTES).' ... ';}else{$s=htmlSpecialChars($var,ENT_NOQUOTES);}$s=strtr($s,preg_match($re,$s)||preg_last_error()?$tableBin:$tableUtf);return"string(".strlen($var).") \"$s\"\n";}elseif(is_array($var)){$s="array(".count($var).") ";$space=str_repeat($space1=' ',$level);static$marker;if($marker===NULL)$marker=uniqid("\x00",TRUE);if(empty($var)){}elseif(isset($var[$marker])){$s.="{\n$space$space1*RECURSION*\n$space}";}elseif($level{\n";$var[$marker]=0;foreach($var
@@ -387,37 +860,42 @@ function
timer($name=NULL){static$time=array();$now=microtime(TRUE);$delta=isset($time[$name])?$now-$time[$name]:0;$time[$name]=$now;return$delta;}public
static
function
-enable($mode=NULL,$logFile=NULL,$email=NULL){error_reporting(E_ALL|E_STRICT);if(is_bool($mode)){self::$productionMode=$mode;}if(self::$productionMode===self::DETECT){if(class_exists('Environment')){self::$productionMode=Environment::isProduction();}elseif(isset($_SERVER['SERVER_ADDR'])||isset($_SERVER['LOCAL_ADDR'])){$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;}}if(self::$productionMode&&$logFile!==FALSE){self::$logFile='log/php_error.log';if(class_exists('Environment')){if(is_string($logFile)){self::$logFile=Environment::expand($logFile);}else
-try{self::$logFile=Environment::expand('%logDir%/php_error.log');}catch(InvalidStateException$e){}}elseif(is_string($logFile)){self::$logFile=$logFile;}ini_set('error_log',self::$logFile);}if(function_exists('ini_set')){ini_set('display_errors',!self::$productionMode);ini_set('html_errors',!self::$logFile&&!self::$consoleMode);ini_set('log_errors',(bool)self::$logFile);}elseif(ini_get('log_errors')!=(bool)self::$logFile||(ini_get('display_errors')!=!self::$productionMode&&ini_get('display_errors')!==(self::$productionMode?'stderr':'stdout'))){throw
+enable($mode=NULL,$logFile=NULL,$email=NULL){error_reporting(E_ALL|E_STRICT);if(is_bool($mode)){self::$productionMode=$mode;}elseif(is_string($mode)){$mode=preg_split('#[,\s]+#',$mode);}if(is_array($mode)){self::$productionMode=!isset($_SERVER['REMOTE_ADDR'])||!in_array($_SERVER['REMOTE_ADDR'],$mode,TRUE);}if(self::$productionMode===self::DETECT){if(class_exists('Environment')){self::$productionMode=Environment::isProduction();}elseif(isset($_SERVER['SERVER_ADDR'])||isset($_SERVER['LOCAL_ADDR'])){$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;}}if(self::$productionMode&&$logFile!==FALSE){self::$logFile='log/php_error.log';if(class_exists('Environment')){if(is_string($logFile)){self::$logFile=Environment::expand($logFile);}else
+try{self::$logFile=Environment::expand('%logDir%/php_error.log');}catch(InvalidStateException$e){}}elseif(is_string($logFile)){self::$logFile=$logFile;}ini_set('error_log',self::$logFile);}if(function_exists('ini_set')){ini_set('display_errors',!self::$productionMode);ini_set('html_errors',!self::$logFile&&!self::$consoleMode);ini_set('log_errors',FALSE);}elseif(ini_get('display_errors')!=!self::$productionMode&&ini_get('display_errors')!==(self::$productionMode?'stderr':'stdout')){throw
new
-LogicException('Function ini_set() must be enabled.');}self::$sendEmails=self::$logFile&&$email;if(self::$sendEmails){if(is_string($email)){self::$emailHeaders['To']=$email;}elseif(is_array($email)){self::$emailHeaders=$email+self::$emailHeaders;}}if(!defined('E_DEPRECATED')){define('E_DEPRECATED',8192);}if(!defined('E_USER_DEPRECATED')){define('E_USER_DEPRECATED',16384);}set_exception_handler(array(__CLASS__,'_exceptionHandler'));set_error_handler(array(__CLASS__,'_errorHandler'));self::$enabled=TRUE;}public
+NotSupportedException('Function ini_set() must be enabled.');}self::$sendEmails=self::$logFile&&$email;if(self::$sendEmails){if(is_string($email)){self::$emailHeaders['To']=$email;}elseif(is_array($email)){self::$emailHeaders=$email+self::$emailHeaders;}}if(!defined('E_DEPRECATED')){define('E_DEPRECATED',8192);}if(!defined('E_USER_DEPRECATED')){define('E_USER_DEPRECATED',16384);}set_exception_handler(array(__CLASS__,'_exceptionHandler'));set_error_handler(array(__CLASS__,'_errorHandler'));self::$enabled=TRUE;}public
static
function
isEnabled(){return
self::$enabled;}public
static
function
+log($message){error_log(@date('[Y-m-d H-i-s] ').trim($message).PHP_EOL,3,self::$logFile);}public
+static
+function
_exceptionHandler(Exception$exception){if(!headers_sent()){header('HTTP/1.1 500 Internal Server Error');}self::processException($exception,TRUE);exit;}public
static
function
_errorHandler($severity,$message,$file,$line,$context){if($severity===E_RECOVERABLE_ERROR||$severity===E_USER_ERROR){throw
new
FatalErrorException($message,0,$severity,$file,$line,$context);}elseif(($severity&error_reporting())!==$severity){return
-NULL;}elseif(self::$strictMode){if(!headers_sent()){header('HTTP/1.1 500 Internal Server Error');}self::processException(new
-FatalErrorException($message,0,$severity,$file,$line,$context),TRUE);exit;}static$types=array(E_WARNING=>'Warning',E_USER_WARNING=>'Warning',E_NOTICE=>'Notice',E_USER_NOTICE=>'Notice',E_STRICT=>'Strict standards',E_DEPRECATED=>'Deprecated',E_USER_DEPRECATED=>'Deprecated');$type=isset($types[$severity])?$types[$severity]:'Unknown error';if(self::$logFile){if(self::$sendEmails){self::sendEmail("$type: $message in $file on line $line");}return
-FALSE;}elseif(!self::$productionMode&&self::$firebugDetected&&!headers_sent()){$message=strip_tags($message);self::fireLog("$type: $message in $file on line $line",self::ERROR);return
+NULL;}elseif(self::$strictMode){self::_exceptionHandler(new
+FatalErrorException($message,0,$severity,$file,$line,$context),TRUE);}static$types=array(E_WARNING=>'Warning',E_USER_WARNING=>'Warning',E_NOTICE=>'Notice',E_USER_NOTICE=>'Notice',E_STRICT=>'Strict standards',E_DEPRECATED=>'Deprecated',E_USER_DEPRECATED=>'Deprecated');$message='PHP '.(isset($types[$severity])?$types[$severity]:'Unknown error').": $message in $file:$line";if(self::$logFile){if(self::$sendEmails){self::sendEmail($message);}self::log($message);return
+NULL;}elseif(!self::$productionMode){self::$errors[]=$message;if(self::$firebugDetected&&!headers_sent()){self::fireLog(strip_tags($message),self::ERROR);}return
NULL;}return
FALSE;}public
static
function
-processException(Exception$exception,$outputAllowed=FALSE){if(!self::$enabled){return;}elseif(self::$logFile){error_log("PHP Fatal error: Uncaught $exception");$file=@strftime('%d-%b-%Y %H-%M-%S ',self::$time).strstr(number_format(self::$time,4,'~',''),'~');$file=dirname(self::$logFile)."/exception $file.html";self::$logHandle=@fopen($file,'x');if(self::$logHandle){ob_start(array(__CLASS__,'_writeFile'),1);self::_paintBlueScreen($exception);ob_end_flush();fclose(self::$logHandle);}if(self::$sendEmails){self::sendEmail((string)$exception);}}elseif(self::$productionMode){}elseif(self::$consoleMode){if($outputAllowed){echo"$exception\n";foreach(self::$colophons
-as$callback){foreach((array)call_user_func($callback,'bluescreen')as$line)echo
-strip_tags($line)."\n";}}}elseif(self::$firebugDetected&&self::$ajaxDetected&&!headers_sent()){self::fireLog($exception,self::EXCEPTION);}elseif($outputAllowed){if(!headers_sent()){@ob_end_clean();while(ob_get_level()&&@ob_end_clean());if(in_array('Content-Encoding: gzip',headers_list()))header('Content-Encoding: identity',TRUE);}self::_paintBlueScreen($exception);}elseif(self::$firebugDetected&&!headers_sent()){self::fireLog($exception,self::EXCEPTION);}foreach(self::$onFatalError
+processException(Exception$exception,$outputAllowed=FALSE){if(!self::$enabled){return;}elseif(self::$logFile){try{$hash=md5($exception.(method_exists($exception,'getPrevious')?$exception->getPrevious():(isset($exception->previous)?$exception->previous:'')));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='compress.zlib://'.dirname(self::$logFile)."/exception ".@date('Y-m-d H-i-s')." $hash.html.gz";if(empty($skip)&&self::$logHandle=@fopen($file,'w')){ob_start();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){}elseif(self::$consoleMode){if($outputAllowed){echo"$exception\n";}}elseif(self::$firebugDetected&&self::$ajaxDetected&&!headers_sent()){self::fireLog($exception,self::EXCEPTION);}elseif($outputAllowed){if(!headers_sent()){@ob_end_clean();while(ob_get_level()&&@ob_end_clean());if(in_array('Content-Encoding: gzip',headers_list()))header('Content-Encoding: identity',TRUE);}self::_paintBlueScreen($exception);}elseif(self::$firebugDetected&&!headers_sent()){self::fireLog($exception,self::EXCEPTION);}foreach(self::$onFatalError
as$handler){call_user_func($handler,$exception);}}public
static
function
+toStringException(Exception$exception){if(self::$enabled){self::_exceptionHandler($exception);}else{trigger_error($exception->getMessage(),E_USER_ERROR);}}public
+static
+function
_paintBlueScreen(Exception$exception){$internals=array();foreach(array('Object','ObjectMixin')as$class){if(class_exists($class,FALSE)){$rc=new
-ReflectionClass($class);$internals[$rc->getFileName()]=TRUE;}}if(class_exists('Environment',FALSE)){$application=Environment::getServiceLocator()->hasService('Nette\Application\Application',TRUE)?Environment::getServiceLocator()->getService('Nette\Application\Application'):NULL;}$colophons=self::$colophons;if(!function_exists('_netteDebugPrintCode')){function
+ReflectionClass($class);$internals[$rc->getFileName()]=TRUE;}}if(class_exists('Environment',FALSE)){$application=Environment::getServiceLocator()->hasService('Nette\Application\Application',TRUE)?Environment::getServiceLocator()->getService('Nette\Application\Application'):NULL;}if(!function_exists('_netteDebugPrintCode')){function
_netteDebugPrintCode($file,$line,$count=15){if(function_exists('ini_set')){ini_set('highlight.comment','#999; font-style: italic');ini_set('highlight.default','#000');ini_set('highlight.html','#06b');ini_set('highlight.keyword','#d24; font-weight: bold');ini_set('highlight.string','#080');}$start=max(1,$line-floor($count/2));$source=@file_get_contents($file);if(!$source)return;$source=explode("\n",highlight_string($source,TRUE));$spans=1;echo$source[0];$source=explode('
',$source[1]);array_unshift($source,NULL);$i=$start;while(--$i>=1){if(preg_match('#.*(?span[^>]*>)#',$source[$i],$m)){if($m[1]!==''){$spans++;echo$m[1];}break;}}$source=array_slice($source,$start,$count,TRUE);end($source);$numWidth=strlen((string)key($source));foreach($source
as$n=>$s){$spans+=substr_count($s,'Line %{$numWidth}s: %s\n%s",$n,strip_tags($s),preg_replace('#[^>]*(<[^>]+>)[^<]*#','$1',$s));}else{printf("Line %{$numWidth}s: %s\n",$n,$s);}}echo
str_repeat('',$spans),'
';}function
@@ -709,12 +1187,10 @@ _netteDump(self::_dump($v,0));echo"\n";}?>
- getPanels()as$name=>$panel):?>
-
-
+IDebugPanel&&$panel=$ex->getPanel()):?>
+ getTab(),FALSE)?>
+
-
@@ -826,10 +1302,17 @@ htmlspecialchars($s),'
';?>
-
-
-
+ - Report generated at
+
+
+
+ - PHP
+
+ - (revision )
@@ -851,39 +1334,156 @@ defaultMailer($message){$host=isset($_SERVER['HTTP_HOST'])?$_SERVER['HTTP_HOST']
as$key=>$value){$header.="$key: $value\r\n";}$body=str_replace("\r\n","\n",$body);if(PHP_OS!='Linux')$body=str_replace("\n","\r\n",$body);mail($to,$subject,$body,$header);}public
static
function
-enableProfiler(){self::$enabledProfiler=TRUE;}public
+enableBar(){self::$enabledBar=TRUE;}public
static
function
-disableProfiler(){self::$enabledProfiler=FALSE;}public
+disableBar(){self::$enabledBar=FALSE;}public
static
function
-addColophon($callback){if(!is_callable($callback)){$able=is_callable($callback,TRUE,$textual);throw
-new
-InvalidArgumentException("Colophon handler '$textual' is not ".($able?'callable.':'valid PHP callback.'));}if(!in_array($callback,self::$colophons,TRUE)){self::$colophons[]=$callback;}}private
+addPanel(IDebugPanel$panel){self::$panels[]=$panel;}public
static
function
-getDefaultColophons($sender){if($sender==='profiler'){$arr[]='Elapsed time: '.number_format((microtime(TRUE)-self::$time)*1000,1,'.',' ').' ms | Allocated memory: '.number_format(memory_get_peak_usage()/1000,1,'.',' ').' kB';foreach((array)self::$counters
-as$name=>$value){if(is_array($value))$value=implode(', ',$value);$arr[]=htmlSpecialChars($name).' = '.htmlSpecialChars($value).'';}$autoloaded=class_exists('AutoLoader',FALSE)?AutoLoader::$count:0;$s=''.count(get_included_files()).'/'.$autoloaded.' files, ';$exclude=array('stdClass','Exception','ErrorException','Traversable','IteratorAggregate','Iterator','ArrayAccess','Serializable','Closure');foreach(get_loaded_extensions()as$ext){$ref=new
-ReflectionExtension($ext);$exclude=array_merge($exclude,$ref->getClassNames());}$classes=array_diff(get_declared_classes(),$exclude);$intf=array_diff(get_declared_interfaces(),$exclude);$func=get_defined_functions();$func=(array)@$func['user'];$consts=get_defined_constants(TRUE);$consts=array_keys((array)@$consts['user']);foreach(array('classes','intf','func','consts')as$item){$s.=''.count($$item).' '.$item.', ';}$arr[]=$s;}if($sender==='bluescreen'){$arr[]='Report generated at '.@date('Y/m/d H:i:s',self::$time);if(isset($_SERVER['HTTP_HOST'],$_SERVER['REQUEST_URI'])){$url=(isset($_SERVER['HTTPS'])&&strcasecmp($_SERVER['HTTPS'],'off')?'https://':'http://').htmlSpecialChars($_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI']);$arr[]=''.$url.'';}$arr[]='PHP '.htmlSpecialChars(PHP_VERSION);if(isset($_SERVER['SERVER_SOFTWARE']))$arr[]=htmlSpecialChars($_SERVER['SERVER_SOFTWARE']);if(class_exists('Framework'))$arr[]=htmlSpecialChars('Nette Framework '.Framework::VERSION).' (revision '.htmlSpecialChars(Framework::REVISION).')';}return$arr;}public
-static
-function
-fireDump($var,$key){self::fireSend(2,array((string)$key=>$var));return$var;}public
+getDefaultPanel($id){switch($id){case'time:tab':?>
ms
+
kB
+
variables
+$m[2]($m[3]) ".($m[3]<7?'▼ ':'► ');}}?>
+
+
+
+Dumped variables
+
+
+
+
+
+
+
+
+
+ $dump):?>
+
+ |
+ |\s+)?(.*)\((\d+)\) #','_netteDumpCb2',$dump)?> |
+
+
+
+
+
+
+
errors
+Errors
+
+
+
+
+get_class($message),'Message'=>$message->getMessage(),'File'=>$message->getFile(),'Line'=>$message->getLine(),'Trace'=>$message->getTrace(),'Type'=>'','Function'=>'');foreach($message['Trace']as&$row){if(empty($row['file']))$row['file']='?';if(empty($row['line']))$row['line']='?';}}elseif($priority===self::GROUP_START){$label=$message;$message=NULL;}return
-self::fireSend(1,self::replaceObjects(array(array('Type'=>$priority,'Label'=>$label),$message)));}private
+self::fireSend('FirebugConsole/0.1',self::replaceObjects(array(array('Type'=>$priority,'Label'=>$label),$message)));}private
static
function
-fireSend($index,$payload){if(self::$productionMode)return
+fireSend($struct,$payload){if(self::$productionMode)return
NULL;if(headers_sent())return
-FALSE;header('X-Wf-Protocol-nette: http://meta.wildfirehq.org/Protocol/JsonStream/0.2');header('X-Wf-nette-Plugin-1: http://meta.firephp.org/Wildfire/Plugin/FirePHP/Library-FirePHPCore/0.2.0');if($index===1){header('X-Wf-nette-Structure-1: http://meta.firephp.org/Wildfire/Structure/FirePHP/FirebugConsole/0.1');}elseif($index===2){header('X-Wf-nette-Structure-2: http://meta.firephp.org/Wildfire/Structure/FirePHP/Dump/0.1');}$payload=json_encode($payload);static$counter;foreach(str_split($payload,4990)as$s){$num=++$counter;header("X-Wf-nette-$index-1-n$num: |$s|\\");}header("X-Wf-nette-$index-1-n$num: |$s|");return
+FALSE;header('X-Wf-Protocol-nette: http://meta.wildfirehq.org/Protocol/JsonStream/0.2');header('X-Wf-nette-Plugin-1: http://meta.firephp.org/Wildfire/Plugin/FirePHP/Library-FirePHPCore/0.2.0');static$structures;$index=isset($structures[$struct])?$structures[$struct]:($structures[$struct]=count($structures)+1);header("X-Wf-nette-Structure-$index: http://meta.firephp.org/Wildfire/Structure/FirePHP/$struct");$payload=json_encode($payload);static$counter;foreach(str_split($payload,4990)as$s){$num=++$counter;header("X-Wf-nette-$index-1-n$num: |$s|\\");}header("X-Wf-nette-$index-1-n$num: |$s|");return
TRUE;}static
private
function
replaceObjects($val){if(is_object($val)){return'object '.get_class($val).'';}elseif(is_string($val)){return@iconv('UTF-16','UTF-8//IGNORE',iconv('UTF-8','UTF-16//IGNORE',$val));}elseif(is_array($val)){foreach($val
-as$k=>$v){unset($val[$k]);$k=@iconv('UTF-16','UTF-8//IGNORE',iconv('UTF-8','UTF-16//IGNORE',$k));$val[$k]=self::replaceObjects($v);}}return$val;}}Debug::_init();if(!function_exists('dump')){function
+as$k=>$v){unset($val[$k]);$k=@iconv('UTF-16','UTF-8//IGNORE',iconv('UTF-8','UTF-16//IGNORE',$k));$val[$k]=self::replaceObjects($v);}}return$val;}}interface
+IDebugPanel{function
+getTab();function
+getPanel();function
+getId();}class
+DebugPanel
+implements
+IDebugPanel{private$id;private$callback;public
+function
+__construct($id,$callback){$this->id=$id;$this->callback=$callback;}public
+function
+getId(){return$this->id;}public
+function
+getTab(){ob_start();call_user_func($this->callback,"$this->id:tab");return
+ob_get_clean();}public
+function
+getPanel(){ob_start();call_user_func($this->callback,"$this->id:panel");return
+ob_get_clean();}}Debug::_init();if(!function_exists('dump')){function
dump($var){foreach($args=func_get_args()as$arg)Debug::dump($arg);return$var;}}class
FatalErrorException
extends
diff --git a/examples/nette-debug.php b/examples/nette-debug.php
index 20660f95..5c58761a 100644
--- a/examples/nette-debug.php
+++ b/examples/nette-debug.php
@@ -1,3 +1,5 @@
+
+
Nette\Debug & dibi example
diff --git a/examples/nette-debug2.php b/examples/nette-debug2.php
index 003c6635..ebe6556e 100644
--- a/examples/nette-debug2.php
+++ b/examples/nette-debug2.php
@@ -1,3 +1,5 @@
+
+
Nette\Debug & dibi example 2
@@ -25,4 +27,4 @@ dibi::connect(array(
// throws error
-Debug::consoleDump( dibi::fetchAll('SELECT * FROM [customers] WHERE [customer_id] < %i', 38), '[customers]' );
+Debug::barDump( dibi::fetchAll('SELECT * FROM [customers] WHERE [customer_id] < %i', 38), '[customers]' );