@@ -69,6 +69,10 @@ public function onKernelRequest(RequestEvent $event): void
69
69
return ;
70
70
}
71
71
72
+ if ($ request ->attributes ->has ('_controller ' )) {
73
+ return ;
74
+ }
75
+
72
76
// the default "action" is get, which does nothing
73
77
$ action = $ request ->get ('action ' , 'get ' );
74
78
$ componentName = (string ) $ request ->get ('component ' );
@@ -107,6 +111,23 @@ public function onKernelRequest(RequestEvent $event): void
107
111
throw new BadRequestHttpException ('Invalid CSRF token. ' );
108
112
}
109
113
114
+ if ('_batch ' === $ action ) {
115
+ // use batch controller
116
+ $ data = $ this ->parseDataFor ($ request );
117
+
118
+ $ request ->attributes ->set ('_controller ' , 'ux.live_component.batch_action_controller ' );
119
+ $ request ->attributes ->set ('serviceId ' , $ metadata ->getServiceId ());
120
+ $ request ->attributes ->set ('actions ' , $ data ['actions ' ]);
121
+ $ request ->attributes ->set ('_mounted_component ' , $ this ->container ->get (LiveComponentHydrator::class)->hydrate (
122
+ $ this ->container ->get (ComponentFactory::class)->get ($ componentName ),
123
+ $ data ['data ' ],
124
+ $ componentName ,
125
+ ));
126
+ $ request ->attributes ->set ('_is_live_batch_action ' , true );
127
+
128
+ return ;
129
+ }
130
+
110
131
$ request ->attributes ->set ('_controller ' , sprintf ('%s::%s ' , $ metadata ->getServiceId (), $ action ));
111
132
}
112
133
@@ -118,18 +139,13 @@ public function onKernelController(ControllerEvent $event): void
118
139
return ;
119
140
}
120
141
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 ' ] ?? [];
142
+ if ($ request ->attributes ->get ('_is_live_batch_action ' )) {
143
+ return ;
130
144
}
131
145
132
- if (!\is_array ($ controller = $ event ->getController ()) || 2 !== \count ($ controller )) {
146
+ $ controller = $ event ->getController ();
147
+
148
+ if (!\is_array ($ controller ) || 2 !== \count ($ controller )) {
133
149
throw new \RuntimeException ('Not a valid live component. ' );
134
150
}
135
151
@@ -143,14 +159,29 @@ public function onKernelController(ControllerEvent $event): void
143
159
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
160
}
145
161
146
- $ mounted = $ this ->container ->get (LiveComponentHydrator::class)->hydrate (
147
- $ component ,
148
- $ data ,
149
- $ request ->attributes ->get ('_component_name ' )
150
- );
151
-
152
- $ request ->attributes ->set ('_mounted_component ' , $ mounted );
162
+ /*
163
+ * Either we:
164
+ * A) To not have a _mounted_component, so hydrate $component
165
+ * B) We DO have a _mounted_component, so no need to hydrate,
166
+ * but we DO need to make sure it's set as the controller.
167
+ */
168
+ if (!$ request ->attributes ->has ('_mounted_component ' )) {
169
+ $ request ->attributes ->set ('_mounted_component ' , $ this ->container ->get (LiveComponentHydrator::class)->hydrate (
170
+ $ component ,
171
+ $ this ->parseDataFor ($ request )['data ' ],
172
+ $ request ->attributes ->get ('_component_name ' )
173
+ ));
174
+ } else {
175
+ // override the component with our already-mounted version
176
+ $ component = $ request ->attributes ->get ('_mounted_component ' )->getComponent ();
177
+ $ event ->setController ([
178
+ $ component ,
179
+ $ action ,
180
+ ]);
181
+ }
153
182
183
+ // read the action arguments from the request, unless they're already set (batch sub-requests)
184
+ $ actionArguments = $ request ->attributes ->get ('_component_action_args ' , $ this ->parseDataFor ($ request )['args ' ]);
154
185
// extra variables to be made available to the controller
155
186
// (for "actions" only)
156
187
foreach (LiveArg::liveArgs ($ component , $ action ) as $ parameter => $ arg ) {
@@ -160,12 +191,49 @@ public function onKernelController(ControllerEvent $event): void
160
191
}
161
192
}
162
193
194
+ /**
195
+ * @return array{
196
+ * data: array,
197
+ * args: array,
198
+ * actions: array
199
+ * }
200
+ */
201
+ private function parseDataFor (Request $ request ): array
202
+ {
203
+ if (!$ request ->attributes ->has ('_live_request_data ' )) {
204
+ if ($ request ->query ->has ('data ' )) {
205
+ return [
206
+ 'data ' => json_decode ($ request ->query ->get ('data ' ), true , 512 , \JSON_THROW_ON_ERROR ),
207
+ 'args ' => [],
208
+ 'actions ' => [],
209
+ ];
210
+ }
211
+
212
+ $ requestData = $ request ->toArray ();
213
+
214
+ $ request ->attributes ->set ('_live_request_data ' , [
215
+ 'data ' => $ requestData ['data ' ] ?? [],
216
+ 'args ' => $ requestData ['args ' ] ?? [],
217
+ 'actions ' => $ requestData ['actions ' ] ?? [],
218
+ ]);
219
+ }
220
+
221
+ return $ request ->attributes ->get ('_live_request_data ' );
222
+ }
223
+
163
224
public function onKernelView (ViewEvent $ event ): void
164
225
{
165
226
if (!$ this ->isLiveComponentRequest ($ request = $ event ->getRequest ())) {
166
227
return ;
167
228
}
168
229
230
+ if (!$ event ->isMainRequest ()) {
231
+ // sub-request, so skip rendering
232
+ $ event ->setResponse (new Response ());
233
+
234
+ return ;
235
+ }
236
+
169
237
$ event ->setResponse ($ this ->createResponse ($ request ->attributes ->get ('_mounted_component ' )));
170
238
}
171
239
0 commit comments