/home/complianthowden/public_html/vendor/nunomaduro/collision/src/Writer.php
<?php

declare(strict_types=1);

namespace NunoMaduro\Collision;

use Closure;
use NunoMaduro\Collision\Contracts\RenderableOnCollisionEditor;
use NunoMaduro\Collision\Contracts\RenderlessEditor;
use NunoMaduro\Collision\Contracts\RenderlessTrace;
use NunoMaduro\Collision\Contracts\SolutionsRepository;
use NunoMaduro\Collision\Exceptions\TestException;
use NunoMaduro\Collision\SolutionsRepositories\NullSolutionsRepository;
use Symfony\Component\Console\Output\ConsoleOutput;
use Symfony\Component\Console\Output\OutputInterface;
use Throwable;
use Whoops\Exception\Frame;
use Whoops\Exception\Inspector;

/**
 * @internal
 *
 * @see \Tests\Unit\WriterTest
 */
final class Writer
{
    /**
     * The number of frames if no verbosity is specified.
     */
    public const VERBOSITY_NORMAL_FRAMES = 1;

    /**
     * Holds an instance of the solutions repository.
     */
    private SolutionsRepository $solutionsRepository;

    /**
     * Holds an instance of the Output.
     */
    private OutputInterface $output;

    /**
     * Holds an instance of the Argument Formatter.
     */
    private ArgumentFormatter $argumentFormatter;

    /**
     * Holds an instance of the Highlighter.
     */
    private Highlighter $highlighter;

    /**
     * Ignores traces where the file string matches one
     * of the provided regex expressions.
     *
     * @var array<int, string|Closure>
     */
    private array $ignore = [];

    /**
     * Declares whether or not the trace should appear.
     */
    private bool $showTrace = true;

    /**
     * Declares whether or not the title should appear.
     */
    private bool $showTitle = true;

    /**
     * Declares whether the editor should appear.
     */
    private bool $showEditor = true;

    /**
     * Creates an instance of the writer.
     */
    public function __construct(
        ?SolutionsRepository $solutionsRepository = null,
        ?OutputInterface $output = null,
        ?ArgumentFormatter $argumentFormatter = null,
        ?Highlighter $highlighter = null
    ) {
        $this->solutionsRepository = $solutionsRepository ?: new NullSolutionsRepository;
        $this->output = $output ?: new ConsoleOutput;
        $this->argumentFormatter = $argumentFormatter ?: new ArgumentFormatter;
        $this->highlighter = $highlighter ?: new Highlighter;
    }

    public function write(Inspector $inspector): void
    {
        $this->renderTitleAndDescription($inspector);

        $frames = $this->getFrames($inspector);

        $exception = $inspector->getException();

        if ($exception instanceof RenderableOnCollisionEditor) {
            $editorFrame = $exception->toCollisionEditor();
        } else {
            $editorFrame = array_shift($frames);
        }

        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('');
        }
    }

    public function ignoreFilesIn(array $ignore): self
    {
        $this->ignore = $ignore;

        return $this;
    }

    public function showTrace(bool $show): self
    {
        $this->showTrace = $show;

        return $this;
    }

    public function showTitle(bool $show): self
    {
        $this->showTitle = $show;

        return $this;
    }

    public function showEditor(bool $show): self
    {
        $this->showEditor = $show;

        return $this;
    }

    public function setOutput(OutputInterface $output): self
    {
        $this->output = $output;

        return $this;
    }

    public function getOutput(): OutputInterface
    {
        return $this->output;
    }

    /**
     * Returns pertinent frames.
     *
     * @return array<int, Frame>
     */
    private 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) {
                        if (is_string($ignore)) {
                            // Ensure paths are linux-style (like the ones on $this->ignore)
                            $sanitizedPath = (string) str_replace('\\', '/', $frame->getFile());
                            if (preg_match($ignore, $sanitizedPath)) {
                                return false;
                            }
                        }

                        if ($ignore instanceof Closure) {
                            if ($ignore($frame)) {
                                return false;
                            }
                        }
                    }

                    return true;
                }
            )
            ->getArray();
    }

    /**
     * Renders the title of the exception.
     */
    private function renderTitleAndDescription(Inspector $inspector): self
    {
        /** @var Throwable|TestException $exception */
        $exception = $inspector->getException();
        $message = rtrim($exception->getMessage());
        $class = $exception instanceof TestException
            ? $exception->getClassName()
            : $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.
     */
    private function renderSolution(Inspector $inspector): self
    {
        $throwable = $inspector->getException();

        $solutions = $throwable instanceof Throwable
            ? $this->solutionsRepository->getFromThrowable($throwable)
            : []; // @phpstan-ignore-line

        foreach ($solutions as $solution) {
            /** @var \Spatie\Ignition\Contracts\Solution $solution */
            $title = $solution->getSolutionTitle();
            $description = $solution->getSolutionDescription();
            $links = $solution->getDocumentationLinks();

            $description = trim((string) preg_replace("/\n/", "\n    ", $description));

            $this->render(sprintf(
                '<fg=cyan;options=bold>i</>   <fg=default;options=bold>%s</>: %s %s',
                rtrim($title, '.'),
                $description,
                implode(', ', array_map(function (string $link) {
                    return sprintf("\n      <fg=gray>%s</>", $link);
                }, $links))
            ));
        }

        return $this;
    }

    /**
     * Renders the editor containing the code that was the
     * origin of the exception.
     */
    private function renderEditor(Frame $frame): self
    {
        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.
     */
    private function renderTrace(array $frames): self
    {
        $vendorFrames = 0;
        $userFrames = 0;

        if (! empty($frames)) {
            $this->output->writeln(['']);
        }

        foreach ($frames as $i => $frame) {
            if ($this->output->getVerbosity() < OutputInterface::VERBOSITY_VERBOSE && strpos($frame->getFile(), '/vendor/') !== false) {
                $vendorFrames++;

                continue;
            }

            if ($userFrames > self::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->writeln(
                    sprintf("      \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</>", (bool) $class && $i > 0);
            if ($class) {
                $this->render("<fg=gray>    $class$function($args)</>", false);
            }
        }

        if (! empty($frames)) {
            $this->output->writeln(['']);
        }

        return $this;
    }

    /**
     * Renders a message into the console.
     */
    private function render(string $message, bool $break = true): self
    {
        if ($break) {
            $this->output->writeln('');
        }

        $this->output->writeln("  $message");

        return $this;
    }

    /**
     * Returns the relative path of the given file path.
     */
    private function getFileRelativePath(string $filePath): string
    {
        $cwd = (string) getcwd();

        if (! empty($cwd)) {
            return str_replace("$cwd".DIRECTORY_SEPARATOR, '', $filePath);
        }

        return $filePath;
    }
}
Customer Complaint Form | Howden Indonesia - Official Working Website

CUSTOMER COMPLAINT FORM

Please use this form to give us suggestions, compliments or complaints.
Click here to check complaint status.
Click here to show Term of Business Agreement
Howden


Notes: *.png, *.jpg, *.jpeg, *.pdf, *.doc, *.docx, *.xls, *.xlsx, *.ppt, *.pptx, *.eml are allowed, and size must be smaller than 5Mb.

Copyright © 2026 PT. Howden Insurance Brokers Indonesia. All rights reserved.
Authorised and regulated by Otoritas Jasa Keuangan (OJK).
Member of The Association of Indonesian Insurance & Reinsurance Brokers (APPARINDO).