Skip to content

Commit

Permalink
Add pluralize and singularize Twig filters
Browse files Browse the repository at this point in the history
  • Loading branch information
welcoMattic committed May 30, 2024
1 parent 9f77ba3 commit 2934564
Show file tree
Hide file tree
Showing 5 changed files with 157 additions and 0 deletions.
6 changes: 6 additions & 0 deletions src/Symfony/Bridge/Twig/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,12 @@
CHANGELOG
=========

7.2
---

* Add `pluralize` Twig filter
* Add `singularize` Twig filter

7.1
---

Expand Down
31 changes: 31 additions & 0 deletions src/Symfony/Bridge/Twig/Extension/StringExtension.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
<?php

/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <[email protected]>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace Symfony\Bridge\Twig\Extension;

use Twig\Extension\AbstractExtension;
use Twig\TwigFilter;

/**
* Twig extension for the string helper.
*
* @author Mathieu Santostefano <[email protected]>
*/
final class StringExtension extends AbstractExtension
{
public function getFilters(): array
{
return [
new TwigFilter('pluralize', [StringRuntime::class, 'pluralize'], ['is_safe' => ['html']]),
new TwigFilter('singularize', [StringRuntime::class, 'singularize'], ['is_safe' => ['html']]),
];
}
}
51 changes: 51 additions & 0 deletions src/Symfony/Bridge/Twig/Extension/StringRuntime.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
<?php

/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <[email protected]>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace Symfony\Bridge\Twig\Extension;

use Symfony\Component\String\Inflector\EnglishInflector;
use Symfony\Component\String\Inflector\FrenchInflector;
use Symfony\Component\String\Inflector\InflectorInterface;
use Twig\Extension\RuntimeExtensionInterface;

/**
* @author Mathieu Santostefano <[email protected]>
*/
final readonly class StringRuntime implements RuntimeExtensionInterface
{
private FrenchInflector $frenchInflector;
private EnglishInflector $englishInflector;

public function pluralize($value, string $lang, bool $singleResult = false): array|string
{
return match (true) {
$singleResult => $this->getInflector($lang)->pluralize($value)[0],
default => $this->getInflector($lang)->pluralize($value),
};
}

public function singularize($value, string $lang, bool $singleResult = false): array|string
{
return match (true) {
$singleResult => $this->getInflector($lang)->singularize($value)[0],
default => $this->getInflector($lang)->singularize($value),
};
}

private function getInflector(string $lang): InflectorInterface
{
return match ($lang) {
'fr' => $this->frenchInflector ?? $this->frenchInflector = new FrenchInflector(),
'en' => $this->englishInflector ?? $this->englishInflector = new EnglishInflector(),
default => throw new \InvalidArgumentException(sprintf('Language "%s" is not supported.', $lang)),
};
}
}
68 changes: 68 additions & 0 deletions src/Symfony/Bridge/Twig/Tests/Extension/StringExtensionTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
<?php

/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <[email protected]>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace Symfony\Bridge\Twig\Tests\Extension;

use PHPUnit\Framework\TestCase;
use Symfony\Bridge\Twig\Extension\StringRuntime;

class StringExtensionTest extends TestCase
{
/**
* @testWith [["partitions"], "fr", false, "partition"]
* ["partitions", "fr", true, "partition"]
* [["persons", "people"], "en", false, "person"]
* ["persons", "en", true, "person"]
*/
public function testPluralize(array|string $expected, string $lang, bool $singleResult, string $value)
{
$extensionRuntime = new StringRuntime();
$this->assertSame($expected, $extensionRuntime->pluralize($value, $lang, $singleResult));
}

/**
* @testWith [["partition"], "fr", false, "partitions"]
* ["partition", "fr", true, "partitions"]
* [["person"], "en", false, "persons"]
* ["person", "en", true, "persons"]
* [["person"], "en", false, "people"]
* ["person", "en", true, "people"]
*/
public function testSingularize(array|string $expected, string $lang, bool $singleResult, string $value)
{
$extensionRuntime = new StringRuntime();
$this->assertSame($expected, $extensionRuntime->singularize($value, $lang, $singleResult));
}

/**
* @testWith [["partitions"], "it", false, "partition"]
* [["partitions"], "it", true, "partition"]
*/
public function testPluralizeInvalidLang(array|string $expected, string $lang, bool $singleResult, string $value)
{
$extensionRuntime = new StringRuntime();
$this->expectException(\InvalidArgumentException::class);
$this->expectExceptionMessage('Language "it" is not supported.');
$this->assertSame($expected, $extensionRuntime->pluralize($value, $lang, $singleResult));
}

/**
* @testWith [["partition"], "it", false, "partitions"]
* [["partition"], "it", true, "partitions"]
*/
public function testSingularizeInvalidLang(array|string $expected, string $lang, bool $singleResult, string $value)
{
$extensionRuntime = new StringRuntime();
$this->expectException(\InvalidArgumentException::class);
$this->expectExceptionMessage('Language "it" is not supported.');
$this->assertSame($expected, $extensionRuntime->singularize($value, $lang, $singleResult));
}
}
1 change: 1 addition & 0 deletions src/Symfony/Bridge/Twig/composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@
"symfony/security-http": "^6.4|^7.0",
"symfony/serializer": "^6.4.3|^7.0.3",
"symfony/stopwatch": "^6.4|^7.0",
"symfony/string": "^7.2",
"symfony/console": "^6.4|^7.0",
"symfony/expression-language": "^6.4|^7.0",
"symfony/web-link": "^6.4|^7.0",
Expand Down

0 comments on commit 2934564

Please sign in to comment.