1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
namespace Victoire\Bundle\TwigBundle\Controller; |
4
|
|
|
|
5
|
|
|
use Doctrine\ORM\EntityManager; |
6
|
|
|
use Symfony\Bundle\TwigBundle\Controller\ExceptionController as BaseExceptionController; |
7
|
|
|
use Symfony\Component\HttpFoundation\Request; |
8
|
|
|
use Symfony\Component\HttpFoundation\RequestStack; |
9
|
|
|
use Symfony\Component\HttpFoundation\Response; |
10
|
|
|
use Symfony\Component\HttpKernel\Exception\FlattenException; |
11
|
|
|
use Symfony\Component\HttpKernel\HttpKernelInterface; |
12
|
|
|
use Symfony\Component\HttpKernel\Log\DebugLoggerInterface; |
13
|
|
|
use Symfony\Component\Routing\Router; |
14
|
|
|
|
15
|
|
|
/** |
16
|
|
|
* Redirects to a victoire error page when facing a Flatted Exception. |
17
|
|
|
*/ |
18
|
|
|
class ExceptionController extends BaseExceptionController |
19
|
|
|
{ |
20
|
|
|
private $em; |
21
|
|
|
|
22
|
|
|
/** |
23
|
|
|
* @var array Available locales for the Victoire website |
24
|
|
|
*/ |
25
|
|
|
private $availableLocales; |
26
|
|
|
/** |
27
|
|
|
* @var string the fallback locale |
28
|
|
|
*/ |
29
|
|
|
private $defaultLocale; |
30
|
|
|
|
31
|
|
|
/** |
32
|
|
|
* ExceptionController constructor. |
33
|
|
|
* |
34
|
|
|
* @param \Twig_Environment $twig |
35
|
|
|
* @param bool $debug |
36
|
|
|
* @param EntityManager $em |
37
|
|
|
* @param HttpKernelInterface $httpKernel |
38
|
|
|
* @param RequestStack $requestStack |
39
|
|
|
* @param Router $router |
40
|
|
|
* @param array $availableLocales |
41
|
|
|
* @param string $defaultLocale |
42
|
|
|
*/ |
43
|
|
|
public function __construct(\Twig_Environment $twig, $debug, EntityManager $em, HttpKernelInterface $httpKernel, RequestStack $requestStack, Router $router, array $availableLocales, $defaultLocale) |
|
|
|
|
44
|
|
|
{ |
45
|
|
|
parent::__construct($twig, $debug); |
46
|
|
|
$this->twig = $twig; |
47
|
|
|
$this->debug = $debug; |
48
|
|
|
$this->em = $em; |
49
|
|
|
$this->kernel = $httpKernel; |
|
|
|
|
50
|
|
|
$this->request = $requestStack->getCurrentRequest(); |
|
|
|
|
51
|
|
|
$this->router = $router; |
|
|
|
|
52
|
|
|
$this->availableLocales = $availableLocales; |
53
|
|
|
$this->defaultLocale = $defaultLocale; |
54
|
|
|
} |
55
|
|
|
|
56
|
|
|
/** |
57
|
|
|
* Converts an Exception to a Response to be able to render a Victoire view. |
58
|
|
|
* |
59
|
|
|
* @param Request $request The request |
60
|
|
|
* @param FlattenException $exception A FlattenException instance |
61
|
|
|
* @param DebugLoggerInterface $logger A DebugLoggerInterface instance |
62
|
|
|
* @param string $_format The format to use for rendering (html, xml, ...) |
63
|
|
|
* |
64
|
|
|
* @throws \InvalidArgumentException When the exception template does not exist |
65
|
|
|
* |
66
|
|
|
* @return Response |
67
|
|
|
*/ |
68
|
|
|
public function showAction(Request $request, FlattenException $exception, DebugLoggerInterface $logger = null, $_format = 'html') |
69
|
|
|
{ |
70
|
|
|
$currentContent = $this->getAndCleanOutputBuffering($request->headers->get('X-Php-Ob-Level', -1)); |
|
|
|
|
71
|
|
|
$code = $exception->getStatusCode(); |
72
|
|
|
|
73
|
|
|
//get request extension |
74
|
|
|
$uriArray = explode('/', rtrim($request->getRequestUri(), '/')); |
75
|
|
|
|
76
|
|
|
$matches = preg_match('/^.*(\..*)$/', array_pop($uriArray), $matches); |
77
|
|
|
|
78
|
|
|
$locale = $request->getLocale(); |
79
|
|
|
if (!in_array($locale, $this->availableLocales, true)) { |
80
|
|
|
$request->setLocale($this->defaultLocale); |
81
|
|
|
} |
82
|
|
|
//if in production environment and the query is not a file |
83
|
|
|
if ($this->debug === false && 0 === $matches) { |
84
|
|
|
$page = $this->em->getRepository('VictoireTwigBundle:ErrorPage')->findOneByCode($code); |
85
|
|
|
if ($page) { |
86
|
|
|
return $this->forward('VictoireTwigBundle:ErrorPage:show', [ |
87
|
|
|
'code' => $page->getCode(), |
88
|
|
|
]); |
89
|
|
|
} |
90
|
|
|
} |
91
|
|
|
|
92
|
|
|
return new Response($this->twig->render( |
93
|
|
|
$this->findTemplate($request, $_format, $code, $this->debug), |
94
|
|
|
[ |
95
|
|
|
'status_code' => $code, |
96
|
|
|
'status_text' => isset(Response::$statusTexts[$code]) ? Response::$statusTexts[$code] : '', |
97
|
|
|
'exception' => $exception, |
98
|
|
|
'logger' => $logger, |
99
|
|
|
'currentContent' => $currentContent, |
100
|
|
|
] |
101
|
|
|
)); |
102
|
|
|
} |
103
|
|
|
|
104
|
|
|
/** |
105
|
|
|
* Forwards the request to another controller. |
106
|
|
|
* |
107
|
|
|
* @param string $controller The controller name (a string like BlogBundle:Post:index) |
108
|
|
|
* @param array $path An array of path parameters |
109
|
|
|
* @param array $query An array of query parameters |
110
|
|
|
* |
111
|
|
|
* @return Response A Response instance |
112
|
|
|
*/ |
113
|
|
|
protected function forward($controller, array $path = [], array $query = []) |
114
|
|
|
{ |
115
|
|
|
$path['_controller'] = $controller; |
116
|
|
|
$subRequest = $this->request->duplicate($query, null, $path); |
117
|
|
|
|
118
|
|
|
return $this->kernel->handle($subRequest, HttpKernelInterface::SUB_REQUEST); |
119
|
|
|
} |
120
|
|
|
} |
121
|
|
|
|
The
EntityManager
might become unusable for example if a transaction is rolled back and it gets closed. Let’s assume that somewhere in your application, or in a third-party library, there is code such as the following:If that code throws an exception and the
EntityManager
is closed. Any other code which depends on the same instance of theEntityManager
during this request will fail.On the other hand, if you instead inject the
ManagerRegistry
, thegetManager()
method guarantees that you will always get a usable manager instance.