useFirebug = isset($_SERVER['HTTP_USER_AGENT']) && strpos($_SERVER['HTTP_USER_AGENT'], 'FirePHP/'); if (isset($config['filter'])) { $this->setFilter($config['filter']); } if (isset($config['explain'])) { $this->explainQuery = (bool) $config['explain']; } } /** * @param string filename * @return DibiProfiler provides a fluent interface */ public function setFile($file) { $this->file = $file; return $this; } /** * @param int * @return DibiProfiler provides a fluent interface */ public function setFilter($filter) { $this->filter = (int) $filter; return $this; } /** * Before event notification. * @param DibiConnection * @param int event name * @param string sql * @return int */ public function before(DibiConnection $connection, $event, $sql = NULL) { if ($event & self::QUERY) dibi::$numOfQueries++; dibi::$elapsedTime = FALSE; self::$tickets[] = array($connection, $event, trim($sql), -microtime(TRUE), NULL, NULL); end(self::$tickets); return key(self::$tickets); } /** * After event notification. * @param int * @param DibiResult * @return void */ public function after($ticket, $res = NULL) { if (!isset(self::$tickets[$ticket])) { throw new InvalidArgumentException('Bad ticket number.'); } $ticket = & self::$tickets[$ticket]; $ticket[3] += microtime(TRUE); list($connection, $event, $sql, $time) = $ticket; dibi::$elapsedTime = $time; dibi::$totalTime += $time; if (($event & $this->filter) === 0) return; if ($event & self::QUERY) { try { $ticket[4] = $count = $res instanceof DibiResult ? count($res) : '-'; } catch (Exception $e) { $count = '?'; } if (count(self::$fireTable) < self::$maxQueries) { self::$fireTable[] = array( sprintf('%0.3f', $time * 1000), strlen($sql) > self::$maxLength ? substr($sql, 0, self::$maxLength) . '...' : $sql, $count, $connection->getConfig('driver') . '/' . $connection->getConfig('name') ); if ($this->explainQuery && $event === self::SELECT) { $tmpSql = dibi::$sql; try { $ticket[5] = dibi::dump($connection->setProfiler(NULL)->nativeQuery('EXPLAIN ' . $sql), TRUE); } catch (DibiException $e) {} $connection->setProfiler($this); dibi::$sql = $tmpSql; } 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 = json_encode(array( array( 'Type' => 'TABLE', 'Label' => 'dibi profiler (' . dibi::$numOfQueries . ' SQL queries took ' . sprintf('%0.3f', dibi::$totalTime * 1000) . ' ms)', ), self::$fireTable, )); foreach (str_split($payload, 4990) as $num => $s) { $num++; header("X-Wf-dibi-1-1-d$num: |$s|\\"); // protocol-, structure-, plugin-, message-index } header("X-Wf-dibi-1-1-d$num: |$s|"); } } if ($this->file) { $this->writeFile( "OK: " . $sql . ($res instanceof DibiResult ? ";\n-- rows: " . $count : '') . "\n-- takes: " . sprintf('%0.3f', $time * 1000) . ' ms' . "\n-- driver: " . $connection->getConfig('driver') . '/' . $connection->getConfig('name') . "\n-- " . date('Y-m-d H:i:s') . "\n\n" ); } } } /** * After exception notification. * @param DibiDriverException * @return void */ public function exception(DibiDriverException $exception) { if ((self::EXCEPTION & $this->filter) === 0) return; if ($this->useFirebug) { // TODO: implement } if ($this->file) { $message = $exception->getMessage(); $code = $exception->getCode(); if ($code) { $message = "[$code] $message"; } $this->writeFile( "ERROR: $message" . "\n-- SQL: " . dibi::$sql . "\n-- driver: " //. $connection->getConfig('driver') . ";\n-- " . date('Y-m-d H:i:s') . "\n\n" ); } } private function writeFile($message) { $handle = fopen($this->file, 'a'); if (!$handle) return; // or throw exception? flock($handle, LOCK_EX); fwrite($handle, $message); 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 = "

Queries: " . dibi::$numOfQueries . (dibi::$totalTime === NULL ? '' : ', time: ' . sprintf('%0.3f', dibi::$totalTime * 1000) . ' ms') . "

"; $i = 0; $classes = array('class="nette-alt"', ''); foreach (self::$tickets as $ticket) { list($connection, $event, $sql, $time, $count, $explain) = $ticket; if (!($event & self::QUERY)) continue; $content .= " "; } $content .= '
TimeSQL StatementRowsConnection
" . sprintf('%0.3f', $time * 1000) . ($explain ? "
explain ►" : '') . "
" . dibi::dump(strlen($sql) > self::$maxLength ? substr($sql, 0, self::$maxLength) . '...' : $sql, TRUE) . ($explain ? "
{$explain}
" : '') . "
{$count} " . htmlSpecialChars($connection->getConfig('driver') . '/' . $connection->getConfig('name')) . "
'; return $content; } /** * Returns panel ID. * @return string */ public function getId() { return get_class($this); } }