1
0
mirror of https://github.com/maximebf/php-debugbar.git synced 2025-05-05 06:27:53 +02:00

added Exceptions and PDO collectors

This commit is contained in:
maximebf 2013-06-18 12:47:22 +09:00
parent 79295b0c4b
commit 4a29e38cea
19 changed files with 948 additions and 71 deletions

View File

@ -5,7 +5,7 @@ include 'bootstrap.php';
try {
throw new Exception('Something failed!');
} catch (Exception $e) {
$debugbar['messages']->addMessage($e, 'error');
$debugbar['exceptions']->addException($e);
}
?>

34
demo/demo_pdo.php Normal file
View File

@ -0,0 +1,34 @@
<?php
include 'bootstrap.php';
use DebugBar\DataCollector\PDO\TraceablePDO;
use DebugBar\DataCollector\PDO\PDOCollector;
$pdo = new TraceablePDO(new PDO('sqlite::memory:'));
$debugbar->addCollector(new PDOCollector($pdo));
$pdo->exec('create table users (name varchar)');
$stmt = $pdo->prepare('insert into users (name) values (?)');
$stmt->execute(array('foo'));
$stmt->execute(array('bar'));
$users = $pdo->query('select * from users')->fetchAll();
$stmt = $pdo->prepare('select * from users where name=?');
$stmt->execute(array('foo'));
$foo = $stmt->fetch();
$pdo->exec('delete from titi');
?>
<html>
<head>
<?php echo $debugbarRenderer->renderHead() ?>
</head>
<body>
<p>PhpDebugBar PDO Demo</p>
<?php
echo $debugbarRenderer->render();
?>
</body>
</html>

View File

@ -35,7 +35,10 @@ class MonologCollector extends AbstractProcessingHandler implements DataCollecto
public function collect()
{
return $this->records;
return array(
'count' => count($this->records),
'records' => $this->records
);
}
public function getName()
@ -48,8 +51,12 @@ class MonologCollector extends AbstractProcessingHandler implements DataCollecto
return array(
"logs" => array(
"widget" => "PhpDebugBar.Widgets.MessagesWidget",
"map" => "monolog",
"map" => "monolog.records",
"default" => "[]"
),
"logs:badge" => array(
"map" => "monolog.count",
"default" => "null"
)
);
}

View File

@ -21,8 +21,36 @@ abstract class DataCollector implements DataCollectorInterface
* @param mixed $var
* @return string
*/
public function varToString($var)
public function formatVar($var)
{
return print_r($var, true);
}
/**
* Transforms a duration in seconds in a readable string
*
* @param float $value
* @return string
*/
public function formatDuration($seconds)
{
return round($seconds * 1000) . 'ms';
}
/**
* Transforms a size in bytes to a human readable string
*
* @param string $size
* @param integer $precision
* @return string
*/
public function formatBytes($size, $precision = 2)
{
if ($size === 0) {
return "0B";
}
$base = log($size) / log(1024);
$suffixes = array('', 'KB', 'MB', 'GB', 'TB');
return round(pow(1024, $base - floor($base)), $precision) . $suffixes[floor($base)];
}
}

View File

@ -1,30 +0,0 @@
<?php
/*
* This file is part of the DebugBar package.
*
* (c) 2013 Maxime Bouroumeau-Fuseau
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace DebugBar\DataCollector;
class DependencyCollector extends DataCollector
{
/**
* {@inheritDoc}
*/
public function collect()
{
return array();
}
/**
* {@inheritDoc}
*/
public function getName()
{
return 'dependency';
}
}

View File

@ -0,0 +1,100 @@
<?php
/*
* This file is part of the DebugBar package.
*
* (c) 2013 Maxime Bouroumeau-Fuseau
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace DebugBar\DataCollector;
use Exception;
/**
* Collects info about exceptions
*/
class ExceptionsCollector extends DataCollector implements Renderable
{
protected $exceptions = array();
/**
* Adds an exception to be profiled in the debug bar
*
* @param Exception $e
*/
public function addException(Exception $e)
{
$this->exceptions[] = $e;
}
/**
* Returns the list of exceptions being profiled
*
* @return array[Exception]
*/
public function getExceptions()
{
return $this->exceptions;
}
/**
* {@inheritDoc}
*/
public function collect()
{
return array(
'count' => count($this->exceptions),
'exceptions' => array_map(array($this, 'formatExceptionData'), $this->exceptions)
);
}
/**
* Returns exception data as an array
*
* @param Exception $e
* @return array
*/
public function formatExceptionData(Exception $e)
{
$lines = file($e->getFile());
$start = $e->getLine() - 4;
$lines = array_slice($lines, $start < 0 ? 0 : $start, 7);
return array(
'type' => get_class($e),
'message' => $e->getMessage(),
'code' => $e->getCode(),
'file' => $e->getFile(),
'line' => $e->getLine(),
'surrounding_lines' => $lines
);
}
/**
* {@inheritDoc}
*/
public function getName()
{
return 'exceptions';
}
/**
* {@inheritDoc}
*/
public function getWidgets()
{
return array(
'exceptions' => array(
'widget' => 'PhpDebugBar.Widgets.ExceptionsWidget',
'map' => 'exceptions.exceptions',
'default' => '[]'
),
'exceptions:badge' => array(
'map' => 'exceptions.count',
'default' => 'null'
)
);
}
}

View File

@ -35,20 +35,6 @@ class MemoryCollector extends DataCollector implements Renderable
$this->peakUsage = memory_get_peak_usage(true);
}
/**
* Transforms a size in bytes to a human readable string
*
* @param string $size
* @param integer $precision
* @return string
*/
public function toReadableString($size, $precision = 2)
{
$base = log($size) / log(1024);
$suffixes = array('', 'KB', 'MB', 'GB', 'TB');
return round(pow(1024, $base - floor($base)), $precision) . $suffixes[floor($base)];
}
/**
* {@inheritDoc}
*/
@ -57,7 +43,7 @@ class MemoryCollector extends DataCollector implements Renderable
$this->updatePeakUsage();
return array(
'peak_usage' => $this->peakUsage,
'peak_usage_str' => $this->toReadableString($this->peakUsage)
'peak_usage_str' => $this->formatBytes($this->peakUsage)
);
}

View File

@ -28,7 +28,7 @@ class MessagesCollector extends DataCollector implements Renderable
public function addMessage($message, $label = 'info')
{
$this->messages[] = array(
'message' => $this->varToString($message),
'message' => $this->formatVar($message),
'is_string' => is_string($message),
'label' => $label,
'time' => microtime(true),
@ -52,7 +52,10 @@ class MessagesCollector extends DataCollector implements Renderable
*/
public function collect()
{
return $this->messages;
return array(
'count' => count($this->messages),
'messages' => $this->messages
);
}
/**
@ -71,8 +74,12 @@ class MessagesCollector extends DataCollector implements Renderable
return array(
"messages" => array(
"widget" => "PhpDebugBar.Widgets.MessagesWidget",
"map" => "messages",
"map" => "messages.messages",
"default" => "[]"
),
"messages:badge" => array(
"map" => "messages.count",
"default" => "null"
)
);
}

View File

@ -0,0 +1,65 @@
<?php
namespace DebugBar\DataCollector\PDO;
use DebugBar\DataCollector\DataCollector;
use DebugBar\DataCollector\Renderable;
class PDOCollector extends DataCollector implements Renderable
{
public function __construct(TraceablePDO $pdo)
{
$this->pdo = $pdo;
}
public function collect()
{
$stmts = array();
foreach ($this->pdo->getExecutedStatements() as $stmt) {
$stmts[] = array(
'sql' => $stmt->getSqlWithParams(),
'row_count' => $stmt->getRowCount(),
'stmt_id' => $stmt->getPreparedId(),
'prepared_stmt' => $stmt->getSql(),
'params' => $stmt->getParameters(),
'duration' => $stmt->getDuration(),
'duration_str' => $this->formatDuration($stmt->getDuration()),
'memory' => $stmt->getMemoryUsage(),
'memory_str' => $this->formatBytes($stmt->getMemoryUsage()),
'is_success' => $stmt->isSuccess(),
'error_code' => $stmt->getErrorCode(),
'error_message' => $stmt->getErrorMessage()
);
}
return array(
'nb_statements' => count($stmts),
'nb_failed_statements' => count($this->pdo->getFailedExecutedStatements()),
'accumulated_duration' => $this->pdo->getAccumulatedStatementsDuration(),
'accumulated_duration_str' => $this->formatDuration($this->pdo->getAccumulatedStatementsDuration()),
'peak_memory_usage' => $this->pdo->getPeakMemoryUsage(),
'peak_memory_usage_str' => $this->formatBytes($this->pdo->getPeakMemoryUsage()),
'statements' => $stmts
);
}
public function getName()
{
return 'pdo';
}
public function getWidgets()
{
return array(
"database" => array(
"widget" => "PhpDebugBar.Widgets.SQLQueriesWidget",
"map" => "pdo",
"default" => "[]"
),
"database:badge" => array(
"map" => "pdo.nb_statements",
"default" => 0
)
);
}
}

View File

@ -0,0 +1,211 @@
<?php
namespace DebugBar\DataCollector\PDO;
use PDO;
use PDOException;
/**
* A PDO proxy which traces statements
*/
class TraceablePDO extends PDO
{
protected $pdo;
protected $executedStatements = array();
public function __construct(PDO $pdo)
{
$this->pdo = $pdo;
$this->pdo->setAttribute(PDO::ATTR_STATEMENT_CLASS, array('DebugBar\DataCollector\PDO\TraceablePDOStatement', array($this)));
}
/**
* {@inheritDoc}
*/
public function beginTransaction()
{
return $this->pdo->beginTransaction();
}
/**
* {@inheritDoc}
*/
public function commit()
{
return $this->pdo->commit();
}
/**
* {@inheritDoc}
*/
public function errorCode()
{
return $this->pdo->errorCode();
}
/**
* {@inheritDoc}
*/
public function errorInfo()
{
return $this->errorInfo();
}
/**
* {@inheritDoc}
*/
public function exec($sql)
{
return $this->profileCall('exec', $sql, func_get_args());
}
/**
* {@inheritDoc}
*/
public function getAttribute($attr)
{
return $this->pdo->getAttribute($attr);
}
/**
* {@inheritDoc}
*/
public function inTransaction()
{
return $this->pdo->inTransaction();
}
/**
* {@inheritDoc}
*/
public function lastInsertId($name = null)
{
return $this->pdo->lastInsertId($name);
}
/**
* {@inheritDoc}
*/
public function prepare($sql, $driver_options = array())
{
return $this->pdo->prepare($sql, $driver_options);
}
/**
* {@inheritDoc}
*/
public function query($sql)
{
return $this->profileCall('query', $sql, func_get_args());
}
/**
* {@inheritDoc}
*/
public function quote($expr, $parameter_type = PDO::PARAM_STR)
{
return $this->pdo->quote($expr, $parameter_type);
}
/**
* {@inheritDoc}
*/
public function rollBack()
{
return $this->pdo->rollBack();
}
/**
* {@inheritDoc}
*/
public function setAttribute($attr, $value)
{
return $this->pdo->setAttribute($attr, $value);
}
/**
* Profiles a call to a PDO method
*
* @param string $method
* @param string $sql
* @param array $args
* @return mixed The result of the call
*/
protected function profileCall($method, $sql, array $args)
{
$start = microtime(true);
$ex = null;
try {
$result = call_user_func_array(array($this->pdo, $method), $args);
} catch (PDOException $e) {
$ex = $e;
}
$duration = microtime(true) - $start;
$memoryUsage = memory_get_peak_usage(true);
if ($this->pdo->getAttribute(PDO::ATTR_ERRMODE) !== PDO::ERRMODE_EXCEPTION && $result === false) {
$error = $this->pdo->errorInfo();
$ex = new PDOException($error[2], $error[0]);
}
$tracedStmt = new TracedStatement($sql, array(), null, 0, $duration, $memoryUsage, $ex);
$this->addExecutedStatement($tracedStmt);
if ($this->pdo->getAttribute(PDO::ATTR_ERRMODE) === PDO::ERRMODE_EXCEPTION && $ex !== null) {
throw $ex;
}
return $result;
}
/**
* Adds an executed TracedStatement
*
* @param TracedStatement $stmt
*/
public function addExecutedStatement(TracedStatement $stmt)
{
$this->executedStatements[] = $stmt;
}
/**
* Returns the accumulated execution time of statements
*
* @return int
*/
public function getAccumulatedStatementsDuration()
{
return array_reduce($this->executedStatements, function($v, $s) { return $v + $s->getDuration(); });
}
/**
* Returns the peak memory usage while performing statements
*
* @return int
*/
public function getPeakMemoryUsage()
{
return array_reduce($this->executedStatements, function($v, $s) { $m = $s->getMemoryUsage(); return $m > $v ? $m : $v; });
}
/**
* Returns the list of executed statements as TracedStatement objects
*
* @return array
*/
public function getExecutedStatements()
{
return $this->executedStatements;
}
/**
* Returns the list of failed statements
*
* @return array
*/
public function getFailedExecutedStatements()
{
return array_filter($this->executedStatements, function($s) { return !$s->isSuccess(); });
}
}

View File

@ -0,0 +1,81 @@
<?php
namespace DebugBar\DataCollector\PDO;
use PDO;
use PDOStatement;
use PDOException;
/**
* A traceable PDO statement to use with Traceablepdo
*/
class TraceablePDOStatement extends PDOStatement
{
protected $pdo;
protected $boundParameters = array();
protected function __construct(TraceablePDO $pdo)
{
$this->pdo = $pdo;
}
/**
* {@inheritDoc}
*/
public function bindColumn($column, &$param) {
$this->boundParameters[$column] = $param;
$args = array_merge(array($column, &$param), array_slice(func_get_args(), 2));
return call_user_func_array(array("parent", 'bindColumn'), $args);
}
/**
* {@inheritDoc}
*/
public function bindParam($param, &$var) {
$this->boundParameters[$param] = $var;
$args = array_merge(array($param, &$var), array_slice(func_get_args(), 2));
return call_user_func_array(array("parent", 'bindParam'), $args);
}
/**
* {@inheritDoc}
*/
public function bindValue($param, $value) {
$this->boundParameters[$param] = $value;
return call_user_func_array(array("parent", 'bindValue'), func_get_args());
}
/**
* {@inheritDoc}
*/
public function execute($params = array())
{
$start = microtime(true);
$ex = null;
try {
$result = parent::execute($params);
} catch (PDOException $e) {
$ex = $e;
}
$preparedId = spl_object_hash($this);
$boundParameters = array_merge($this->boundParameters, $params);
$duration = microtime(true) - $start;
$memoryUsage = memory_get_peak_usage(true);
if ($this->pdo->getAttribute(PDO::ATTR_ERRMODE) !== PDO::ERRMODE_EXCEPTION && $result === false) {
$error = $this->errorInfo();
$ex = new PDOException($error[2], $error[0]);
}
$tracedStmt = new TracedStatement($this->queryString, $boundParameters,
$preparedId, $this->rowCount(), $duration, $memoryUsage, $ex);
$this->pdo->addExecutedStatement($tracedStmt);
if ($this->pdo->getAttribute(PDO::ATTR_ERRMODE) === PDO::ERRMODE_EXCEPTION && $ex !== null) {
throw $ex;
}
return $result;
}
}

View File

@ -0,0 +1,189 @@
<?php
namespace DebugBar\DataCollector\PDO;
/**
* Holds information about a statement
*/
class TracedStatement
{
protected $sql;
protected $rowCount;
protected $parameters;
protected $duration;
protected $memoryUsage;
protected $exception;
/**
* Traces a call and returns a TracedStatement
*
* @param callback $callback
* @param array $args Callback args
* @param string $sql The SQL query string
* @return TracedStatement
*/
public static function traceCall($callback, array $args, $sql = '')
{
$start = microtime(true);
$result = call_user_func_array($callback, $args);
$duration = microtime(true) - $start;
$memoryUsage = memory_get_peak_usage(true);
$tracedStmt = new TracedStatement($sql, array(), null, 0, $duration, $memoryUsage);
return array($tracedStmt, $result);
}
/**
* @param string $sql
* @param array $params
* @param string $preparedId
* @param integer $rowCount
* @param integer $duration
* @param integer $memoryUsage
* @param \Exception $e
*/
public function __construct($sql, array $params = array(), $preparedId = null, $rowCount = 0, $duration = 0, $memoryUsage = 0, \Exception $e = null)
{
$this->sql = $sql;
$this->rowCount = $rowCount;
$this->parameters = $params;
$this->preparedId = $preparedId;
$this->duration = $duration;
$this->memoryUsage = $memoryUsage;
$this->exception = $e;
}
/**
* Returns the SQL string used for the query
*
* @return string
*/
public function getSql()
{
return $this->sql;
}
/**
* Returns the SQL string with any parameters used embedded
*
* @return string
*/
public function getSqlWithParams()
{
$sql = $this->sql;
foreach ($this->parameters as $k => $v) {
$v = sprintf('<%s>', $v);
if (!is_numeric($k)) {
$sql = str_replace($k, $v, $sql);
} else {
$p = strpos($sql, '?');
$sql = substr($sql, 0, $p) . $v. substr($sql, $p + 1);
}
}
return $sql;
}
/**
* Returns the number of rows affected/returned
*
* @return int
*/
public function getRowCount()
{
return $this->rowCount;
}
/**
* Returns an array of parameters used with the query
*
* @return array
*/
public function getParameters()
{
return $this->parameters;
}
/**
* Returns the prepared statement id
*
* @return string
*/
public function getPreparedId()
{
return $this->preparedId;
}
/**
* Checks if this is a prepared statement
*
* @return boolean
*/
public function isPrepared()
{
return $this->preparedId !== null;
}
/**
* Returns the duration in seconds of the execution
*
* @return int
*/
public function getDuration()
{
return $this->duration;
}
/**
* Returns the peak memory usage during the execution
*
* @return int
*/
public function getMemoryUsage()
{
return $this->memoryUsage;
}
/**
* Checks if the statement was successful
*
* @return boolean
*/
public function isSuccess()
{
return $this->exception === null;
}
/**
* Returns the exception triggered
*
* @return \Exception
*/
public function getException()
{
return $this->exception;
}
/**
* Returns the exception's code
*
* @return string
*/
public function getErrorCode()
{
return $this->exception !== null ? $this->exception->getCode() : 0;
}
/**
* Returns the exception's message
*
* @return string
*/
public function getErrorMessage()
{
return $this->exception !== null ? $this->exception->getMessage() : '';
}
}

View File

@ -25,7 +25,7 @@ class RequestDataCollector extends DataCollector implements Renderable
foreach ($vars as $var) {
if (isset($GLOBALS[$var])) {
$data["$" . $var] = $this->varToString($GLOBALS[$var]);
$data["$" . $var] = $this->formatVar($GLOBALS[$var]);
}
}

View File

@ -64,7 +64,7 @@ class TimeDataCollector extends DataCollector implements Renderable
$this->measures[$name]['end'] = $end;
$this->measures[$name]['relative_end'] = $end - $this->requestEndTime;
$this->measures[$name]['duration'] = $end - $this->measures[$name]['start'];
$this->measures[$name]['duration_str'] = $this->toReadableString($this->measures[$name]['duration']);
$this->measures[$name]['duration_str'] = $this->formatDuration($this->measures[$name]['duration']);
}
/**
@ -123,17 +123,6 @@ class TimeDataCollector extends DataCollector implements Renderable
return microtime(true) - $this->requestStartTime;
}
/**
* Transforms a duration in seconds in a readable string
*
* @param float $value
* @return string
*/
public function toReadableString($value)
{
return round($value * 1000) . 'ms';
}
/**
* {@inheritDoc}
*/
@ -150,7 +139,7 @@ class TimeDataCollector extends DataCollector implements Renderable
'start' => $this->requestStartTime,
'end' => $this->requestEndTime,
'duration' => $this->getRequestDuration(),
'duration_str' => $this->toReadableString($this->getRequestDuration()),
'duration_str' => $this->formatDuration($this->getRequestDuration()),
'measures' => array_values($this->measures)
);
}

View File

@ -205,6 +205,7 @@ class JavascriptRenderer
* - icon: icon name
* - tooltip: string
* - widget: widget class name
* - title: tab title
* - map: a property name from the data to map the control to
* - default: a js string, default value of the data map
*
@ -375,12 +376,13 @@ class JavascriptRenderer
foreach ($controls as $name => $options) {
if (isset($options['widget'])) {
$js .= sprintf("%s.createTab(\"%s\", new %s());\n",
$js .= sprintf("%s.createTab(\"%s\", new %s()%s);\n",
$varname,
$name,
$options['widget']
$options['widget'],
isset($options['title']) ? sprintf(', "%s"', $options['title']) : ''
);
} else {
} else if (strpos($name, ':') === false) {
$js .= sprintf("%s.createIndicator(\"%s\", \"%s\", \"%s\");\n",
$varname,
$name,

View File

@ -15,6 +15,7 @@ use DebugBar\DataCollector\MessagesCollector;
use DebugBar\DataCollector\TimeDataCollector;
use DebugBar\DataCollector\RequestDataCollector;
use DebugBar\DataCollector\MemoryCollector;
use DebugBar\DataCollector\ExceptionsCollector;
/**
* Debug bar subclass which adds all included collectors
@ -31,5 +32,6 @@ class StandardDebugBar extends DebugBar
$this->addCollector(new RequestDataCollector());
$this->addCollector(new TimeDataCollector());
$this->addCollector(new MemoryCollector());
$this->addCollector(new ExceptionsCollector());
}
}

View File

@ -51,6 +51,19 @@
background-image: -ms-linear-gradient(bottom, rgb(173,173,173) 41%, rgb(209,209,209) 71%);
background-image: -webkit-gradient(linear, left bottom, left top, color-stop(0.41, rgb(173,173,173)), color-stop(0.71, rgb(209,209,209)));
}
.phpdebugbar-tab .badge {
display: none;
margin-left: 5px;
font-size: 11px;
padding: 1px 6px;
background: #ccc;
border-radius: 4px;
color: #555;
}
.phpdebugbar-tab .badge.important {
background: #ed6868;
color: white;
}
.phpdebugbar-close-btn {
display: none;
@ -126,6 +139,7 @@
.phpdebugbar-widgets-list .list-item {
padding: 3px 6px;
border-bottom: 1px solid #eee;
position: relative;
}
.phpdebugbar-widgets-list .list-item:hover {
background: #fafafa;
@ -249,3 +263,90 @@
top: 5px;
border-radius: 2px;
}
/* -------------------------------------- */
.phpdebugbar-widgets-exceptions .list-item {
cursor: pointer;
}
.phpdebugbar-widgets-exceptions .list-item .message {
display: block;
color: red;
}
.phpdebugbar-widgets-exceptions .list-item .filename {
display: block;
font-style: italic;
color: #555;
}
.phpdebugbar-widgets-exceptions .list-item .type {
display: block;
position: absolute;
right: 4px;
top: 4px;
font-weight: bold;
}
.phpdebugbar-widgets-exceptions .list-item .file {
display: none;
margin: 10px;
padding: 5px;
border: 1px solid #ddd;
font-family: monospace;
}
/* -------------------------------------- */
.phpdebugbar-widgets-sqlqueries .status {
font-family: monospace;
padding: 6px 6px;
border-bottom: 1px solid #ddd;
font-weight: bold;
color: #555;
background: #fafafa;
}
.phpdebugbar-widgets-sqlqueries .list-item.error {
color: red;
}
.phpdebugbar-widgets-sqlqueries .duration,
.phpdebugbar-widgets-sqlqueries .memory,
.phpdebugbar-widgets-sqlqueries .row-count,
.phpdebugbar-widgets-sqlqueries .stmt-id {
float: right;
margin-left: 8px;
color: #888;
}
.phpdebugbar-widgets-sqlqueries .status .duration,
.phpdebugbar-widgets-sqlqueries .status .memory,
.phpdebugbar-widgets-sqlqueries .status .row-count,
.phpdebugbar-widgets-sqlqueries .status .stmt-id {
color: #555;
}
.phpdebugbar-widgets-sqlqueries .duration:before,
.phpdebugbar-widgets-sqlqueries .memory:before,
.phpdebugbar-widgets-sqlqueries .row-count:before,
.phpdebugbar-widgets-sqlqueries .stmt-id:before {
font-family: FontAwesome;
margin-right: 4px;
font-size: 12px;
}
.phpdebugbar-widgets-sqlqueries .duration:before {
content: "\f017";
}
.phpdebugbar-widgets-sqlqueries .memory:before {
content: "\f085";
}
.phpdebugbar-widgets-sqlqueries .row-count:before {
content: "\f0ce";
}
.phpdebugbar-widgets-sqlqueries .stmt-id:before {
content: "\f08d";
}
.phpdebugbar-widgets-sqlqueries .list-item .error {
display: block;
font-weight: bold;
}

View File

@ -62,7 +62,9 @@ PhpDebugBar.DebugBar = (function($) {
* @param {Object} widget
*/
var Tab = function(title, widget) {
this.tab = $('<a href="javascript:" class="phpdebugbar-tab" />').text(title);
this.tab = $('<a href="javascript:" class="phpdebugbar-tab" />')
this.tabText = $('<span class="text" />').text(title).appendTo(this.tab);
this.badge = $('<span class="badge" />').appendTo(this.tab);
this.panel = $('<div class="phpdebugbar-panel" />');
this.replaceWidget(widget);
};
@ -77,6 +79,20 @@ PhpDebugBar.DebugBar = (function($) {
this.tab.text(text);
};
/**
* Sets the badge value of the tab
*
* @this {Tab}
* @param {String} value
*/
Tab.prototype.setBadgeValue = function(value) {
if (value === null) {
this.badge.hide();
} else {
this.badge.text(value).show();
}
};
/**
* Replaces the widget inside the panel
*
@ -544,7 +560,10 @@ PhpDebugBar.DebugBar = (function($) {
var self = this;
$.each(this.dataMap, function(key, def) {
var d = getDictValue(data, def[0], def[1]);
if (self.isIndicator(key)) {
if (key.indexOf(':') != -1) {
key = key.split(':')[0];
self.getTab(key).setBadgeValue(d);
} else if (self.isIndicator(key)) {
self.getIndicator(key).setText(d);
} else {
self.getTab(key).widget.setData(d);

View File

@ -354,6 +354,92 @@ PhpDebugBar.Widgets = (function($) {
widgets.TimelineWidget = TimelineWidget;
// ------------------------------------------------------------------
/**
* Widget for the displaying exceptions
*
* @this {ExceptionsWidget}
* @constructor
* @param {Object} data
*/
var ExceptionsWidget = function(data) {
this.element = $('<div class="phpdebugbar-widgets-exceptions" />');
this.list = new ListWidget(null, function(li, e) {
$('<span class="message" />').text(e.message).appendTo(li);
$('<span class="filename" />').text(e.file + "#" + e.line).appendTo(li);
$('<span class="type" />').text(e.type).appendTo(li);
var file = $('<div class="file" />').html(htmlize(e.surrounding_lines.join(""))).appendTo(li);
li.click(function() {
if (file.is(':visible')) {
file.hide();
} else {
file.show();
}
});
});
this.element.append(this.list.element);
if (data) {
this.setData(data);
}
};
ExceptionsWidget.prototype.setData = function(data) {
this.list.setData(data);
if (data.length == 1) {
this.list.element.children().first().find('.file').show();
}
};
widgets.ExceptionsWidget = ExceptionsWidget;
// ------------------------------------------------------------------
/**
* Widget for the displaying sql queries
*
* @this {SQLQueriesWidget}
* @constructor
* @param {Object} data
*/
var SQLQueriesWidget = function(data) {
this.element = $('<div class="phpdebugbar-widgets-sqlqueries" />');
this.status = $('<div class="status" />').appendTo(this.element);
this.list = new ListWidget(null, function(li, stmt) {
$('<span class="sql" />').text(stmt.sql).appendTo(li);
$('<span class="duration" title="Duration (s)" />').text(stmt.duration_str).appendTo(li);
$('<span class="memory" title="Peak memory usage" />').text(stmt.memory_str).appendTo(li);
if (!stmt.is_success) {
li.addClass('error');
li.append($('<span class="error" />').text("[" + stmt.error_code + "] " + stmt.error_message));
} else {
$('<span class="row-count" title="Row count" />').text(stmt.row_count).appendTo(li);
}
if (stmt.stmt_id) {
$('<span class="stmt-id" title="Prepared statement ID" />').text(stmt.stmt_id).appendTo(li);
}
});
this.element.append(this.list.element);
if (data) {
this.setData(data);
}
};
SQLQueriesWidget.prototype.setData = function(data) {
this.list.setData(data.statements);
this.status.empty()
.append($('<span />').text(data.nb_statements + " statements were executed" + (data.nb_failed_statements > 0 ? (", " + data.nb_failed_statements + " of which failed") : "")))
.append($('<span class="duration" title="Accumulated duration (s)" />').text(data.accumulated_duration_str))
.append($('<span class="memory" title="Peak memory usage" />').text(data.peak_memory_usage_str));
};
widgets.SQLQueriesWidget = SQLQueriesWidget;
// ------------------------------------------------------------------
return widgets;