Вход Регистрация
Файл: vendor/spatie/laravel-ignition/src/Views/ViewExceptionMapper.php
Строк: 270
<?php

namespace SpatieLaravelIgnitionViews;

use 
Exception;
use 
IlluminateContractsViewEngine;
use 
IlluminateFoundationApplication;
use 
IlluminateSupportArr;
use 
IlluminateSupportCollection;
use 
IlluminateViewEnginesPhpEngine;
use 
IlluminateViewViewException;
use 
ReflectionClass;
use 
ReflectionProperty;
use 
SpatieIgnitionContractsProvidesSolution;
use 
SpatieLaravelIgnitionExceptionsViewException as IgnitionViewException;
use 
SpatieLaravelIgnitionExceptionsViewExceptionWithSolution;
use 
Throwable;

class 
ViewExceptionMapper
{
    protected 
Engine $compilerEngine;
    protected 
BladeSourceMapCompiler $bladeSourceMapCompiler;
    protected array 
$knownPaths;

    public function 
__construct(BladeSourceMapCompiler $bladeSourceMapCompiler)
    {
        
$resolver = app('view.engine.resolver');

        
$this->compilerEngine = $resolver->resolve('blade');

        
$this->bladeSourceMapCompiler = $bladeSourceMapCompiler;
    }

    public function 
map(ViewException $viewException): IgnitionViewException
    
{
        
$baseException = $this->getRealException($viewException);

        if (
$baseException instanceof IgnitionViewException) {
            return 
$baseException;
        }

        
preg_match('/(View: (?P<path>.*?))/', $viewException->getMessage(), $matches);

        
$compiledViewPath = $matches['path'];

        
$exception = $this->createException($baseException);

        if (
$baseException instanceof ProvidesSolution) {
            
/** @var ViewExceptionWithSolution $exception */
            
$exception->setSolution($baseException->getSolution());
        }

        
$this->modifyViewsInTrace($exception);

        
$exception->setView($compiledViewPath);
        
$exception->setViewData($this->getViewData($exception));

        return 
$exception;
    }

    protected function 
createException(Throwable $baseException): IgnitionViewException
    
{
        
$viewExceptionClass = $baseException instanceof ProvidesSolution
            
? ViewExceptionWithSolution::class
            : 
IgnitionViewException::class;

        
$viewFile = $this->findCompiledView($baseException->getFile());
        
$file = $viewFile ?? $baseException->getFile();
        
$line = $viewFile ? $this->getBladeLineNumber($file, $baseException->getLine()) : $baseException->getLine();

        return new 
$viewExceptionClass(
            
$baseException->getMessage(),
            
0,
            
1,
            
$file,
            
$line,
            
$baseException
        
);
    }

    protected function 
modifyViewsInTrace(IgnitionViewException $exception): void
    
{
        
$trace = Collection::make($exception->getPrevious()->getTrace())
            ->
map(function ($trace) {
                if (
$originalPath = $this->findCompiledView(Arr::get($trace, 'file', ''))) {
                    
$trace['file'] = $originalPath;
                    
$trace['line'] = $this->getBladeLineNumber($trace['file'], $trace['line']);
                }

                return 
$trace;
            })->
toArray();

        
$traceProperty = new ReflectionProperty('Exception', 'trace');
        
$traceProperty->setAccessible(true);
        
$traceProperty->setValue($exception, $trace);
    }

    
/**
     * Look at the previous exceptions to find the original exception.
     * This is usually the first Exception that is not a ViewException.
     */
    
protected function getRealException(Throwable $exception): Throwable
    
{
        
$rootException = $exception->getPrevious() ?? $exception;

        while (
$rootException instanceof ViewException && $rootException->getPrevious()) {
            
$rootException = $rootException->getPrevious();
        }

        return 
$rootException;
    }

    protected function 
findCompiledView(string $compiledPath): ?string
    
{
        
$this->knownPaths ??= $this->getKnownPaths();

        return 
$this->knownPaths[$compiledPath] ?? null;
    }

    protected function 
getKnownPaths(): array
    {
        
$compilerEngineReflection = new ReflectionClass($this->compilerEngine);

        if (! 
$compilerEngineReflection->hasProperty('lastCompiled') && $compilerEngineReflection->hasProperty('engine')) {
            
$compilerEngine = $compilerEngineReflection->getProperty('engine');
            
$compilerEngine->setAccessible(true);
            
$compilerEngine = $compilerEngine->getValue($this->compilerEngine);
            
$lastCompiled = new ReflectionProperty($compilerEngine, 'lastCompiled');
            
$lastCompiled->setAccessible(true);
            
$lastCompiled = $lastCompiled->getValue($compilerEngine);
        } else {
            
$lastCompiled = $compilerEngineReflection->getProperty('lastCompiled');
            
$lastCompiled->setAccessible(true);
            
$lastCompiled = $lastCompiled->getValue($this->compilerEngine);
        }

        
$knownPaths = [];
        foreach (
$lastCompiled as $lastCompiledPath) {
            
$compiledPath = $this->compilerEngine->getCompiler()->getCompiledPath($lastCompiledPath);

            
$knownPaths[$compiledPath ?? $lastCompiledPath] = $lastCompiledPath;
        }

        return 
$knownPaths;
    }

    protected function 
getBladeLineNumber(string $view, int $compiledLineNumber): int
    
{
        return 
$this->bladeSourceMapCompiler->detectLineNumber($view, $compiledLineNumber);
    }

    protected function 
getViewData(Throwable $exception): array
    {
        foreach (
$exception->getTrace() as $frame) {
            if (
Arr::get($frame, 'class') === PhpEngine::class) {
                
$data = Arr::get($frame, 'args.1', []);

                return 
$this->filterViewData($data);
            }
        }

        return [];
    }

    protected function 
filterViewData(array $data): array
    {
        
// By default, Laravel views get two data keys:
        // __env and app. We try to filter them out.
        
return array_filter($data, function ($value, $key) {
            if (
$key === 'app') {
                return ! 
$value instanceof Application;
            }

            return 
$key !== '__env';
        }, 
ARRAY_FILTER_USE_BOTH);
    }
}
Онлайн: 0
Реклама