implement twig serialize filter

This commit is contained in:
Jesse Rushlow 2021-02-26 18:06:15 -05:00
parent 252f85c2c2
commit abb534ab56
No known key found for this signature in database
GPG Key ID: 79712BB7E139D5AC
9 changed files with 173 additions and 1 deletions

View File

@ -1,6 +1,11 @@
CHANGELOG CHANGELOG
========= =========
5.3.0
-----
* Added a new `serialize` filter to serialize objects using the Serializer component
5.2.0 5.2.0
----- -----

View File

@ -0,0 +1,28 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* 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;
/**
* @author Jesse Rushlow <jr@rushlow.dev>
*/
final class SerializerExtension extends AbstractExtension
{
public function getFilters(): array
{
return [
new TwigFilter('serialize', [SerializerRuntime::class, 'serialize']),
];
}
}

View File

@ -0,0 +1,33 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* 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\Serializer\SerializerInterface;
use Twig\Extension\RuntimeExtensionInterface;
/**
* @author Jesse Rushlow <jr@rushlow.dev>
*/
final class SerializerRuntime implements RuntimeExtensionInterface
{
private $serializer;
public function __construct(SerializerInterface $serializer)
{
$this->serializer = $serializer;
}
public function serialize($data, string $format = 'json', array $context = []): string
{
return $this->serializer->serialize($data, $format, $context);
}
}

View File

@ -0,0 +1,18 @@
<?php
namespace Symfony\Bridge\Twig\Tests\Extension\Fixtures;
use Symfony\Component\Serializer\Annotation\Groups;
/**
* @author Jesse Rushlow <jr@rushlow.dev>
*/
class SerializerModelFixture
{
/**
* @Groups({"read"})
*/
public $name = 'howdy';
public $title = 'fixture';
}

View File

@ -0,0 +1,70 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* 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 Doctrine\Common\Annotations\AnnotationReader;
use PHPUnit\Framework\TestCase;
use Symfony\Bridge\Twig\Extension\SerializerExtension;
use Symfony\Bridge\Twig\Extension\SerializerRuntime;
use Symfony\Bridge\Twig\Tests\Extension\Fixtures\SerializerModelFixture;
use Symfony\Component\Serializer\Encoder\JsonEncoder;
use Symfony\Component\Serializer\Encoder\YamlEncoder;
use Symfony\Component\Serializer\Mapping\Factory\ClassMetadataFactory;
use Symfony\Component\Serializer\Mapping\Loader\AnnotationLoader;
use Symfony\Component\Serializer\Normalizer\ObjectNormalizer;
use Symfony\Component\Serializer\Serializer;
use Twig\Environment;
use Twig\Loader\ArrayLoader;
use Twig\RuntimeLoader\RuntimeLoaderInterface;
/**
* @author Jesse Rushlow <jr@rushlow.dev>
*/
class SerializerExtensionTest extends TestCase
{
/**
* @dataProvider serializerDataProvider
*/
public function testSerializeFilter(string $template, string $expectedResult)
{
$twig = $this->getTwig($template);
self::assertSame($expectedResult, $twig->render('template', ['object' => new SerializerModelFixture()]));
}
public function serializerDataProvider(): \Generator
{
yield ['{{ object|serialize }}', '{&quot;name&quot;:&quot;howdy&quot;,&quot;title&quot;:&quot;fixture&quot;}'];
yield ['{{ object|serialize(\'yaml\') }}', '{ name: howdy, title: fixture }'];
yield ['{{ object|serialize(\'yaml\', {groups: \'read\'}) }}', '{ name: howdy }'];
}
private function getTwig(string $template): Environment
{
$meta = new ClassMetadataFactory(new AnnotationLoader(new AnnotationReader()));
$runtime = new SerializerRuntime(new Serializer([new ObjectNormalizer($meta)], [new JsonEncoder(), new YamlEncoder()]));
$mockRuntimeLoader = $this->createMock(RuntimeLoaderInterface::class);
$mockRuntimeLoader
->method('load')
->willReturnMap([
['Symfony\Bridge\Twig\Extension\SerializerRuntime', $runtime],
])
;
$twig = new Environment(new ArrayLoader(['template' => $template]));
$twig->addExtension(new SerializerExtension());
$twig->addRuntimeLoader($mockRuntimeLoader);
return $twig;
}
}

View File

@ -22,6 +22,7 @@
"twig/twig": "^2.13|^3.0.4" "twig/twig": "^2.13|^3.0.4"
}, },
"require-dev": { "require-dev": {
"doctrine/annotations": "^1.12",
"egulias/email-validator": "^2.1.10", "egulias/email-validator": "^2.1.10",
"phpdocumentor/reflection-docblock": "^3.0|^4.0|^5.0", "phpdocumentor/reflection-docblock": "^3.0|^4.0|^5.0",
"symfony/asset": "^4.4|^5.0", "symfony/asset": "^4.4|^5.0",

View File

@ -1,6 +1,11 @@
CHANGELOG CHANGELOG
========= =========
5.3.0
-----
* Added support for the new `serialize` filter (from Twig Bridge)
5.2.0 5.2.0
----- -----
@ -33,7 +38,7 @@ CHANGELOG
4.1.0 4.1.0
----- -----
* added priority to Twig extensions * added priority to Twig extensions
* deprecated relying on the default value (`false`) of the `twig.strict_variables` configuration option. The `%kernel.debug%` parameter will be the new default in 5.0 * deprecated relying on the default value (`false`) of the `twig.strict_variables` configuration option. The `%kernel.debug%` parameter will be the new default in 5.0
4.0.0 4.0.0

View File

@ -120,5 +120,10 @@ class ExtensionPass implements CompilerPassInterface
} else { } else {
$container->getDefinition('workflow.twig_extension')->addTag('twig.extension'); $container->getDefinition('workflow.twig_extension')->addTag('twig.extension');
} }
if ($container->has('serializer')) {
$container->getDefinition('twig.runtime.serializer')->addTag('twig.runtime');
$container->getDefinition('twig.extension.serializer')->addTag('twig.extension');
}
} }
} }

View File

@ -23,6 +23,8 @@ use Symfony\Bridge\Twig\Extension\HttpKernelExtension;
use Symfony\Bridge\Twig\Extension\HttpKernelRuntime; use Symfony\Bridge\Twig\Extension\HttpKernelRuntime;
use Symfony\Bridge\Twig\Extension\ProfilerExtension; use Symfony\Bridge\Twig\Extension\ProfilerExtension;
use Symfony\Bridge\Twig\Extension\RoutingExtension; use Symfony\Bridge\Twig\Extension\RoutingExtension;
use Symfony\Bridge\Twig\Extension\SerializerExtension;
use Symfony\Bridge\Twig\Extension\SerializerRuntime;
use Symfony\Bridge\Twig\Extension\StopwatchExtension; use Symfony\Bridge\Twig\Extension\StopwatchExtension;
use Symfony\Bridge\Twig\Extension\TranslationExtension; use Symfony\Bridge\Twig\Extension\TranslationExtension;
use Symfony\Bridge\Twig\Extension\WebLinkExtension; use Symfony\Bridge\Twig\Extension\WebLinkExtension;
@ -160,5 +162,10 @@ return static function (ContainerConfigurator $container) {
->factory([TwigErrorRenderer::class, 'isDebug']) ->factory([TwigErrorRenderer::class, 'isDebug'])
->args([service('request_stack'), param('kernel.debug')]), ->args([service('request_stack'), param('kernel.debug')]),
]) ])
->set('twig.runtime.serializer', SerializerRuntime::class)
->args([service('serializer')])
->set('twig.extension.serializer', SerializerExtension::class)
; ;
}; };