/**
  * @author David Grudl
  * @see    https://github.com/nette/tracy
  */
 protected static function formatMessage(Throwable $message) : string
 {
     $tmp = [];
     while ($message) {
         $tmp[] = ($message instanceof \ErrorException ? Helpers::errorTypeToString($message->getSeverity()) . ': ' . $message->getMessage() : Helpers::getClass($message) . ': ' . $message->getMessage()) . ' in ' . $message->getFile() . ':' . $message->getLine();
         $message = $message->getPrevious();
     }
     $message = implode($tmp, "\ncaused by ");
     return trim($message);
 }
Exemple #2
0
 /**
  * @return mixed
  */
 private static function toJson(&$var, $options, $level = 0)
 {
     if (is_bool($var) || is_null($var) || is_int($var)) {
         return $var;
     } elseif (is_float($var)) {
         return is_finite($var) ? strpos($tmp = json_encode($var), '.') ? $var : array('number' => "{$tmp}.0") : array('type' => (string) $var);
     } elseif (is_string($var)) {
         return self::encodeString($var, $options[self::TRUNCATE]);
     } elseif (is_array($var)) {
         static $marker;
         if ($marker === NULL) {
             $marker = uniqid("", TRUE);
         }
         if (isset($var[$marker]) || $level >= $options[self::DEPTH]) {
             return array(NULL);
         }
         $res = array();
         $var[$marker] = TRUE;
         foreach ($var as $k => &$v) {
             if ($k !== $marker) {
                 $k = preg_match('#^\\w{1,50}\\z#', $k) ? $k : '"' . self::encodeString($k, $options[self::TRUNCATE]) . '"';
                 $res[] = array($k, self::toJson($v, $options, $level + 1));
             }
         }
         unset($var[$marker]);
         return $res;
     } elseif (is_object($var)) {
         $obj =& self::$liveStorage[spl_object_hash($var)];
         if ($obj && $obj['level'] <= $level) {
             return array('object' => $obj['id']);
         }
         if ($options[self::LOCATION] & self::LOCATION_CLASS) {
             $rc = $var instanceof \Closure ? new \ReflectionFunction($var) : new \ReflectionClass($var);
             $editor = Helpers::editorUri($rc->getFileName(), $rc->getStartLine());
         }
         static $counter = 1;
         $obj = $obj ?: array('id' => self::$livePrefix . '0' . $counter++, 'name' => Helpers::getClass($var), 'editor' => empty($editor) ? NULL : array('file' => $rc->getFileName(), 'line' => $rc->getStartLine(), 'url' => $editor), 'level' => $level, 'object' => $var);
         if ($level < $options[self::DEPTH] || !$options[self::DEPTH]) {
             $obj['level'] = $level;
             $obj['items'] = array();
             foreach (self::exportObject($var, $options[self::OBJECT_EXPORTERS]) as $k => $v) {
                 $vis = 0;
                 if (isset($k[0]) && $k[0] === "") {
                     $vis = $k[1] === '*' ? 1 : 2;
                     $k = substr($k, strrpos($k, "") + 1);
                 }
                 $k = preg_match('#^\\w{1,50}\\z#', $k) ? $k : '"' . self::encodeString($k, $options[self::TRUNCATE]) . '"';
                 $obj['items'][] = array($k, self::toJson($v, $options, $level + 1), $vis);
             }
         }
         return array('object' => $obj['id']);
     } elseif (is_resource($var)) {
         $obj =& self::$liveStorage[(string) $var];
         if (!$obj) {
             $type = get_resource_type($var);
             $obj = array('id' => self::$livePrefix . (int) $var, 'name' => $type . ' resource');
             if (isset(self::$resources[$type])) {
                 foreach (call_user_func(self::$resources[$type], $var) as $k => $v) {
                     $obj['items'][] = array($k, self::toJson($v, $options, $level + 1));
                 }
             }
         }
         return array('resource' => $obj['id']);
     } else {
         return array('type' => 'unknown type');
     }
 }
Exemple #3
0
 /**
  * Dump implementation for JSON.
  * @param  mixed  variable to dump
  * @param  int    current recursion level
  * @return string
  */
 private function jsonDump(&$var, $level = 0)
 {
     if (is_bool($var) || is_null($var) || is_int($var) || is_float($var)) {
         return $var;
     } elseif (is_string($var)) {
         return Dumper::encodeString($var, $this->maxLength);
     } elseif (is_array($var)) {
         static $marker;
         if ($marker === NULL) {
             $marker = uniqid("", TRUE);
         }
         if (isset($var[$marker])) {
             return "…RECURSION…";
         } elseif ($level < $this->maxDepth || !$this->maxDepth) {
             $var[$marker] = TRUE;
             $res = [];
             foreach ($var as $k => &$v) {
                 if ($k !== $marker) {
                     $res[$this->jsonDump($k)] = $this->jsonDump($v, $level + 1);
                 }
             }
             unset($var[$marker]);
             return $res;
         } else {
             return " … ";
         }
     } elseif (is_object($var)) {
         $arr = (array) $var;
         static $list = [];
         if (in_array($var, $list, TRUE)) {
             return "…RECURSION…";
         } elseif ($level < $this->maxDepth || !$this->maxDepth) {
             $list[] = $var;
             $res = ["" => '(object) ' . Helpers::getClass($var)];
             foreach ($arr as $k => &$v) {
                 if (isset($k[0]) && $k[0] === "") {
                     $k = substr($k, strrpos($k, "") + 1);
                 }
                 $res[$this->jsonDump($k)] = $this->jsonDump($v, $level + 1);
             }
             array_pop($list);
             return $res;
         } else {
             return " … ";
         }
     } elseif (is_resource($var)) {
         return 'resource ' . get_resource_type($var);
     } else {
         return 'unknown type';
     }
 }
Exemple #4
0
 protected function getTitle($message, $priority)
 {
     if ($message instanceof \Exception) {
         return Tracy\Helpers::getClass($message);
     } else {
         return $priority;
     }
 }
Exemple #5
0
	/**
	 * Dump implementation for JSON.
	 * @param  mixed  variable to dump
	 * @param  int    current recursion level
	 * @return string
	 */
	private static function jsonDump(& $var, $level = 0)
	{
		if (is_bool($var) || is_null($var) || is_int($var) || is_float($var)) {
			return $var;

		} elseif (is_string($var)) {
			if (Debugger::$maxLen && strlen($var) > Debugger::$maxLen) {
				$var = substr($var, 0, Debugger::$maxLen) . " \xE2\x80\xA6 ";
			}
			return Helpers::fixEncoding($var);

		} elseif (is_array($var)) {
			static $marker;
			if ($marker === NULL) {
				$marker = uniqid("\x00", TRUE);
			}
			if (isset($var[$marker])) {
				return "\xE2\x80\xA6RECURSION\xE2\x80\xA6";

			} elseif ($level < Debugger::$maxDepth || !Debugger::$maxDepth) {
				$var[$marker] = TRUE;
				$res = array();
				foreach ($var as $k => & $v) {
					if ($k !== $marker) {
						$res[self::jsonDump($k)] = self::jsonDump($v, $level + 1);
					}
				}
				unset($var[$marker]);
				return $res;

			} else {
				return " \xE2\x80\xA6 ";
			}

		} elseif (is_object($var)) {
			$arr = (array) $var;
			static $list = array();
			if (in_array($var, $list, TRUE)) {
				return "\xE2\x80\xA6RECURSION\xE2\x80\xA6";

			} elseif ($level < Debugger::$maxDepth || !Debugger::$maxDepth) {
				$list[] = $var;
				$res = array("\x00" => '(object) ' . Helpers::getClass($var));
				foreach ($arr as $k => & $v) {
					if ($k[0] === "\x00") {
						$k = substr($k, strrpos($k, "\x00") + 1);
					}
					$res[self::jsonDump($k)] = self::jsonDump($v, $level + 1);
				}
				array_pop($list);
				return $res;

			} else {
				return " \xE2\x80\xA6 ";
			}

		} elseif (is_resource($var)) {
			return 'resource ' . get_resource_type($var);

		} else {
			return 'unknown type';
		}
	}
Exemple #6
0
	/**
	 * Logs message or exception to file (if not disabled) and sends email notification (if enabled).
	 * @param  string|Exception
	 * @param  int  one of constant Debugger::INFO, WARNING, ERROR (sends email), EXCEPTION (sends email), CRITICAL (sends email)
	 * @return string logged error filename
	 */
	public static function log($message, $priority = self::INFO)
	{
		if (!self::$logDirectory) {
			return;
		}

		$exceptionFilename = NULL;
		if ($message instanceof \Exception || $message instanceof \Throwable) {
			$exception = $message;
			while ($exception) {
				$tmp[] = ($exception instanceof ErrorException
					? 'Fatal error: ' . $exception->getMessage()
					: Helpers::getClass($exception) . ': ' . $exception->getMessage())
					. ' in ' . $exception->getFile() . ':' . $exception->getLine();
				$exception = $exception->getPrevious();
			}
			$exception = $message;
			$message = implode($tmp, "\ncaused by ");

			$hash = md5(preg_replace('~(Resource id #)\d+~', '$1', $exception));
			$exceptionFilename = 'exception-' . @date('Y-m-d-H-i-s') . "-$hash.html";
			foreach (new \DirectoryIterator(self::$logDirectory) as $entry) {
				if (strpos($entry, $hash)) {
					$exceptionFilename = $entry;
					$saved = TRUE;
					break;
				}
			}
		} elseif (!is_string($message)) {
			$message = Dumper::toText($message);
		}

		if ($exceptionFilename) {
			$exceptionFilename = self::$logDirectory . '/' . $exceptionFilename;
			if (empty($saved) && $logHandle = @fopen($exceptionFilename, 'w')) {
				ob_start(); // double buffer prevents sending HTTP headers in some PHP
				ob_start(function ($buffer) use ($logHandle) { fwrite($logHandle, $buffer); }, 4096);
				self::getBlueScreen()->render($exception);
				ob_end_flush();
				ob_end_clean();
				fclose($logHandle);
			}
		}

		self::getLogger()->log(array(
			@date('[Y-m-d H-i-s]'),
			trim($message),
			self::$source ? ' @  ' . self::$source : NULL,
			$exceptionFilename ? ' @@  ' . basename($exceptionFilename) : NULL
		), $priority);

		return $exceptionFilename ? strtr($exceptionFilename, '\\/', DIRECTORY_SEPARATOR . DIRECTORY_SEPARATOR) : NULL;
	}
Exemple #7
0
	private static function dumpObject(& $var, $options, $level)
	{
		if ($var instanceof \Closure) {
			$rc = new \ReflectionFunction($var);
			$fields = array();
			foreach ($rc->getParameters() as $param) {
				$fields[] = '$' . $param->getName();
			}
			$fields = array(
				'file' => $rc->getFileName(), 'line' => $rc->getStartLine(),
				'variables' => $rc->getStaticVariables(), 'parameters' => implode(', ', $fields)
			);
		} elseif ($var instanceof \SplFileInfo) {
			$fields = array('path' => $var->getPathname());
		} elseif ($var instanceof \SplObjectStorage) {
			$fields = array();
			foreach (clone $var as $obj) {
				$fields[] = array('object' => $obj, 'data' => $var[$obj]);
			}
		} else {
			$fields = (array) $var;
		}

		static $list = array();
		$rc = $var instanceof \Closure ? new \ReflectionFunction($var) : new \ReflectionClass($var);
		$out = '<span class="tracy-dump-object"'
			. ($options[self::LOCATION] && ($editor = Helpers::editorUri($rc->getFileName(), $rc->getStartLine())) ? ' data-tracy-href="' . htmlspecialchars($editor) . '"' : '')
			. '>' . htmlspecialchars(Helpers::getClass($var)) . '</span> <span class="tracy-dump-hash">#' . substr(md5(spl_object_hash($var)), 0, 4) . '</span>';

		if (empty($fields)) {
			return $out . "\n";

		} elseif (in_array($var, $list, TRUE)) {
			return $out . " { <i>RECURSION</i> }\n";

		} elseif (!$options[self::DEPTH] || $level < $options[self::DEPTH] || $var instanceof \Closure) {
			$collapsed = $level ? count($fields) >= $options[self::COLLAPSE_COUNT] : $options[self::COLLAPSE];
			$out = '<span class="tracy-toggle' . ($collapsed ? ' tracy-collapsed' : '') . '">'
				. $out . "</span>\n<div" . ($collapsed ? ' class="tracy-collapsed"' : '') . '>';
			$list[] = $var;
			foreach ($fields as $k => & $v) {
				$vis = '';
				if ($k[0] === "\x00") {
					$vis = ' <span class="tracy-dump-visibility">' . ($k[1] === '*' ? 'protected' : 'private') . '</span>';
					$k = substr($k, strrpos($k, "\x00") + 1);
				}
				$k = preg_match('#^\w{1,50}\z#', $k) ? $k : '"' . htmlspecialchars(self::encodeString($k, $options[self::TRUNCATE]), ENT_NOQUOTES, 'UTF-8') . '"';
				$out .= '<span class="tracy-dump-indent">   ' . str_repeat('|  ', $level) . '</span>'
					. '<span class="tracy-dump-key">' . $k . "</span>$vis => "
					. self::dumpVar($v, $options, $level + 1);
			}
			array_pop($list);
			return $out . '</div>';

		} else {
			return $out . " { ... }\n";
		}
	}