Вход Регистрация
Файл: vendor/symfony/error-handler/Exception/FlattenException.php
Строк: 423
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace SymfonyComponentErrorHandlerException;

use 
SymfonyComponentHttpFoundationExceptionRequestExceptionInterface;
use 
SymfonyComponentHttpFoundationResponse;
use 
SymfonyComponentHttpKernelExceptionHttpExceptionInterface;
use 
SymfonyComponentVarDumperCasterCaster;
use 
SymfonyComponentVarDumperClonerData;
use 
SymfonyComponentVarDumperClonerStub;
use 
SymfonyComponentVarDumperClonerVarCloner;

/**
 * FlattenException wraps a PHP Error or Exception to be able to serialize it.
 *
 * Basically, this class removes all objects from the trace.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class FlattenException
{
    private 
string $message;
    private 
string|int $code;
    private ?
self $previous null;
    private array 
$trace;
    private 
string $traceAsString;
    private 
string $class;
    private 
int $statusCode;
    private 
string $statusText;
    private array 
$headers;
    private 
string $file;
    private 
int $line;
    private ?
string $asString null;
    private 
Data $dataRepresentation;

    public static function 
create(Exception $exception, ?int $statusCode null, array $headers = []): static
    {
        return static::
createFromThrowable($exception$statusCode$headers);
    }

    public static function 
createFromThrowable(Throwable $exception, ?int $statusCode null, array $headers = []): static
    {
        
$e = new static();
        
$e->setMessage($exception->getMessage());
        
$e->setCode($exception->getCode());

        if (
$exception instanceof HttpExceptionInterface) {
            
$statusCode $exception->getStatusCode();
            
$headers array_merge($headers$exception->getHeaders());
        } elseif (
$exception instanceof RequestExceptionInterface) {
            
$statusCode 400;
        }

        
$statusCode ??= 500;

        if (
class_exists(Response::class) && isset(Response::$statusTexts[$statusCode])) {
            
$statusText Response::$statusTexts[$statusCode];
        } else {
            
$statusText 'Whoops, looks like something went wrong.';
        }

        
$e->setStatusText($statusText);
        
$e->setStatusCode($statusCode);
        
$e->setHeaders($headers);
        
$e->setTraceFromThrowable($exception);
        
$e->setClass(get_debug_type($exception));
        
$e->setFile($exception->getFile());
        
$e->setLine($exception->getLine());

        
$previous $exception->getPrevious();

        if (
$previous instanceof Throwable) {
            
$e->setPrevious(static::createFromThrowable($previous));
        }

        return 
$e;
    }

    public static function 
createWithDataRepresentation(Throwable $throwable, ?int $statusCode null, array $headers = [], ?VarCloner $cloner null): static
    {
        
$e = static::createFromThrowable($throwable$statusCode$headers);

        static 
$defaultCloner;

        if (!
$cloner ??= $defaultCloner) {
            
$cloner $defaultCloner = new VarCloner();
            
$cloner->addCasters([
                
Throwable::class => function (Throwable $e, array $aStub $sbool $isNested): array {
                    if (!
$isNested) {
                        unset(
$a[Caster::PREFIX_PROTECTED.'message']);
                        unset(
$a[Caster::PREFIX_PROTECTED.'code']);
                        unset(
$a[Caster::PREFIX_PROTECTED.'file']);
                        unset(
$a[Caster::PREFIX_PROTECTED.'line']);
                        unset(
$a["Errortrace"], $a["Exceptiontrace"]);
                        unset(
$a["Errorprevious"], $a["Exceptionprevious"]);
                    }

                    return 
$a;
                },
            ]);
        }

        return 
$e->setDataRepresentation($cloner->cloneVar($throwable));
    }

    public function 
toArray(): array
    {
        
$exceptions = [];
        foreach (
array_merge([$this], $this->getAllPrevious()) as $exception) {
            
$exceptions[] = [
                
'message' => $exception->getMessage(),
                
'class' => $exception->getClass(),
                
'trace' => $exception->getTrace(),
                
'data' => $exception->getDataRepresentation(),
            ];
        }

        return 
$exceptions;
    }

    public function 
getStatusCode(): int
    
{
        return 
$this->statusCode;
    }

    
/**
     * @return $this
     */
    
public function setStatusCode(int $code): static
    {
        
$this->statusCode $code;

        return 
$this;
    }

    public function 
getHeaders(): array
    {
        return 
$this->headers;
    }

    
/**
     * @return $this
     */
    
public function setHeaders(array $headers): static
    {
        
$this->headers $headers;

        return 
$this;
    }

    public function 
getClass(): string
    
{
        return 
$this->class;
    }

    
/**
     * @return $this
     */
    
public function setClass(string $class): static
    {
        
$this->class str_contains($class"@anonymous") ? (get_parent_class($class) ?: key(class_implements($class)) ?: 'class').'@anonymous' $class;

        return 
$this;
    }

    public function 
getFile(): string
    
{
        return 
$this->file;
    }

    
/**
     * @return $this
     */
    
public function setFile(string $file): static
    {
        
$this->file $file;

        return 
$this;
    }

    public function 
getLine(): int
    
{
        return 
$this->line;
    }

    
/**
     * @return $this
     */
    
public function setLine(int $line): static
    {
        
$this->line $line;

        return 
$this;
    }

    public function 
getStatusText(): string
    
{
        return 
$this->statusText;
    }

    
/**
     * @return $this
     */
    
public function setStatusText(string $statusText): static
    {
        
$this->statusText $statusText;

        return 
$this;
    }

    public function 
getMessage(): string
    
{
        return 
$this->message;
    }

    
/**
     * @return $this
     */
    
public function setMessage(string $message): static
    {
        if (
str_contains($message"@anonymous")) {
            
$message preg_replace_callback('/[a-zA-Z_x7f-xff][\\a-zA-Z0-9_x7f-xff]*+@anonymousx00.*?.php(?:0x?|:[0-9]++$)?[0-9a-fA-F]++/'fn ($m) => class_exists($m[0], false) ? (get_parent_class($m[0]) ?: key(class_implements($m[0])) ?: 'class').'@anonymous' $m[0], $message);
        }

        
$this->message $message;

        return 
$this;
    }

    
/**
     * @return int|string int most of the time (might be a string with PDOException)
     */
    
public function getCode(): int|string
    
{
        return 
$this->code;
    }

    
/**
     * @return $this
     */
    
public function setCode(int|string $code): static
    {
        
$this->code $code;

        return 
$this;
    }

    public function 
getPrevious(): ?self
    
{
        return 
$this->previous;
    }

    
/**
     * @return $this
     */
    
public function setPrevious(?self $previous): static
    {
        
$this->previous $previous;

        return 
$this;
    }

    
/**
     * @return self[]
     */
    
public function getAllPrevious(): array
    {
        
$exceptions = [];
        
$e $this;
        while (
$e $e->getPrevious()) {
            
$exceptions[] = $e;
        }

        return 
$exceptions;
    }

    public function 
getTrace(): array
    {
        return 
$this->trace;
    }

    
/**
     * @return $this
     */
    
public function setTraceFromThrowable(Throwable $throwable): static
    {
        
$this->traceAsString $throwable->getTraceAsString();

        return 
$this->setTrace($throwable->getTrace(), $throwable->getFile(), $throwable->getLine());
    }

    
/**
     * @return $this
     */
    
public function setTrace(array $trace, ?string $file, ?int $line): static
    {
        
$this->trace = [];
        
$this->trace[] = [
            
'namespace' => '',
            
'short_class' => '',
            
'class' => '',
            
'type' => '',
            
'function' => '',
            
'file' => $file,
            
'line' => $line,
            
'args' => [],
        ];
        foreach (
$trace as $entry) {
            
$class '';
            
$namespace '';
            if (isset(
$entry['class'])) {
                
$parts explode('\', $entry['class']);
                $class = array_pop($parts);
                $namespace = implode('
\', $parts);
            }

            $this->trace[] = [
                '
namespace' => $namespace,
                '
short_class' => $class,
                '
class' => $entry['class'] ?? '',
                '
type' => $entry['type'] ?? '',
                '
function' => $entry['function'] ?? null,
                '
file' => $entry['file'] ?? null,
                '
line' => $entry['line'] ?? null,
                '
args' => isset($entry['args']) ? $this->flattenArgs($entry['args']) : [],
            ];
        }

        return $this;
    }

    public function getDataRepresentation(): ?Data
    {
        return $this->dataRepresentation ?? null;
    }

    /**
     * @return $this
     */
    public function setDataRepresentation(Data $data): static
    {
        $this->dataRepresentation = $data;

        return $this;
    }

    private function flattenArgs(array $args, int $level = 0, int &$count = 0): array
    {
        $result = [];
        foreach ($args as $key => $value) {
            if (++$count > 1e4) {
                return ['
array', '*SKIPPED over 10000 entries*'];
            }
            if ($value instanceof __PHP_Incomplete_Class) {
                $result[$key] = ['
incomplete-object', $this->getClassNameFromIncomplete($value)];
            } elseif (is_object($value)) {
                $result[$key] = ['
object', get_debug_type($value)];
            } elseif (is_array($value)) {
                if ($level > 10) {
                    $result[$key] = ['
array', '*DEEP NESTED ARRAY*'];
                } else {
                    $result[$key] = ['
array', $this->flattenArgs($value, $level + 1, $count)];
                }
            } elseif (null === $value) {
                $result[$key] = ['
null', null];
            } elseif (is_bool($value)) {
                $result[$key] = ['
boolean', $value];
            } elseif (is_int($value)) {
                $result[$key] = ['
integer', $value];
            } elseif (is_float($value)) {
                $result[$key] = ['
float', $value];
            } elseif (is_resource($value)) {
                $result[$key] = ['
resource', get_resource_type($value)];
            } else {
                $result[$key] = ['
string', (string) $value];
            }
        }

        return $result;
    }

    private function getClassNameFromIncomplete(__PHP_Incomplete_Class $value): string
    {
        $array = new ArrayObject($value);

        return $array['
__PHP_Incomplete_Class_Name'];
    }

    public function getTraceAsString(): string
    {
        return $this->traceAsString;
    }

    /**
     * @return $this
     */
    public function setAsString(?string $asString): static
    {
        $this->asString = $asString;

        return $this;
    }

    public function getAsString(): string
    {
        if (null !== $this->asString) {
            return $this->asString;
        }

        $message = '';
        $next = false;

        foreach (array_reverse(array_merge([$this], $this->getAllPrevious())) as $exception) {
            if ($next) {
                $message .= '
Next ';
            } else {
                $next = true;
            }
            $message .= $exception->getClass();

            if ('' != $exception->getMessage()) {
                $message .= '
'.$exception->getMessage();
            }

            $message .= ' 
in '.$exception->getFile().':'.$exception->getLine().
                "nStack trace:n".$exception->getTraceAsString()."nn";
        }

        return rtrim($message);
    }
}
Онлайн: 0
Реклама