vendor/symfony/debug/Exception/FlattenException.php line 24

Open in your IDE?
  1. <?php
  2. /*
  3.  * This file is part of the Symfony package.
  4.  *
  5.  * (c) Fabien Potencier <fabien@symfony.com>
  6.  *
  7.  * For the full copyright and license information, please view the LICENSE
  8.  * file that was distributed with this source code.
  9.  */
  10. namespace Symfony\Component\Debug\Exception;
  11. use Symfony\Component\HttpFoundation\Exception\RequestExceptionInterface;
  12. use Symfony\Component\HttpKernel\Exception\HttpExceptionInterface;
  13. /**
  14.  * FlattenException wraps a PHP Error or Exception to be able to serialize it.
  15.  *
  16.  * Basically, this class removes all objects from the trace.
  17.  *
  18.  * @author Fabien Potencier <fabien@symfony.com>
  19.  */
  20. class FlattenException
  21. {
  22.     private $message;
  23.     private $code;
  24.     private $previous;
  25.     private $trace;
  26.     private $traceAsString;
  27.     private $class;
  28.     private $statusCode;
  29.     private $headers;
  30.     private $file;
  31.     private $line;
  32.     public static function create(\Exception $exception$statusCode null, array $headers = [])
  33.     {
  34.         return static::createFromThrowable($exception$statusCode$headers);
  35.     }
  36.     public static function createFromThrowable(\Throwable $exception, ?int $statusCode null, array $headers = []): self
  37.     {
  38.         $e = new static();
  39.         $e->setMessage($exception->getMessage());
  40.         $e->setCode($exception->getCode());
  41.         if ($exception instanceof HttpExceptionInterface) {
  42.             $statusCode $exception->getStatusCode();
  43.             $headers array_merge($headers$exception->getHeaders());
  44.         } elseif ($exception instanceof RequestExceptionInterface) {
  45.             $statusCode 400;
  46.         }
  47.         if (null === $statusCode) {
  48.             $statusCode 500;
  49.         }
  50.         $e->setStatusCode($statusCode);
  51.         $e->setHeaders($headers);
  52.         $e->setTraceFromThrowable($exception);
  53.         $e->setClass($exception instanceof FatalThrowableError $exception->getOriginalClassName() : \get_class($exception));
  54.         $e->setFile($exception->getFile());
  55.         $e->setLine($exception->getLine());
  56.         $previous $exception->getPrevious();
  57.         if ($previous instanceof \Throwable) {
  58.             $e->setPrevious(static::createFromThrowable($previous));
  59.         }
  60.         return $e;
  61.     }
  62.     public function toArray()
  63.     {
  64.         $exceptions = [];
  65.         foreach (array_merge([$this], $this->getAllPrevious()) as $exception) {
  66.             $exceptions[] = [
  67.                 'message' => $exception->getMessage(),
  68.                 'class' => $exception->getClass(),
  69.                 'trace' => $exception->getTrace(),
  70.             ];
  71.         }
  72.         return $exceptions;
  73.     }
  74.     public function getStatusCode()
  75.     {
  76.         return $this->statusCode;
  77.     }
  78.     /**
  79.      * @return $this
  80.      */
  81.     public function setStatusCode($code)
  82.     {
  83.         $this->statusCode $code;
  84.         return $this;
  85.     }
  86.     public function getHeaders()
  87.     {
  88.         return $this->headers;
  89.     }
  90.     /**
  91.      * @return $this
  92.      */
  93.     public function setHeaders(array $headers)
  94.     {
  95.         $this->headers $headers;
  96.         return $this;
  97.     }
  98.     public function getClass()
  99.     {
  100.         return $this->class;
  101.     }
  102.     /**
  103.      * @return $this
  104.      */
  105.     public function setClass($class)
  106.     {
  107.         $this->class 'c' === $class[0] && === strpos($class"class@anonymous\0") ? get_parent_class($class).'@anonymous' $class;
  108.         return $this;
  109.     }
  110.     public function getFile()
  111.     {
  112.         return $this->file;
  113.     }
  114.     /**
  115.      * @return $this
  116.      */
  117.     public function setFile($file)
  118.     {
  119.         $this->file $file;
  120.         return $this;
  121.     }
  122.     public function getLine()
  123.     {
  124.         return $this->line;
  125.     }
  126.     /**
  127.      * @return $this
  128.      */
  129.     public function setLine($line)
  130.     {
  131.         $this->line $line;
  132.         return $this;
  133.     }
  134.     public function getMessage()
  135.     {
  136.         return $this->message;
  137.     }
  138.     /**
  139.      * @return $this
  140.      */
  141.     public function setMessage($message)
  142.     {
  143.         if (false !== strpos($message"class@anonymous\0")) {
  144.             $message preg_replace_callback('/class@anonymous\x00.*?\.php0x?[0-9a-fA-F]++/', function ($m) {
  145.                 return class_exists($m[0], false) ? get_parent_class($m[0]).'@anonymous' $m[0];
  146.             }, $message);
  147.         }
  148.         $this->message $message;
  149.         return $this;
  150.     }
  151.     public function getCode()
  152.     {
  153.         return $this->code;
  154.     }
  155.     /**
  156.      * @return $this
  157.      */
  158.     public function setCode($code)
  159.     {
  160.         $this->code $code;
  161.         return $this;
  162.     }
  163.     public function getPrevious()
  164.     {
  165.         return $this->previous;
  166.     }
  167.     /**
  168.      * @return $this
  169.      */
  170.     public function setPrevious(self $previous)
  171.     {
  172.         $this->previous $previous;
  173.         return $this;
  174.     }
  175.     public function getAllPrevious()
  176.     {
  177.         $exceptions = [];
  178.         $e $this;
  179.         while ($e $e->getPrevious()) {
  180.             $exceptions[] = $e;
  181.         }
  182.         return $exceptions;
  183.     }
  184.     public function getTrace()
  185.     {
  186.         return $this->trace;
  187.     }
  188.     /**
  189.      * @deprecated since 4.1, use {@see setTraceFromThrowable()} instead.
  190.      */
  191.     public function setTraceFromException(\Exception $exception)
  192.     {
  193.         @trigger_error(sprintf('The "%s()" method is deprecated since Symfony 4.1, use "setTraceFromThrowable()" instead.'__METHOD__), E_USER_DEPRECATED);
  194.         $this->setTraceFromThrowable($exception);
  195.     }
  196.     public function setTraceFromThrowable(\Throwable $throwable)
  197.     {
  198.         $this->traceAsString $throwable->getTraceAsString();
  199.         return $this->setTrace($throwable->getTrace(), $throwable->getFile(), $throwable->getLine());
  200.     }
  201.     /**
  202.      * @return $this
  203.      */
  204.     public function setTrace($trace$file$line)
  205.     {
  206.         $this->trace = [];
  207.         $this->trace[] = [
  208.             'namespace' => '',
  209.             'short_class' => '',
  210.             'class' => '',
  211.             'type' => '',
  212.             'function' => '',
  213.             'file' => $file,
  214.             'line' => $line,
  215.             'args' => [],
  216.         ];
  217.         foreach ($trace as $entry) {
  218.             $class '';
  219.             $namespace '';
  220.             if (isset($entry['class'])) {
  221.                 $parts explode('\\'$entry['class']);
  222.                 $class array_pop($parts);
  223.                 $namespace implode('\\'$parts);
  224.             }
  225.             $this->trace[] = [
  226.                 'namespace' => $namespace,
  227.                 'short_class' => $class,
  228.                 'class' => isset($entry['class']) ? $entry['class'] : '',
  229.                 'type' => isset($entry['type']) ? $entry['type'] : '',
  230.                 'function' => isset($entry['function']) ? $entry['function'] : null,
  231.                 'file' => isset($entry['file']) ? $entry['file'] : null,
  232.                 'line' => isset($entry['line']) ? $entry['line'] : null,
  233.                 'args' => isset($entry['args']) ? $this->flattenArgs($entry['args']) : [],
  234.             ];
  235.         }
  236.         return $this;
  237.     }
  238.     private function flattenArgs($args$level 0, &$count 0)
  239.     {
  240.         $result = [];
  241.         foreach ($args as $key => $value) {
  242.             if (++$count 1e4) {
  243.                 return ['array''*SKIPPED over 10000 entries*'];
  244.             }
  245.             if ($value instanceof \__PHP_Incomplete_Class) {
  246.                 // is_object() returns false on PHP<=7.1
  247.                 $result[$key] = ['incomplete-object'$this->getClassNameFromIncomplete($value)];
  248.             } elseif (\is_object($value)) {
  249.                 $result[$key] = ['object', \get_class($value)];
  250.             } elseif (\is_array($value)) {
  251.                 if ($level 10) {
  252.                     $result[$key] = ['array''*DEEP NESTED ARRAY*'];
  253.                 } else {
  254.                     $result[$key] = ['array'$this->flattenArgs($value$level 1$count)];
  255.                 }
  256.             } elseif (null === $value) {
  257.                 $result[$key] = ['null'null];
  258.             } elseif (\is_bool($value)) {
  259.                 $result[$key] = ['boolean'$value];
  260.             } elseif (\is_int($value)) {
  261.                 $result[$key] = ['integer'$value];
  262.             } elseif (\is_float($value)) {
  263.                 $result[$key] = ['float'$value];
  264.             } elseif (\is_resource($value)) {
  265.                 $result[$key] = ['resource'get_resource_type($value)];
  266.             } else {
  267.                 $result[$key] = ['string', (string) $value];
  268.             }
  269.         }
  270.         return $result;
  271.     }
  272.     private function getClassNameFromIncomplete(\__PHP_Incomplete_Class $value)
  273.     {
  274.         $array = new \ArrayObject($value);
  275.         return $array['__PHP_Incomplete_Class_Name'];
  276.     }
  277.     public function getTraceAsString()
  278.     {
  279.         return $this->traceAsString;
  280.     }
  281.     public function getAsString()
  282.     {
  283.         $message '';
  284.         $next false;
  285.         foreach (array_reverse(array_merge([$this], $this->getAllPrevious())) as $exception) {
  286.             if ($next) {
  287.                 $message .= 'Next ';
  288.             } else {
  289.                 $next true;
  290.             }
  291.             $message .= $exception->getClass();
  292.             if ('' != $exception->getMessage()) {
  293.                 $message .= ': '.$exception->getMessage();
  294.             }
  295.             $message .= ' in '.$exception->getFile().':'.$exception->getLine().
  296.                 "\nStack trace:\n".$exception->getTraceAsString()."\n\n";
  297.         }
  298.         return rtrim($message);
  299.     }
  300. }