diff options
| author | Jan-Hendrik Willms <tleilax+studip@gmail.com> | 2025-02-27 19:47:17 +0000 |
|---|---|---|
| committer | David Siegfried <david.siegfried@uni-vechta.de> | 2025-02-27 19:47:17 +0000 |
| commit | ea81d27a628a4c4df304bc3465ee057eeed85f80 (patch) | |
| tree | a00f8a6ba4d7b35c13e2ee00d68c0da7864de177 /lib/classes/ExceptionDisplay.php | |
| parent | 0896c2670d96dfe88c6a396ba4b333c547271a64 (diff) | |
allow file locations in displayed exceptions to be linked to your editor, fixes #5175
Closes #5175
Merge request studip/studip!3866
Diffstat (limited to 'lib/classes/ExceptionDisplay.php')
| -rw-r--r-- | lib/classes/ExceptionDisplay.php | 82 |
1 files changed, 82 insertions, 0 deletions
diff --git a/lib/classes/ExceptionDisplay.php b/lib/classes/ExceptionDisplay.php new file mode 100644 index 0000000..7001a4c --- /dev/null +++ b/lib/classes/ExceptionDisplay.php @@ -0,0 +1,82 @@ +<?php +/** + * The ExceptionDisplay class is used to dump an exception as a string for + * display. + * + * By setting the environment variable EDITOR_URL you may activate linking the + * file locations to your editor. + * + * @author Jan-Hendrik Willms <tleilax+studip@gmail.com> + * @since Stud.IP 6.1 + */ +final class ExceptionDisplay implements Stringable +{ + private const MARKUP_REGEXP = '~(?<file>(?:\w+/)*\w+\.\w+)(?:\((?<line0>\d+)\)| on line (?<line1>\d+))~m'; + + public static function from(Throwable $e): self + { + return new self($e); + } + + private ?string $editor_url; + + private function __construct( + private Throwable $exception + ) { + $this->editor_url = $_ENV['EDITOR_URL'] ?? null; + } + + private function reducePathToRelative(string $input): string + { + return str_replace($GLOBALS['STUDIP_BASE_PATH'] . '/', '', $input); + } + + public function display(bool $as_html = false, bool $deep = false): string + { + $result = ''; + $result .= sprintf("%s: %s\n", _('Typ'), get_class($this->exception)); + $result .= sprintf("%s: %s\n", _('Nachricht'), $this->reducePathToRelative($this->exception->getMessage())); + $result .= sprintf("%s: %d\n", _('Code'), $this->exception->getCode()); + + $trace = sprintf("#$ %s(%u)\n", $this->exception->getFile(), $this->exception->getLine()); + $trace .= $this->exception->getTraceAsString(); + + $result .= sprintf("%s:\n%s\n", _('Stack trace'), $this->reducePathToRelative($trace)); + + if ($deep && $this->exception->getPrevious()) { + $result .= "\n"; + $result .= _('Vorherige Exception:') . "\n"; + $result .= self::from($this->exception->getPrevious())->display(false, $deep); + } + + if (!$as_html) { + return $result; + } + + $result = htmlReady($result, br: true); + + if (Studip\ENV === 'development' && $this->editor_url) { + $result = preg_replace_callback( + self::MARKUP_REGEXP, + function ($matches) { + return studip_interpolate('<a href="%{link}">%{label}</a>', [ + 'label' => $matches['file'] . '(' . ($matches['line0'] ?: $matches['line1']) . ')', + 'link' => studip_interpolate($this->editor_url, [ + 'file' => $matches['file'], + 'line' => $matches['line0'] ?: $matches['line1'], + ]), + ]); + }, + $result + ); + } + + return $result; + + } + + public function __toString(): string + { + return $this->display(); + } +} |
