private static function dump($struct) { if (class_exists('Nette\\Diagnostics\\Dumper')) { return Nette\Diagnostics\Dumper::toText($struct); } return Nette\Diagnostics\Helpers::textDump($struct); }
/** * Function prints from where were method/function called * @author Filip Procházka <*****@*****.**> * * @param int $level * @param bool $return * @param bool $fullTrace */ function wc($level = 1, $return = FALSE, $fullTrace = FALSE) { if (Debugger::$productionMode) { return; } $o = function ($t) { return (isset($t->class) ? htmlspecialchars($t->class) . "->" : NULL) . htmlspecialchars($t->function) . '()'; }; $f = function ($t) { return isset($t->file) ? '(' . Helpers::editorLink($t->file, $t->line) . ')' : NULL; }; $trace = debug_backtrace(); $target = (object) $trace[$level]; $caller = (object) $trace[$level + 1]; $message = NULL; if ($fullTrace) { array_shift($trace); foreach ($trace as $call) { $message .= $o((object) $call) . " \n"; } } else { $message = $o($target) . " called from " . $o($caller) . $f($caller); } if ($return) { return strip_tags($message); } echo "<pre class='nette-dump'>" . nl2br($message) . "</pre>"; }
private function renderHtml() { $res = '<style>code, pre {white-space:nowrap} a {text-decoration:none} pre {color:gray;display:inline} big {color:red}</style><code>'; foreach ($this->list as $item) { $res .= Helpers::editorLink($item[0], $item[1]) . ' ' . str_replace(self::BOM, '<big>BOM</big>', Dumper::toHtml($item[2])) . "<br>\n"; } return $res . '</code>'; }
public static function initialize(Nette\Application\Application $application, Nette\Http\IRequest $httpRequest) { Debugger::$bar->addPanel(new self($application->getRouter(), $httpRequest)); Debugger::$blueScreen->addPanel(function ($e) use($application) { if ($e === NULL) { return array('tab' => 'Nette Application', 'panel' => '<h3>Requests</h3>' . Nette\Diagnostics\Helpers::clickableDump($application->getRequests()) . '<h3>Presenter</h3>' . Nette\Diagnostics\Helpers::clickableDump($application->getPresenter())); } }); }
public function getPanel() { $template = parent::getTemplate(); $template->setFile(__DIR__ . '/templates/panel.latte'); $template->identity = $this->identity; $template->user = $this->user; $template->dumper = function ($variable, $collapsed = false) { if (class_exists('Nette\\Diagnostics\\Dumper')) { return Dumper::toHtml($variable, [Dumper::COLLAPSE => $collapsed]); } // Nette 2.0 back compatibility return \Nette\Diagnostics\Helpers::clickableDump($variable, $collapsed); }; ob_start(); if ($this->parent) { $template->render(); } return ob_get_clean(); }
/** * Returns syntax highlighted source code. * @param string * @param int * @param int * @return string */ public static function highlightPhp($source, $line, $lines = 15, $vars = array()) { if (function_exists('ini_set')) { ini_set('highlight.comment', '#998; 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'); } $source = str_replace(array("\r\n", "\r"), "\n", $source); $source = explode("\n", highlight_string($source, TRUE)); $spans = 1; $out = $source[0]; // <code><span color=highlight.html> $source = explode('<br />', $source[1]); array_unshift($source, NULL); $start = $i = max(1, $line - floor($lines * 2 / 3)); while (--$i >= 1) { // find last highlighted block if (preg_match('#.*(</?span[^>]*>)#', $source[$i], $m)) { if ($m[1] !== '</span>') { $spans++; $out .= $m[1]; } break; } } $source = array_slice($source, $start, $lines, TRUE); end($source); $numWidth = strlen((string) key($source)); foreach ($source as $n => $s) { $spans += substr_count($s, '<span') - substr_count($s, '</span'); $s = str_replace(array("\r", "\n"), array('', ''), $s); preg_match_all('#<[^>]+>#', $s, $tags); if ($n == $line) { $out .= sprintf("<span class='highlight'>%{$numWidth}s: %s\n</span>%s", $n, strip_tags($s), implode('', $tags[0])); } else { $out .= sprintf("<span class='line'>%{$numWidth}s:</span> %s\n", $n, $s); } } $out .= str_repeat('</span>', $spans) . '</code>'; $out = preg_replace_callback('#">\\$(\\w+)( )?</span>#', function ($m) use($vars) { return isset($vars[$m[1]]) ? '" title="' . str_replace('"', '"', strip_tags(Helpers::htmlDump($vars[$m[1]]))) . $m[0] : $m[0]; }, $out); return "<pre><div>{$out}</div></pre>"; }
public function getPanel() { $this->disabled = TRUE; $s = ''; $h = 'htmlSpecialChars'; foreach ($this->queries as $i => $query) { list($sql, $params, $time, $rows, $connection, $source) = $query; $explain = NULL; // EXPLAIN is called here to work SELECT FOUND_ROWS() if ($this->explain && preg_match('#\\s*SELECT\\s#iA', $sql)) { try { $explain = $connection->queryArgs('EXPLAIN ' . $sql, $params)->fetchAll(); } catch (\PDOException $e) { } } $s .= '<tr><td>' . sprintf('%0.3f', $time * 1000); if ($explain) { static $counter; $counter++; $s .= "<br /><a href='#' class='nette-toggler' rel='#nette-DbConnectionPanel-row-{$counter}'>explain ►</a>"; } $s .= '</td><td class="nette-DbConnectionPanel-sql">' . Connection::highlightSql(Nette\Utils\Strings::truncate($sql, self::$maxLength)); if ($explain) { $s .= "<table id='nette-DbConnectionPanel-row-{$counter}' class='nette-collapsed'><tr>"; foreach ($explain[0] as $col => $foo) { $s .= "<th>{$h($col)}</th>"; } $s .= "</tr>"; foreach ($explain as $row) { $s .= "<tr>"; foreach ($row as $col) { $s .= "<td>{$h($col)}</td>"; } $s .= "</tr>"; } $s .= "</table>"; } if ($source) { $s .= Nette\Diagnostics\Helpers::editorLink($source[0], $source[1])->class('nette-DbConnectionPanel-source'); } $s .= '</td><td>'; foreach ($params as $param) { $s .= Debugger::dump($param, TRUE); } $s .= '</td><td>' . $rows . '</td></tr>'; } return empty($this->queries) ? '' : '<style> #nette-debug td.nette-DbConnectionPanel-sql { background: white !important } #nette-debug .nette-DbConnectionPanel-source { color: #BBB !important } #nette-debug nette-DbConnectionPanel tr table { margin: 8px 0; max-height: 150px; overflow:auto } </style> <h1>Queries: ' . count($this->queries) . ($this->totalTime ? ', time: ' . sprintf('%0.3f', $this->totalTime * 1000) . ' ms' : '') . '</h1> <div class="nette-inner nette-DbConnectionPanel"> <table> <tr><th>Time ms</th><th>SQL Statement</th><th>Params</th><th>Rows</th></tr>' . $s . ' </table> </div>'; }
/** * Handler to catch warnings and notices. * @param int level of the error raised * @param string error message * @param string file that the error was raised in * @param int line number the error was raised at * @param array an array of variables that existed in the scope the error was triggered in * @return bool FALSE to call normal error handler, NULL otherwise * @throws ErrorException * @internal */ public static function _errorHandler($severity, $message, $file, $line, $context) { if (self::$scream) { error_reporting(E_ALL | E_STRICT); } if (self::$lastError !== FALSE && ($severity & error_reporting()) === $severity) { // tryError mode self::$lastError = new \ErrorException($message, 0, $severity, $file, $line); return NULL; } if ($severity === E_RECOVERABLE_ERROR || $severity === E_USER_ERROR) { if (Helpers::findTrace(debug_backtrace(PHP_VERSION_ID >= 50306 ? DEBUG_BACKTRACE_IGNORE_ARGS : FALSE), '*::__toString')) { $previous = isset($context['e']) && $context['e'] instanceof \Exception ? $context['e'] : NULL; $e = new ErrorException($message, 0, $severity, $file, $line, $previous); $e->context = $context; self::_exceptionHandler($e); } $e = new ErrorException($message, 0, $severity, $file, $line); $e->context = $context; throw $e; } elseif (($severity & error_reporting()) !== $severity) { return FALSE; // calls normal error handler to fill-in error_get_last() } elseif (!self::$productionMode && (is_bool(self::$strictMode) ? self::$strictMode : (self::$strictMode & $severity) === $severity)) { $e = new ErrorException($message, 0, $severity, $file, $line); $e->context = $context; self::_exceptionHandler($e); } $message = 'PHP ' . (isset(self::$errorTypes[$severity]) ? self::$errorTypes[$severity] : 'Unknown error') . ": {$message}"; $count =& self::getBar()->getPanel(__CLASS__ . ':errors')->data["{$file}|{$line}|{$message}"]; if ($count++) { // repeated error return NULL; } elseif (self::$productionMode) { self::log("{$message} in {$file}:{$line}", self::ERROR); return NULL; } else { self::fireLog(new ErrorException($message, 0, $severity, $file, $line)); return self::isHtmlMode() ? NULL : FALSE; // FALSE calls normal error handler } }
public static function initializePanel(Nette\Application\Application $application) { Debugger::$blueScreen->addPanel(function ($e) use($application) { return $e ? NULL : array('tab' => 'Nette Application', 'panel' => '<h3>Requests</h3>' . Nette\Diagnostics\Helpers::clickableDump($application->getRequests()) . '<h3>Presenter</h3>' . Nette\Diagnostics\Helpers::clickableDump($application->getPresenter())); }); }
function getPanel() { ob_start(); ?> <style class="nette-debug">#nette-debug .nette-UserPanel pre{background:#FDF5CE;padding:.4em .7em;border:1px dotted silver;overflow:auto}</style> <div class="nette-UserPanel"> <h1><?php if ($this->user->isLoggedIn()) { ?> Logged in<?php } else { ?> Unlogged<?php } ?> </h1> <?php if ($this->user->getIdentity()) { echo Helpers::clickableDump($this->user->getIdentity()); } else { ?> <p>no identity</p><?php } ?> </div> <?php return ob_get_clean(); }
function getPanel() { ob_start(); $data = $this->data; if ($this->id === 'dumps') { ?> <style>#nette-debug .nette-DumpPanel h2{font:11pt/1.5 sans-serif;margin:0;padding:2px 8px;background:#3484d2;color:white}#nette-debug .nette-DumpPanel table{width:100%}#nette-debug .nette-DumpPanel a{color:#333;background:transparent}#nette-debug .nette-DumpPanel a abbr{font-family:sans-serif;color:#999}#nette-debug .nette-DumpPanel pre .php-array,#nette-debug .nette-DumpPanel pre .php-object{color:#c16549}</style> <h1>Dumped variables</h1> <div class="nette-inner nette-DumpPanel"> <?php foreach ($data as $item) { ?> <?php if ($item['title']) { ?> <h2><?php echo htmlspecialchars($item['title']); ?> </h2> <?php } ?> <table> <?php $i = 0; ?> <?php foreach ($item['dump'] as $key => $dump) { ?> <tr class="<?php echo $i++ % 2 ? 'nette-alt' : ''; ?> "> <th><?php echo htmlspecialchars($key); ?> </th> <td><?php echo $dump; ?> </td> </tr> <?php } ?> </table> <?php } ?> </div> <?php } elseif ($this->id === 'errors') { ?> <h1>Errors</h1> <div class="nette-inner"> <table> <?php $i = 0; foreach ($data as $item => $count) { list($message, $file, $line) = explode('|', $item); ?> <tr class="<?php echo $i++ % 2 ? 'nette-alt' : ''; ?> "> <td class="nette-right"><?php echo $count ? "{$count}×" : ''; ?> </td> <td><pre><?php echo htmlspecialchars($message), ' in ', Helpers::editorLink($file, $line), ':', $line; ?> </pre></td> </tr> <?php } ?> </table> </div> <?php } return ob_get_clean(); }
/** * @param array * @return string */ protected function processQuery(array $query) { $s = '<tr>'; $s .= '<td>' . sprintf('%0.3f', $query[self::TIME] * 1000); if ($this->doExplains && isset($query[self::EXPLAIN])) { static $counter; $counter++; $s .= "<br /><a href='#' class='nette-toggler' rel='#nette-Doctrine2Panel-row-{$counter}'>explain ►</a>"; } $s .= '</td>'; $s .= '<td class="nette-Doctrine2Panel-sql" style="min-width: 400px">' . Helpers::dumpSql($query[self::SQL]); if ($this->doExplains && isset($query[self::EXPLAIN])) { $s .= "<table id='nette-Doctrine2Panel-row-{$counter}' class='nette-collapsed'><tr>"; foreach ($query[self::EXPLAIN][0] as $col => $foo) { $s .= '<th>' . htmlSpecialChars($col) . '</th>'; } $s .= '</tr>'; foreach ($query[self::EXPLAIN] as $row) { $s .= '<tr>'; foreach ($row as $col) { $s .= '<td>' . htmlSpecialChars($col) . '</td>'; } $s .= '</tr>'; } $s .= '</table>'; } $s .= '</td>'; $s .= '<td>' . \Nette\Diagnostics\Helpers::clickableDump($query[self::PARAMS], TRUE) . '</td>'; $s .= '</tr>'; return $s; }
public static function dump($variable, $collapsed = false) { if (class_exists('Nette\\Diagnostics\\Dumper')) { return \Nette\Diagnostics\Dumper::toHtml($variable, [\Nette\Diagnostics\Dumper::COLLAPSE => $collapsed]); } // Nette 2.0 back compatibility return \Nette\Diagnostics\Helpers::clickableDump($variable, $collapsed); }
public function getPanel() { $this->disabled = TRUE; $s = ''; $h = 'htmlSpecialChars'; $counts = array(); $transactionTime = null; foreach ($this->queries as $i => $query) { list($sql, $params, $time, $rows, $connection, $source) = $query; $command = ''; if (preg_match('#^\\s*(\\w+)#', $sql, $m)) { $command = strtoupper($m[1]); @$counts[$command]++; } if ($sql == 'TRANSACTION BEGIN') { $transactionTime = 0; } elseif (preg_match('#TRANSACTION (COMMIT|ROLLBACK)#', $sql)) { $time = $transactionTime; $transactionTime = null; } elseif ($transactionTime !== null) { $transactionTime += $time; } foreach ((array) $params as $param) { if (!is_numeric($param)) { $param = str_replace("'", "\\'", $param); } $sql = preg_replace('#\\?#', "'{$param}'", $sql, 1); } $explain = NULL; // EXPLAIN is called here to work SELECT FOUND_ROWS() if ($this->explain && preg_match('#\\s*\\(?\\s*SELECT\\s#iA', $sql)) { try { $cmd = is_string($this->explain) ? $this->explain : 'EXPLAIN'; $explain = $connection->queryArgs("{$cmd} {$sql}", $params)->fetchAll(); } catch (PDOException $e) { } } $s .= "<tr class='nette-DbConnectionPanel-type-{$command}'><td>" . sprintf('%0.3f', $time * 1000); if ($explain) { static $counter; $counter++; $s .= "<br /><a href='#' class='nette-toggle-collapsed' data-ref='#nette-DbConnectionPanel-row-{$counter}'>explain </a>"; } $s .= '</td><td class="nette-DbConnectionPanel-sql">' . Helpers::dumpSql(self::$maxLength ? Nette\Utils\Strings::truncate($sql, self::$maxLength) : $sql); if ($explain) { $s .= "<table id='nette-DbConnectionPanel-row-{$counter}' class='nette-collapsed'><tr>"; foreach ($explain[0] as $col => $foo) { $s .= "<th>{$h($col)}</th>"; } $s .= "</tr>"; foreach ($explain as $row) { $s .= "<tr>"; foreach ($row as $col) { $s .= "<td>{$h($col)}</td>"; } $s .= "</tr>"; } $s .= "</table>"; } if ($source) { $s .= Nette\Diagnostics\Helpers::editorLink($source[0], $source[1])->class('nette-DbConnectionPanel-source'); } $s .= '</td>'; $s .= '<td>' . $rows . '</td></tr>'; } $c = ''; foreach ($counts as $command => $count) { $c .= "<tr><th>{$command}</th><td>{$count}</td><td><input type='checkbox' class='nette-DbConnectionPanel-type-switcher' name='{$command}' id='nette-DbConnectionPanel-type-{$command}' checked='checked' /></td></tr>"; } return empty($this->queries) ? '' : '<style> #nette-debug td.nette-DbConnectionPanel-sql { background: white !important } #nette-debug .nette-DbConnectionPanel-source { color: #BBB !important } </style> <script type="text/javascript"> (function() { var FW = typeof Tracy !== "undefined" ? Tracy : Nette; var $ = typeof FW.Q !== "undefined" ? FW.Q.factory : FW.Query.factory; $(".nette-DbConnectionPanel-type-switcher").bind("click", function(e) { var name = this.name; if (this.checked) { $(".nette-DbConnectionPanel-type-" + name).show(); } else { $(".nette-DbConnectionPanel-type-" + name).hide(); } }); })(); </script> <h1>Queries: ' . count($this->queries) . ($this->totalTime ? ', time: ' . sprintf('%0.3f', $this->totalTime * 1000) . ' ms' : '') . '</h1> <div class="nette-inner nette-DbConnectionPanel"> <table> <tr><th>Type</th><th>Count</th><th>Filter</th></tr>' . $c . ' </table> <br /> <table> <tr><th>Time ms</th><th>SQL Statement</th><th>Rows</th></tr>' . $s . ' </table> </div>'; }
/** * @param $presenter Presenter * @param $response PresenterResponse * @internal */ public function onShutdown($presenter, $response) { $this->response = $response; $application = Environment::getApplication(); $presenter = $application->getPresenter(); $request = $presenter->getRequest(); $httpRequest = Environment::getHttpRequest(); $entry = array(); if ($signal = $presenter->getSignal()) { $receiver = empty($signal[0]) ? $presenter->name : $signal[0]; $signal = $receiver . " :: " . $signal[1]; } if ($response !== NULL) { $rInfo = get_class($response); if ($response->getReflection()->hasMethod('getCode')) { $rInfo .= ' (' . $response->code . ')'; } } $entry['info']['presenter'] = $presenter->backlink(); $entry['info']['response'] = $response === NULL ? 'NO RESPONSE' : $rInfo; $entry['info']['uri'] = $httpRequest->getUrl(); $entry['info']['uriPath'] = $httpRequest->getUrl()->path; $entry['info']['request'] = $request->getMethod(); $entry['info']['signal'] = $signal; $entry['info']['time'] = number_format((microtime(TRUE) - Debugger::$time) * 1000, 1, '.', ' '); $entry['dumps']['HttpRequest'] = Helpers::clickableDump($httpRequest); $entry['dumps']['PresenterRequest'] = Helpers::clickableDump($request); $entry['dumps']['Presenter'] = Helpers::clickableDump($presenter); $entry['dumps']['PresenterResponse'] = Helpers::clickableDump($response); foreach (self::$dumps as $key => $dump) { if (is_numeric($key)) { $entry['dumps'][] = $dump; } else { $entry['dumps'][$key] = $dump; } } $session = Environment::getSession('debug/RequestsPanel'); if (!isset($session->logs)) { $session->logs = array(); } $session->logs[] = $entry; }
public function getPanel() { $this->disabled = TRUE; $s = ''; foreach ($this->queries as $query) { list($connection, $sql, $params, $source, $time, $rows, $error) = $query; $explain = NULL; // EXPLAIN is called here to work SELECT FOUND_ROWS() if (!$error && $this->explain && preg_match('#\\s*\\(?\\s*SELECT\\s#iA', $sql)) { try { $cmd = is_string($this->explain) ? $this->explain : 'EXPLAIN'; $explain = $connection->queryArgs("{$cmd} {$sql}", $params)->fetchAll(); } catch (\PDOException $e) { } } $s .= '<tr><td>'; if ($error) { $s .= '<span title="' . htmlSpecialChars($error, ENT_IGNORE | ENT_QUOTES) . '">ERROR</span>'; } elseif ($time !== NULL) { $s .= sprintf('%0.3f', $time * 1000); } if ($explain) { static $counter; $counter++; $s .= "<br /><a class='nette-toggle-collapsed' href='#nette-DbConnectionPanel-row-{$counter}'>explain</a>"; } $s .= '</td><td class="nette-DbConnectionPanel-sql">' . Helpers::dumpSql($sql, $params); if ($explain) { $s .= "<table id='nette-DbConnectionPanel-row-{$counter}' class='nette-collapsed'><tr>"; foreach ($explain[0] as $col => $foo) { $s .= '<th>' . htmlSpecialChars($col) . '</th>'; } $s .= "</tr>"; foreach ($explain as $row) { $s .= "<tr>"; foreach ($row as $col) { $s .= '<td>' . htmlSpecialChars($col) . '</td>'; } $s .= "</tr>"; } $s .= "</table>"; } if ($source) { $s .= Nette\Diagnostics\Helpers::editorLink($source[0], $source[1])->class('nette-DbConnectionPanel-source'); } $s .= '</td><td>' . $rows . '</td></tr>'; } return $this->count ? '<style class="nette-debug"> #nette-debug td.nette-DbConnectionPanel-sql { background: white !important } #nette-debug .nette-DbConnectionPanel-source { color: #BBB !important } </style> <h1 title="' . htmlSpecialChars($connection->getDsn()) . '">Queries: ' . $this->count . ($this->totalTime ? ', time: ' . sprintf('%0.3f', $this->totalTime * 1000) . ' ms' : '') . ', ' . htmlSpecialChars($this->name) . '</h1> <div class="nette-inner nette-DbConnectionPanel"> <table> <tr><th>Time ms</th><th>SQL Query</th><th>Rows</th></tr>' . $s . ' </table>' . (count($this->queries) < $this->count ? '<p>...and more</p>' : '') . '</div>' : ''; }
/** * @param \Exception $e * @return array */ public static function renderException($e) { if ($e instanceof PayPal\ErrorResponseException) { return array('tab' => 'PayPalRequest', 'panel' => '<p><b>Request:</b></p>' . Nette\Diagnostics\Helpers::clickableDump($e->getData(), TRUE) . '<p><b>Response:</b></p>' . Nette\Diagnostics\Helpers::clickableDump($e->getResponse(), TRUE)); } }
/** * Dumps information about a variable in Nette Debug Bar. * @param mixed variable to dump * @param string optional title * @return mixed variable itself */ public static function barDump($var, $title = NULL) { if (!self::$productionMode) { $dump = array(); foreach (is_array($var) ? $var : array('' => $var) as $key => $val) { $dump[$key] = Helpers::clickableDump($val); } self::$dumpPanel->data[] = array('title' => $title, 'dump' => $dump); } return $var; }
/** * @param array * @return string */ protected function processQuery(array $query) { $s = ''; $h = 'htmlSpecialChars'; list($sql, $params, $time, $rows, $connection, $source) = $query; $s .= '<tr><td>' . sprintf('%0.3f', $time * 1000); $s .= '</td><td class="nette-Doctrine2Panel-sql">' . Connection::highlightSql($sql); if ($source) { list($file, $line) = $source; if (Debugger::$editor) { $s .= \Nette\Diagnostics\Helpers::editorLink($file, $line); } else { $s .= "<span class='nette-Doctrine2Panel-source' title='{$h($file)}:$line'>" . $h(basename(dirname($file)) . '/' . basename($file)) . ":" . $line . "</span>"; } } $s .= '</td><td>'; $s .= \Nette\Diagnostics\Helpers::clickableDump($params, TRUE); $s .= '</td><td>' . $rows . '</td></tr>'; return $s; }