Skip to content

Commit 240028f

Browse files
committed
bug #532 [Live] coerce falsey strings to scalar types (kbond)
This PR was merged into the 2.x branch. Discussion ---------- [Live] coerce falsey strings to scalar types | Q | A | ------------- | --- | Bug fix? | no | New feature? | yes | Tickets | Fix #526 | License | MIT I chose to allow _weird_ values to be cast to the proper type instead of throwing an exception (ie `0 === (int) 'apple'`). Commits ------- f122b89 [Live] coerce falsey strings to scalar types
2 parents 05ad23f + f122b89 commit 240028f

File tree

4 files changed

+94
-0
lines changed

4 files changed

+94
-0
lines changed

src/LiveComponent/src/LiveComponentHydrator.php

+17
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,8 @@ public function hydrate(object $component, array $data, string $componentName):
148148
if ($method = $liveProp->hydrateMethod()) {
149149
// TODO: Error checking
150150
$value = $component->$method($value);
151+
} elseif (\is_string($value) && $type && \in_array($type->getName(), ['int', 'float', 'bool'], true)) {
152+
$value = self::coerceScalarValue($value, $type);
151153
} elseif (!$value && $type && $type->allowsNull() && is_a($type->getName(), \BackedEnum::class, true) && !\in_array($value, array_map(fn (\BackedEnum $e) => $e->value, $type->getName()::cases()))) {
152154
$value = null;
153155
} elseif (null !== $value && $type && !$type->isBuiltin()) {
@@ -189,6 +191,21 @@ public function hydrate(object $component, array $data, string $componentName):
189191
return new MountedComponent($componentName, $component, $attributes);
190192
}
191193

194+
private static function coerceScalarValue(string $value, \ReflectionNamedType $type): int|float|bool|null
195+
{
196+
$value = trim($value);
197+
198+
if ('' === $value && $type->allowsNull()) {
199+
return null;
200+
}
201+
202+
return match ($type->getName()) {
203+
'int' => (int) $value,
204+
'float' => (float) $value,
205+
'bool' => (bool) $value,
206+
};
207+
}
208+
192209
/**
193210
* Transforms a path like `post.name` into `[post][name]`.
194211
*
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <[email protected]>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\UX\LiveComponent\Tests\Fixtures\Component;
13+
14+
use Symfony\UX\LiveComponent\Attribute\AsLiveComponent;
15+
use Symfony\UX\LiveComponent\Attribute\LiveProp;
16+
use Symfony\UX\LiveComponent\DefaultActionTrait;
17+
18+
#[AsLiveComponent('scalar_types')]
19+
final class ScalarTypes
20+
{
21+
use DefaultActionTrait;
22+
23+
#[LiveProp(writable: true)]
24+
public int $int = 1;
25+
26+
#[LiveProp(writable: true)]
27+
public float $float = 1.0;
28+
29+
#[LiveProp(writable: true)]
30+
public bool $bool = true;
31+
32+
#[LiveProp(writable: true)]
33+
public ?int $nullableInt = 1;
34+
35+
#[LiveProp(writable: true)]
36+
public ?float $nullableFloat = 1.0;
37+
38+
#[LiveProp(writable: true)]
39+
public ?bool $nullableBool = true;
40+
}

src/LiveComponent/tests/Fixtures/templates/components/scalar_types.html.twig

Whitespace-only changes.

src/LiveComponent/tests/Integration/LiveComponentHydratorTest.php

+37
Original file line numberDiff line numberDiff line change
@@ -382,4 +382,41 @@ public function testComponentWithNormalizableObjects(): void
382382
$this->assertSame('foo', $component->embeddable1->name);
383383
$this->assertSame('qux', $component->embeddable2->name);
384384
}
385+
386+
/**
387+
* @dataProvider falseyValueProvider
388+
*/
389+
public function testCoerceFalseyValuesForScalarTypes($prop, $value, $expected): void
390+
{
391+
$dehydrated = $this->dehydrateComponent($this->mountComponent('scalar_types'))->all();
392+
393+
$dehydrated[$prop] = $value;
394+
395+
$hydrated = $this->hydrateComponent($this->getComponent('scalar_types'), $dehydrated, 'scalar_types')
396+
->getComponent()
397+
;
398+
399+
$this->assertSame($expected, $hydrated->$prop);
400+
}
401+
402+
public static function falseyValueProvider(): iterable
403+
{
404+
yield ['int', '', 0];
405+
yield ['int', ' ', 0];
406+
yield ['int', 'apple', 0];
407+
yield ['float', '', 0.0];
408+
yield ['float', ' ', 0.0];
409+
yield ['float', 'apple', 0.0];
410+
yield ['bool', '', false];
411+
yield ['bool', ' ', false];
412+
413+
yield ['nullableInt', '', null];
414+
yield ['nullableInt', ' ', null];
415+
yield ['nullableInt', 'apple', 0];
416+
yield ['nullableFloat', '', null];
417+
yield ['nullableFloat', ' ', null];
418+
yield ['nullableFloat', 'apple', 0.0];
419+
yield ['nullableBool', '', null];
420+
yield ['nullableBool', ' ', null];
421+
}
385422
}

0 commit comments

Comments
 (0)