29
29
use Symfony \Contracts \Service \ServiceSubscriberInterface ;
30
30
use Symfony \UX \LiveComponent \Attribute \AsLiveComponent ;
31
31
use Symfony \UX \LiveComponent \Attribute \LiveArg ;
32
+ use Symfony \UX \LiveComponent \Controller \BatchActionController ;
32
33
use Symfony \UX \LiveComponent \LiveComponentHydrator ;
33
34
use Symfony \UX \TwigComponent \ComponentFactory ;
34
35
use Symfony \UX \TwigComponent \ComponentMetadata ;
@@ -69,6 +70,11 @@ public function onKernelRequest(RequestEvent $event): void
69
70
return ;
70
71
}
71
72
73
+ if (!$ event ->isMainRequest ()) {
74
+ // sub request
75
+ return ;
76
+ }
77
+
72
78
// the default "action" is get, which does nothing
73
79
$ action = $ request ->get ('action ' , 'get ' );
74
80
$ componentName = (string ) $ request ->get ('component ' );
@@ -107,6 +113,22 @@ public function onKernelRequest(RequestEvent $event): void
107
113
throw new BadRequestHttpException ('Invalid CSRF token. ' );
108
114
}
109
115
116
+ if ('_batch ' === $ action ) {
117
+ // use batch controller
118
+ $ data = $ this ->parseDataFor ($ request );
119
+
120
+ $ request ->attributes ->set ('_controller ' , 'ux.live_component.batch_action_controller ' );
121
+ $ request ->attributes ->set ('serviceId ' , $ metadata ->getServiceId ());
122
+ $ request ->attributes ->set ('actions ' , $ data ['actions ' ]);
123
+ $ request ->attributes ->set ('mounted ' , $ this ->container ->get (LiveComponentHydrator::class)->hydrate (
124
+ $ this ->container ->get (ComponentFactory::class)->get ($ componentName ),
125
+ $ data ['data ' ],
126
+ $ componentName ,
127
+ ));
128
+
129
+ return ;
130
+ }
131
+
110
132
$ request ->attributes ->set ('_controller ' , sprintf ('%s::%s ' , $ metadata ->getServiceId (), $ action ));
111
133
}
112
134
@@ -118,18 +140,13 @@ public function onKernelController(ControllerEvent $event): void
118
140
return ;
119
141
}
120
142
121
- $ actionArguments = [];
122
- if ($ request ->query ->has ('data ' )) {
123
- // ?data=
124
- $ data = json_decode ($ request ->query ->get ('data ' ), true , 512 , \JSON_THROW_ON_ERROR );
125
- } else {
126
- // OR body of the request is JSON
127
- $ requestData = json_decode ($ request ->getContent (), true , 512 , \JSON_THROW_ON_ERROR );
128
- $ data = $ requestData ['data ' ] ?? [];
129
- $ actionArguments = $ requestData ['args ' ] ?? [];
143
+ $ controller = $ event ->getController ();
144
+
145
+ if ($ controller instanceof BatchActionController) {
146
+ return ;
130
147
}
131
148
132
- if (!\is_array ($ controller = $ event -> getController () ) || 2 !== \count ($ controller )) {
149
+ if (!\is_array ($ controller ) || 2 !== \count ($ controller )) {
133
150
throw new \RuntimeException ('Not a valid live component. ' );
134
151
}
135
152
@@ -143,13 +160,21 @@ public function onKernelController(ControllerEvent $event): void
143
160
throw new NotFoundHttpException (sprintf ('The action "%s" either doesn \'t exist or is not allowed in "%s". Make sure it exist and has the LiveAction attribute above it. ' , $ action , \get_class ($ component )));
144
161
}
145
162
146
- $ mounted = $ this ->container ->get (LiveComponentHydrator::class)->hydrate (
147
- $ component ,
148
- $ data ,
149
- $ request ->attributes ->get ('_component_name ' )
150
- );
163
+ if ($ event ->isMainRequest ()) {
164
+ $ data = $ this ->parseDataFor ($ request );
165
+
166
+ $ request ->attributes ->set ('_component_action_args ' , $ data ['args ' ]);
167
+ $ request ->attributes ->set ('_mounted_component ' , $ this ->container ->get (LiveComponentHydrator::class)->hydrate (
168
+ $ component ,
169
+ $ data ['data ' ],
170
+ $ request ->attributes ->get ('_component_name ' )
171
+ ));
172
+ } else {
173
+ // sub-request
174
+ $ event ->setController ([$ request ->attributes ->get ('_mounted_component ' )->getComponent (), $ action ]);
175
+ }
151
176
152
- $ request ->attributes ->set ( ' _mounted_component ' , $ mounted );
177
+ $ actionArguments = $ request ->attributes ->get ( ' _component_action_args ' , [] );
153
178
154
179
// extra variables to be made available to the controller
155
180
// (for "actions" only)
@@ -160,12 +185,45 @@ public function onKernelController(ControllerEvent $event): void
160
185
}
161
186
}
162
187
188
+ /**
189
+ * @return array{
190
+ * data: array,
191
+ * args: array,
192
+ * actions: array
193
+ * }
194
+ */
195
+ private function parseDataFor (Request $ request ): array
196
+ {
197
+ if ($ request ->query ->has ('data ' )) {
198
+ return [
199
+ 'data ' => json_decode ($ request ->query ->get ('data ' ), true , 512 , \JSON_THROW_ON_ERROR ),
200
+ 'args ' => [],
201
+ 'actions ' => [],
202
+ ];
203
+ }
204
+
205
+ $ requestData = json_decode ($ request ->getContent (), true , 512 , \JSON_THROW_ON_ERROR );
206
+
207
+ return [
208
+ 'data ' => $ requestData ['data ' ] ?? [],
209
+ 'args ' => $ requestData ['args ' ] ?? [],
210
+ 'actions ' => $ requestData ['actions ' ] ?? [],
211
+ ];
212
+ }
213
+
163
214
public function onKernelView (ViewEvent $ event ): void
164
215
{
165
216
if (!$ this ->isLiveComponentRequest ($ request = $ event ->getRequest ())) {
166
217
return ;
167
218
}
168
219
220
+ if (!$ event ->isMainRequest ()) {
221
+ // sub-request, so skip rendering
222
+ $ event ->setResponse (new Response ());
223
+
224
+ return ;
225
+ }
226
+
169
227
$ event ->setResponse ($ this ->createResponse ($ request ->attributes ->get ('_mounted_component ' )));
170
228
}
171
229
0 commit comments