1: <?php
2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22:
23: defined('XOOPS_ROOT_PATH') || exit('Restricted access');
24:
25: 26: 27: 28: 29: 30: 31: 32:
33: class XoopsLogger
34: {
35: 36: 37: 38: 39:
40: public $queries = array();
41: public $blocks = array();
42: public $extra = array();
43: public $logstart = array();
44: public $logend = array();
45: public $errors = array();
46: public $deprecated = array();
47: 48: 49:
50:
51: public $usePopup = false;
52: public $activated = true;
53:
54: 55: 56:
57: public $renderingEnabled = false;
58:
59: 60: 61:
62: public function __construct()
63: {
64: }
65:
66: 67: 68:
69: public function XoopsLogger()
70: {
71: }
72:
73: 74: 75:
76: public function instance()
77: {
78: return XoopsLogger::getInstance();
79: }
80:
81: 82: 83: 84: 85:
86: public static function getInstance()
87: {
88: static $instance;
89: if (!isset($instance)) {
90: $instance = new XoopsLogger();
91:
92: set_error_handler('XoopsErrorHandler_HandleError');
93:
94: set_exception_handler(array($instance, 'handleException'));
95: }
96:
97: return $instance;
98: }
99:
100: 101: 102: 103: 104: 105:
106: public function enableRendering()
107: {
108: if (!$this->renderingEnabled) {
109: ob_start(array(&$this, 'render'));
110: $this->renderingEnabled = true;
111: }
112: }
113:
114: 115: 116: 117: 118:
119: public function microtime()
120: {
121: $now = explode(' ', microtime());
122:
123: return (float)$now[0] + (float)$now[1];
124: }
125:
126: 127: 128: 129: 130:
131: public function startTime($name = 'XOOPS')
132: {
133: if ($this->activated) {
134: $this->logstart[$name] = $this->microtime();
135: }
136: }
137:
138: 139: 140: 141: 142:
143: public function stopTime($name = 'XOOPS')
144: {
145: if ($this->activated) {
146: $this->logend[$name] = $this->microtime();
147: }
148: }
149:
150: 151: 152: 153: 154: 155: 156: 157:
158: public function addQuery($sql, $error = null, $errno = null, $query_time = null)
159: {
160: if ($this->activated) {
161: $this->queries[] = array('sql' => $sql, 'error' => $error, 'errno' => $errno, 'query_time' => $query_time);
162: }
163: }
164:
165: 166: 167: 168: 169: 170: 171:
172: public function addBlock($name, $cached = false, $cachetime = 0)
173: {
174: if ($this->activated) {
175: $this->blocks[] = array('name' => $name, 'cached' => $cached, 'cachetime' => $cachetime);
176: }
177: }
178:
179: 180: 181: 182: 183: 184:
185: public function addExtra($name, $msg)
186: {
187: if ($this->activated) {
188: $this->extra[] = array('name' => $name, 'msg' => $msg);
189: }
190: }
191:
192: 193: 194: 195: 196: 197: 198: 199:
200: public function addDeprecated($msg)
201: {
202: if ($this->activated) {
203: $this->deprecated[] = $msg;
204: }
205: }
206:
207: 208: 209: 210: 211: 212: 213: 214:
215: public function handleError($errno, $errstr, $errfile, $errline)
216: {
217: if ($this->activated && ($errno & error_reporting())) {
218:
219: $this->errors[] = compact('errno', 'errstr', 'errfile', 'errline');
220: }
221: if ($errno == E_USER_ERROR) {
222: $trace = true;
223: if (substr($errstr, 0, '8') === 'notrace:') {
224: $trace = false;
225: $errstr = substr($errstr, 8);
226: }
227: echo sprintf(_XOOPS_FATAL_MESSAGE, $errstr);
228: if ($trace && function_exists('debug_backtrace')) {
229: echo "<div style='color:#f0f0f0;background-color:#f0f0f0;'>" . _XOOPS_FATAL_BACKTRACE . ':<br>';
230: $trace = debug_backtrace();
231: array_shift($trace);
232: foreach ($trace as $step) {
233: if (isset($step['file'])) {
234: echo $this->sanitizePath($step['file']);
235: echo ' (' . $step['line'] . ")\n<br>";
236: }
237: }
238: echo '</div>';
239: }
240: exit();
241: }
242: }
243:
244: 245: 246: 247: 248: 249: 250:
251: public function handleException($e)
252: {
253: if ($this->isThrowable($e)) {
254: $msg = get_class($e) . ': ' . $e->getMessage();
255: $this->handleError(E_USER_ERROR, $msg, $e->getFile(), $e->getLine());
256: }
257: }
258:
259: 260: 261: 262: 263: 264: 265:
266: protected function isThrowable($e)
267: {
268: $type = interface_exists('\Throwable', false) ? '\Throwable' : '\Exception';
269: return $e instanceof $type;
270: }
271:
272: 273: 274: 275: 276: 277: 278: 279:
280: public function sanitizePath($path)
281: {
282: $path = str_replace(array('\\', XOOPS_ROOT_PATH, str_replace('\\', '/', realpath(XOOPS_ROOT_PATH))), array('/', '', ''), $path);
283:
284: return $path;
285: }
286:
287: 288: 289: 290: 291:
292: public function render($output)
293: {
294: global $xoopsUser;
295: if (!$this->activated) {
296: return $output;
297: }
298:
299: $log = $this->dump($this->usePopup ? 'popup' : '');
300: $this->renderingEnabled = $this->activated = false;
301: $pattern = '<!--{xo-logger-output}-->';
302: $pos = strpos($output, $pattern);
303: if ($pos !== false) {
304: return substr($output, 0, $pos) . $log . substr($output, $pos + strlen($pattern));
305: } else {
306: return $output . $log;
307: }
308: }
309:
310: 311: 312: 313: 314: 315: 316:
317: public function dump($mode = '')
318: {
319: include XOOPS_ROOT_PATH . '/class/logger/render.php';
320:
321: return $ret;
322: }
323:
324: 325: 326: 327: 328: 329: 330:
331: public function dumpTime($name = 'XOOPS', $unset = false)
332: {
333: if (!$this->activated) {
334: return null;
335: }
336:
337: if (!isset($this->logstart[$name])) {
338: return 0;
339: }
340: $stop = isset($this->logend[$name]) ? $this->logend[$name] : $this->microtime();
341: $start = $this->logstart[$name];
342:
343: if ($unset) {
344: unset($this->logstart[$name]);
345: }
346:
347: return $stop - $start;
348: }
349:
350: 351: 352: 353: 354: 355: 356: 357: 358: 359: 360:
361: public function triggerError($errkey = 0, $errStr = '', $errFile = '', $errLine = '', $errNo = 0)
362: {
363: $GLOBALS['xoopsLogger']->addDeprecated('\'$xoopsLogger->triggerError();\' is deprecated since XOOPS 2.5.4');
364:
365: if (!empty($errStr)) {
366: $errStr = sprintf($errStr, $errkey);
367: }
368: $errFile = $this->sanitizePath($errFile);
369: $this->handleError($errNo, $errStr, $errFile, $errLine);
370: }
371:
372: 373: 374: 375: 376:
377: public function dumpAll()
378: {
379: $GLOBALS['xoopsLogger']->addDeprecated('\'$xoopsLogger->dumpAll();\' is deprecated since XOOPS 2.5.4, please use \'$xoopsLogger->dump(\'\');\' instead.');
380:
381: return $this->dump('');
382: }
383:
384: 385: 386: 387: 388:
389: public function dumpBlocks()
390: {
391: $GLOBALS['xoopsLogger']->addDeprecated('\'$xoopsLogger->dumpBlocks();\' is deprecated since XOOPS 2.5.4, please use \'$xoopsLogger->dump(\'blocks\');\' instead.');
392:
393: return $this->dump('blocks');
394: }
395:
396: 397: 398: 399: 400:
401: public function dumpExtra()
402: {
403: $GLOBALS['xoopsLogger']->addDeprecated('\'$xoopsLogger->dumpExtra();\' is deprecated since XOOPS 2.5.4, please use \'$xoopsLogger->dump(\'extra\');\' instead.');
404:
405: return $this->dump('extra');
406: }
407:
408: 409: 410: 411: 412:
413: public function dumpQueries()
414: {
415: $GLOBALS['xoopsLogger']->addDeprecated('\'$xoopsLogger->dumpQueries();\' is deprecated since XOOPS 2.5.4, please use \'$xoopsLogger->dump(\'queries\');\' instead.');
416:
417: return $this->dump('queries');
418: }
419: 420: 421:
422: }
423:
424: 425: 426: 427: 428: 429: 430: 431: 432: 433: 434: 435: 436: 437: 438:
439: function XoopsErrorHandler_HandleError($errNo, $errStr, $errFile, $errLine, $errContext = null)
440: {
441: 442: 443: 444: 445: 446: 447:
448: $logger = XoopsLogger::getInstance();
449: $logger->handleError($errNo, $errStr, $errFile, $errLine, $errContext);
450: return null;
451: }
452: