Namespaces

  • Latte
    • Loaders
    • Macros
    • Runtime
  • Nette
    • Application
      • Responses
      • Routers
      • UI
    • Bridges
      • ApplicationDI
      • ApplicationLatte
      • ApplicationTracy
      • CacheDI
      • CacheLatte
      • DatabaseDI
      • DatabaseTracy
      • DITracy
      • FormsDI
      • FormsLatte
      • Framework
      • HttpDI
      • HttpTracy
      • MailDI
      • ReflectionDI
      • SecurityDI
      • SecurityTracy
    • Caching
      • Storages
    • ComponentModel
    • Database
      • Conventions
      • Drivers
      • Table
    • DI
      • Config
        • Adapters
      • Extensions
    • Forms
      • Controls
      • Rendering
    • Http
    • Iterators
    • Loaders
    • Localization
    • Mail
    • Neon
    • PhpGenerator
    • Reflection
    • Security
    • Utils
  • none
  • Tracy
    • Bridges
      • Nette

Classes

  • Bar
  • BlueScreen
  • Debugger
  • Dumper
  • FireLogger
  • Helpers
  • Logger
  • OutputDebugger

Interfaces

  • IBarPanel
  • ILogger
  • Overview
  • Namespace
  • Class
  • Tree
  • Deprecated
  1: <?php
  2: 
  3: /**
  4:  * This file is part of the Tracy (https://tracy.nette.org)
  5:  * Copyright (c) 2004 David Grudl (https://davidgrudl.com)
  6:  */
  7: 
  8: namespace Tracy;
  9: 
 10: 
 11: /**
 12:  * Debug Bar.
 13:  */
 14: class Bar
 15: {
 16:     /** @var IBarPanel[] */
 17:     private $panels = [];
 18: 
 19:     /** @var bool */
 20:     private $dispatched;
 21: 
 22: 
 23:     /**
 24:      * Add custom panel.
 25:      * @param  IBarPanel
 26:      * @param  string
 27:      * @return self
 28:      */
 29:     public function addPanel(IBarPanel $panel, $id = NULL)
 30:     {
 31:         if ($id === NULL) {
 32:             $c = 0;
 33:             do {
 34:                 $id = get_class($panel) . ($c++ ? "-$c" : '');
 35:             } while (isset($this->panels[$id]));
 36:         }
 37:         $this->panels[$id] = $panel;
 38:         return $this;
 39:     }
 40: 
 41: 
 42:     /**
 43:      * Returns panel with given id
 44:      * @param  string
 45:      * @return IBarPanel|NULL
 46:      */
 47:     public function getPanel($id)
 48:     {
 49:         return isset($this->panels[$id]) ? $this->panels[$id] : NULL;
 50:     }
 51: 
 52: 
 53:     /**
 54:      * Renders debug bar.
 55:      * @return void
 56:      */
 57:     public function render()
 58:     {
 59:         $useSession = $this->dispatched && session_status() === PHP_SESSION_ACTIVE;
 60:         $redirectQueue = & $_SESSION['_tracy']['redirect'];
 61: 
 62:         if (!Helpers::isHtmlMode() && !Helpers::isAjax()) {
 63:             return;
 64: 
 65:         } elseif (Helpers::isAjax()) {
 66:             $rows[] = (object) ['type' => 'ajax', 'panels' => $this->renderPanels('-ajax')];
 67:             $dumps = Dumper::fetchLiveData();
 68:             $contentId = $useSession ? $_SERVER['HTTP_X_TRACY_AJAX'] . '-ajax' : NULL;
 69: 
 70:         } elseif (preg_match('#^Location:#im', implode("\n", headers_list()))) { // redirect
 71:             $redirectQueue = array_slice((array) $redirectQueue, -10);
 72:             Dumper::fetchLiveData();
 73:             Dumper::$livePrefix = count($redirectQueue) . 'p';
 74:             $redirectQueue[] = [
 75:                 'panels' => $this->renderPanels('-r' . count($redirectQueue)),
 76:                 'dumps' => Dumper::fetchLiveData(),
 77:             ];
 78:             return;
 79: 
 80:         } else {
 81:             $rows[] = (object) ['type' => 'main', 'panels' => $this->renderPanels()];
 82:             $dumps = Dumper::fetchLiveData();
 83:             foreach (array_reverse((array) $redirectQueue) as $info) {
 84:                 $rows[] = (object) ['type' => 'redirect', 'panels' => $info['panels']];
 85:                 $dumps += $info['dumps'];
 86:             }
 87:             $redirectQueue = NULL;
 88:             $contentId = $useSession ? substr(md5(uniqid('', TRUE)), 0, 10) : NULL;
 89:         }
 90: 
 91:         ob_start(function () {});
 92:         require __DIR__ . '/assets/Bar/panels.phtml';
 93:         require __DIR__ . '/assets/Bar/bar.phtml';
 94:         $content = Helpers::fixEncoding(ob_get_clean());
 95: 
 96:         if ($contentId) {
 97:             $queue = & $_SESSION['_tracy']['bar'];
 98:             $queue = array_slice(array_filter((array) $queue), -5, NULL, TRUE);
 99:             $queue[$contentId] = ['content' => $content, 'dumps' => $dumps];
100:         }
101: 
102:         if (Helpers::isHtmlMode()) {
103:             $baseUrl = extension_loaded('xdebug') ? '?XDEBUG_SESSION_STOP=1&' : '?';
104:             require __DIR__ . '/assets/Bar/loader.phtml';
105:         }
106:     }
107: 
108: 
109:     /**
110:      * @return array
111:      */
112:     private function renderPanels($suffix = NULL)
113:     {
114:         set_error_handler(function ($severity, $message, $file, $line) {
115:             if (error_reporting() & $severity) {
116:                 throw new \ErrorException($message, 0, $severity, $file, $line);
117:             }
118:         });
119: 
120:         $obLevel = ob_get_level();
121:         $panels = [];
122: 
123:         foreach ($this->panels as $id => $panel) {
124:             $idHtml = preg_replace('#[^a-z0-9]+#i', '-', $id) . $suffix;
125:             try {
126:                 $tab = (string) $panel->getTab();
127:                 $panelHtml = $tab ? (string) $panel->getPanel() : NULL;
128:                 if ($tab && $panel instanceof \Nette\Diagnostics\IBarPanel) {
129:                     $e = new \Exception('Support for Nette\Diagnostics\IBarPanel is deprecated');
130:                 }
131: 
132:             } catch (\Throwable $e) {
133:             } catch (\Exception $e) {
134:             }
135:             if (isset($e)) {
136:                 while (ob_get_level() > $obLevel) { // restore ob-level if broken
137:                     ob_end_clean();
138:                 }
139:                 $idHtml = "error-$idHtml";
140:                 $tab = "Error in $id";
141:                 $panelHtml = "<h1>Error: $id</h1><div class='tracy-inner'>" . nl2br(Helpers::escapeHtml($e)) . '</div>';
142:                 unset($e);
143:             }
144:             $panels[] = (object) ['id' => $idHtml, 'tab' => $tab, 'panel' => $panelHtml];
145:         }
146: 
147:         restore_error_handler();
148:         return $panels;
149:     }
150: 
151: 
152:     /**
153:      * Renders debug bar assets.
154:      * @return bool
155:      */
156:     public function dispatchAssets()
157:     {
158:         if (isset($_GET['_tracy_bar']) && $_GET['_tracy_bar'] === 'assets') {
159:             header('Content-Type: text/javascript');
160:             header('Cache-Control: max-age=864000');
161:             header_remove('Pragma');
162:             header_remove('Set-Cookie');
163:             $css = file_get_contents(__DIR__ . '/assets/Bar/bar.css')
164:                 . file_get_contents(__DIR__ . '/assets/Toggle/toggle.css')
165:                 . file_get_contents(__DIR__ . '/assets/Dumper/dumper.css')
166:                 . file_get_contents(__DIR__ . '/assets/BlueScreen/bluescreen.css');
167:             $js = file_get_contents(__DIR__ . '/assets/Bar/bar.js')
168:                 . file_get_contents(__DIR__ . '/assets/Toggle/toggle.js')
169:                 . file_get_contents(__DIR__ . '/assets/Dumper/dumper.js')
170:                 . file_get_contents(__DIR__ . '/assets/BlueScreen/bluescreen.js');
171:             echo 'localStorage.setItem("tracy-style", ' . json_encode($css) . ');';
172:             echo 'localStorage.setItem("tracy-script", ' . json_encode($js) . ');';
173:             echo 'localStorage.setItem("tracy-version", ' . json_encode(Debugger::VERSION) . ');';
174:             return TRUE;
175:         }
176:     }
177: 
178: 
179:     /**
180:      * Renders debug bar content.
181:      * @return bool
182:      */
183:     public function dispatchContent()
184:     {
185:         $this->dispatched = TRUE;
186:         if (Helpers::isAjax()) {
187:             header('X-Tracy-Ajax: 1'); // session must be already locked
188:         }
189:         if (preg_match('#^content(-ajax)?.(\w+)$#', isset($_GET['_tracy_bar']) ? $_GET['_tracy_bar'] : '', $m)) {
190:             $session = & $_SESSION['_tracy']['bar'][$m[2] . $m[1]];
191:             header('Content-Type: text/javascript');
192:             header('Cache-Control: max-age=60');
193:             header_remove('Set-Cookie');
194:             if ($session) {
195:                 $method = $m[1] ? 'loadAjax' : 'init';
196:                 echo "Tracy.Debug.$method(", json_encode($session['content']), ', ', json_encode($session['dumps']), ');';
197:                 $session = NULL;
198:             }
199:             $session = & $_SESSION['_tracy']['bluescreen'][$m[2]];
200:             if ($session) {
201:                 echo "Tracy.BlueScreen.loadAjax(", json_encode($session['content']), ', ', json_encode($session['dumps']), ');';
202:                 $session = NULL;
203:             }
204:             return TRUE;
205:         }
206:     }
207: 
208: }
209: 
Nette 2.4-20161109 API API documentation generated by ApiGen 2.8.0