ILIAS  release_5-1 Revision 5.0.0-5477-g43f3e3fab5f
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 
12 namespace Monolog\Handler;
13 
15 
22 {
23  protected static $initialized = false;
24  protected static $records = array();
25 
36  protected function getDefaultFormatter()
37  {
38  return new LineFormatter('[[%channel%]]{macro: autolabel} [[%level_name%]]{font-weight: bold} %message%');
39  }
40 
44  protected function write(array $record)
45  {
46  // Accumulate records
47  self::$records[] = $record;
48 
49  // Register shutdown handler if not already done
50  if (PHP_SAPI !== 'cli' && !self::$initialized) {
51  self::$initialized = true;
52  register_shutdown_function(array('Monolog\Handler\BrowserConsoleHandler', 'send'));
53  }
54  }
55 
60  public static function send()
61  {
62  $htmlTags = true;
63  // Check content type
64  foreach (headers_list() as $header) {
65  if (stripos($header, 'content-type:') === 0) {
66  // This handler only works with HTML and javascript outputs
67  // text/javascript is obsolete in favour of application/javascript, but still used
68  if (stripos($header, 'application/javascript') !== false || stripos($header, 'text/javascript') !== false) {
69  $htmlTags = false;
70  } elseif (stripos($header, 'text/html') === false) {
71  return;
72  }
73  break;
74  }
75  }
76 
77  if (count(self::$records)) {
78  if ($htmlTags) {
79  echo '<script>' , self::generateScript() , '</script>';
80  } else {
81  echo self::generateScript();
82  }
83  self::reset();
84  }
85  }
86 
90  public static function reset()
91  {
92  self::$records = array();
93  }
94 
95  private static function generateScript()
96  {
97  $script = array();
98  foreach (self::$records as $record) {
99  $context = self::dump('Context', $record['context']);
100  $extra = self::dump('Extra', $record['extra']);
101 
102  if (empty($context) && empty($extra)) {
103  $script[] = self::call_array('log', self::handleStyles($record['formatted']));
104  } else {
105  $script = array_merge($script,
106  array(self::call_array('groupCollapsed', self::handleStyles($record['formatted']))),
107  $context,
108  $extra,
109  array(self::call('groupEnd'))
110  );
111  }
112  }
113 
114  return "(function (c) {if (c && c.groupCollapsed) {\n" . implode("\n", $script) . "\n}})(console);";
115  }
116 
117  private static function handleStyles($formatted)
118  {
119  $args = array(self::quote('font-weight: normal'));
120  $format = '%c' . $formatted;
121  preg_match_all('/\[\[(.*?)\]\]\{([^}]*)\}/s', $format, $matches, PREG_OFFSET_CAPTURE | PREG_SET_ORDER);
122 
123  foreach (array_reverse($matches) as $match) {
124  $args[] = self::quote(self::handleCustomStyles($match[2][0], $match[1][0]));
125  $args[] = '"font-weight: normal"';
126 
127  $pos = $match[0][1];
128  $format = substr($format, 0, $pos) . '%c' . $match[1][0] . '%c' . substr($format, $pos + strlen($match[0][0]));
129  }
130 
131  array_unshift($args, self::quote($format));
132 
133  return $args;
134  }
135 
136  private static function handleCustomStyles($style, $string)
137  {
138  static $colors = array('blue', 'green', 'red', 'magenta', 'orange', 'black', 'grey');
139  static $labels = array();
140 
141  return preg_replace_callback('/macro\s*:(.*?)(?:;|$)/', function ($m) use ($string, &$colors, &$labels) {
142  if (trim($m[1]) === 'autolabel') {
143  // Format the string as a label with consistent auto assigned background color
144  if (!isset($labels[$string])) {
145  $labels[$string] = $colors[count($labels) % count($colors)];
146  }
147  $color = $labels[$string];
148 
149  return "background-color: $color; color: white; border-radius: 3px; padding: 0 2px 0 2px";
150  }
151 
152  return $m[1];
153  }, $style);
154  }
155 
156  private static function dump($title, array $dict)
157  {
158  $script = array();
159  $dict = array_filter($dict);
160  if (empty($dict)) {
161  return $script;
162  }
163  $script[] = self::call('log', self::quote('%c%s'), self::quote('font-weight: bold'), self::quote($title));
164  foreach ($dict as $key => $value) {
165  $value = json_encode($value);
166  if (empty($value)) {
167  $value = self::quote('');
168  }
169  $script[] = self::call('log', self::quote('%s: %o'), self::quote($key), $value);
170  }
171 
172  return $script;
173  }
174 
175  private static function quote($arg)
176  {
177  return '"' . addcslashes($arg, "\"\n\\") . '"';
178  }
179 
180  private static function call()
181  {
182  $args = func_get_args();
183  $method = array_shift($args);
184 
185  return self::call_array($method, $args);
186  }
187 
188  private static function call_array($method, array $args)
189  {
190  return 'c.' . $method . '(' . implode(', ', $args) . ');';
191  }
192 }
$style
Definition: example_012.php:70
Base Handler class providing the Handler structure.
static send()
Convert records to javascript console commands and send it to the browser.
$records
Definition: simple_test.php:17
Handler sending logs to browser&#39;s javascript console with no browser extension required.
$header
static reset()
Forget all logged records.
Formats incoming records into a one-line string.