Skip to content

Commit

Permalink
feature #48820 [HttpFoundation] ParameterBag::getEnum() (nikophil)
Browse files Browse the repository at this point in the history
This PR was merged into the 6.3 branch.

Discussion
----------

[HttpFoundation] ParameterBag::getEnum()

| Q             | A
| ------------- | ---
| Branch?       | 6.3
| Bug fix?      | no
| New feature?  | yes
| Deprecations? | no
| License       | MIT
| Doc PR        | todo if the PR gets accepted

Adds availability to get an enum directly from a parameter bag:
```php
$bag->getEnum('key', Foo::class)
```

Commits
-------

e4ba7b7 [HttpFoundation] ParameterBag::getEnum()
  • Loading branch information
fabpot committed Jan 5, 2023
2 parents a14eb6b + e4ba7b7 commit 6b6c67a
Show file tree
Hide file tree
Showing 5 changed files with 97 additions and 0 deletions.
1 change: 1 addition & 0 deletions src/Symfony/Component/HttpFoundation/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ CHANGELOG
6.3
---

* Add `ParameterBag::getEnum()`
* Create migration for session table when pdo handler is used

6.2
Expand Down
19 changes: 19 additions & 0 deletions src/Symfony/Component/HttpFoundation/InputBag.php
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,25 @@ public function set(string $key, mixed $value)
$this->parameters[$key] = $value;
}

/**
* Returns the parameter value converted to an enum.
*
* @template T of \BackedEnum
*
* @param class-string<T> $class
* @param ?T $default
*
* @return ?T
*/
public function getEnum(string $key, string $class, \BackedEnum $default = null): ?\BackedEnum
{
try {
return parent::getEnum($key, $class, $default);
} catch (\UnexpectedValueException $e) {
throw new BadRequestException($e->getMessage(), $e->getCode(), $e);
}
}

public function filter(string $key, mixed $default = null, int $filter = \FILTER_DEFAULT, mixed $options = []): mixed
{
$value = $this->has($key) ? $this->all()[$key] : $default;
Expand Down
25 changes: 25 additions & 0 deletions src/Symfony/Component/HttpFoundation/ParameterBag.php
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,31 @@ public function getBoolean(string $key, bool $default = false): bool
return $this->filter($key, $default, \FILTER_VALIDATE_BOOL);
}

/**
* Returns the parameter value converted to an enum.
*
* @template T of \BackedEnum
*
* @param class-string<T> $class
* @param ?T $default
*
* @return ?T
*/
public function getEnum(string $key, string $class, \BackedEnum $default = null): ?\BackedEnum
{
$value = $this->get($key);

if (null === $value) {
return $default;
}

try {
return $class::from($value);
} catch (\ValueError|\TypeError $e) {
throw new \UnexpectedValueException(sprintf('Parameter "%s" cannot be converted to enum: %s.', $key, $e->getMessage()), $e->getCode(), $e);
}
}

/**
* Filter key.
*
Expand Down
17 changes: 17 additions & 0 deletions src/Symfony/Component/HttpFoundation/Tests/InputBagTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -106,4 +106,21 @@ public function testFilterArrayWithoutArrayFlag()
$bag = new InputBag(['foo' => ['bar', 'baz']]);
$bag->filter('foo', \FILTER_VALIDATE_INT);
}

public function testGetEnum()
{
$bag = new InputBag(['valid-value' => 1]);

$this->assertSame(Foo::Bar, $bag->getEnum('valid-value', Foo::class));
}

public function testGetEnumThrowsExceptionWithInvalidValue()
{
$bag = new InputBag(['invalid-value' => 2]);

$this->expectException(BadRequestException::class);
$this->expectExceptionMessage('Parameter "invalid-value" cannot be converted to enum: 2 is not a valid backing value for enum "Symfony\Component\HttpFoundation\Tests\Foo".');

$this->assertNull($bag->getEnum('invalid-value', Foo::class));
}
}
35 changes: 35 additions & 0 deletions src/Symfony/Component/HttpFoundation/Tests/ParameterBagTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -226,4 +226,39 @@ public function testGetBoolean()
$this->assertFalse($bag->getBoolean('string_false'), '->getBoolean() gets the string false as boolean false');
$this->assertFalse($bag->getBoolean('unknown'), '->getBoolean() returns false if a parameter is not defined');
}

public function testGetEnum()
{
$bag = new ParameterBag(['valid-value' => 1]);

$this->assertSame(Foo::Bar, $bag->getEnum('valid-value', Foo::class));

$this->assertNull($bag->getEnum('invalid-key', Foo::class));
$this->assertSame(Foo::Bar, $bag->getEnum('invalid-key', Foo::class, Foo::Bar));
}

public function testGetEnumThrowsExceptionWithNotBackingValue()
{
$bag = new ParameterBag(['invalid-value' => 2]);

$this->expectException(\UnexpectedValueException::class);
$this->expectExceptionMessage('Parameter "invalid-value" cannot be converted to enum: 2 is not a valid backing value for enum "Symfony\Component\HttpFoundation\Tests\Foo".');

$this->assertNull($bag->getEnum('invalid-value', Foo::class));
}

public function testGetEnumThrowsExceptionWithInvalidValueType()
{
$bag = new ParameterBag(['invalid-value' => ['foo']]);

$this->expectException(\UnexpectedValueException::class);
$this->expectExceptionMessage('Parameter "invalid-value" cannot be converted to enum: Symfony\Component\HttpFoundation\Tests\Foo::from(): Argument #1 ($value) must be of type int, array given.');

$this->assertNull($bag->getEnum('invalid-value', Foo::class));
}
}

enum Foo: int
{
case Bar = 1;
}

0 comments on commit 6b6c67a

Please sign in to comment.