PageRenderTime 50ms CodeModel.GetById 18ms RepoModel.GetById 1ms app.codeStats 0ms

/lib/debug/sfWebDebug.class.php

https://github.com/bheneka/gitta
PHP | 820 lines | 597 code | 92 blank | 131 comment | 62 complexity | 66b5be144c8c9d036269563a9cce3a1a MD5 | raw file
  1. <?php
  2. /*
  3. * This file is part of the symfony package.
  4. * (c) 2004-2006 Fabien Potencier <fabien.potencier@symfony-project.com>
  5. *
  6. * For the full copyright and license information, please view the LICENSE
  7. * file that was distributed with this source code.
  8. */
  9. /**
  10. * sfWebDebug creates debug information for easy debugging in the browser.
  11. *
  12. * @package symfony
  13. * @subpackage debug
  14. * @author Fabien Potencier <fabien.potencier@symfony-project.com>
  15. * @version SVN: $Id$
  16. */
  17. class sfWebDebug
  18. {
  19. protected
  20. $dispatcher = null,
  21. $logger = null,
  22. $options = array(),
  23. $panels = array();
  24. /**
  25. * Constructor.
  26. *
  27. * Available options:
  28. *
  29. * * image_root_path: The image root path
  30. * * request_parameters: The current request parameters
  31. *
  32. * @param sfEventDispatcher $dispatcher The event dispatcher
  33. * @param sfVarLogger $logger The logger
  34. * @param array $options An array of options
  35. */
  36. public function __construct(sfEventDispatcher $dispatcher, sfVarLogger $logger, array $options = array())
  37. {
  38. $this->dispatcher = $dispatcher;
  39. $this->logger = $logger;
  40. $this->options = $options;
  41. if (!isset($this->options['image_root_path']))
  42. {
  43. $this->options['image_root_path'] = '';
  44. }
  45. if (!isset($this->options['request_parameters']))
  46. {
  47. $this->options['request_parameters'] = array();
  48. }
  49. $this->configure();
  50. $this->dispatcher->notify(new sfEvent($this, 'debug.web.load_panels'));
  51. }
  52. /**
  53. * Configures the web debug toolbar.
  54. */
  55. public function configure()
  56. {
  57. $this->setPanel('symfony_version', new sfWebDebugPanelSymfonyVersion($this));
  58. if (sfConfig::get('sf_debug') && sfConfig::get('sf_cache'))
  59. {
  60. $this->setPanel('cache', new sfWebDebugPanelCache($this));
  61. }
  62. if (sfConfig::get('sf_logging_enabled'))
  63. {
  64. $this->setPanel('config', new sfWebDebugPanelConfig($this));
  65. $this->setPanel('view', new sfWebDebugPanelView($this));
  66. }
  67. $this->setPanel('logs', new sfWebDebugPanelLogs($this));
  68. $this->setPanel('memory', new sfWebDebugPanelMemory($this));
  69. if (sfConfig::get('sf_debug'))
  70. {
  71. $this->setPanel('time', new sfWebDebugPanelTimer($this));
  72. }
  73. $this->setPanel('mailer', new sfWebDebugPanelMailer($this));
  74. }
  75. /**
  76. * Gets the logger.
  77. *
  78. * @return sfVarLogger The logger instance
  79. */
  80. public function getLogger()
  81. {
  82. return $this->logger;
  83. }
  84. /**
  85. * Gets the event dispatcher.
  86. *
  87. * @return sfEventDispatcher The event dispatcher
  88. */
  89. public function getEventDispatcher()
  90. {
  91. return $this->dispatcher;
  92. }
  93. /**
  94. * Gets the registered panels.
  95. *
  96. * @return array The panels
  97. */
  98. public function getPanels()
  99. {
  100. return $this->panels;
  101. }
  102. /**
  103. * Sets a panel by name.
  104. *
  105. * @param string $name The panel name
  106. * @param sfWebDebugPanel $panel The panel
  107. */
  108. public function setPanel($name, sfWebDebugPanel $panel)
  109. {
  110. $this->panels[$name] = $panel;
  111. }
  112. /**
  113. * Removes a panel by name.
  114. *
  115. * @param string $name The panel name
  116. */
  117. public function removePanel($name)
  118. {
  119. unset($this->panels[$name]);
  120. }
  121. /**
  122. * Gets an option value by name.
  123. *
  124. * @param string $name The option name
  125. *
  126. * @return mixed The option value
  127. */
  128. public function getOption($name, $default = null)
  129. {
  130. return isset($this->options[$name]) ? $this->options[$name] : $default;
  131. }
  132. /**
  133. * Injects the web debug toolbar into a given HTML string.
  134. *
  135. * @param string $content The HTML content
  136. *
  137. * @return string The content with the web debug toolbar injected
  138. */
  139. public function injectToolbar($content)
  140. {
  141. if (function_exists('mb_stripos'))
  142. {
  143. $posFunction = 'mb_stripos';
  144. $posrFunction = 'mb_strripos';
  145. $substrFunction = 'mb_substr';
  146. }
  147. else
  148. {
  149. $posFunction = 'stripos';
  150. $posrFunction = 'strripos';
  151. $substrFunction = 'substr';
  152. }
  153. if (false !== $pos = $posFunction($content, '</head>'))
  154. {
  155. $styles = '<style type="text/css">'.str_replace(array("\r", "\n"), ' ', $this->getStylesheet()).'</style>';
  156. $content = $substrFunction($content, 0, $pos).$styles.$substrFunction($content, $pos);
  157. }
  158. $debug = $this->asHtml();
  159. if (false === $pos = $posrFunction($content, '</body>'))
  160. {
  161. $content .= $debug;
  162. }
  163. else
  164. {
  165. $content = $substrFunction($content, 0, $pos).'<script type="text/javascript">'.$this->getJavascript().'</script>'.$debug.$substrFunction($content, $pos);
  166. }
  167. return $content;
  168. }
  169. /**
  170. * Returns the web debug toolbar as HTML.
  171. *
  172. * @return string The web debug toolbar HTML
  173. */
  174. public function asHtml()
  175. {
  176. $current = isset($this->options['request_parameters']['sfWebDebugPanel']) ? $this->options['request_parameters']['sfWebDebugPanel'] : null;
  177. $titles = array();
  178. $panels = array();
  179. foreach ($this->panels as $name => $panel)
  180. {
  181. if ($title = $panel->getTitle())
  182. {
  183. if (($content = $panel->getPanelContent()) || $panel->getTitleUrl())
  184. {
  185. $id = sprintf('sfWebDebug%sDetails', $name);
  186. $titles[] = sprintf('<li%s><a title="%s" href="%s"%s>%s</a></li>',
  187. $panel->getStatus() ? ' class="sfWebDebug'.ucfirst($this->getPriority($panel->getStatus())).'"' : '',
  188. $panel->getPanelTitle(),
  189. $panel->getTitleUrl() ? $panel->getTitleUrl() : '#',
  190. $panel->getTitleUrl() ? '' : ' onclick="sfWebDebugShowDetailsFor(\''.$id.'\'); return false;"',
  191. $title
  192. );
  193. $panels[] = sprintf('<div id="%s" class="sfWebDebugTop" style="display:%s"><h1>%s</h1>%s</div>',
  194. $id,
  195. $name == $current ? 'block' : 'none',
  196. $panel->getPanelTitle(),
  197. $content
  198. );
  199. }
  200. else
  201. {
  202. $titles[] = sprintf('<li>%s</li>', $title);
  203. }
  204. }
  205. }
  206. return '
  207. <div id="sfWebDebug">
  208. <div id="sfWebDebugBar">
  209. <a href="#" onclick="sfWebDebugToggleMenu(); return false;"><img src="'.$this->options['image_root_path'].'/sf.png" alt="Debug toolbar" /></a>
  210. <ul id="sfWebDebugDetails" class="sfWebDebugMenu">
  211. '.implode("\n", $titles).'
  212. <li class="last">
  213. <a href="#" onclick="document.getElementById(\'sfWebDebug\').style.display=\'none\'; return false;"><img src="'.$this->options['image_root_path'].'/close.png" alt="Close" /></a>
  214. </li>
  215. </ul>
  216. </div>
  217. '.implode("\n", $panels).'
  218. </div>
  219. ';
  220. }
  221. /**
  222. * Converts a priority value to a string.
  223. *
  224. * @param integer $value The priority value
  225. *
  226. * @return string The priority as a string
  227. */
  228. public function getPriority($value)
  229. {
  230. if ($value >= sfLogger::INFO)
  231. {
  232. return 'info';
  233. }
  234. else if ($value >= sfLogger::WARNING)
  235. {
  236. return 'warning';
  237. }
  238. else
  239. {
  240. return 'error';
  241. }
  242. }
  243. /**
  244. * Gets the javascript code to inject in the head tag.
  245. *
  246. * @param string The javascript code
  247. */
  248. public function getJavascript()
  249. {
  250. return <<<EOF
  251. /* <![CDATA[ */
  252. function sfWebDebugGetElementsByClassName(strClass, strTag, objContElm)
  253. {
  254. // http://muffinresearch.co.uk/archives/2006/04/29/getelementsbyclassname-deluxe-edition/
  255. strTag = strTag || "*";
  256. objContElm = objContElm || document;
  257. var objColl = (strTag == '*' && document.all) ? document.all : objContElm.getElementsByTagName(strTag);
  258. var arr = new Array();
  259. var delim = strClass.indexOf('|') != -1 ? '|' : ' ';
  260. var arrClass = strClass.split(delim);
  261. var j = objColl.length;
  262. for (var i = 0; i < j; i++) {
  263. if(objColl[i].className == undefined) continue;
  264. var arrObjClass = objColl[i].className.split ? objColl[i].className.split(' ') : [];
  265. if (delim == ' ' && arrClass.length > arrObjClass.length) continue;
  266. var c = 0;
  267. comparisonLoop:
  268. {
  269. var l = arrObjClass.length;
  270. for (var k = 0; k < l; k++) {
  271. var n = arrClass.length;
  272. for (var m = 0; m < n; m++) {
  273. if (arrClass[m] == arrObjClass[k]) c++;
  274. if (( delim == '|' && c == 1) || (delim == ' ' && c == arrClass.length)) {
  275. arr.push(objColl[i]);
  276. break comparisonLoop;
  277. }
  278. }
  279. }
  280. }
  281. }
  282. return arr;
  283. }
  284. function sfWebDebugToggleMenu()
  285. {
  286. var element = document.getElementById('sfWebDebugDetails');
  287. var cacheElements = sfWebDebugGetElementsByClassName('sfWebDebugCache');
  288. var mainCacheElements = sfWebDebugGetElementsByClassName('sfWebDebugActionCache');
  289. var panelElements = sfWebDebugGetElementsByClassName('sfWebDebugTop');
  290. if (element.style.display != 'none')
  291. {
  292. for (var i = 0; i < panelElements.length; ++i)
  293. {
  294. panelElements[i].style.display = 'none';
  295. }
  296. // hide all cache information
  297. for (var i = 0; i < cacheElements.length; ++i)
  298. {
  299. cacheElements[i].style.display = 'none';
  300. }
  301. for (var i = 0; i < mainCacheElements.length; ++i)
  302. {
  303. mainCacheElements[i].style.border = 'none';
  304. }
  305. }
  306. else
  307. {
  308. for (var i = 0; i < cacheElements.length; ++i)
  309. {
  310. cacheElements[i].style.display = '';
  311. }
  312. for (var i = 0; i < mainCacheElements.length; ++i)
  313. {
  314. mainCacheElements[i].style.border = '1px solid #f00';
  315. }
  316. }
  317. sfWebDebugToggle('sfWebDebugDetails');
  318. sfWebDebugToggle('sfWebDebugShowMenu');
  319. sfWebDebugToggle('sfWebDebugHideMenu');
  320. }
  321. function sfWebDebugShowDetailsFor(element)
  322. {
  323. if (typeof element == 'string')
  324. element = document.getElementById(element);
  325. var panelElements = sfWebDebugGetElementsByClassName('sfWebDebugTop');
  326. for (var i = 0; i < panelElements.length; ++i)
  327. {
  328. if (panelElements[i] != element)
  329. {
  330. panelElements[i].style.display = 'none';
  331. }
  332. }
  333. sfWebDebugToggle(element);
  334. }
  335. function sfWebDebugToggle(element)
  336. {
  337. if (typeof element == 'string')
  338. element = document.getElementById(element);
  339. if (element)
  340. element.style.display = element.style.display == 'none' ? '' : 'none';
  341. }
  342. function sfWebDebugToggleMessages(klass)
  343. {
  344. var elements = sfWebDebugGetElementsByClassName(klass);
  345. var x = elements.length;
  346. for (var i = 0; i < x; ++i)
  347. {
  348. sfWebDebugToggle(elements[i]);
  349. }
  350. }
  351. function sfWebDebugToggleAllLogLines(show, klass)
  352. {
  353. var elements = sfWebDebugGetElementsByClassName(klass);
  354. var x = elements.length;
  355. for (var i = 0; i < x; ++i)
  356. {
  357. elements[i].style.display = show ? '' : 'none';
  358. }
  359. }
  360. function sfWebDebugShowOnlyLogLines(type)
  361. {
  362. var types = new Array();
  363. types[0] = 'info';
  364. types[1] = 'warning';
  365. types[2] = 'error';
  366. for (klass in types)
  367. {
  368. var elements = sfWebDebugGetElementsByClassName('sfWebDebug' + types[klass].substring(0, 1).toUpperCase() + types[klass].substring(1, types[klass].length));
  369. var x = elements.length;
  370. for (var i = 0; i < x; ++i)
  371. {
  372. if ('tr' == elements[i].tagName.toLowerCase())
  373. {
  374. elements[i].style.display = (type == types[klass]) ? '' : 'none';
  375. }
  376. }
  377. }
  378. }
  379. /* ]]> */
  380. EOF;
  381. }
  382. /**
  383. * Gets the stylesheet code to inject in the head tag.
  384. *
  385. * @param string The stylesheet code
  386. */
  387. public function getStylesheet()
  388. {
  389. return <<<EOF
  390. #sfWebDebug
  391. {
  392. padding: 0;
  393. margin: 0;
  394. font-family: Arial, sans-serif;
  395. font-size: 12px;
  396. color: #333;
  397. text-align: left;
  398. line-height: 12px;
  399. }
  400. #sfWebDebug a, #sfWebDebug a:hover
  401. {
  402. text-decoration: none;
  403. border: none;
  404. background-color: transparent;
  405. color: #000;
  406. }
  407. #sfWebDebug img
  408. {
  409. float: none;
  410. margin: 0;
  411. border: 0;
  412. display: inline;
  413. }
  414. #sfWebDebugBar
  415. {
  416. position: absolute;
  417. margin: 0;
  418. padding: 1px 0;
  419. right: 0px;
  420. top: 0px;
  421. opacity: 0.80;
  422. filter: alpha(opacity:80);
  423. z-index: 10000;
  424. white-space: nowrap;
  425. background-color: #ddd;
  426. }
  427. #sfWebDebugBar[id]
  428. {
  429. position: fixed;
  430. }
  431. #sfWebDebugBar img
  432. {
  433. vertical-align: middle;
  434. }
  435. #sfWebDebugBar .sfWebDebugMenu
  436. {
  437. padding: 5px;
  438. padding-left: 0;
  439. display: inline;
  440. margin: 0;
  441. }
  442. #sfWebDebugBar .sfWebDebugMenu li
  443. {
  444. display: inline;
  445. list-style: none;
  446. margin: 0;
  447. padding: 0 6px;
  448. }
  449. #sfWebDebugBar .sfWebDebugMenu li.last
  450. {
  451. margin: 0;
  452. padding: 0;
  453. border: 0;
  454. }
  455. #sfWebDebugDatabaseDetails li
  456. {
  457. margin: 0;
  458. margin-left: 30px;
  459. padding: 5px 0;
  460. }
  461. #sfWebDebugShortMessages li
  462. {
  463. margin-bottom: 10px;
  464. padding: 5px;
  465. background-color: #ddd;
  466. }
  467. #sfWebDebugShortMessages li
  468. {
  469. list-style: none;
  470. }
  471. #sfWebDebugDetails
  472. {
  473. margin-right: 7px;
  474. }
  475. #sfWebDebug pre
  476. {
  477. line-height: 1.3;
  478. margin-bottom: 10px;
  479. }
  480. #sfWebDebug h1
  481. {
  482. font-size: 16px;
  483. font-weight: bold;
  484. margin: 20px 0;
  485. padding: 0;
  486. border: 0px;
  487. background-color: #eee;
  488. }
  489. #sfWebDebug h2
  490. {
  491. font-size: 14px;
  492. font-weight: bold;
  493. margin: 10px 0;
  494. padding: 0;
  495. border: 0px;
  496. background: none;
  497. }
  498. #sfWebDebug h3
  499. {
  500. font-size: 12px;
  501. font-weight: bold;
  502. margin: 10px 0;
  503. padding: 0;
  504. border: 0px;
  505. background: none;
  506. }
  507. #sfWebDebug .sfWebDebugTop
  508. {
  509. position: absolute;
  510. left: 0px;
  511. top: 0px;
  512. width: 98%;
  513. padding: 0 1%;
  514. margin: 0;
  515. z-index: 9999;
  516. background-color: #efefef;
  517. border-bottom: 1px solid #aaa;
  518. }
  519. #sfWebDebugLog
  520. {
  521. margin: 0;
  522. padding: 3px;
  523. font-size: 11px;
  524. }
  525. #sfWebDebugLogMenu
  526. {
  527. margin-bottom: 5px;
  528. }
  529. #sfWebDebugLogMenu li
  530. {
  531. display: inline;
  532. list-style: none;
  533. margin: 0;
  534. padding: 0 5px;
  535. border-right: 1px solid #aaa;
  536. }
  537. #sfWebDebugConfigSummary
  538. {
  539. display: inline;
  540. padding: 5px;
  541. background-color: #ddd;
  542. border: 1px solid #aaa;
  543. margin: 20px 0;
  544. }
  545. #sfWebDebugConfigSummary li
  546. {
  547. list-style: none;
  548. display: inline;
  549. margin: 0;
  550. padding: 0 5px;
  551. }
  552. #sfWebDebugConfigSummary li.last
  553. {
  554. border: 0;
  555. }
  556. .sfWebDebugInfo, .sfWebDebugInfo td
  557. {
  558. background-color: #ddd;
  559. }
  560. .sfWebDebugWarning, .sfWebDebugWarning td
  561. {
  562. background-color: orange !important;
  563. }
  564. .sfWebDebugError, .sfWebDebugError td
  565. {
  566. background-color: #f99 !important;
  567. }
  568. .sfWebDebugLogNumber
  569. {
  570. width: 1%;
  571. }
  572. .sfWebDebugLogType
  573. {
  574. width: 1%;
  575. white-space: nowrap;
  576. }
  577. .sfWebDebugLogType, #sfWebDebug .sfWebDebugLogType a
  578. {
  579. color: darkgreen;
  580. }
  581. #sfWebDebug .sfWebDebugLogType a:hover
  582. {
  583. text-decoration: underline;
  584. }
  585. .sfWebDebugLogInfo
  586. {
  587. color: blue;
  588. }
  589. .ison
  590. {
  591. color: #3f3;
  592. margin-right: 5px;
  593. }
  594. .isoff
  595. {
  596. color: #f33;
  597. margin-right: 5px;
  598. text-decoration: line-through;
  599. }
  600. .sfWebDebugLogs
  601. {
  602. padding: 0;
  603. margin: 0;
  604. border: 1px solid #999;
  605. font-family: Arial;
  606. font-size: 11px;
  607. }
  608. .sfWebDebugLogs tr
  609. {
  610. padding: 0;
  611. margin: 0;
  612. border: 0;
  613. }
  614. .sfWebDebugLogs td
  615. {
  616. margin: 0;
  617. border: 0;
  618. padding: 1px 3px;
  619. vertical-align: top;
  620. }
  621. .sfWebDebugLogs th
  622. {
  623. margin: 0;
  624. border: 0;
  625. padding: 3px 5px;
  626. vertical-align: top;
  627. background-color: #999;
  628. color: #eee;
  629. white-space: nowrap;
  630. }
  631. .sfWebDebugDebugInfo
  632. {
  633. color: #999;
  634. font-size: 11px;
  635. margin: 5px 0 5px 10px;
  636. padding: 2px 0 2px 5px;
  637. border-left: 1px solid #aaa;
  638. line-height: 1.25em;
  639. }
  640. .sfWebDebugDebugInfo .sfWebDebugLogInfo,
  641. .sfWebDebugDebugInfo a.sfWebDebugFileLink
  642. {
  643. color: #333 !important;
  644. }
  645. .sfWebDebugCache
  646. {
  647. padding: 0;
  648. margin: 0;
  649. font-family: Arial;
  650. position: absolute;
  651. overflow: hidden;
  652. z-index: 995;
  653. font-size: 9px;
  654. padding: 2px;
  655. filter:alpha(opacity=85);
  656. -moz-opacity:0.85;
  657. opacity: 0.85;
  658. }
  659. #sfWebDebugSymfonyVersion
  660. {
  661. margin-left: 0;
  662. padding: 1px 4px;
  663. background-color: #666;
  664. color: #fff;
  665. }
  666. #sfWebDebugviewDetails ul
  667. {
  668. padding-left: 2em;
  669. margin: .5em 0;
  670. list-style: none;
  671. }
  672. #sfWebDebugviewDetails li
  673. {
  674. margin-bottom: .5em;
  675. }
  676. #sfWebDebug .sfWebDebugDataType,
  677. #sfWebDebug .sfWebDebugDataType a
  678. {
  679. color: #666;
  680. font-style: italic;
  681. }
  682. #sfWebDebug .sfWebDebugDataType a:hover
  683. {
  684. text-decoration: underline;
  685. }
  686. #sfWebDebugDatabaseLogs
  687. {
  688. margin-bottom: 10px;
  689. }
  690. #sfWebDebugDatabaseLogs ol
  691. {
  692. margin: 0;
  693. padding: 0;
  694. margin-left: 20px;
  695. list-style: decimal;
  696. }
  697. #sfWebDebugDatabaseLogs li
  698. {
  699. padding: 6px;
  700. }
  701. #sfWebDebugDatabaseLogs li:nth-child(odd)
  702. {
  703. background-color: #CCC;
  704. }
  705. .sfWebDebugDatabaseQuery
  706. {
  707. margin-bottom: .5em;
  708. margin-top: 0;
  709. }
  710. .sfWebDebugDatabaseLogInfo
  711. {
  712. color: #666;
  713. font-size: 11px;
  714. }
  715. .sfWebDebugDatabaseQuery .sfWebDebugLogInfo
  716. {
  717. color: #909;
  718. font-weight: bold;
  719. }
  720. .sfWebDebugHighlight
  721. {
  722. background: #FFC;
  723. }
  724. EOF;
  725. }
  726. }