Skip to content

Commit

Permalink
feature #48669 [ExpressionLanguage] Add enum expression function (a…
Browse files Browse the repository at this point in the history
…lexandre-daubois)

This PR was merged into the 6.3 branch.

Discussion
----------

[ExpressionLanguage] Add `enum` expression function

| Q             | A
| ------------- | ---
| Branch?       | 6.3
| Bug fix?      | no
| New feature?  | yes
| Deprecations? | no
| Tickets       | Fix #48593
| License       | MIT
| Doc PR        | symfony/symfony-docs#17632

Commits
-------

53bfee4 [ExpressionLanguage] Add `enum` expression function
  • Loading branch information
nicolas-grekas committed Jan 9, 2023
2 parents 5a832f4 + 53bfee4 commit c759e4e
Show file tree
Hide file tree
Showing 5 changed files with 83 additions and 0 deletions.
5 changes: 5 additions & 0 deletions src/Symfony/Component/ExpressionLanguage/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
CHANGELOG
=========

6.3
---

* Add `enum` expression function

6.2
---

Expand Down
13 changes: 13 additions & 0 deletions src/Symfony/Component/ExpressionLanguage/ExpressionLanguage.php
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,19 @@ public function registerProvider(ExpressionFunctionProviderInterface $provider)
protected function registerFunctions()
{
$this->addFunction(ExpressionFunction::fromPhp('constant'));

$this->addFunction(new ExpressionFunction('enum',
static fn ($str): string => sprintf("(\constant(\$v = (%s))) instanceof \UnitEnum ? \constant(\$v) : throw new \TypeError(\sprintf('The string \"%%s\" is not the name of a valid enum case.', \$v))", $str),
static function ($arguments, $str): \UnitEnum {
$value = \constant($str);

if (!$value instanceof \UnitEnum) {
throw new \TypeError(sprintf('The string "%s" is not the name of a valid enum case.', $str));
}

return $value;
}
));
}

private function getLexer(): Lexer
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@
use Symfony\Component\ExpressionLanguage\ExpressionLanguage;
use Symfony\Component\ExpressionLanguage\ParsedExpression;
use Symfony\Component\ExpressionLanguage\SyntaxError;
use Symfony\Component\ExpressionLanguage\Tests\Fixtures\FooBackedEnum;
use Symfony\Component\ExpressionLanguage\Tests\Fixtures\FooEnum;
use Symfony\Component\ExpressionLanguage\Tests\Fixtures\TestProvider;

class ExpressionLanguageTest extends TestCase
Expand Down Expand Up @@ -78,6 +80,53 @@ public function testConstantFunction()
$this->assertEquals('\constant("PHP_VERSION")', $expressionLanguage->compile('constant("PHP_VERSION")'));
}

public function testEnumFunctionWithConstantThrows()
{
$this->expectException(\TypeError::class);
$this->expectExceptionMessage('The string "PHP_VERSION" is not the name of a valid enum case.');
$expressionLanguage = new ExpressionLanguage();
$expressionLanguage->evaluate('enum("PHP_VERSION")');
}

public function testCompiledEnumFunctionWithConstantThrows()
{
$this->expectException(\TypeError::class);
$this->expectExceptionMessage('The string "PHP_VERSION" is not the name of a valid enum case.');
$expressionLanguage = new ExpressionLanguage();
eval($expressionLanguage->compile('enum("PHP_VERSION")').';');
}

public function testEnumFunction()
{
$expressionLanguage = new ExpressionLanguage();
$this->assertSame(FooEnum::Foo, $expressionLanguage->evaluate('enum("Symfony\\\\Component\\\\ExpressionLanguage\\\\Tests\\\\Fixtures\\\\FooEnum::Foo")'));
}

public function testCompiledEnumFunction()
{
$result = null;
$expressionLanguage = new ExpressionLanguage();
eval(sprintf('$result = %s;', $expressionLanguage->compile('enum("Symfony\\\\Component\\\\ExpressionLanguage\\\\Tests\\\\Fixtures\\\\FooEnum::Foo")')));

$this->assertSame(FooEnum::Foo, $result);
}

public function testBackedEnumFunction()
{
$expressionLanguage = new ExpressionLanguage();
$this->assertSame(FooBackedEnum::Bar, $expressionLanguage->evaluate('enum("Symfony\\\\Component\\\\ExpressionLanguage\\\\Tests\\\\Fixtures\\\\FooBackedEnum::Bar")'));
$this->assertSame('Foo', $expressionLanguage->evaluate('enum("Symfony\\\\Component\\\\ExpressionLanguage\\\\Tests\\\\Fixtures\\\\FooBackedEnum::Bar").value'));
}

public function testCompiledEnumFunctionWithBackedEnum()
{
$result = null;
$expressionLanguage = new ExpressionLanguage();
eval(sprintf('$result = %s;', $expressionLanguage->compile('enum("Symfony\\\\Component\\\\ExpressionLanguage\\\\Tests\\\\Fixtures\\\\FooBackedEnum::Bar")')));

$this->assertSame(FooBackedEnum::Bar, $result);
}

public function testProviders()
{
$expressionLanguage = new ExpressionLanguage(null, [new TestProvider()]);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<?php

namespace Symfony\Component\ExpressionLanguage\Tests\Fixtures;

enum FooBackedEnum: string
{
case Bar = 'Foo';
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<?php

namespace Symfony\Component\ExpressionLanguage\Tests\Fixtures;

enum FooEnum
{
case Foo;
}

0 comments on commit c759e4e

Please sign in to comment.