Skip to content

Commit e7e88c3

Browse files
committed
bug #2096 Fix compatibility with symfony 3.4 and \Error (GuigZ-)
This PR was merged into the 2.7 branch. Discussion ---------- Fix compatibility with symfony 3.4 and \Error Commits ------- 62a422d fix(throwable): fix template data with symfony 3.4
2 parents e7b0d91 + 62a422d commit e7e88c3

File tree

3 files changed

+149
-11
lines changed

3 files changed

+149
-11
lines changed

Controller/ExceptionController.php

Lines changed: 21 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,12 @@
1111

1212
namespace FOS\RestBundle\Controller;
1313

14+
use FOS\RestBundle\Exception\FlattenException as FosFlattenException;
1415
use FOS\RestBundle\Util\ExceptionValueMap;
1516
use FOS\RestBundle\View\View;
1617
use FOS\RestBundle\View\ViewHandlerInterface;
1718
use Symfony\Component\HttpFoundation\Request;
1819
use Symfony\Component\HttpFoundation\Response;
19-
use Symfony\Component\Debug\Exception\FlattenException as LegacyFlattenException;
2020
use Symfony\Component\ErrorHandler\Exception\FlattenException;
2121
use Symfony\Component\HttpKernel\Exception\HttpExceptionInterface;
2222
use Symfony\Component\HttpKernel\Log\DebugLoggerInterface;
@@ -73,7 +73,12 @@ public function showAction(Request $request, $exception, DebugLoggerInterface $l
7373
}
7474
$templateData = $this->getTemplateData($currentContent, $code, $exception, $logger);
7575

76-
$view = $this->createView($exception, $code, $templateData, $request, $this->showException);
76+
if ($exception instanceof \Exception) {
77+
$view = $this->createView($exception, $code, $templateData, $request, $this->showException);
78+
} else {
79+
$view = $this->createViewFromThrowable($exception, $code, $templateData, $request, $this->showException);
80+
}
81+
7782
$response = $this->viewHandler->handle($view);
7883

7984
return $response;
@@ -90,11 +95,7 @@ public function showAction(Request $request, $exception, DebugLoggerInterface $l
9095
*/
9196
protected function createView(\Exception $exception, $code, array $templateData, Request $request, $showException)
9297
{
93-
$view = new View($exception, $code, $exception instanceof HttpExceptionInterface ? $exception->getHeaders() : []);
94-
$view->setTemplateVar('raw_exception');
95-
$view->setTemplateData($templateData);
96-
97-
return $view;
98+
return $this->createViewFromThrowable($exception, $code, $templateData);
9899
}
99100

100101
/**
@@ -109,22 +110,31 @@ protected function getStatusCode(\Exception $exception)
109110
return $this->getStatusCodeFromThrowable($exception);
110111
}
111112

113+
private function createViewFromThrowable(\Throwable $exception, $code, array $templateData): View
114+
{
115+
$view = new View($exception, $code, $exception instanceof HttpExceptionInterface ? $exception->getHeaders() : []);
116+
$view->setTemplateVar('raw_exception');
117+
$view->setTemplateData($templateData);
118+
119+
return $view;
120+
}
121+
112122
/**
113123
* Determines the template parameters to pass to the view layer.
114124
*
115125
* @param string $currentContent
116126
* @param int $code
117-
* @param \Exception $exception
127+
* @param \Throwable $throwable
118128
* @param DebugLoggerInterface $logger
119129
*
120130
* @return array
121131
*/
122-
private function getTemplateData($currentContent, $code, \Exception $exception, DebugLoggerInterface $logger = null)
132+
private function getTemplateData($currentContent, $code, \Throwable $throwable, DebugLoggerInterface $logger = null)
123133
{
124134
if (class_exists(FlattenException::class)) {
125-
$exception = FlattenException::createFromThrowable($exception);
135+
$exception = FlattenException::createFromThrowable($throwable);
126136
} else {
127-
$exception = LegacyFlattenException::create($exception);
137+
$exception = FosFlattenException::createFromThrowable($throwable);
128138
}
129139

130140
return [

Exception/FlattenException.php

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the FOSRestBundle package.
5+
*
6+
* (c) FriendsOfSymfony <http://friendsofsymfony.github.com/>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace FOS\RestBundle\Exception;
13+
14+
use Symfony\Component\Debug\Exception\FlattenException as LegacyFlattenException;
15+
use Symfony\Component\HttpFoundation\Exception\RequestExceptionInterface;
16+
use Symfony\Component\HttpKernel\Exception\HttpExceptionInterface;
17+
18+
if (method_exists(LegacyFlattenException::class, 'createFromThrowable')) {
19+
/**
20+
* @internal
21+
*/
22+
class FlattenException extends LegacyFlattenException
23+
{
24+
}
25+
} else {
26+
/**
27+
* @internal
28+
*/
29+
class FlattenException extends LegacyFlattenException
30+
{
31+
private $traceAsString;
32+
33+
/**
34+
* @return static
35+
*/
36+
public static function createFromThrowable(\Throwable $exception, int $statusCode = null, array $headers = [])
37+
{
38+
$e = new static();
39+
$e->setMessage($exception->getMessage());
40+
$e->setCode($exception->getCode());
41+
42+
if ($exception instanceof HttpExceptionInterface) {
43+
$statusCode = $exception->getStatusCode();
44+
$headers = array_merge($headers, $exception->getHeaders());
45+
} elseif ($exception instanceof RequestExceptionInterface) {
46+
$statusCode = 400;
47+
}
48+
49+
if (null === $statusCode) {
50+
$statusCode = 500;
51+
}
52+
53+
$e->setStatusCode($statusCode);
54+
$e->setHeaders($headers);
55+
$e->setTraceFromThrowable($exception);
56+
$e->setClass($exception instanceof FatalThrowableError ? $exception->getOriginalClassName() : \get_class($exception));
57+
$e->setFile($exception->getFile());
58+
$e->setLine($exception->getLine());
59+
60+
$previous = $exception->getPrevious();
61+
62+
if ($previous instanceof \Throwable) {
63+
$e->setPrevious(static::createFromThrowable($previous));
64+
}
65+
66+
return $e;
67+
}
68+
69+
public function setTraceFromThrowable(\Throwable $throwable)
70+
{
71+
$this->traceAsString = $throwable->getTraceAsString();
72+
73+
return $this->setTrace($throwable->getTrace(), $throwable->getFile(), $throwable->getLine());
74+
}
75+
}
76+
}
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the FOSRestBundle package.
5+
*
6+
* (c) FriendsOfSymfony <http://friendsofsymfony.github.com/>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace FOS\RestBundle\Tests\Controller;
13+
14+
use FOS\RestBundle\Controller\ExceptionController;
15+
use FOS\RestBundle\Util\ExceptionValueMap;
16+
use FOS\RestBundle\View\View;
17+
use FOS\RestBundle\View\ViewHandlerInterface;
18+
use PHPUnit\Framework\TestCase;
19+
use Symfony\Component\HttpFoundation\Request;
20+
use Symfony\Component\HttpFoundation\Response;
21+
22+
class ExceptionControllerTest extends TestCase
23+
{
24+
/**
25+
* @dataProvider provideThrowables
26+
*/
27+
public function testShowActionWithError(\Throwable $throwable): void
28+
{
29+
$request = Request::create('/');
30+
$request->headers->set('X-Php-Ob-Level', '2');
31+
32+
$response = new Response();
33+
34+
$viewHandler = $this->createMock(ViewHandlerInterface::class);
35+
$viewHandler->expects($this->once())
36+
->method('handle')
37+
->with($this->isInstanceOf(View::class))
38+
->willReturn($response);
39+
40+
$controller = new ExceptionController($viewHandler, new ExceptionValueMap([]), true);
41+
42+
$this->assertSame($response, $controller->showAction($request, $throwable));
43+
}
44+
45+
public function provideThrowables(): array
46+
{
47+
return [
48+
[new \Error()],
49+
[new \Exception()],
50+
];
51+
}
52+
}

0 commit comments

Comments
 (0)