ok
Direktori : /home2/selectio/www/ecommerce-website/website/vendor/nunomaduro/collision/src/ |
Current File : /home2/selectio/www/ecommerce-website/website/vendor/nunomaduro/collision/src/Writer.php |
<?php declare(strict_types=1); namespace NunoMaduro\Collision; use NunoMaduro\Collision\Contracts\ArgumentFormatter as ArgumentFormatterContract; use NunoMaduro\Collision\Contracts\Highlighter as HighlighterContract; use NunoMaduro\Collision\Contracts\RenderlessEditor; use NunoMaduro\Collision\Contracts\RenderlessTrace; use NunoMaduro\Collision\Contracts\SolutionsRepository; use NunoMaduro\Collision\Contracts\Writer as WriterContract; use NunoMaduro\Collision\SolutionsRepositories\NullSolutionsRepository; use Symfony\Component\Console\Output\ConsoleOutput; use Symfony\Component\Console\Output\OutputInterface; use Whoops\Exception\Frame; use Whoops\Exception\Inspector; /** * @internal * * @see \Tests\Unit\WriterTest */ final class Writer implements WriterContract { /** * The number of frames if no verbosity is specified. */ public const VERBOSITY_NORMAL_FRAMES = 1; /** * Holds an instance of the solutions repository. * * @var \NunoMaduro\Collision\Contracts\SolutionsRepository */ private $solutionsRepository; /** * Holds an instance of the Output. * * @var \Symfony\Component\Console\Output\OutputInterface */ protected $output; /** * Holds an instance of the Argument Formatter. * * @var \NunoMaduro\Collision\Contracts\ArgumentFormatter */ protected $argumentFormatter; /** * Holds an instance of the Highlighter. * * @var \NunoMaduro\Collision\Contracts\Highlighter */ protected $highlighter; /** * Ignores traces where the file string matches one * of the provided regex expressions. * * @var string[] */ protected $ignore = []; /** * Declares whether or not the trace should appear. * * @var bool */ protected $showTrace = true; /** * Declares whether or not the title should appear. * * @var bool */ protected $showTitle = true; /** * Declares whether or not the editor should appear. * * @var bool */ protected $showEditor = true; /** * Creates an instance of the writer. */ public function __construct( SolutionsRepository $solutionsRepository = null, OutputInterface $output = null, ArgumentFormatterContract $argumentFormatter = null, HighlighterContract $highlighter = null ) { $this->solutionsRepository = $solutionsRepository ?: new NullSolutionsRepository(); $this->output = $output ?: new ConsoleOutput(); $this->argumentFormatter = $argumentFormatter ?: new ArgumentFormatter(); $this->highlighter = $highlighter ?: new Highlighter(); } /** * {@inheritdoc} */ public function write(Inspector $inspector): void { $this->renderTitleAndDescription($inspector); $frames = $this->getFrames($inspector); $editorFrame = array_shift($frames); $exception = $inspector->getException(); if ($this->showEditor && $editorFrame !== null && !$exception instanceof RenderlessEditor ) { $this->renderEditor($editorFrame); } $this->renderSolution($inspector); if ($this->showTrace && !empty($frames) && !$exception instanceof RenderlessTrace) { $this->renderTrace($frames); } elseif (!$exception instanceof RenderlessEditor) { $this->output->writeln(''); } } /** * {@inheritdoc} */ public function ignoreFilesIn(array $ignore): WriterContract { $this->ignore = $ignore; return $this; } /** * {@inheritdoc} */ public function showTrace(bool $show): WriterContract { $this->showTrace = $show; return $this; } /** * {@inheritdoc} */ public function showTitle(bool $show): WriterContract { $this->showTitle = $show; return $this; } /** * {@inheritdoc} */ public function showEditor(bool $show): WriterContract { $this->showEditor = $show; return $this; } /** * {@inheritdoc} */ public function setOutput(OutputInterface $output): WriterContract { $this->output = $output; return $this; } /** * {@inheritdoc} */ public function getOutput(): OutputInterface { return $this->output; } /** * Returns pertinent frames. */ protected function getFrames(Inspector $inspector): array { return $inspector->getFrames() ->filter( function ($frame) { // If we are in verbose mode, we always // display the full stack trace. if ($this->output->getVerbosity() >= OutputInterface::VERBOSITY_VERBOSE) { return true; } foreach ($this->ignore as $ignore) { // Ensure paths are linux-style (like the ones on $this->ignore) // @phpstan-ignore-next-line $sanitizedPath = (string) str_replace('\\', '/', $frame->getFile()); if (preg_match($ignore, $sanitizedPath)) { return false; } } return true; } ) ->getArray(); } /** * Renders the title of the exception. */ protected function renderTitleAndDescription(Inspector $inspector): WriterContract { $exception = $inspector->getException(); $message = rtrim($exception->getMessage()); $class = $inspector->getExceptionName(); if ($this->showTitle) { $this->render("<bg=red;options=bold> $class </>"); $this->output->writeln(''); } $this->output->writeln("<fg=default;options=bold> $message</>"); return $this; } /** * Renders the solution of the exception, if any. */ protected function renderSolution(Inspector $inspector): WriterContract { $throwable = $inspector->getException(); $solutions = $this->solutionsRepository->getFromThrowable($throwable); foreach ($solutions as $solution) { /** @var \Facade\IgnitionContracts\Solution $solution */ $title = $solution->getSolutionTitle(); $description = $solution->getSolutionDescription(); $links = $solution->getDocumentationLinks(); $description = trim((string) preg_replace("/\n/", "\n ", $description)); $this->render(sprintf( '<fg=blue;options=bold>• </><fg=default;options=bold>%s</>: %s %s', rtrim($title, '.'), $description, implode(', ', array_map(function (string $link) { return sprintf("\n <fg=blue>%s</>", $link); }, $links)) )); } return $this; } /** * Renders the editor containing the code that was the * origin of the exception. */ protected function renderEditor(Frame $frame): WriterContract { if ($frame->getFile() !== 'Unknown') { $file = $this->getFileRelativePath((string) $frame->getFile()); // getLine() might return null so cast to int to get 0 instead $line = (int) $frame->getLine(); $this->render('at <fg=green>' . $file . '</>' . ':<fg=green>' . $line . '</>'); $content = $this->highlighter->highlight((string) $frame->getFileContents(), (int) $frame->getLine()); $this->output->writeln($content); } return $this; } /** * Renders the trace of the exception. */ protected function renderTrace(array $frames): WriterContract { $vendorFrames = 0; $userFrames = 0; foreach ($frames as $i => $frame) { if ($this->output->getVerbosity() < OutputInterface::VERBOSITY_VERBOSE && strpos($frame->getFile(), '/vendor/') !== false) { $vendorFrames++; continue; } if ($userFrames > static::VERBOSITY_NORMAL_FRAMES && $this->output->getVerbosity() < OutputInterface::VERBOSITY_VERBOSE) { break; } $userFrames++; $file = $this->getFileRelativePath($frame->getFile()); $line = $frame->getLine(); $class = empty($frame->getClass()) ? '' : $frame->getClass() . '::'; $function = $frame->getFunction(); $args = $this->argumentFormatter->format($frame->getArgs()); $pos = str_pad((string) ((int) $i + 1), 4, ' '); if ($vendorFrames > 0) { $this->output->write( sprintf("\n \e[2m+%s vendor frames \e[22m", $vendorFrames) ); $vendorFrames = 0; } $this->render("<fg=yellow>$pos</><fg=default;options=bold>$file</>:<fg=default;options=bold>$line</>"); $this->render("<fg=white> $class$function($args)</>", false); } return $this; } /** * Renders an message into the console. * * @return $this */ protected function render(string $message, bool $break = true): WriterContract { if ($break) { $this->output->writeln(''); } $this->output->writeln(" $message"); return $this; } /** * Returns the relative path of the given file path. */ protected function getFileRelativePath(string $filePath): string { $cwd = (string) getcwd(); if (!empty($cwd)) { return str_replace("$cwd/", '', $filePath); } return $filePath; } }