feature #40323 [TwigBridge][TwigBundle] Twig serialize filter (jrushlow)
This PR was merged into the 5.3-dev branch.
Discussion
----------
[TwigBridge][TwigBundle] Twig serialize filter
| Q | A
| ------------- | ---
| Branch? | 5.x
| Bug fix? | no
| New feature? | yes
| Deprecations? | no
| Tickets | Fix #40227
| License | MIT
| Doc PR | symfony/symfony-docs#15039
Adds a new `serialize` filter for Twig utilizing the Serializer component. As suggested in #40227 - would allow you to pass a serialized object to the front end without needing to make an ajax call.
Commits
-------
abb534ab56
implement twig serialize filter
This commit is contained in:
commit
3a92844519
@ -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
|
||||||
-----
|
-----
|
||||||
|
|
||||||
|
28
src/Symfony/Bridge/Twig/Extension/SerializerExtension.php
Normal file
28
src/Symfony/Bridge/Twig/Extension/SerializerExtension.php
Normal 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']),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
33
src/Symfony/Bridge/Twig/Extension/SerializerRuntime.php
Normal file
33
src/Symfony/Bridge/Twig/Extension/SerializerRuntime.php
Normal 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);
|
||||||
|
}
|
||||||
|
}
|
@ -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';
|
||||||
|
}
|
@ -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 }}', '{"name":"howdy","title":"fixture"}'];
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
@ -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",
|
||||||
|
@ -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
|
||||||
-----
|
-----
|
||||||
|
|
||||||
|
@ -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');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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)
|
||||||
;
|
;
|
||||||
};
|
};
|
||||||
|
Reference in New Issue
Block a user