From 0f373656b5952513aee0ef76845cfb86650a3cb9 Mon Sep 17 00:00:00 2001 From: Ryan Weaver Date: Thu, 22 Sep 2022 12:13:26 -0400 Subject: [PATCH] mildly reworking to follow the logic of what is happening more clearly --- .../src/Controller/BatchActionController.php | 6 +- .../EventListener/LiveComponentSubscriber.php | 69 +++++++++++-------- 2 files changed, 42 insertions(+), 33 deletions(-) diff --git a/src/LiveComponent/src/Controller/BatchActionController.php b/src/LiveComponent/src/Controller/BatchActionController.php index 7241f3894de..61d65a32166 100644 --- a/src/LiveComponent/src/Controller/BatchActionController.php +++ b/src/LiveComponent/src/Controller/BatchActionController.php @@ -28,17 +28,15 @@ public function __construct(private HttpKernelInterface $kernel) { } - public function __invoke(Request $request, MountedComponent $mounted, string $serviceId, array $actions): ?Response + public function __invoke(Request $request, MountedComponent $_mounted_component, string $serviceId, array $actions): ?Response { - $request->attributes->set('_mounted_component', $mounted); - foreach ($actions as $action) { $name = $action['name'] ?? throw new BadRequestHttpException('Invalid JSON'); $subRequest = $request->duplicate(attributes: [ '_controller' => [$serviceId, $name], '_component_action_args' => $action['args'] ?? [], - '_mounted_component' => $mounted, + '_mounted_component' => $_mounted_component, '_route' => 'live_component', ]); diff --git a/src/LiveComponent/src/EventListener/LiveComponentSubscriber.php b/src/LiveComponent/src/EventListener/LiveComponentSubscriber.php index 5bc0e9da792..6bc4cca56ef 100644 --- a/src/LiveComponent/src/EventListener/LiveComponentSubscriber.php +++ b/src/LiveComponent/src/EventListener/LiveComponentSubscriber.php @@ -29,7 +29,6 @@ use Symfony\Contracts\Service\ServiceSubscriberInterface; use Symfony\UX\LiveComponent\Attribute\AsLiveComponent; use Symfony\UX\LiveComponent\Attribute\LiveArg; -use Symfony\UX\LiveComponent\Controller\BatchActionController; use Symfony\UX\LiveComponent\LiveComponentHydrator; use Symfony\UX\TwigComponent\ComponentFactory; use Symfony\UX\TwigComponent\ComponentMetadata; @@ -70,8 +69,7 @@ public function onKernelRequest(RequestEvent $event): void return; } - if (!$event->isMainRequest()) { - // sub request + if ($request->attributes->has('_controller')) { return; } @@ -120,11 +118,12 @@ public function onKernelRequest(RequestEvent $event): void $request->attributes->set('_controller', 'ux.live_component.batch_action_controller'); $request->attributes->set('serviceId', $metadata->getServiceId()); $request->attributes->set('actions', $data['actions']); - $request->attributes->set('mounted', $this->container->get(LiveComponentHydrator::class)->hydrate( + $request->attributes->set('_mounted_component', $this->container->get(LiveComponentHydrator::class)->hydrate( $this->container->get(ComponentFactory::class)->get($componentName), $data['data'], $componentName, )); + $request->attributes->set('_is_live_batch_action', true); return; } @@ -140,12 +139,12 @@ public function onKernelController(ControllerEvent $event): void return; } - $controller = $event->getController(); - - if ($controller instanceof BatchActionController) { + if ($request->attributes->get('_is_live_batch_action')) { return; } + $controller = $event->getController(); + if (!\is_array($controller) || 2 !== \count($controller)) { throw new \RuntimeException('Not a valid live component.'); } @@ -160,22 +159,29 @@ public function onKernelController(ControllerEvent $event): void 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))); } - if ($event->isMainRequest()) { - $data = $this->parseDataFor($request); - - $request->attributes->set('_component_action_args', $data['args']); + /* + * Either we: + * A) To not have a _mounted_component, so hydrate $component + * B) We DO have a _mounted_component, so no need to hydrate, + * but we DO need to make sure it's set as the controller. + */ + if (!$request->attributes->has('_mounted_component')) { $request->attributes->set('_mounted_component', $this->container->get(LiveComponentHydrator::class)->hydrate( $component, - $data['data'], + $this->parseDataFor($request)['data'], $request->attributes->get('_component_name') )); } else { - // sub-request - $event->setController([$request->attributes->get('_mounted_component')->getComponent(), $action]); + // override the component with our already-mounted version + $component = $request->attributes->get('_mounted_component')->getComponent(); + $event->setController([ + $component, + $action, + ]); } - $actionArguments = $request->attributes->get('_component_action_args', []); - + // read the action arguments from the request, unless they're already set (batch sub-requests) + $actionArguments = $request->attributes->get('_component_action_args', $this->parseDataFor($request)['args']); // extra variables to be made available to the controller // (for "actions" only) foreach (LiveArg::liveArgs($component, $action) as $parameter => $arg) { @@ -194,21 +200,26 @@ public function onKernelController(ControllerEvent $event): void */ private function parseDataFor(Request $request): array { - if ($request->query->has('data')) { - return [ - 'data' => json_decode($request->query->get('data'), true, 512, \JSON_THROW_ON_ERROR), - 'args' => [], - 'actions' => [], - ]; - } + if (!$request->attributes->has('_live_request_data')) { + + if ($request->query->has('data')) { + return [ + 'data' => json_decode($request->query->get('data'), true, 512, \JSON_THROW_ON_ERROR), + 'args' => [], + 'actions' => [], + ]; + } - $requestData = json_decode($request->getContent(), true, 512, \JSON_THROW_ON_ERROR); + $requestData = json_decode($request->getContent(), true, 512, \JSON_THROW_ON_ERROR); - return [ - 'data' => $requestData['data'] ?? [], - 'args' => $requestData['args'] ?? [], - 'actions' => $requestData['actions'] ?? [], - ]; + $request->attributes->set('_live_request_data', [ + 'data' => $requestData['data'] ?? [], + 'args' => $requestData['args'] ?? [], + 'actions' => $requestData['actions'] ?? [], + ]); + } + + return $request->attributes->get('_live_request_data'); } public function onKernelView(ViewEvent $event): void