Formats the standard PHP backtrace (debug_backtrace).

@param array $btrace
The backtrace.

@return string
Returns the formatted backtrace.

@author Oleg Schildt
492436
protected function format_backtrace($btrace)
    {
        if (empty($btrace) || count($btrace) == 0) {
            return "backtrace empty";
        }
        
        $trace = "";
        
        foreach ($btrace as $nr => &$btrace_entry) {
            if ($nr == 0) {
                $trace .= $btrace_entry["args"][2] . "\r\n" . "line: " . $btrace_entry["args"][3] . "\r\n" . $btrace_entry["args"][1];
                
                $cstack = $this->extract_call_stack($btrace);
                if (!empty($cstack)) {
                    $trace .= "\r\n\r\nCall stack:\r\n\r\n" . $cstack;
                }
                
                continue;
            }
        }
        
        return $trace;
    }
717577
private function formatStacktraceForExceptions($exceptions)
    {
        if (!is_array($exceptions)) {
            $exceptions = [$exceptions];
        }

        $this->root = $this->findApplicationRoot();

        $trace = '';
        foreach ($exceptions as $ex) {
            if ($ex instanceof Throwable) {
                $trace .= $this->formatExceptionStacktrace($ex);
            }
        }

        return $trace;
    }
1010629
private function _trace($strMessage)
    {
        $arrTrace = array_reverse(debug_backtrace());
        $strFunc = '';
        $strBacktrace = htmlspecialchars($strMessage)."\n\n";
        foreach ($arrTrace as $val) {
            // avoid the last line, which says the error is from the error class
            if ($val == $arrTrace[count($arrTrace) - 1]) {
                break;
            }
            $strBacktrace .= str_replace(PSI_APP_ROOT, ".", $val['file']).' on line '.$val['line'];
            if ($strFunc) {
                $strBacktrace .= ' in function '.$strFunc;
            }
            if ($val['function'] == 'include' || $val['function'] == 'require' || $val['function'] == 'include_once' || $val['function'] == 'require_once') {
                $strFunc = '';
            } else {
                $strFunc = $val['function'].'(';
                if (isset($val['args'][0])) {
                    $strFunc .= ' ';
                    $strComma = '';
                    foreach ($val['args'] as $valArgs) {
                        $strFunc .= $strComma.$this->_printVar($valArgs);
                        $strComma = ', ';
                    }
                    $strFunc .= ' ';
                }
                $strFunc .= ')';
            }
            $strBacktrace .= "\n";
        }

        return $strBacktrace;
    }
387417
public static function formatTrace(array $trace, $indent = '') {
        $appRoot = self::di('config')['app.dir.root'];
        $result  = '';

        $size = sizeof($trace);
        $callLen = $lineLen = 0;

        for ($i=0; $i < $size; $i++) {               // align FILE and LINE
            $frame = &$trace[$i];

            $call = self::getFQFunctionName($frame, $nsLowerCase=true);

            if ($call!='{main}' && !strEndsWith($call, '{closure}'))
                $call.='()';
            $callLen = max($callLen, strlen($call));
            $frame['call'] = $call;

            $frame['line'] = isset($frame['line']) ? ' # line '.$frame['line'].',' : '';
            $lineLen = max($lineLen, strlen($frame['line']));

            if (isset($frame['file']))                 $frame['file'] = ' file: '.(!$appRoot ? $frame['file'] : strRightFrom($frame['file'], $appRoot.DIRECTORY_SEPARATOR, 1, false, $frame['file']));
            elseif (strStartsWith($call, 'phalcon\\')) $frame['file'] = ' [php-phalcon]';
            else                                       $frame['file'] = ' [php]';
        }
        if ($appRoot) {
            $trace[] = ['call'=>'', 'line'=>'', 'file'=>' file base: '.$appRoot];
            $i++;
        }

        for ($i=0; $i < $size; $i++) {
            $result .= $indent.str_pad($trace[$i]['call'], $callLen).' '.str_pad($trace[$i]['line'], $lineLen).$trace[$i]['file'].NL;
        }

        return $result;
    }
945897
public static function backtrace($trace = null)
	{
		$trace or $trace = debug_backtrace();

		if (\Fuel::$is_cli) {
			// Special case for CLI since the var_dump of a backtrace is of little use.
			$str = '';
			foreach ($trace as $i => $frame)
			{
				$line = "#$i\t";

				if ( ! isset($frame['file']))
				{
					$line .= "[internal function]";
				}
				else
				{
					$line .= $frame['file'] . ":" . $frame['line'];
				}

				$line .= "\t";

				if (isset($frame['function']))
				{
					if (isset($frame['class']))
					{
						$line .= $frame['class'] . '::';
					}

					$line .= $frame['function'] . "()";
				}

				$str .= $line . "\n";

			}

			return $str;
		}
		else
		{
			return static::dump($trace);
		}
	}
1186824
public static function stacktrace( $stack = null, $withPre = false )
	{
		if ( is_null( $stack ) )
			$stack = debug_backtrace();
		$output = $withPre ? '<pre>' : '';

		$stackLen = count( $stack );
		for ( $i = 1; $i < $stackLen; $i++ )
		{
			$entry = $stack[$i];

			$func = $entry['function'] . '(';
			$argsLen = count( $entry['args'] );

			for ( $j = 0; $j < $argsLen; $j++ )
			{
				$my_entry = $entry['args'][$j];

				if ( is_string( $my_entry ) )
					$func .= $my_entry;

				if ( $j < $argsLen - 1 )
					$func .= ', ';
			}
			$func .= ')';

			$entry_file = 'NO_FILE';

			if ( array_key_exists( 'file', $entry ) )
				$entry_file = $entry['file'];

			$entry_line = 'NO_LINE';

			if ( array_key_exists( 'line', $entry ) )
				$entry_line = $entry['line'];

			$output .= $entry_file . ':' . $entry_line . ' - ' . $func . PHP_EOL;
		}

		if ( $withPre )
			$output .= $output . '</pre>';

		return $output;
	}
366146
public static function normalizeBacktrace(array $trace)
    {
        $trace = new Data($trace);

        $args = [];

        foreach ($trace['args'] as $arg) {
            if (is_array($arg)) {
                $arg = 'Array';
            } elseif (is_object($arg)) {
                $arg = ReflectionHelper::getShortName($arg);
            } elseif (is_string($arg)) {
                if (Mbstring::strlen($arg) > 20) {
                    $arg = Utf8String::substr($arg, 0, 20) . '...';
                }

                $arg = Str::wrap($arg);
            } elseif ($arg === null) {
                $arg = 'NULL';
            } elseif (is_bool($arg)) {
                $arg = $arg ? 'TRUE' : 'FALSE';
            }

            $args[] = $arg;
        }

        return [
            'file' => !empty($trace['file']) ? static::replaceRoot($trace['file']) . ' (' . $trace['line'] . ')' : null,
            'function' => ($trace['class'] ? $trace['class'] . $trace['type'] : null) . $trace['function'] .
                sprintf('(%s)', implode(', ', $args)),
            'pathname' => $trace['file'],
            'line' => $trace['line']
        ];
    }
650116
public static function caller(int $back = 0)
    {
        $bt = debug_backtrace();
        $trace = $bt[$back] ?? null;

        $file = $trace['file'] ?? '';
        $line = $trace['line'] ?? -1;

        return array( $file, intval($line) );
    }
992103
public static function traceBegin()
    {
        $dbg = debug_backtrace();
        $str = '=> ';
        if (!empty ($dbg[1]['class'])) {
            $str .= $dbg[1]['class'] . '::';
        }
        $str .= $dbg[1]['function'] . '(';
        if (is_array($dbg[1]['args'])) {
            foreach ($dbg[1]['args'] as $index => $arg) {
                if ($index != 0) {
                    $str .= ', ';
                }
                if (is_object($arg)) {
                    $str .= get_class($arg);
                } else {
                    $str .= str_replace(array("\r\n", "\n", "\r"), "", var_export($arg, true));
                }
            }
        }
        if (isset($dbg[1]['file'])) {
            $file = basename($dbg[1]['file']);
        } else {
            $file = 'unknown_file';
        }
        if (isset($dbg[1]['line'])) {
            $line = $dbg[1]['line'];
        } else {
            $line = 'unknown_line';
        }
        $str .= ') [' . $file . ':' . $line . ']';
        phpCAS :: log($str);
        if (!isset(self::$_PHPCAS_DEBUG['indent'])) {
            self::$_PHPCAS_DEBUG['indent'] = 0;
        } else {
            self::$_PHPCAS_DEBUG['indent']++;
        }
    }
340259
protected function trace()
    {
        foreach (\array_reverse($this->backtrace) as $stackFrame) {
            if ($this->isDebugCall($stackFrame)) {
                return $stackFrame;
            }
        }

        return \end($this->backtrace);
    }
821430
public static function backTrace() {

        $str = "<br />[backTrace]";
        foreach (debug_backtrace() as $row) {
            $str .= "<br />FILE: "
                    . $row['file'] . " FUNC: " . $row['function']
                    . " LINE: " . $row['line'] . " ARGS: "
                    . print_r($row['args'], true);
        }
        return $str;
    }
409866
static public function backtrace($deep=0)
    {
        $bt = debug_backtrace(DEBUG_BACKTRACE_PROVIDE_OBJECT, $deep + 1);
        if (isset($bt[$deep])) {
            return $bt[$deep];
        }

        return array();
    }
196701
public static function parseBacktrace()
	{
		$file = '-';
		$line = 0;

		// Loop through the backtrace items
		foreach (self::getBacktrace() as $item)
		{
			// Looking for the last instance of one of the following classes...
			// this will be our indicator of the command that originated this query
			if (isset($item['class'])
			 && ($item['class'] == 'Hubzero\Database\Relational'
			 ||  $item['class'] == 'Hubzero\Database\Relationship\Relationship'
			 ||  $item['class'] == 'Hubzero\Database\Rows'))
			{

				$file = (isset($item['file'])) ? str_replace(PATH_CORE, '', $item['file']) : $file;
				$line = (isset($item['line'])) ? $item['line'] : $line;
			}
		}

		return array($file, $line);
	}
720602
protected function _backtrace_formatArgsHelper($arg) {
        $value = $arg;
        if (is_object($arg)) {
            $value = sprintf('OBJECT(%s)', get_class($arg));
        } elseif (is_resource($arg)) {
            $value = 'RESOURCE';
        } elseif (is_array($arg)) {
            $value = 'ARRAY[%s](%s)';
            $c = array();
            foreach ($arg as $k => $v) {
                $c[] = sprintf('%s => %s', $k,
                    $this->_backtrace_formatArgsHelper($v));
            }
            $value = sprintf($value, count($arg), implode(', ', $c));
        } elseif (is_string($arg)) {
            $value = sprintf('\'%s\'', $arg);
        } elseif (is_bool($arg)) {
            $value = $arg ? 'TRUE' : 'FALSE';
        } elseif (is_null($arg)) {
            $value = 'NULL';
        }
        return $value;
    }
763008
private function getTrace()
    {
        $trace = array();

        if (PHP_VERSION_ID >= 50400) {
            $trace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 10);
        } else if (PHP_VERSION_ID >= 50306) {
            $trace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS);
        } else {
            $trace = debug_backtrace();
        }
        if (empty($trace)) {
            return '';
        }
        array_shift($trace); // ignore $this->getTrace();
        array_shift($trace); // ignore $this->process()
        $i = 0;
        $returnArray = array();
        while (isset($trace[$i]['class']) && false === strpos($trace[$i]['class'], 'Zend\\Log')
            && false === strpos($trace[$i]['class'], 'DhErrorLogging')) {
            $i++;
            $returnArray[] = array(
                'file'     => isset($trace[$i]['file'])   ? $trace[$i]['file']   : null,
                'line'     => isset($trace[$i]['line'])   ? $trace[$i]['line']   : null,
                'class'    => isset($trace[$i]['class'])    ? $trace[$i]['class']    : null,
                'function' => isset($trace[$i]['function']) ? $trace[$i]['function'] : null,
            );
        }

        return $returnArray;
    }
271094
public static function filter_backtrace($bt, $ignoredFunctions = null)
    {
        $defaultIgnoredFunctions = array(
            'SilverStripe\\Logging\\Log::log',
            'SilverStripe\\Dev\\Backtrace::backtrace',
            'SilverStripe\\Dev\\Backtrace::filtered_backtrace',
            'Zend_Log_Writer_Abstract->write',
            'Zend_Log->log',
            'Zend_Log->__call',
            'Zend_Log->err',
            'SilverStripe\\Dev\\DebugView->writeTrace',
            'SilverStripe\\Dev\\CliDebugView->writeTrace',
            'SilverStripe\\Dev\\Debug::emailError',
            'SilverStripe\\Dev\\Debug::warningHandler',
            'SilverStripe\\Dev\\Debug::noticeHandler',
            'SilverStripe\\Dev\\Debug::fatalHandler',
            'errorHandler',
            'SilverStripe\\Dev\\Debug::showError',
            'SilverStripe\\Dev\\Debug::backtrace',
            'exceptionHandler'
        );

        if ($ignoredFunctions) {
            foreach ($ignoredFunctions as $ignoredFunction) {
                $defaultIgnoredFunctions[] = $ignoredFunction;
            }
        }

        while ($bt && in_array(self::full_func_name($bt[0]), $defaultIgnoredFunctions)) {
            array_shift($bt);
        }

        $ignoredArgs = static::config()->get('ignore_function_args');

        // Filter out arguments
        foreach ($bt as $i => $frame) {
            $match = false;
            if (!empty($bt[$i]['class'])) {
                foreach ($ignoredArgs as $fnSpec) {
                    if (is_array($fnSpec) &&
                        ('*' == $fnSpec[0] || $bt[$i]['class'] == $fnSpec[0]) &&
                        $bt[$i]['function'] == $fnSpec[1]
                    ) {
                        $match = true;
                    }
                }
            } else {
                if (in_array($bt[$i]['function'], $ignoredArgs)) {
                    $match = true;
                }
            }
            if ($match) {
                foreach ($bt[$i]['args'] as $j => $arg) {
                    $bt[$i]['args'][$j] = '<filtered>';
                }
            }
        }

        return $bt;
    }
767948
protected function extract_call_stack($btrace)
    {
        if (empty($btrace) || !is_array($btrace)) {
            return "";
        }
        
        $trace = "";
        
        $indent = "";
        foreach ($btrace as $btrace_entry) {
            
            
            if (!empty($btrace_entry["function"]) && ($btrace_entry["function"] == "handle_error" || strpos($btrace_entry["function"], "{closure}") !== false || $btrace_entry["function"] == "handleError" || $btrace_entry["function"] == "trigger_error")) {
                continue;
            }
            
            if (empty($btrace_entry["file"])) {
                continue;
            }
            
            if (!empty($btrace_entry["function"])) {
                $trace .= $indent . str_replace("SmartFactory\\", "", $btrace_entry["function"]) . "() ";
            }
            
            $trace .= "[";
            
            $trace .= str_replace($this->app_root, "", str_replace("\\", "/", $btrace_entry["file"]));
            
            $trace .= ", ";
            
            if (empty($btrace_entry["line"])) {
                $trace .= "line number undefined";
            } else {
                $trace .= $btrace_entry["line"];
            }
            
            $trace .= "]";
            
            $args = (isset($btrace_entry["args"])) ? $btrace_entry["args"] : [];
            $args_str = $this->make_arg_list($args);
            
            if (!empty($btrace_entry["function"]) && !empty($args_str)) {
                $trace .= "  " . str_replace("SmartFactory\\", "", $btrace_entry["function"]) . "(" . $args_str . ")";
            }
            
            $trace .= "\r\n";
            
            $indent .= "  ";
        }
        
        return trim($trace);
    }