1
|
|
|
<?php |
2
|
|
|
/** |
3
|
|
|
* Created by PhpStorm. |
4
|
|
|
* User: taachja1 |
5
|
|
|
* Date: 13/04/16 |
6
|
|
|
* Time: 10:16 |
7
|
|
|
*/ |
8
|
|
|
|
9
|
|
|
namespace Graviton\CoreBundle\Listener; |
10
|
|
|
|
11
|
|
|
use Monolog\Logger; |
12
|
|
|
use Symfony\Component\Debug\Exception\ContextErrorException; |
13
|
|
|
use Symfony\Component\HttpFoundation\JsonResponse; |
14
|
|
|
use Graviton\JsonSchemaBundle\Exception\ValidationException; |
15
|
|
|
use Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent; |
16
|
|
|
use Xiag\Rql\Parser\Exception\SyntaxErrorException; |
17
|
|
|
use Graviton\ExceptionBundle\Exception\SerializationException; |
18
|
|
|
|
19
|
|
|
/** |
20
|
|
|
* Class JsonExceptionListener |
21
|
|
|
* @package Graviton\CoreBundle\Listener |
22
|
|
|
*/ |
23
|
|
|
class JsonExceptionListener |
24
|
|
|
{ |
25
|
|
|
|
26
|
|
|
/** |
27
|
|
|
* @var Logger |
28
|
|
|
*/ |
29
|
|
|
private $logger; |
30
|
|
|
|
31
|
|
|
/** |
32
|
|
|
* set Logger |
33
|
|
|
* |
34
|
|
|
* @param Logger $logger logger |
35
|
|
|
* |
36
|
|
|
* @return void |
37
|
|
|
*/ |
38
|
|
|
public function setLogger($logger) |
39
|
|
|
{ |
40
|
|
|
$this->logger = $logger; |
41
|
|
|
} |
42
|
|
|
|
43
|
|
|
/** |
44
|
|
|
* Should not handle Validation Exceptions and only service exceptions |
45
|
|
|
* |
46
|
|
|
* @param GetResponseForExceptionEvent $event Sf Event |
47
|
|
|
* |
48
|
|
|
* @return void |
49
|
|
|
*/ |
50
|
|
|
public function onKernelException(GetResponseForExceptionEvent $event) |
51
|
|
|
{ |
52
|
|
|
$exception = $event->getException(); |
53
|
|
|
|
54
|
|
|
// Should return a error 400 bad request |
55
|
|
|
if ($exception instanceof ValidationException |
56
|
|
|
|| $exception instanceof SyntaxErrorException) { |
57
|
|
|
return; |
58
|
|
|
} |
59
|
|
|
|
60
|
|
|
// Some Exceptions have status code and if 400 it should be handled by them |
61
|
|
|
if (method_exists($exception, 'getStatusCode') |
62
|
|
|
&& (400 == (int)$exception->getStatusCode())) { |
63
|
|
|
return; |
64
|
|
|
} |
65
|
|
|
|
66
|
|
|
$data = $this->decorateKnownCases($exception); |
67
|
|
|
|
68
|
|
|
if (!is_array($data)) { |
69
|
|
|
$data = [ |
70
|
|
|
'code' => $exception->getCode(), |
71
|
|
|
'message' => $exception->getMessage() |
72
|
|
|
]; |
73
|
|
|
} |
74
|
|
|
|
75
|
|
|
if ($this->logger instanceof Logger) { |
76
|
|
|
$this->logger->critical($exception); |
77
|
|
|
} |
78
|
|
|
|
79
|
|
|
$response = new JsonResponse($data); |
80
|
|
|
$event->setResponse($response); |
81
|
|
|
} |
82
|
|
|
|
83
|
|
|
/** |
84
|
|
|
* Here we can pick up known cases that can happen and render a more detailed error message for the client. |
85
|
|
|
* It may be cumbersome, but it's good to detail error messages then just to let general error messages |
86
|
|
|
* generate support issues and work for us. |
87
|
|
|
* |
88
|
|
|
* @param \Exception $exception exception |
89
|
|
|
* |
90
|
|
|
* @return array|null either a error message array or null if the general should be displayed |
91
|
|
|
*/ |
92
|
|
|
private function decorateKnownCases($exception) |
93
|
|
|
{ |
94
|
|
|
if ( |
95
|
|
|
$exception instanceof ContextErrorException && |
96
|
|
|
strpos($exception->getMessage(), 'Undefined index: $id') !== false |
97
|
|
|
) { |
98
|
|
|
return [ |
99
|
|
|
'code' => $exception->getCode(), |
100
|
|
|
'message' => 'An incomplete internal MongoDB ref has been discovered that can not be rendered. '. |
101
|
|
|
'Did you pass a select() RQL statement and shaved off on the wrong level? Try to select a level '. |
102
|
|
|
'higher.' |
103
|
|
|
]; |
104
|
|
|
} elseif ( |
105
|
|
|
$exception instanceof SerializationException && |
106
|
|
|
strpos($exception->getMessage(), 'Cannot serialize content class') !== false |
107
|
|
|
) { |
108
|
|
|
$error = $exception->getMessage(); |
109
|
|
|
$message = strpos($error, 'not be found.') !== false ? |
110
|
|
|
substr($error, 0, strpos($error, 'not be found.')).'not be found.' : $error; |
111
|
|
|
preg_match('/\bwith id: (.*);.*?\bdocument\\\(.*)".*?\bidentifier "(.*)"/is', $message, $matches); |
112
|
|
|
if (array_key_exists(3, $matches)) { |
113
|
|
|
$sentence = 'Internal Database reference error as been discovered. '. |
114
|
|
|
'The object id: "%s" has a reference to document: "%s" with id: "%s" that could not be found.'; |
115
|
|
|
$message = sprintf($sentence, $matches[1], $matches[2], $matches[3]); |
116
|
|
|
} |
117
|
|
|
return [ |
118
|
|
|
'code' => $exception->getCode(), |
119
|
|
|
'message' => $message |
120
|
|
|
]; |
121
|
|
|
} |
122
|
|
|
} |
123
|
|
|
} |
124
|
|
|
|