Development

/branches/1.2/lib/debug/sfWebDebug.class.php

You must first sign up to be able to contribute.

root/branches/1.2/lib/debug/sfWebDebug.class.php

Revision 26968, 13.6 kB (checked in by FabianLange, 4 years ago)

[1.2] backport of r26957 fix for web debug toolbar handling svg elements

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