ILIAS  release_5-2 Revision v5.2.25-18-g3f80b828510
BrowserConsoleHandler.php
Go to the documentation of this file.
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
12namespace Monolog\Handler;
13
15
22{
23 protected static $initialized = false;
24 protected static $records = array();
25
35 protected function getDefaultFormatter()
36 {
37 return new LineFormatter('[[%channel%]]{macro: autolabel} [[%level_name%]]{font-weight: bold} %message%');
38 }
39
43 protected function write(array $record)
44 {
45 // Accumulate records
46 self::$records[] = $record;
47
48 // Register shutdown handler if not already done
49 if (!self::$initialized) {
50 self::$initialized = true;
52 }
53 }
54
59 public static function send()
60 {
61 $format = self::getResponseFormat();
62 if ($format === 'unknown') {
63 return;
64 }
65
66 if (count(self::$records)) {
67 if ($format === 'html') {
68 self::writeOutput('<script>' . self::generateScript() . '</script>');
69 } elseif ($format === 'js') {
70 self::writeOutput(self::generateScript());
71 }
73 }
74 }
75
79 public static function reset()
80 {
81 self::$records = array();
82 }
83
87 protected function registerShutdownFunction()
88 {
89 if (PHP_SAPI !== 'cli') {
90 register_shutdown_function(array('Monolog\Handler\BrowserConsoleHandler', 'send'));
91 }
92 }
93
99 protected static function writeOutput($str)
100 {
101 echo $str;
102 }
103
113 protected static function getResponseFormat()
114 {
115 // Check content type
116 foreach (headers_list() as $header) {
117 if (stripos($header, 'content-type:') === 0) {
118 // This handler only works with HTML and javascript outputs
119 // text/javascript is obsolete in favour of application/javascript, but still used
120 if (stripos($header, 'application/javascript') !== false || stripos($header, 'text/javascript') !== false) {
121 return 'js';
122 }
123 if (stripos($header, 'text/html') === false) {
124 return 'unknown';
125 }
126 break;
127 }
128 }
129
130 return 'html';
131 }
132
133 private static function generateScript()
134 {
135 $script = array();
136 foreach (self::$records as $record) {
137 $context = self::dump('Context', $record['context']);
138 $extra = self::dump('Extra', $record['extra']);
139
140 if (empty($context) && empty($extra)) {
141 $script[] = self::call_array('log', self::handleStyles($record['formatted']));
142 } else {
143 $script = array_merge($script,
144 array(self::call_array('groupCollapsed', self::handleStyles($record['formatted']))),
145 $context,
146 $extra,
147 array(self::call('groupEnd'))
148 );
149 }
150 }
151
152 return "(function (c) {if (c && c.groupCollapsed) {\n" . implode("\n", $script) . "\n}})(console);";
153 }
154
155 private static function handleStyles($formatted)
156 {
157 $args = array(self::quote('font-weight: normal'));
158 $format = '%c' . $formatted;
159 preg_match_all('/\[\[(.*?)\]\]\{([^}]*)\}/s', $format, $matches, PREG_OFFSET_CAPTURE | PREG_SET_ORDER);
160
161 foreach (array_reverse($matches) as $match) {
162 $args[] = self::quote(self::handleCustomStyles($match[2][0], $match[1][0]));
163 $args[] = '"font-weight: normal"';
164
165 $pos = $match[0][1];
166 $format = substr($format, 0, $pos) . '%c' . $match[1][0] . '%c' . substr($format, $pos + strlen($match[0][0]));
167 }
168
169 array_unshift($args, self::quote($format));
170
171 return $args;
172 }
173
174 private static function handleCustomStyles($style, $string)
175 {
176 static $colors = array('blue', 'green', 'red', 'magenta', 'orange', 'black', 'grey');
177 static $labels = array();
178
179 return preg_replace_callback('/macro\s*:(.*?)(?:;|$)/', function ($m) use ($string, &$colors, &$labels) {
180 if (trim($m[1]) === 'autolabel') {
181 // Format the string as a label with consistent auto assigned background color
182 if (!isset($labels[$string])) {
183 $labels[$string] = $colors[count($labels) % count($colors)];
184 }
185 $color = $labels[$string];
186
187 return "background-color: $color; color: white; border-radius: 3px; padding: 0 2px 0 2px";
188 }
189
190 return $m[1];
191 }, $style);
192 }
193
194 private static function dump($title, array $dict)
195 {
196 $script = array();
197 $dict = array_filter($dict);
198 if (empty($dict)) {
199 return $script;
200 }
201 $script[] = self::call('log', self::quote('%c%s'), self::quote('font-weight: bold'), self::quote($title));
202 foreach ($dict as $key => $value) {
203 $value = json_encode($value);
204 if (empty($value)) {
205 $value = self::quote('');
206 }
207 $script[] = self::call('log', self::quote('%s: %o'), self::quote($key), $value);
208 }
209
210 return $script;
211 }
212
213 private static function quote($arg)
214 {
215 return '"' . addcslashes($arg, "\"\n\\") . '"';
216 }
217
218 private static function call()
219 {
220 $args = func_get_args();
221 $method = array_shift($args);
222
223 return self::call_array($method, $args);
224 }
225
226 private static function call_array($method, array $args)
227 {
228 return 'c.' . $method . '(' . implode(', ', $args) . ');';
229 }
230}
An exception for terminatinating execution or to throw for unit testing.
Formats incoming records into a one-line string.
Base Handler class providing the Handler structure.
Handler sending logs to browser's javascript console with no browser extension required.
static reset()
Forget all logged records.
getDefaultFormatter()
Gets the default formatter.FormatterInterface
registerShutdownFunction()
Wrapper for register_shutdown_function to allow overriding.
write(array $record)
Writes the record down to the log of the implementing handler.void
static writeOutput($str)
Wrapper for echo to allow overriding.
static send()
Convert records to javascript console commands and send it to the browser.
static getResponseFormat()
Checks the format of the response.
$header
$style
Definition: example_012.php:70
$records
Definition: simple_test.php:22