Skip to content

Commit

Permalink
bug #1893 Revert #1694 "[LiveComponent] set LiveArg value to null if …
Browse files Browse the repository at this point in the history
…empty string" (smnandre)

This PR was squashed before being merged into the 2.x branch.

Discussion
----------

Revert #1694 "[LiveComponent] set LiveArg value to null if empty string"

This reverts commit 538cc61. temporarely (we need to release a version)

| Q             | A
| ------------- | ---
| Bug fix?      | yes
| New feature?  | no <!-- please update src/**/CHANGELOG.md files -->
| Issues        | Fix #1694
| License       | MIT

Let's see...

Commits
-------

a87c207 Revert #1694 "[LiveComponent] set LiveArg value to null if empty string"
  • Loading branch information
kbond committed Jun 6, 2024
2 parents b5e4b84 + a87c207 commit 933808a
Show file tree
Hide file tree
Showing 10 changed files with 110 additions and 286 deletions.
71 changes: 33 additions & 38 deletions src/LiveComponent/src/Attribute/LiveArg.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,49 +11,44 @@

namespace Symfony\UX\LiveComponent\Attribute;

use Symfony\Component\HttpKernel\Attribute\ValueResolver;
use Symfony\UX\LiveComponent\ValueResolver\LiveArgValueResolver;

if (class_exists(ValueResolver::class)) {
/**
* An attribute to configure a LiveArg (custom argument passed to a LiveAction).
*
* @see https://symfony.com/bundles/ux-live-component/current/index.html#actions-arguments
*
* @author Tomas Norkūnas <[email protected]>
* @author Jannes Drijkoningen <[email protected]>
*/
#[\Attribute(\Attribute::TARGET_PARAMETER)]
final class LiveArg extends ValueResolver
{
public function __construct(
/**
* @param string|null $name The name of the argument received by the LiveAction
*/
public ?string $name = null,
bool $disabled = false,
string $resolver = LiveArgValueResolver::class,
) {
parent::__construct($resolver, $disabled);
}
/**
* An attribute to configure a LiveArg (custom argument passed to a LiveAction).
*
* @see https://symfony.com/bundles/ux-live-component/current/index.html#actions-arguments
*
* @author Tomas Norkūnas <[email protected]>
*/
#[\Attribute(\Attribute::TARGET_PARAMETER)]
final class LiveArg
{
public function __construct(
/**
* @param string|null $name The name of the argument received by the LiveAction
*/
public ?string $name = null,
) {
}
} else {

/**
* An attribute to configure a LiveArg (custom argument passed to a LiveAction).
*
* @see https://symfony.com/bundles/ux-live-component/current/index.html#actions-arguments
* @internal
*
* @author Tomas Norkūnas <[email protected]>
* @return array<string, string>
*/
#[\Attribute(\Attribute::TARGET_PARAMETER)]
final class LiveArg
public static function liveArgs(object $component, string $action): array
{
public function __construct(
/**
* @param string|null $name The name of the argument received by the LiveAction
*/
public ?string $name = null,
) {
$method = new \ReflectionMethod($component, $action);
$liveArgs = [];

foreach ($method->getParameters() as $parameter) {
foreach ($parameter->getAttributes(self::class) as $liveArg) {
/** @var LiveArg $attr */
$attr = $liveArg->newInstance();
$parameterName = $parameter->getName();

$liveArgs[$parameterName] = $attr->name ?? $parameterName;
}
}

return $liveArgs;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,6 @@
use Symfony\UX\LiveComponent\Util\LiveControllerAttributesCreator;
use Symfony\UX\LiveComponent\Util\QueryStringPropsExtractor;
use Symfony\UX\LiveComponent\Util\TwigAttributeHelperFactory;
use Symfony\UX\LiveComponent\ValueResolver\LiveArgValueResolver;
use Symfony\UX\TwigComponent\ComponentFactory;
use Symfony\UX\TwigComponent\ComponentRenderer;

Expand Down Expand Up @@ -262,9 +261,6 @@ function (ChildDefinition $definition, AsLiveComponent $attribute) {
'%kernel.secret%',
])
->addTag('kernel.cache_warmer');

$container->register(LiveArgValueResolver::class, LiveArgValueResolver::class)
->addTag('controller.argument_value_resolver', ['priority' => 0]);
}

private function isAssetMapperAvailable(ContainerBuilder $container): bool
Expand Down
82 changes: 75 additions & 7 deletions src/LiveComponent/src/EventListener/LiveComponentSubscriber.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@

use Psr\Container\ContainerInterface;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpFoundation\Exception\JsonException;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Event\ControllerEvent;
Expand All @@ -28,10 +29,10 @@
use Symfony\Component\Security\Csrf\CsrfTokenManagerInterface;
use Symfony\Contracts\Service\ServiceSubscriberInterface;
use Symfony\UX\LiveComponent\Attribute\AsLiveComponent;
use Symfony\UX\LiveComponent\Attribute\LiveArg;
use Symfony\UX\LiveComponent\LiveComponentHydrator;
use Symfony\UX\LiveComponent\Metadata\LiveComponentMetadataFactory;
use Symfony\UX\LiveComponent\Util\LiveControllerAttributesCreator;
use Symfony\UX\LiveComponent\Util\LiveRequestDataParser;
use Symfony\UX\TwigComponent\ComponentFactory;
use Symfony\UX\TwigComponent\ComponentMetadata;
use Symfony\UX\TwigComponent\ComponentRenderer;
Expand Down Expand Up @@ -115,7 +116,7 @@ public function onKernelRequest(RequestEvent $event): void

if ('_batch' === $action) {
// use batch controller
$data = LiveRequestDataParser::parseDataFor($request);
$data = $this->parseDataFor($request);

$request->attributes->set('_controller', 'ux.live_component.batch_action_controller');
$request->attributes->set('serviceId', $metadata->getServiceId());
Expand Down Expand Up @@ -194,6 +195,61 @@ public function onKernelController(ControllerEvent $event): void
$action,
]);
}

// 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) {
if (isset($actionArguments[$arg])) {
$request->attributes->set($parameter, $actionArguments[$arg]);
}
}
}

/**
* @return array{
* data: array,
* args: array,
* actions: array
* // has "fingerprint" and "tag" string key, keyed by component id
* children: array
* propsFromParent: array
* }
*/
private static function parseDataFor(Request $request): array
{
if (!$request->attributes->has('_live_request_data')) {
if ($request->query->has('props')) {
$liveRequestData = [
'props' => self::parseJsonFromQuery($request, 'props'),
'updated' => self::parseJsonFromQuery($request, 'updated'),
'args' => [],
'actions' => [],
'children' => self::parseJsonFromQuery($request, 'children'),
'propsFromParent' => self::parseJsonFromQuery($request, 'propsFromParent'),
];
} else {
try {
$requestData = json_decode($request->request->get('data'), true, 512, \JSON_BIGINT_AS_STRING | \JSON_THROW_ON_ERROR);
} catch (\JsonException $e) {
throw new JsonException('Could not decode request body.', $e->getCode(), $e);
}

$liveRequestData = [
'props' => $requestData['props'] ?? [],
'updated' => $requestData['updated'] ?? [],
'args' => $requestData['args'] ?? [],
'actions' => $requestData['actions'] ?? [],
'children' => $requestData['children'] ?? [],
'propsFromParent' => $requestData['propsFromParent'] ?? [],
];
}

$request->attributes->set('_live_request_data', $liveRequestData);
}

return $request->attributes->get('_live_request_data');
}

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

$liveRequestData = LiveRequestDataParser::parseDataFor($request);
$componentAttributes = $hydrator->hydrate(
$component,
$liveRequestData['props'],
$liveRequestData['updated'],
$this->parseDataFor($request)['props'],
$this->parseDataFor($request)['updated'],
$metadataFactory->getMetadata($componentName),
$liveRequestData['propsFromParent']
$this->parseDataFor($request)['propsFromParent']
);

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

$mountedComponent->addExtraMetadata(
InterceptChildComponentRenderSubscriber::CHILDREN_FINGERPRINTS_METADATA_KEY,
$liveRequestData['children']
$this->parseDataFor($request)['children']
);

return $mountedComponent;
}

private static function parseJsonFromQuery(Request $request, string $key): array
{
if (!$request->query->has($key)) {
return [];
}

try {
return json_decode($request->query->get($key), true, 512, \JSON_THROW_ON_ERROR);
} catch (\JsonException $exception) {
throw new JsonException(sprintf('Invalid JSON on query string "%s".', $key), 0, $exception);
}
}
}
82 changes: 0 additions & 82 deletions src/LiveComponent/src/Util/LiveRequestDataParser.php

This file was deleted.

59 changes: 0 additions & 59 deletions src/LiveComponent/src/ValueResolver/LiveArgValueResolver.php

This file was deleted.

Loading

0 comments on commit 933808a

Please sign in to comment.