'; /** * Set a custom logo for HTML Handler * * @param string $logoHtml * @return self */ protected function setLogo(string $logoHtml): self { $this->logo = $logoHtml; return $this; } /** * This will return the MaplePHP logotype * * @return string */ protected function getLogo(): string { return $this->logo; } /** * This is the visible code block * * @param array $data * @param string $code * @param int $index * @return string */ protected function getCodeBlock(array $data, string $code, int $index = 0): string { $class = (string)($data['class'] ?? ""); $function = (string)($data['function'] ?? ""); $functionName = ($function !== "") ? ' (' . $function . ')' : ''; return "
" . $class . $functionName . "
{$data['file']}
" . $code . "
"; } /** * This is a navigation item that will point to code block * * @param int $index * @param int $length * @param array $stack * @return string */ protected function getNavBlock(int $index, int $length, array $stack): string { $active = ($index === 0) ? " active" : ""; $class = (string)($stack['class'] ?? ""); $function = (string)($stack['function'] ?? ""); $functionName = ($function !== "") ? ' (' . $function . ')' : ''; return " " . "" . ($length - $index) . ". $class . $functionName " . ltrim((string)$stack['file'], "/") . ": {$stack['line']} " ; } protected function getRows(string $title, ?array $rows): string { $out = '
'; $out .= '

' . $title . '

'; if (is_array($rows) && count($rows) > 0) { foreach ($rows as $key => $value) { if (is_array($value)) { $value = json_encode($value); } $value = htmlspecialchars((string)$value, ENT_QUOTES, 'UTF-8'); $value = $this->excerpt($value, 400); $out .= ''; } } else { $out .= '
None
'; } $out .= '
'; return $out; } /** * This will add the navigation block html structure * If you wish to edit the block then you should edit the "getNavBlock" method * * @param array $trace * @return string */ protected function getTraceNavBlock(array $trace): string { $output = ""; $length = count($trace); foreach ($trace as $index => $stackPoint) { if (is_array($stackPoint) && isset($stackPoint['file']) && is_file((string)$stackPoint['file'])) { $output .= $this->getNavBlock($index, $length, $stackPoint); } } return $output; } /** * Utilizing a "byte" excerpt * Going for performance with byte calculation instead of precision with multibyte. * * @param string $value * @param int $length * @return string */ protected function excerpt(string $value, int $length): string { if (strlen($value) > $length) { $value = trim(substr($value, 0, $length)) . "..."; } return $value; } /** * Get code between start and end span from file * * @param StreamInterface $stream * @param int $errorLine * @param int $startSpan * @param int $endSpan * @return string */ protected function getContentsBetween(StreamInterface $stream, int $errorLine, int $startSpan = 10, int $endSpan = 12): string { $index = 1; $output = ''; $startLine = $errorLine - $startSpan; $endLine = $errorLine + $endSpan; if ($startLine < 1) { $startLine = 1; } while (!$stream->eof()) { $line = $stream->read((int)$stream->getSize()); $lines = explode("\n", $line); foreach ($lines as $lineContent) { if ($index >= $startLine && $index <= $endLine) { $output .= ''; $output .= ''. $index .''; if ($errorLine === $index) { $output .= "" . htmlspecialchars($lineContent) . "\n"; } else { $output .= "" . htmlspecialchars($lineContent) . "\n"; } $output .= ''; } if ($index > $endLine) { break; } $index++; } } return $output; } /** * Used to fetch valid asset * * @param string $file * @return string * @throws ErrorException */ public function getAssetContent(string $file): string { $ending = explode(".", $file); $ending = end($ending); if (!($ending === "css" || $ending === "js")) { throw new ErrorException("Only JS and CSS files are allowed as assets files"); } $filePath = (str_starts_with($file, "/") ? realpath($file) : (string)realpath(__DIR__ . "/../") . "/" . $file); $stream = $this->getStream($filePath); return $stream->getContents(); } /** * Will return the severity exception breadcrumb * * @param ExceptionItem $meta * @return string */ public function getSeverityBreadcrumb(ExceptionItem $meta): string { $breadcrumb = get_class($meta->getException()); $severityConstant = $meta->getSeverityConstant(); if ($severityConstant !== null) { $breadcrumb .= " ($severityConstant)"; } return "
$breadcrumb
"; } /** * This will add the code block structure * If you wish to edit the block then you should edit the "getCodeBlock" method * * @param array $trace * @return array */ final protected function getTraceCodeBlock(array $trace): array { $block = []; foreach ($trace as $key => $stackPoint) { if (is_array($stackPoint) && isset($stackPoint['file']) && is_file((string)$stackPoint['file'])) { $stream = $this->getStream($stackPoint['file']); $code = $this->getContentsBetween($stream, (int)$stackPoint['line']); $block[] = $this->getCodeBlock($stackPoint, $code, $key); $stream->close(); } } return $block; } }