scratch – Blame information for rev 120
?pathlinks?
Rev | Author | Line No. | Line |
---|---|---|---|
120 | 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 | } |