/** * Parses the stack trace, and makes it look pretty. * * This includes adding in the syntax highlighting, * highlighting the colours for the files, * and padding with whitespace. * * If stackTrace is null, then null is returned. */ private function parseStackTrace($code, $message, $errLine, $errFile, &$stackTrace, $root, $altInfo = null) { if ($stackTrace !== null) { /* * For whitespace padding. */ $lineLen = 0; $fileLen = 0; // parse the stack trace, and remove the long urls foreach ($stackTrace as $i => $trace) { if ($trace) { if (isset($trace['line'])) { $lineLen = max($lineLen, strlen($trace['line'])); } else { $trace['line'] = ''; } $info = ''; if ($i === 0 && $altInfo !== null) { $info = $altInfo; /* * Skip for the first iteration, * as it's usually magical PHP calls. */ } else { if ($i > 0 && (isset($trace['class']) || isset($trace['type']) || isset($trace['function']))) { $args = array(); if (isset($trace['args'])) { foreach ($trace['args'] as $arg) { $args[] = ErrorHandler::identifyTypeHTML($arg, 1); } } $info = ErrorHandler::syntaxHighlightFunction(isset($trace['class']) ? $trace['class'] : null, isset($trace['type']) ? $trace['type'] : null, isset($trace['function']) ? $trace['function'] : null, $args); } else { if (isset($trace['info']) && $trace['info'] !== '') { $info = ErrorHandler::syntaxHighlight($trace['info']); } else { if (isset($trace['file']) && !isset($trace['info'])) { $contents = $this->getFileContents($trace['file']); if ($contents) { $info = ErrorHandler::syntaxHighlight(trim($contents[$trace['line'] - 1])); } } } } } $trace['info'] = $info; if (isset($trace['file'])) { list($type, $file) = $this->getFolderType($root, $trace['file']); $trace['file_type'] = $type; $trace['is_native'] = false; } else { $file = '[Internal PHP]'; $trace['file_type'] = ''; $trace['is_native'] = true; } $trace['file'] = $file; $fileLen = max($fileLen, strlen($file)); $stackTrace[$i] = $trace; } } /* * We are allowed to highlight just once, that's it. */ $highlightI = -1; foreach ($stackTrace as $i => $trace) { if ($trace['line'] === $errLine && $trace['file'] === $errFile) { $highlightI = $i; break; } } foreach ($stackTrace as $i => $trace) { if ($trace) { // line $line = str_pad($trace['line'], $lineLen, ' ', STR_PAD_LEFT); // file $file = $trace['file']; $fileKlass = ''; if ($trace['is_native']) { $fileKlass = 'file-internal-php'; } else { $fileKlass = 'filename ' . ErrorHandler::folderTypeToCSS($trace['file_type']); } $file = $file . str_pad('', $fileLen - strlen($file), ' ', STR_PAD_LEFT); // info $info = $trace['info']; if ($info) { $info = str_replace("\n", '\\n', $info); $info = str_replace("\r", '\\r', $info); } else { $info = ' '; } // line + file + info $stackStr = "<td class='linenumber'>{$line}</td>" . "<td class='{$fileKlass}'>{$file}</td>" . "<td class='lineinfo'>{$info}</td>"; if ($trace['is_native']) { $cssClass = 'is-native '; } else { $cssClass = ''; } if ($highlightI === $i) { $cssClass .= ' highlight'; } else { if ($highlightI > $i) { $cssClass .= ' pre-highlight'; } } if ($i !== 0 && isset($trace['exception']) && $trace['exception']) { $ex = $trace['exception']; $exHtml = '<tr class="error-stack-trace-exception"><td>' . 'exception "' . htmlspecialchars($ex->getMessage()) . '"' . '</td></tr>'; } else { $exHtml = ''; } $data = ''; if (isset($trace['file-lines-id'])) { $data = 'data-file-lines-id="' . $trace['file-lines-id'] . '"'; } $stackTrace[$i] = "{$exHtml}<tr class='error-stack-trace-line {$cssClass}' {$data}>{$stackStr}</tr>"; } } return '<table id="error-stack-trace">' . join("", $stackTrace) . '</table>'; } else { return null; } }