14
14
namespace ApiPlatform \Laravel \State ;
15
15
16
16
use ApiPlatform \Metadata \Error ;
17
+ use ApiPlatform \Metadata \Exception \RuntimeException ;
17
18
use ApiPlatform \Metadata \Operation ;
18
19
use ApiPlatform \State \ProviderInterface ;
19
20
use Illuminate \Contracts \Foundation \Application ;
21
+ use Illuminate \Database \Eloquent \Model ;
20
22
use Illuminate \Foundation \Http \FormRequest ;
21
23
use Illuminate \Support \Facades \Validator ;
22
24
use Illuminate \Validation \ValidationException ;
25
+ use Symfony \Component \Serializer \Normalizer \NormalizerInterface ;
23
26
24
27
/**
25
28
* @implements ProviderInterface<object>
@@ -34,12 +37,13 @@ final class ValidateProvider implements ProviderInterface
34
37
public function __construct (
35
38
private readonly ProviderInterface $ inner ,
36
39
private readonly Application $ app ,
40
+ // TODO: trigger deprecation in API Platform 4.2 when this is not defined
41
+ private readonly ?NormalizerInterface $ normalizer = null ,
37
42
) {
38
43
}
39
44
40
45
public function provide (Operation $ operation , array $ uriVariables = [], array $ context = []): object |array |null
41
46
{
42
- $ request = $ context ['request ' ];
43
47
$ body = $ this ->inner ->provide ($ operation , $ uriVariables , $ context );
44
48
45
49
if ($ operation instanceof Error) {
@@ -74,12 +78,7 @@ public function provide(Operation $operation, array $uriVariables = [], array $c
74
78
return $ body ;
75
79
}
76
80
77
- // In Symfony, validation is done on the Resource object (here $body) using Deserialization before Validation
78
- // Here, we did not deserialize yet, we validate on the raw body before.
79
- $ validationBody = $ request ->request ->all ();
80
- if ('jsonapi ' === $ request ->getRequestFormat ()) {
81
- $ validationBody = $ validationBody ['data ' ]['attributes ' ];
82
- }
81
+ $ validationBody = $ this ->getBodyForValidation ($ body );
83
82
84
83
$ validator = Validator::make ($ validationBody , $ rules );
85
84
if ($ validator ->fails ()) {
@@ -88,4 +87,35 @@ public function provide(Operation $operation, array $uriVariables = [], array $c
88
87
89
88
return $ body ;
90
89
}
90
+
91
+ /**
92
+ * @return array<string, mixed>
93
+ */
94
+ private function getBodyForValidation (mixed $ body ): array
95
+ {
96
+ if (!$ body ) {
97
+ return [];
98
+ }
99
+
100
+ if ($ body instanceof Model) {
101
+ return $ body ->toArray ();
102
+ }
103
+
104
+ if ($ this ->normalizer ) {
105
+ if (!\is_array ($ v = $ this ->normalizer ->normalize ($ body ))) {
106
+ throw new RuntimeException ('An array is expected. ' );
107
+ }
108
+
109
+ return $ v ;
110
+ }
111
+
112
+ // hopefully this path never gets used, its there for BC-layer only
113
+ // TODO: deprecation in API Platform 4.2
114
+ // TODO: remove in 5.0
115
+ if ($ s = json_encode ($ body )) {
116
+ return json_decode ($ s , true );
117
+ }
118
+
119
+ throw new RuntimeException ('Could not transform the denormalized body in an array for validation ' );
120
+ }
91
121
}
0 commit comments