1515use Symfony \Component \HttpKernel \Event \ExceptionEvent ;
1616use Symfony \Component \HttpKernel \Exception \AccessDeniedHttpException ;
1717use Symfony \Component \HttpKernel \Exception \HttpExceptionInterface ;
18+ use Symfony \Component \HttpKernel \Exception \UnprocessableEntityHttpException ;
1819use Symfony \Component \Security \Core \Exception \AccessDeniedException ;
20+ use Symfony \Component \Validator \Exception \ValidationFailedException ;
1921use Symfony \Component \Validator \Exception \ValidatorException ;
2022
2123class ExceptionListener
@@ -24,7 +26,6 @@ class ExceptionListener
2426 SubscriptionCreationException::class => null ,
2527 AttributeDefinitionCreationException::class => null ,
2628 AdminAttributeCreationException::class => null ,
27- ValidatorException::class => 400 ,
2829 AccessDeniedException::class => 403 ,
2930 AccessDeniedHttpException::class => 403 ,
3031 AttachmentFileNotFoundException::class => 404 ,
@@ -36,33 +37,85 @@ public function onKernelException(ExceptionEvent $event): void
3637 {
3738 $ exception = $ event ->getThrowable ();
3839
40+ if ($ exception instanceof ValidationFailedException
41+ || $ exception instanceof ValidatorException
42+ || $ exception instanceof UnprocessableEntityHttpException
43+ ) {
44+ $ event ->setResponse (
45+ new JsonResponse ([
46+ 'message ' => 'Validation failed ' ,
47+ 'errors ' => $ this ->parseFlatValidationMessage ($ exception ->getMessage ()),
48+ ], 422 )
49+ );
50+
51+ return ;
52+ }
53+
3954 foreach (self ::EXCEPTION_STATUS_MAP as $ class => $ statusCode ) {
4055 if ($ exception instanceof $ class ) {
41- $ status = $ statusCode ?? $ exception ->getStatusCode ();
56+ $ status = $ statusCode ?? (
57+ method_exists ($ exception , 'getStatusCode ' )
58+ ? $ exception ->getStatusCode ()
59+ : 400
60+ );
61+
4262 $ event ->setResponse (
4363 new JsonResponse ([
44- 'message ' => $ exception ->getMessage ()
64+ 'message ' => $ exception ->getMessage (),
4565 ], $ status )
4666 );
67+
4768 return ;
4869 }
4970 }
5071
5172 if ($ exception instanceof HttpExceptionInterface) {
5273 $ event ->setResponse (
5374 new JsonResponse ([
54- 'message ' => $ exception ->getMessage ()
75+ 'message ' => $ exception ->getMessage (),
5576 ], $ exception ->getStatusCode ())
5677 );
78+
5779 return ;
5880 }
5981
6082 if ($ exception instanceof Exception) {
6183 $ event ->setResponse (
6284 new JsonResponse ([
63- 'message ' => $ exception ->getMessage ()
85+ 'message ' => $ exception ->getMessage (),
6486 ], 500 )
6587 );
6688 }
6789 }
90+
91+ /**
92+ * @return array<string, array<int, string>>
93+ */
94+ private function parseFlatValidationMessage (string $ message ): array
95+ {
96+ $ errors = [];
97+ $ lines = preg_split ('/\r\n|\r|\n/ ' , $ message ) ?: [];
98+
99+ foreach ($ lines as $ line ) {
100+ $ line = trim ($ line );
101+
102+ if ($ line === '' ) {
103+ continue ;
104+ }
105+
106+ $ parts = explode (': ' , $ line , 2 );
107+
108+ if (count ($ parts ) !== 2 ) {
109+ $ errors ['_global ' ][] = $ line ;
110+ continue ;
111+ }
112+
113+ $ field = trim ($ parts [0 ]);
114+ $ errorMessage = trim ($ parts [1 ]);
115+
116+ $ errors [$ field ][] = $ errorMessage ;
117+ }
118+
119+ return $ errors ;
120+ }
68121}
0 commit comments