27
27
use Illuminate \Auth \AuthenticationException ;
28
28
use Illuminate \Contracts \Container \Container ;
29
29
use Illuminate \Foundation \Exceptions \Handler as ExceptionsHandler ;
30
- use Illuminate \Http \Request ;
31
30
use Negotiation \Negotiator ;
32
31
use Symfony \Component \HttpFoundation \Exception \RequestExceptionInterface ;
33
32
use Symfony \Component \HttpKernel \Exception \HttpExceptionInterface as SymfonyHttpExceptionInterface ;
@@ -52,112 +51,114 @@ public function __construct(
52
51
?Negotiator $ negotiator = null ,
53
52
private readonly ?array $ exceptionToStatus = null ,
54
53
private readonly ?bool $ debug = false ,
54
+ private readonly ?array $ errorFormats = null ,
55
55
) {
56
56
$ this ->resourceMetadataCollectionFactory = $ resourceMetadataCollectionFactory ;
57
57
$ this ->negotiator = $ negotiator ;
58
- // calls register
59
58
parent ::__construct ($ container );
60
- $ this ->register ();
61
59
}
62
60
63
- public function register (): void
61
+ public function render ( $ request , \ Throwable $ exception )
64
62
{
65
- $ this ->renderable ( function ( \ Throwable $ exception , Request $ request ) {
66
- $ apiOperation = $ this -> initializeOperation ( $ request );
67
- if (!$ apiOperation ) {
68
- return null ;
69
- }
63
+ $ apiOperation = $ this ->initializeOperation ( $ request );
64
+
65
+ if (!$ apiOperation ) {
66
+ return parent :: render ( $ request , $ exception ) ;
67
+ }
70
68
71
- $ formats = config ( ' api-platform.error_formats ' ) ?? ['jsonproblem ' => ['application/problem+json ' ]];
72
- $ format = $ request ->getRequestFormat () ?? $ this ->getRequestFormat ($ request , $ formats , false );
69
+ $ formats = $ this -> errorFormats ?? ['jsonproblem ' => ['application/problem+json ' ]];
70
+ $ format = $ request ->getRequestFormat () ?? $ this ->getRequestFormat ($ request , $ formats , false );
73
71
74
- if ($ this ->resourceClassResolver ->isResourceClass ($ exception ::class)) {
75
- $ resourceCollection = $ this ->resourceMetadataCollectionFactory ->create ($ exception ::class);
72
+ if ($ this ->resourceClassResolver ->isResourceClass ($ exception ::class)) {
73
+ $ resourceCollection = $ this ->resourceMetadataCollectionFactory ->create ($ exception ::class);
76
74
77
- $ operation = null ;
78
- foreach ($ resourceCollection as $ resource ) {
79
- foreach ($ resource ->getOperations () as $ op ) {
80
- foreach ($ op ->getOutputFormats () as $ key => $ value ) {
81
- if ($ key === $ format ) {
82
- $ operation = $ op ;
83
- break 3 ;
84
- }
75
+ $ operation = null ;
76
+ foreach ($ resourceCollection as $ resource ) {
77
+ foreach ($ resource ->getOperations () as $ op ) {
78
+ foreach ($ op ->getOutputFormats () as $ key => $ value ) {
79
+ if ($ key === $ format ) {
80
+ $ operation = $ op ;
81
+ break 3 ;
85
82
}
86
83
}
87
84
}
85
+ }
88
86
89
- // No operation found for the requested format, we take the first available
90
- if (!$ operation ) {
91
- $ operation = $ resourceCollection ->getOperation ();
92
- }
93
- $ errorResource = $ exception ;
94
- if ($ errorResource instanceof ProblemExceptionInterface && $ operation instanceof HttpOperation) {
95
- $ statusCode = $ this ->getStatusCode ($ apiOperation , $ operation , $ exception );
96
- $ operation = $ operation ->withStatus ($ statusCode );
97
- if ($ errorResource instanceof StatusAwareExceptionInterface) {
98
- $ errorResource ->setStatus ($ statusCode );
99
- }
100
- }
101
- } else {
102
- // Create a generic, rfc7807 compatible error according to the wanted format
103
- $ operation = $ this ->resourceMetadataCollectionFactory ->create (Error::class)->getOperation ($ this ->getFormatOperation ($ format ));
104
- // status code may be overridden by the exceptionToStatus option
105
- $ statusCode = 500 ;
106
- if ($ operation instanceof HttpOperation) {
107
- $ statusCode = $ this ->getStatusCode ($ apiOperation , $ operation , $ exception );
108
- $ operation = $ operation ->withStatus ($ statusCode );
87
+ // No operation found for the requested format, we take the first available
88
+ if (!$ operation ) {
89
+ $ operation = $ resourceCollection ->getOperation ();
90
+ }
91
+ $ errorResource = $ exception ;
92
+ if ($ errorResource instanceof ProblemExceptionInterface && $ operation instanceof HttpOperation) {
93
+ $ statusCode = $ this ->getStatusCode ($ apiOperation , $ operation , $ exception );
94
+ $ operation = $ operation ->withStatus ($ statusCode );
95
+ if ($ errorResource instanceof StatusAwareExceptionInterface) {
96
+ $ errorResource ->setStatus ($ statusCode );
109
97
}
110
-
111
- $ errorResource = Error::createFromException ($ exception , $ statusCode );
112
98
}
113
-
114
- /** @var HttpOperation $operation */
115
- if (!$ operation ->getProvider ()) {
116
- static ::$ error = $ errorResource ;
117
- $ operation = $ operation ->withProvider ([self ::class, 'provide ' ]);
99
+ } else {
100
+ // Create a generic, rfc7807 compatible error according to the wanted format
101
+ $ operation = $ this ->resourceMetadataCollectionFactory ->create (Error::class)->getOperation ($ this ->getFormatOperation ($ format ));
102
+ // status code may be overridden by the exceptionToStatus option
103
+ $ statusCode = 500 ;
104
+ if ($ operation instanceof HttpOperation) {
105
+ $ statusCode = $ this ->getStatusCode ($ apiOperation , $ operation , $ exception );
106
+ $ operation = $ operation ->withStatus ($ statusCode );
118
107
}
119
108
120
- // For our swagger Ui errors
121
- if ('html ' === $ format ) {
122
- $ operation = $ operation ->withOutputFormats (['html ' => ['text/html ' ]]);
123
- }
109
+ $ errorResource = Error::createFromException ($ exception , $ statusCode );
110
+ }
124
111
125
- $ identifiers = [];
126
- try {
127
- $ identifiers = $ this -> identifiersExtractor ?->getIdentifiersFromItem( $ errorResource, $ operation ) ?? [] ;
128
- } catch ( \ Exception $ e ) {
129
- }
112
+ /** @var HttpOperation $operation */
113
+ if (! $ operation -> getProvider ()) {
114
+ static :: $ error = $ errorResource ;
115
+ $ operation = $ operation -> withProvider ([ self ::class, ' provide ' ]);
116
+ }
130
117
131
- $ normalizationContext = $ operation -> getNormalizationContext () ?? [];
132
- if (!( $ normalizationContext [ ' api_error_resource ' ] ?? false ) ) {
133
- $ normalizationContext += [ ' api_error_resource ' => true ] ;
134
- }
118
+ // For our swagger Ui errors
119
+ if (' html ' === $ format ) {
120
+ $ operation = $ operation -> withOutputFormats ([ ' html ' => [ ' text/html ' ]]) ;
121
+ }
135
122
136
- if (!isset ($ normalizationContext [AbstractObjectNormalizer::IGNORED_ATTRIBUTES ])) {
137
- $ normalizationContext [AbstractObjectNormalizer::IGNORED_ATTRIBUTES ] = true === $ this ->debug ? [] : ['originalTrace ' ];
138
- }
123
+ $ identifiers = [];
124
+ try {
125
+ $ identifiers = $ this ->identifiersExtractor ?->getIdentifiersFromItem($ errorResource , $ operation ) ?? [];
126
+ } catch (\Exception $ e ) {
127
+ }
139
128
140
- $ operation = $ operation ->withNormalizationContext ($ normalizationContext );
141
-
142
- $ dup = $ request ->duplicate (null , null , []);
143
- $ dup ->setMethod ('GET ' );
144
- $ dup ->attributes ->set ('_api_resource_class ' , $ operation ->getClass ());
145
- $ dup ->attributes ->set ('_api_previous_operation ' , $ apiOperation );
146
- $ dup ->attributes ->set ('_api_operation ' , $ operation );
147
- $ dup ->attributes ->set ('_api_operation_name ' , $ operation ->getName ());
148
- $ dup ->attributes ->set ('exception ' , $ exception );
149
- // These are for swagger
150
- $ dup ->attributes ->set ('_api_original_route ' , $ request ->attributes ->get ('_route ' ));
151
- $ dup ->attributes ->set ('_api_original_uri_variables ' , $ request ->attributes ->get ('_api_uri_variables ' ));
152
- $ dup ->attributes ->set ('_api_original_route_params ' , $ request ->attributes ->get ('_route_params ' ));
153
- $ dup ->attributes ->set ('_api_requested_operation ' , $ request ->attributes ->get ('_api_requested_operation ' ));
154
-
155
- foreach ($ identifiers as $ name => $ value ) {
156
- $ dup ->attributes ->set ($ name , $ value );
157
- }
129
+ $ normalizationContext = $ operation ->getNormalizationContext () ?? [];
130
+ if (!($ normalizationContext ['api_error_resource ' ] ?? false )) {
131
+ $ normalizationContext += ['api_error_resource ' => true ];
132
+ }
133
+
134
+ if (!isset ($ normalizationContext [AbstractObjectNormalizer::IGNORED_ATTRIBUTES ])) {
135
+ $ normalizationContext [AbstractObjectNormalizer::IGNORED_ATTRIBUTES ] = true === $ this ->debug ? [] : ['originalTrace ' ];
136
+ }
158
137
138
+ $ operation = $ operation ->withNormalizationContext ($ normalizationContext );
139
+
140
+ $ dup = $ request ->duplicate (null , null , []);
141
+ $ dup ->setMethod ('GET ' );
142
+ $ dup ->attributes ->set ('_api_resource_class ' , $ operation ->getClass ());
143
+ $ dup ->attributes ->set ('_api_previous_operation ' , $ apiOperation );
144
+ $ dup ->attributes ->set ('_api_operation ' , $ operation );
145
+ $ dup ->attributes ->set ('_api_operation_name ' , $ operation ->getName ());
146
+ $ dup ->attributes ->set ('exception ' , $ exception );
147
+ // These are for swagger
148
+ $ dup ->attributes ->set ('_api_original_route ' , $ request ->attributes ->get ('_route ' ));
149
+ $ dup ->attributes ->set ('_api_original_uri_variables ' , $ request ->attributes ->get ('_api_uri_variables ' ));
150
+ $ dup ->attributes ->set ('_api_original_route_params ' , $ request ->attributes ->get ('_route_params ' ));
151
+ $ dup ->attributes ->set ('_api_requested_operation ' , $ request ->attributes ->get ('_api_requested_operation ' ));
152
+
153
+ foreach ($ identifiers as $ name => $ value ) {
154
+ $ dup ->attributes ->set ($ name , $ value );
155
+ }
156
+
157
+ try {
159
158
return $ this ->apiPlatformController ->__invoke ($ dup );
160
- });
159
+ } catch (\Throwable $ e ) {
160
+ return parent ::render ($ dup , $ e );
161
+ }
161
162
}
162
163
163
164
private function getStatusCode (?HttpOperation $ apiOperation , ?HttpOperation $ errorOperation , \Throwable $ exception ): int
0 commit comments