Development

/branches/1.3/lib/log/sfWebDebugLogger.class.php

You must first sign up to be able to contribute.

root/branches/1.3/lib/log/sfWebDebugLogger.class.php

Revision 30790, 5.5 kB (checked in by Kris.Wallsmith, 4 years ago)

[1.3, 1.4] fixed logging of PHP errors to the WDT when error messages include a "%" character

  • Property svn:mime-type set to text/x-php
  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
Line 
1 <?php
2
3 /*
4  * This file is part of the symfony package.
5  * (c) 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  * sfWebDebugLogger logs messages into the web debug toolbar.
13  *
14  * @package    symfony
15  * @subpackage log
16  * @author     Fabien Potencier <fabien.potencier@symfony-project.com>
17  * @version    SVN: $Id$
18  */
19 class sfWebDebugLogger extends sfVarLogger
20 {
21   protected
22     $context       = null,
23     $webDebugClass = null,
24     $webDebug      = null;
25
26   /**
27    * Initializes this logger.
28    *
29    * Available options:
30    *
31    *  * web_debug_class: The web debug class (sfWebDebug by default)
32    *
33    * @param  sfEventDispatcher $dispatcher  A sfEventDispatcher instance
34    * @param  array             $options     An array of options.
35    *
36    * @return Boolean           true, if initialization completes successfully, otherwise false.
37    *
38    * @see sfVarLogger
39    */
40   public function initialize(sfEventDispatcher $dispatcher, $options = array())
41   {
42     $this->context = sfContext::getInstance();
43
44     $this->webDebugClass = isset($options['web_debug_class']) ? $options['web_debug_class'] : 'sfWebDebug';
45
46     if (sfConfig::get('sf_web_debug'))
47     {
48       $dispatcher->connect('context.load_factories', array($this, 'listenForLoadFactories'));
49       $dispatcher->connect('response.filter_content', array($this, 'filterResponseContent'));
50     }
51
52     $this->registerErrorHandler();
53
54     return parent::initialize($dispatcher, $options);
55   }
56
57   /**
58    * Registers logger with PHP error handler.
59    */
60   protected function registerErrorHandler()
61   {
62     set_error_handler(array($this,'handlePhpError'));
63   }
64
65   /**
66    * PHP error handler send PHP errors to log.
67    *
68    * PHP user space error handler can not handle E_ERROR, E_PARSE,
69    * E_CORE_ERROR, E_CORE_WARNING, E_COMPILE_ERROR, E_COMPILE_WARNING,
70    * and most of E_STRICT.
71    *
72    * @param string $errno      The level of the error raised, as an integer.
73    * @param string $errstr     The error message, as a string.
74    * @param string $errfile    The filename that the error was raised in, as a string.
75    * @param string $errline    The line number the error was raised at, as an integer.
76    * @param array  $errcontext An array that points to the active symbol table at the point the error occurred.
77    */
78   public function handlePhpError($errno, $errstr, $errfile, $errline, $errcontext = array())
79   {
80     if (($errno & error_reporting()) == 0)
81     {
82       return false;
83     }
84
85     $message = sprintf(' %%s at %s on line %s (%s)', $errfile, $errline, str_replace('%', '%%', $errstr));
86     switch ($errno)
87     {
88       case E_STRICT:
89         $this->dispatcher->notify(new sfEvent($this, 'application.log', array('priority' => sfLogger::ERR, sprintf($message, 'Strict notice'))));
90         break;
91       case E_NOTICE:
92         $this->dispatcher->notify(new sfEvent($this, 'application.log', array('priority' => sfLogger::NOTICE, sprintf($message, 'Notice'))));
93         break;
94       case E_WARNING:
95         $this->dispatcher->notify(new sfEvent($this, 'application.log', array('priority' => sfLogger::WARNING, sprintf($message, 'Warning'))));
96         break;
97       case E_RECOVERABLE_ERROR:
98         $this->dispatcher->notify(new sfEvent($this, 'application.log', array('priority' => sfLogger::ERR, sprintf($message, 'Error'))));
99         break;
100     }
101
102     return false; // do not prevent default error handling
103   }
104
105   /**
106    * Listens for the context.load_factories event.
107    *
108    * @param sfEvent $event
109    */
110   public function listenForLoadFactories(sfEvent $event)
111   {
112     $path = sprintf('%s/%s/images', $event->getSubject()->getRequest()->getRelativeUrlRoot(), sfConfig::get('sf_web_debug_web_dir'));
113     $path = str_replace('//', '/', $path);
114
115     $this->webDebug = new $this->webDebugClass($this->dispatcher, $this, array(
116       'image_root_path'    => $path,
117       'request_parameters' => $event->getSubject()->getRequest()->getParameterHolder()->getAll(),
118     ));
119   }
120
121   /**
122    * Listens to the response.filter_content event.
123    *
124    * @param  sfEvent $event   The sfEvent instance
125    * @param  string  $content The response content
126    *
127    * @return string  The filtered response content
128    */
129   public function filterResponseContent(sfEvent $event, $content)
130   {
131     if (!sfConfig::get('sf_web_debug'))
132     {
133       return $content;
134     }
135
136     // log timers information
137     $messages = array();
138     foreach (sfTimerManager::getTimers() as $name => $timer)
139     {
140       $messages[] = sprintf('%s %.2f ms (%d)', $name, $timer->getElapsedTime() * 1000, $timer->getCalls());
141     }
142     $this->dispatcher->notify(new sfEvent($this, 'application.log', $messages));
143
144     // don't add debug toolbar:
145     // * for XHR requests
146     // * if response status code is in the 3xx range
147     // * if not rendering to the client
148     // * if HTTP headers only
149     $response = $event->getSubject();
150     $request  = $this->context->getRequest();
151     if (
152       null === $this->webDebug
153       ||
154       !$this->context->has('request')
155       ||
156       !$this->context->has('response')
157       ||
158       !$this->context->has('controller')
159       ||
160       $request->isXmlHttpRequest()
161       ||
162       strpos($response->getContentType(), 'html') === false
163       ||
164       '3' == substr($response->getStatusCode(), 0, 1)
165       ||
166       $this->context->getController()->getRenderMode() != sfView::RENDER_CLIENT
167       ||
168       $response->isHeaderOnly()
169     )
170     {
171       return $content;
172     }
173
174     return $this->webDebug->injectToolbar($content);
175   }
176 }
177
Note: See TracBrowser for help on using the browser.