Skip to content

Commit a87c207

Browse files
smnandrekbond
authored andcommitted
Revert #1694 "[LiveComponent] set LiveArg value to null if empty string"
1 parent b5e4b84 commit a87c207

File tree

10 files changed

+110
-286
lines changed

10 files changed

+110
-286
lines changed

src/LiveComponent/src/Attribute/LiveArg.php

Lines changed: 33 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -11,49 +11,44 @@
1111

1212
namespace Symfony\UX\LiveComponent\Attribute;
1313

14-
use Symfony\Component\HttpKernel\Attribute\ValueResolver;
15-
use Symfony\UX\LiveComponent\ValueResolver\LiveArgValueResolver;
16-
17-
if (class_exists(ValueResolver::class)) {
18-
/**
19-
* An attribute to configure a LiveArg (custom argument passed to a LiveAction).
20-
*
21-
* @see https://symfony.com/bundles/ux-live-component/current/index.html#actions-arguments
22-
*
23-
* @author Tomas Norkūnas <norkunas.tom@gmail.com>
24-
* @author Jannes Drijkoningen <jannesdrijkoningen@gmail.com>
25-
*/
26-
#[\Attribute(\Attribute::TARGET_PARAMETER)]
27-
final class LiveArg extends ValueResolver
28-
{
29-
public function __construct(
30-
/**
31-
* @param string|null $name The name of the argument received by the LiveAction
32-
*/
33-
public ?string $name = null,
34-
bool $disabled = false,
35-
string $resolver = LiveArgValueResolver::class,
36-
) {
37-
parent::__construct($resolver, $disabled);
38-
}
14+
/**
15+
* An attribute to configure a LiveArg (custom argument passed to a LiveAction).
16+
*
17+
* @see https://symfony.com/bundles/ux-live-component/current/index.html#actions-arguments
18+
*
19+
* @author Tomas Norkūnas <norkunas.tom@gmail.com>
20+
*/
21+
#[\Attribute(\Attribute::TARGET_PARAMETER)]
22+
final class LiveArg
23+
{
24+
public function __construct(
25+
/**
26+
* @param string|null $name The name of the argument received by the LiveAction
27+
*/
28+
public ?string $name = null,
29+
) {
3930
}
40-
} else {
31+
4132
/**
42-
* An attribute to configure a LiveArg (custom argument passed to a LiveAction).
43-
*
44-
* @see https://symfony.com/bundles/ux-live-component/current/index.html#actions-arguments
33+
* @internal
4534
*
46-
* @author Tomas Norkūnas <norkunas.tom@gmail.com>
35+
* @return array<string, string>
4736
*/
48-
#[\Attribute(\Attribute::TARGET_PARAMETER)]
49-
final class LiveArg
37+
public static function liveArgs(object $component, string $action): array
5038
{
51-
public function __construct(
52-
/**
53-
* @param string|null $name The name of the argument received by the LiveAction
54-
*/
55-
public ?string $name = null,
56-
) {
39+
$method = new \ReflectionMethod($component, $action);
40+
$liveArgs = [];
41+
42+
foreach ($method->getParameters() as $parameter) {
43+
foreach ($parameter->getAttributes(self::class) as $liveArg) {
44+
/** @var LiveArg $attr */
45+
$attr = $liveArg->newInstance();
46+
$parameterName = $parameter->getName();
47+
48+
$liveArgs[$parameterName] = $attr->name ?? $parameterName;
49+
}
5750
}
51+
52+
return $liveArgs;
5853
}
5954
}

src/LiveComponent/src/DependencyInjection/LiveComponentExtension.php

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,6 @@
4747
use Symfony\UX\LiveComponent\Util\LiveControllerAttributesCreator;
4848
use Symfony\UX\LiveComponent\Util\QueryStringPropsExtractor;
4949
use Symfony\UX\LiveComponent\Util\TwigAttributeHelperFactory;
50-
use Symfony\UX\LiveComponent\ValueResolver\LiveArgValueResolver;
5150
use Symfony\UX\TwigComponent\ComponentFactory;
5251
use Symfony\UX\TwigComponent\ComponentRenderer;
5352

@@ -262,9 +261,6 @@ function (ChildDefinition $definition, AsLiveComponent $attribute) {
262261
'%kernel.secret%',
263262
])
264263
->addTag('kernel.cache_warmer');
265-
266-
$container->register(LiveArgValueResolver::class, LiveArgValueResolver::class)
267-
->addTag('controller.argument_value_resolver', ['priority' => 0]);
268264
}
269265

270266
private function isAssetMapperAvailable(ContainerBuilder $container): bool

src/LiveComponent/src/EventListener/LiveComponentSubscriber.php

Lines changed: 75 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313

1414
use Psr\Container\ContainerInterface;
1515
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
16+
use Symfony\Component\HttpFoundation\Exception\JsonException;
1617
use Symfony\Component\HttpFoundation\Request;
1718
use Symfony\Component\HttpFoundation\Response;
1819
use Symfony\Component\HttpKernel\Event\ControllerEvent;
@@ -28,10 +29,10 @@
2829
use Symfony\Component\Security\Csrf\CsrfTokenManagerInterface;
2930
use Symfony\Contracts\Service\ServiceSubscriberInterface;
3031
use Symfony\UX\LiveComponent\Attribute\AsLiveComponent;
32+
use Symfony\UX\LiveComponent\Attribute\LiveArg;
3133
use Symfony\UX\LiveComponent\LiveComponentHydrator;
3234
use Symfony\UX\LiveComponent\Metadata\LiveComponentMetadataFactory;
3335
use Symfony\UX\LiveComponent\Util\LiveControllerAttributesCreator;
34-
use Symfony\UX\LiveComponent\Util\LiveRequestDataParser;
3536
use Symfony\UX\TwigComponent\ComponentFactory;
3637
use Symfony\UX\TwigComponent\ComponentMetadata;
3738
use Symfony\UX\TwigComponent\ComponentRenderer;
@@ -115,7 +116,7 @@ public function onKernelRequest(RequestEvent $event): void
115116

116117
if ('_batch' === $action) {
117118
// use batch controller
118-
$data = LiveRequestDataParser::parseDataFor($request);
119+
$data = $this->parseDataFor($request);
119120

120121
$request->attributes->set('_controller', 'ux.live_component.batch_action_controller');
121122
$request->attributes->set('serviceId', $metadata->getServiceId());
@@ -194,6 +195,61 @@ public function onKernelController(ControllerEvent $event): void
194195
$action,
195196
]);
196197
}
198+
199+
// read the action arguments from the request, unless they're already set (batch sub-requests)
200+
$actionArguments = $request->attributes->get('_component_action_args', $this->parseDataFor($request)['args']);
201+
// extra variables to be made available to the controller
202+
// (for "actions" only)
203+
foreach (LiveArg::liveArgs($component, $action) as $parameter => $arg) {
204+
if (isset($actionArguments[$arg])) {
205+
$request->attributes->set($parameter, $actionArguments[$arg]);
206+
}
207+
}
208+
}
209+
210+
/**
211+
* @return array{
212+
* data: array,
213+
* args: array,
214+
* actions: array
215+
* // has "fingerprint" and "tag" string key, keyed by component id
216+
* children: array
217+
* propsFromParent: array
218+
* }
219+
*/
220+
private static function parseDataFor(Request $request): array
221+
{
222+
if (!$request->attributes->has('_live_request_data')) {
223+
if ($request->query->has('props')) {
224+
$liveRequestData = [
225+
'props' => self::parseJsonFromQuery($request, 'props'),
226+
'updated' => self::parseJsonFromQuery($request, 'updated'),
227+
'args' => [],
228+
'actions' => [],
229+
'children' => self::parseJsonFromQuery($request, 'children'),
230+
'propsFromParent' => self::parseJsonFromQuery($request, 'propsFromParent'),
231+
];
232+
} else {
233+
try {
234+
$requestData = json_decode($request->request->get('data'), true, 512, \JSON_BIGINT_AS_STRING | \JSON_THROW_ON_ERROR);
235+
} catch (\JsonException $e) {
236+
throw new JsonException('Could not decode request body.', $e->getCode(), $e);
237+
}
238+
239+
$liveRequestData = [
240+
'props' => $requestData['props'] ?? [],
241+
'updated' => $requestData['updated'] ?? [],
242+
'args' => $requestData['args'] ?? [],
243+
'actions' => $requestData['actions'] ?? [],
244+
'children' => $requestData['children'] ?? [],
245+
'propsFromParent' => $requestData['propsFromParent'] ?? [],
246+
];
247+
}
248+
249+
$request->attributes->set('_live_request_data', $liveRequestData);
250+
}
251+
252+
return $request->attributes->get('_live_request_data');
197253
}
198254

199255
public function onKernelView(ViewEvent $event): void
@@ -298,22 +354,34 @@ private function hydrateComponent(object $component, string $componentName, Requ
298354
$metadataFactory = $this->container->get(LiveComponentMetadataFactory::class);
299355
\assert($metadataFactory instanceof LiveComponentMetadataFactory);
300356

301-
$liveRequestData = LiveRequestDataParser::parseDataFor($request);
302357
$componentAttributes = $hydrator->hydrate(
303358
$component,
304-
$liveRequestData['props'],
305-
$liveRequestData['updated'],
359+
$this->parseDataFor($request)['props'],
360+
$this->parseDataFor($request)['updated'],
306361
$metadataFactory->getMetadata($componentName),
307-
$liveRequestData['propsFromParent']
362+
$this->parseDataFor($request)['propsFromParent']
308363
);
309364

310365
$mountedComponent = new MountedComponent($componentName, $component, $componentAttributes);
311366

312367
$mountedComponent->addExtraMetadata(
313368
InterceptChildComponentRenderSubscriber::CHILDREN_FINGERPRINTS_METADATA_KEY,
314-
$liveRequestData['children']
369+
$this->parseDataFor($request)['children']
315370
);
316371

317372
return $mountedComponent;
318373
}
374+
375+
private static function parseJsonFromQuery(Request $request, string $key): array
376+
{
377+
if (!$request->query->has($key)) {
378+
return [];
379+
}
380+
381+
try {
382+
return json_decode($request->query->get($key), true, 512, \JSON_THROW_ON_ERROR);
383+
} catch (\JsonException $exception) {
384+
throw new JsonException(sprintf('Invalid JSON on query string "%s".', $key), 0, $exception);
385+
}
386+
}
319387
}

src/LiveComponent/src/Util/LiveRequestDataParser.php

Lines changed: 0 additions & 82 deletions
This file was deleted.

src/LiveComponent/src/ValueResolver/LiveArgValueResolver.php

Lines changed: 0 additions & 59 deletions
This file was deleted.

0 commit comments

Comments
 (0)