Skip to content

Commit

Permalink
bug #416 [Live] Support (de)hydrating nullable backed Enum's (kbond)
Browse files Browse the repository at this point in the history
This PR was merged into the 2.x branch.

Discussion
----------

[Live] Support (de)hydrating nullable backed Enum's

| Q             | A
| ------------- | ---
| Bug fix?      | yes
| New feature?  | no
| Tickets       | Fix #414
| License       | MIT

Commits
-------

bfd7f8d [Live] support (de)hydrating Enum's
  • Loading branch information
weaverryan committed Aug 11, 2022
2 parents 9aa183d + bfd7f8d commit 5893aca
Show file tree
Hide file tree
Showing 7 changed files with 128 additions and 2 deletions.
7 changes: 5 additions & 2 deletions src/LiveComponent/src/LiveComponentHydrator.php
Original file line number Diff line number Diff line change
Expand Up @@ -166,12 +166,15 @@ public function hydrate(object $component, array $data, string $componentName):
}

$value = $dehydratedValue;
$type = $property->getType() instanceof \ReflectionNamedType ? $property->getType() : null;

if ($method = $liveProp->hydrateMethod()) {
// TODO: Error checking
$value = $component->$method($dehydratedValue);
} elseif ($property->getType() instanceof \ReflectionNamedType && !$property->getType()->isBuiltin()) {
$value = $this->normalizer->denormalize($value, $property->getType()->getName(), 'json', [self::LIVE_CONTEXT => true]);
} 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()))) {
$value = null;
} elseif (null !== $value && $type && !$type->isBuiltin()) {
$value = $this->normalizer->denormalize($value, $type->getName(), 'json', [self::LIVE_CONTEXT => true]);
}

foreach ($liveProp->exposed() as $exposedProperty) {
Expand Down
29 changes: 29 additions & 0 deletions src/LiveComponent/tests/Fixtures/Component/WithEnums.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
<?php

namespace Symfony\UX\LiveComponent\Tests\Fixtures\Component;

use Symfony\UX\LiveComponent\Attribute\AsLiveComponent;
use Symfony\UX\LiveComponent\Attribute\LiveProp;
use Symfony\UX\LiveComponent\DefaultActionTrait;
use Symfony\UX\LiveComponent\Tests\Fixtures\Enum\EmptyStringEnum;
use Symfony\UX\LiveComponent\Tests\Fixtures\Enum\IntEnum;
use Symfony\UX\LiveComponent\Tests\Fixtures\Enum\StringEnum;
use Symfony\UX\LiveComponent\Tests\Fixtures\Enum\ZeroIntEnum;

#[AsLiveComponent('with_enum')]
final class WithEnums
{
use DefaultActionTrait;

#[LiveProp(writable: true)]
public ?IntEnum $int = null;

#[LiveProp(writable: true)]
public ?StringEnum $string = null;

#[LiveProp(writable: true)]
public ?ZeroIntEnum $zeroInt = null;

#[LiveProp(writable: true)]
public ?EmptyStringEnum $emptyString = null;
}
8 changes: 8 additions & 0 deletions src/LiveComponent/tests/Fixtures/Enum/EmptyStringEnum.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<?php

namespace Symfony\UX\LiveComponent\Tests\Fixtures\Enum;

enum EmptyStringEnum: string
{
case EMPTY = '';
}
9 changes: 9 additions & 0 deletions src/LiveComponent/tests/Fixtures/Enum/IntEnum.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<?php

namespace Symfony\UX\LiveComponent\Tests\Fixtures\Enum;

enum IntEnum: int
{
case HIGH = 10;
case LOW = 1;
}
9 changes: 9 additions & 0 deletions src/LiveComponent/tests/Fixtures/Enum/StringEnum.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<?php

namespace Symfony\UX\LiveComponent\Tests\Fixtures\Enum;

enum StringEnum: string
{
case PENDING = 'pending';
case ACTIVE = 'active';
}
8 changes: 8 additions & 0 deletions src/LiveComponent/tests/Fixtures/Enum/ZeroIntEnum.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<?php

namespace Symfony\UX\LiveComponent\Tests\Fixtures\Enum;

enum ZeroIntEnum: int
{
case ZERO = 0;
}
60 changes: 60 additions & 0 deletions src/LiveComponent/tests/Integration/LiveComponentHydratorTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,10 @@
use Symfony\UX\LiveComponent\Tests\Fixtures\Component\Component3;
use Symfony\UX\LiveComponent\Tests\Fixtures\Component\ComponentWithArrayProp;
use Symfony\UX\LiveComponent\Tests\Fixtures\Entity\Entity1;
use Symfony\UX\LiveComponent\Tests\Fixtures\Enum\EmptyStringEnum;
use Symfony\UX\LiveComponent\Tests\Fixtures\Enum\IntEnum;
use Symfony\UX\LiveComponent\Tests\Fixtures\Enum\StringEnum;
use Symfony\UX\LiveComponent\Tests\Fixtures\Enum\ZeroIntEnum;
use Symfony\UX\LiveComponent\Tests\LiveComponentTestHelper;
use Zenstruck\Foundry\Test\Factories;
use Zenstruck\Foundry\Test\ResetDatabase;
Expand Down Expand Up @@ -279,4 +283,60 @@ public function testCanDehydrateAndHydrateComponentsWithEmptyAttributes(): void

$this->assertSame([], $mounted->getAttributes()->all());
}

/**
* @requires PHP >= 8.1
*/
public function testCanHydrateEnums(): void
{
$mounted = $this->mountComponent('with_enum');

$dehydrated = $this->dehydrateComponent($mounted);

$this->assertNull($dehydrated['int']);
$this->assertNull($dehydrated['string']);

$mounted = $this->hydrateComponent($this->getComponent('with_enum'), $dehydrated, $mounted->getName());

$this->assertNull($mounted->getComponent()->int);
$this->assertNull($mounted->getComponent()->string);

$dehydrated['int'] = IntEnum::LOW->value;
$dehydrated['string'] = StringEnum::PENDING->value;

$mounted = $this->hydrateComponent($this->getComponent('with_enum'), $dehydrated, $mounted->getName());

$this->assertSame(IntEnum::LOW, $mounted->getComponent()->int);
$this->assertSame(StringEnum::PENDING, $mounted->getComponent()->string);

$dehydrated['int'] = null;
$dehydrated['string'] = null;

$mounted = $this->hydrateComponent($this->getComponent('with_enum'), $dehydrated, $mounted->getName());

$this->assertNull($mounted->getComponent()->int);
$this->assertNull($mounted->getComponent()->string);

$dehydrated['int'] = '';
$dehydrated['string'] = '';

$mounted = $this->hydrateComponent($this->getComponent('with_enum'), $dehydrated, $mounted->getName());

$this->assertNull($mounted->getComponent()->int);
$this->assertNull($mounted->getComponent()->string);

$dehydrated['zeroInt'] = 0;
$dehydrated['emptyString'] = '';

$mounted = $this->hydrateComponent($this->getComponent('with_enum'), $dehydrated, $mounted->getName());

$this->assertSame(ZeroIntEnum::ZERO, $mounted->getComponent()->zeroInt);
$this->assertSame(EmptyStringEnum::EMPTY, $mounted->getComponent()->emptyString);

$dehydrated['zeroInt'] = '0';

$mounted = $this->hydrateComponent($this->getComponent('with_enum'), $dehydrated, $mounted->getName());

$this->assertSame(ZeroIntEnum::ZERO, $mounted->getComponent()->zeroInt);
}
}

0 comments on commit 5893aca

Please sign in to comment.