scratch – Blame information for rev 115

Subversion Repositories:
Rev:
Rev Author Line No. Line
115 office 1 <?php
2  
3 /*
4 * This file is part of the Monolog package.
5 *
6 * (c) Jordi Boggiano <j.boggiano@seld.be>
7 *
8 * For the full copyright and license information, please view the LICENSE
9 * file that was distributed with this source code.
10 */
11  
12 namespace Monolog\Handler;
13  
14 use Exception;
15 use Monolog\Formatter\LineFormatter;
16 use Monolog\Logger;
17 use PhpConsole\Connector;
18 use PhpConsole\Handler;
19 use PhpConsole\Helper;
20  
21 /**
22 * Monolog handler for Google Chrome extension "PHP Console"
23 *
24 * Display PHP error/debug log messages in Google Chrome console and notification popups, executes PHP code remotely
25 *
26 * Usage:
27 * 1. Install Google Chrome extension https://chrome.google.com/webstore/detail/php-console/nfhmhhlpfleoednkpnnnkolmclajemef
28 * 2. See overview https://github.com/barbushin/php-console#overview
29 * 3. Install PHP Console library https://github.com/barbushin/php-console#installation
30 * 4. Example (result will looks like http://i.hizliresim.com/vg3Pz4.png)
31 *
32 * $logger = new \Monolog\Logger('all', array(new \Monolog\Handler\PHPConsoleHandler()));
33 * \Monolog\ErrorHandler::register($logger);
34 * echo $undefinedVar;
35 * $logger->addDebug('SELECT * FROM users', array('db', 'time' => 0.012));
36 * PC::debug($_SERVER); // PHP Console debugger for any type of vars
37 *
38 * @author Sergey Barbushin https://www.linkedin.com/in/barbushin
39 */
40 class PHPConsoleHandler extends AbstractProcessingHandler
41 {
42 private $options = array(
43 'enabled' => true, // bool Is PHP Console server enabled
44 'classesPartialsTraceIgnore' => array('Monolog\\'), // array Hide calls of classes started with...
45 'debugTagsKeysInContext' => array(0, 'tag'), // bool Is PHP Console server enabled
46 'useOwnErrorsHandler' => false, // bool Enable errors handling
47 'useOwnExceptionsHandler' => false, // bool Enable exceptions handling
48 'sourcesBasePath' => null, // string Base path of all project sources to strip in errors source paths
49 'registerHelper' => true, // bool Register PhpConsole\Helper that allows short debug calls like PC::debug($var, 'ta.g.s')
50 'serverEncoding' => null, // string|null Server internal encoding
51 'headersLimit' => null, // int|null Set headers size limit for your web-server
52 'password' => null, // string|null Protect PHP Console connection by password
53 'enableSslOnlyMode' => false, // bool Force connection by SSL for clients with PHP Console installed
54 'ipMasks' => array(), // array Set IP masks of clients that will be allowed to connect to PHP Console: array('192.168.*.*', '127.0.0.1')
55 'enableEvalListener' => false, // bool Enable eval request to be handled by eval dispatcher(if enabled, 'password' option is also required)
56 'dumperDetectCallbacks' => false, // bool Convert callback items in dumper vars to (callback SomeClass::someMethod) strings
57 'dumperLevelLimit' => 5, // int Maximum dumped vars array or object nested dump level
58 'dumperItemsCountLimit' => 100, // int Maximum dumped var same level array items or object properties number
59 'dumperItemSizeLimit' => 5000, // int Maximum length of any string or dumped array item
60 'dumperDumpSizeLimit' => 500000, // int Maximum approximate size of dumped vars result formatted in JSON
61 'detectDumpTraceAndSource' => false, // bool Autodetect and append trace data to debug
62 'dataStorage' => null, // PhpConsole\Storage|null Fixes problem with custom $_SESSION handler(see http://goo.gl/Ne8juJ)
63 );
64  
65 /** @var Connector */
66 private $connector;
67  
68 /**
69 * @param array $options See \Monolog\Handler\PHPConsoleHandler::$options for more details
70 * @param Connector|null $connector Instance of \PhpConsole\Connector class (optional)
71 * @param int $level
72 * @param bool $bubble
73 * @throws Exception
74 */
75 public function __construct(array $options = array(), Connector $connector = null, $level = Logger::DEBUG, $bubble = true)
76 {
77 if (!class_exists('PhpConsole\Connector')) {
78 throw new Exception('PHP Console library not found. See https://github.com/barbushin/php-console#installation');
79 }
80 parent::__construct($level, $bubble);
81 $this->options = $this->initOptions($options);
82 $this->connector = $this->initConnector($connector);
83 }
84  
85 private function initOptions(array $options)
86 {
87 $wrongOptions = array_diff(array_keys($options), array_keys($this->options));
88 if ($wrongOptions) {
89 throw new Exception('Unknown options: ' . implode(', ', $wrongOptions));
90 }
91  
92 return array_replace($this->options, $options);
93 }
94  
95 private function initConnector(Connector $connector = null)
96 {
97 if (!$connector) {
98 if ($this->options['dataStorage']) {
99 Connector::setPostponeStorage($this->options['dataStorage']);
100 }
101 $connector = Connector::getInstance();
102 }
103  
104 if ($this->options['registerHelper'] && !Helper::isRegistered()) {
105 Helper::register();
106 }
107  
108 if ($this->options['enabled'] && $connector->isActiveClient()) {
109 if ($this->options['useOwnErrorsHandler'] || $this->options['useOwnExceptionsHandler']) {
110 $handler = Handler::getInstance();
111 $handler->setHandleErrors($this->options['useOwnErrorsHandler']);
112 $handler->setHandleExceptions($this->options['useOwnExceptionsHandler']);
113 $handler->start();
114 }
115 if ($this->options['sourcesBasePath']) {
116 $connector->setSourcesBasePath($this->options['sourcesBasePath']);
117 }
118 if ($this->options['serverEncoding']) {
119 $connector->setServerEncoding($this->options['serverEncoding']);
120 }
121 if ($this->options['password']) {
122 $connector->setPassword($this->options['password']);
123 }
124 if ($this->options['enableSslOnlyMode']) {
125 $connector->enableSslOnlyMode();
126 }
127 if ($this->options['ipMasks']) {
128 $connector->setAllowedIpMasks($this->options['ipMasks']);
129 }
130 if ($this->options['headersLimit']) {
131 $connector->setHeadersLimit($this->options['headersLimit']);
132 }
133 if ($this->options['detectDumpTraceAndSource']) {
134 $connector->getDebugDispatcher()->detectTraceAndSource = true;
135 }
136 $dumper = $connector->getDumper();
137 $dumper->levelLimit = $this->options['dumperLevelLimit'];
138 $dumper->itemsCountLimit = $this->options['dumperItemsCountLimit'];
139 $dumper->itemSizeLimit = $this->options['dumperItemSizeLimit'];
140 $dumper->dumpSizeLimit = $this->options['dumperDumpSizeLimit'];
141 $dumper->detectCallbacks = $this->options['dumperDetectCallbacks'];
142 if ($this->options['enableEvalListener']) {
143 $connector->startEvalRequestsListener();
144 }
145 }
146  
147 return $connector;
148 }
149  
150 public function getConnector()
151 {
152 return $this->connector;
153 }
154  
155 public function getOptions()
156 {
157 return $this->options;
158 }
159  
160 public function handle(array $record)
161 {
162 if ($this->options['enabled'] && $this->connector->isActiveClient()) {
163 return parent::handle($record);
164 }
165  
166 return !$this->bubble;
167 }
168  
169 /**
170 * Writes the record down to the log of the implementing handler
171 *
172 * @param array $record
173 * @return void
174 */
175 protected function write(array $record)
176 {
177 if ($record['level'] < Logger::NOTICE) {
178 $this->handleDebugRecord($record);
179 } elseif (isset($record['context']['exception']) && $record['context']['exception'] instanceof Exception) {
180 $this->handleExceptionRecord($record);
181 } else {
182 $this->handleErrorRecord($record);
183 }
184 }
185  
186 private function handleDebugRecord(array $record)
187 {
188 $tags = $this->getRecordTags($record);
189 $message = $record['message'];
190 if ($record['context']) {
191 $message .= ' ' . json_encode($this->connector->getDumper()->dump(array_filter($record['context'])));
192 }
193 $this->connector->getDebugDispatcher()->dispatchDebug($message, $tags, $this->options['classesPartialsTraceIgnore']);
194 }
195  
196 private function handleExceptionRecord(array $record)
197 {
198 $this->connector->getErrorsDispatcher()->dispatchException($record['context']['exception']);
199 }
200  
201 private function handleErrorRecord(array $record)
202 {
203 $context = $record['context'];
204  
205 $this->connector->getErrorsDispatcher()->dispatchError(
206 isset($context['code']) ? $context['code'] : null,
207 isset($context['message']) ? $context['message'] : $record['message'],
208 isset($context['file']) ? $context['file'] : null,
209 isset($context['line']) ? $context['line'] : null,
210 $this->options['classesPartialsTraceIgnore']
211 );
212 }
213  
214 private function getRecordTags(array &$record)
215 {
216 $tags = null;
217 if (!empty($record['context'])) {
218 $context = & $record['context'];
219 foreach ($this->options['debugTagsKeysInContext'] as $key) {
220 if (!empty($context[$key])) {
221 $tags = $context[$key];
222 if ($key === 0) {
223 array_shift($context);
224 } else {
225 unset($context[$key]);
226 }
227 break;
228 }
229 }
230 }
231  
232 return $tags ?: strtolower($record['level_name']);
233 }
234  
235 /**
236 * {@inheritDoc}
237 */
238 protected function getDefaultFormatter()
239 {
240 return new LineFormatter('%message%');
241 }
242 }