Class it_debug:
/**
* Return short stackdump
* @param $p['levels'] number of stack levels to return (default: 0 = all)
* @param $p['skiplevels'] number of stack levels to omit
* @param $p['skipfiles'] regular expression of filenames to omit
* @param $p['trace'] Stack trace to compact
*/
static function backtrace($p = array())
{
$frames = $p['trace'] ?? ($p['format'] ? array_slice(debug_backtrace(0), $p['skiplevels']) : null);
if ($p['format'] == "long")
{
foreach ($frames as $frame)
if ($tracesize < 100000 && ($tracesize += strlen(print_r($frame, true))) < 100000) # save mem
$outframes[] = $frame;
$result = $outframes ? print_r($outframes, true) . "\n" : null;
}
else if ($p['format'] == "medium")
{
foreach ($frames as $frame)
{
$locations[] = basename($frame['file']) . ":" . $frame['line'];
$argstrings = [];
foreach ((array)$frame['args'] as $arg)
{
$t = trim(it::replace(['^array \(\s*' => "[", ',\n\)$' => "]", '^array \( \)' => "[]", " +" => " ", "\n" => ""], var_export($arg, true)), " ,");
$argstrings[] = strlen($t) < 60 ? $t : it::replace(["^(.{0,60} |.{0,60}).*" => '$1'], $t) . "..." . (is_array($arg) ? "]" : (is_object($arg) ? "}" :""));
}
$allargs = join(", ", $argstrings);
if ($frame['type'] == "->" || $frame['type'] == "::")
$funcs[] = $frame['class'] . $frame['type'] . $frame['function'] . "($allargs)";
else
$funcs[] = $frame['function'] ? $frame['function'] . "($allargs)" : "[inline]";
$maxlen = max(it::map('strlen', $locations));
}
foreach ($locations as $idx => $location)
$result .= str_pad($location, $maxlen + 2) . $funcs[$idx] . "\n";
}
else
{
foreach (self::debug_backtrace($p) as $frame)
{
$fn = $frame['file'];
$fn = (it::match('auto_prepend', $fn) ? basename(dirname(dirname($fn))) . "/" : (it::match('/(cgi|bin)/', $fn) ? basename(dirname($fn)) . "/" : "")) . basename($fn);
if ($fn)
$result[] = $fn . ":" . $frame['line'];
}
$result = implode(" ", (array)$result);
}
return $result;
}