8000 [TwigBridge] Add `emojify` twig filter · symfony/symfony@3d78c87 · GitHub
[go: up one dir, main page]

Skip to content

Commit 3d78c87

Browse files
committed
[TwigBridge] Add emojify twig filter
1 parent 695bd1a commit 3d78c87

File tree

8 files changed

+107
-1
lines changed

8 files changed

+107
-1
lines changed

src/Symfony/Bridge/Twig/CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,11 @@
11
CHANGELOG
22
=========
33

4+
7.1
5+
---
6+
7+
* Add `emojify` twig filter
8+
49
7.0
510
---
611

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
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\Bridge\Twig\Extension;
13+
14+
use Symfony\Component\Emoji\EmojiTransliterator;
15+
use Twig\Extension\AbstractExtension;
16+
use Twig\TwigFilter;
17+
18+
/**
19+
* @author Grégoire Pineau <lyrixx@lyrixx.info>
20+
*/
21+
final class EmojiExtension extends AbstractExtension
22+
{
23+
private static array $transliterators = [];
24+
25+
public function __construct(
26+
private readonly string $defaultCatalog = 'text',
27+
) {
28+
if (!class_exists(EmojiTransliterator::class)) {
29+
throw new \LogicException('You cannot use the "emojify" filter as the "Emoji" component is not installed. Try running "composer require symfony/emoji".');
30+
}
31+
}
32+
33+
public function getFilters(): array
34+
{
35+
return [
36+
new TwigFilter('emojify', $this->emojify(...)),
37+
];
38+
}
39+
40+
/**
41+
* Converts emoji short code (:wave:) to real emoji (👋)
42+
*/
43+
public function emojify(string $string, ?string $catalog = null): string
44+
{
45+
$catalog ??= $this->defaultCatalog;
46+
47+
try {
48+
$tr = self::$transliterators[$catalog] ??= EmojiTransliterator::create($catalog, EmojiTransliterator::REVERSE);
49+
} catch (\IntlException $e) {
50+
throw new \LogicException(sprintf('The emoji catalog "%s" is not available.', $catalog), previous: $e);
51+
}
52+
53+
return (string) $tr->transliterate($string);
54+
}
55+
}
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
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\Bridge\Twig\Tests\Extension;
13+
14+
use PHPUnit\Framework\TestCase;
15+
use Symfony\Bridge\Twig\Extension\EmojiExtension;
16+
17+
/**
18+
* @requires extension intl
19+
*/
20+
class EmojiExtensionTest extends TestCase
21+
{
22+
/**
23+
* @testWith ["🅰️", ":a:"]
24+
* ["🅰️", ":a:", "slack"]
25+
* ["🅰", ":a:", "github"]
26+
*/
27+
public function testEmojify(string $expected, string $string, ?string $catalog = null)
28+
{
29+
$extension = new EmojiExtension();
30+
$this->assertSame($expected, $extension->emojify($string, $catalog));
31+
}
32+
}

src/Symfony/Bridge/Twig/UndefinedCallableHandler.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ class UndefinedCallableHandler
3737
'asset_version' => 'asset',
3838
'importmap' => 'asset-mapper',
3939
'dump' => 'debug-bundle',
40+
'emojify' => 'emoji',
4041
'encore_entry_link_tags' => 'webpack-encore-bundle',
4142
'encore_entry_script_tags' => 'webpack-encore-bundle',
4243
'expression' => 'expression-language',

src/Symfony/Bridge/Twig/composer.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
"symfony/asset": "^6.4|^7.0",
2828
"symfony/asset-mapper": "^6.4|^7.0",
2929
"symfony/dependency-injection": "^6.4|^7.0",
30+
"symfony/emoji": "^7.1",
3031
"symfony/finder": "^6.4|^7.0",
3132
"symfony/form": "^6.4|^7.0",
3233
"symfony/html-sanitizer": "^6.4|^7.0",

src/Symfony/Bundle/TwigBundle/DependencyInjection/Compiler/ExtensionPass.php

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
use Symfony\Component\DependencyInjection\Alias;
1616
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
1717
use Symfony\Component\DependencyInjection\ContainerBuilder;
18+
use Symfony\Component\Emoji\EmojiTransliterator;
1819
use Symfony\Component\ExpressionLanguage\Expression;
1920
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
2021
use Symfony\Component\Workflow\Workflow;
@@ -31,6 +32,10 @@ public function process(ContainerBuilder $container): void
3132
$container->removeDefinition('twig.extension.assets');
3233
}
3334

35+
if (!class_exists(EmojiTransliterator::class)) {
36+
$container->removeDefinition('twig.extension.emoji');
37+
}
38+
3439
if (!class_exists(Expression::class)) {
3540
$container->removeDefinition('twig.extension.expression');
3641
}
@@ -125,6 +130,10 @@ public function process(ContainerBuilder $container): void
125130
$container->getDefinition('twig.extension.expression')->addTag('twig.extension');
126131
}
127132

133+
if ($container->hasDefinition('twig.extension.emoji')) {
134+
$container->getDefinition('twig.extension.emoji')->addTag('twig.extension');
135+
}
136+
128137
if (!class_exists(Workflow::class) || !$container->has('workflow.registry')) {
129138
$container->removeDefinition('workflow.twig_extension');
130139
} else {

src/Symfony/Bundle/TwigBundle/Resources/config/twig.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
use Symfony\Bridge\Twig\ErrorRenderer\TwigErrorRenderer;
1818
use Symfony\Bridge\Twig\EventListener\TemplateAttributeListener;
1919
use Symfony\Bridge\Twig\Extension\AssetExtension;
20+
use Symfony\Bridge\Twig\Extension\EmojiExtension;
2021
use Symfony\Bridge\Twig\Extension\ExpressionExtension;
2122
use Symfony\Bridge\Twig\Extension\HtmlSanitizerExtension;
2223
use Symfony\Bridge\Twig\Extension\HttpFoundationExtension;
@@ -115,6 +116,8 @@
115116

116117
->set('twig.extension.expression', ExpressionExtension::class)
117118

119+
->set('twig.extension.emoji', EmojiExtension::class)
120+
118121
->set('twig.extension.htmlsanitizer', HtmlSanitizerExtension::class)
119122
->args([tagged_locator('html_sanitizer', 'sanitizer')])
120123

src/Symfony/Bundle/TwigBundle/composer.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
"composer-runtime-api": ">=2.1",
2121
"symfony/config": "^6.4|^7.0",
2222
"symfony/dependency-injection": "^6.4|^7.0",
23-
"symfony/twig-bridge": "^6.4|^7.0",
23+
"symfony/twig-bridge": "^7.1",
2424
"symfony/http-foundation": "^6.4|^7.0",
2525
"symfony/http-kernel": "^6.4|^7.0",
2626
"twig/twig": "^3.0.4"

0 commit comments

Comments
 (0)
0