Base.php

<?php

namespace Lia\Exception;

/**
 * Prints out trace information for the call into Liaison, so you see the non-liaison source of the error above the stack trace
 *
 * @todo delete all other Exceptions in the code base.
 * @todo Add some extensibility to this class
 * @todo Write subclasses on an as-needed basis. Maybe I can just write an array of ExceptionName=>SpecialMessage & Base::throw('ExceptionName'); or something. Or `onExceptionName()` to return a message or something
 * @todo create Exception Templates that let you customize the output of all exceptions.
 */
class Base extends \Exception {

    protected $trace;
    protected $message;
    protected $dir;

    protected $subs = [];

    public $liaMessage;

    public function __construct($message){

        $this->dir = dirname(dirname(__DIR__));
        // $this->trace = $this->getExternalTrace();

        $this->liaMessage = $message;

        parent::__construct("\n");
        $this->message = $message;
    }



    public function getExternalTrace(){
        if ($this->trace!=null)return  $this->trace;

        $list = $this->getTrace();
        $et = null;

        $message = "";

        foreach ($list as $depth => $trace){        #2 [internal function]: Lia\Route\Router->global_contentFor()
            $trace['line'] = $trace['line'] ?? '--n/a--';
            $file = $trace['file'] ?? '--n/a--';
            $trace['file'] = $file;
            $sub = substr($file,0,strlen($this->dir));
            if ($file=='--n/a--'){
                $message .= "Anonymous functions at stack #".$depth."\n";
                continue;
            } else if ($sub==$this->dir){
                continue;
            }
            $et = $trace;
            $next = $list[$depth+1] ?? null;
            break;
        }
        $trace = (object) array_merge(
            ['raw'=>$et,
            'depth'=>$depth,
            'extraInfo'=>$message,
            ],
            $et,
        );
        $trace->calledClass = $trace->class;
        unset($trace->class);
        $trace->calledFunction = $trace->function;
        if ($trace->function=='__call'){
            //@TODO get the args (using debug_backtrace in the constructor) & provide the actual method call.
        }

        unset($trace->function);
        $trace->fromClass = $next['class'] ?? '--n/a--';
        $trace->fromFunction = $next['function'] ?? '--n/a--';

        $this->trace = $trace;
        return $trace;
    }
    
    public function __toString(){
        $trace = $this->getExternalTrace();
        // $traceRaw = print_r($trace,true);
        $parent = parent::__toString();
        $message = $this->liaMessage;
        $html = 
        <<<HTML
        <div style="white-space:normal">
            <h1>Exception</h1>
            <pre>
                {$message}
            </pre>
            <p>Error caused by calling  {$trace->calledClass}->{$trace->calledFunction} from:</p>
            <ul>
                <li>File: {$trace->file}</li>
                <li>Line: {$trace->line}</li>
                <li>Class: {$trace->fromClass}</li>
                <li>Function: {$trace->fromFunction}</li>
                <li>Stack trace depth: #{$trace->depth}</li>
                <li>Extra Info: {$trace->extraInfo}</li>
            </ul>
        </div>
            {$parent}
        HTML;

        return $html;
        // return "Babies";
    }
}