From 46b3702fc1c0c2e5930f415cab9d0668847031a2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lu=C3=ADs=20Cobucci?= Date: Sun, 22 Apr 2018 13:20:52 +0200 Subject: [PATCH] Add support for Twig as template engine --- README.md | 1 + composer.json | 2 + src/Formatter/Twig.php | 61 +++++++++++++++++++++++++++ templates/twig/person.twig | 8 ++++ tests/Formatter/TwigTest.php | 82 ++++++++++++++++++++++++++++++++++++ 5 files changed, 154 insertions(+) create mode 100644 src/Formatter/Twig.php create mode 100644 templates/twig/person.twig create mode 100644 tests/Formatter/TwigTest.php diff --git a/README.md b/README.md index 2a23a7c6..e190c8da 100644 --- a/README.md +++ b/README.md @@ -153,6 +153,7 @@ We provide some basic formatters by default: * `StringCast` * `JmsSerializer` (requires you to also install and configure [`jms/serializer`](https://jmsyst.com/libs/serializer)) * `Plates` (requires you to also install and configure [`league/plates`](http://platesphp.com)) +* `Twig` (requires you to also install and configure [`twig/twig`](https://twig.symfony.com)) If you want to create a customised formatter the only thing needed is to implement the `Formatter` interface: diff --git a/composer.json b/composer.json index 4639fc8b..81084f8a 100644 --- a/composer.json +++ b/composer.json @@ -34,12 +34,14 @@ "phpstan/phpstan-strict-rules": "^0.10@dev", "phpunit/phpunit": "^7.0", "squizlabs/php_codesniffer": "^3.2", + "twig/twig": "^2.0", "zendframework/zend-diactoros": "^1.7" }, "suggest": { "jms/serializer": "For content formatting using a more flexible serializer", "league/plates": "For content formatting using Plates as template engine", "middlewares/negotiation": "For acceptable format identification", + "twig/twig": "For content formatting using Twig as template engine", "zendframework/zend-diactoros": "For concrete implementation of PSR-7" }, "autoload": { diff --git a/src/Formatter/Twig.php b/src/Formatter/Twig.php new file mode 100644 index 00000000..fb0a21d2 --- /dev/null +++ b/src/Formatter/Twig.php @@ -0,0 +1,61 @@ +environment = $environment; + $this->attributeName = $attributeName; + } + + /** + * {@inheritdoc} + */ + public function format($content, array $attributes = []): string + { + try { + return $this->render($content, $attributes); + } catch (Throwable $exception) { + throw new ContentCouldNotBeFormatted( + 'An error occurred while formatting using twig', + $exception->getCode(), + $exception + ); + } + } + + /** + * @param mixed $content + * @param mixed[] $attributes + * + * @throws Throwable + */ + private function render($content, array $attributes = []): string + { + $template = $attributes[$this->attributeName] ?? ''; + + return $this->environment->render($template, ['content' => $content]); + } +} diff --git a/templates/twig/person.twig b/templates/twig/person.twig new file mode 100644 index 00000000..b6e7e5e7 --- /dev/null +++ b/templates/twig/person.twig @@ -0,0 +1,8 @@ +
+
+
Identifier
+
{{ content.id }}
+
Name
+
{{ content.name }}
+
+
diff --git a/tests/Formatter/TwigTest.php b/tests/Formatter/TwigTest.php new file mode 100644 index 00000000..ba8f7f2e --- /dev/null +++ b/tests/Formatter/TwigTest.php @@ -0,0 +1,82 @@ +environment = new Twig_Environment( + new Twig_Loader_Filesystem('templates/twig', dirname(__DIR__, 2) . '/') + ); + } + + /** + * @test + * + * @covers ::__construct() + * @covers ::format() + * @covers ::render() + */ + public function formatShouldReturnContentFormattedByPlates(): void + { + $formatter = new Twig($this->environment); + $content = $formatter->format(new PersonDto(1, 'Testing'), ['template' => 'person.twig']); + + self::assertContains('
1
', $content); + self::assertContains('
Testing
', $content); + } + + /** + * @test + * + * @covers ::__construct() + * @covers ::format() + * @covers ::render() + */ + public function formatShouldReadTemplateNameFromCustomAttribute(): void + { + $formatter = new Twig($this->environment, 'fancy!'); + $content = $formatter->format(new PersonDto(1, 'Testing'), ['fancy!' => 'person.twig']); + + self::assertContains('
1
', $content); + self::assertContains('
Testing
', $content); + } + + /** + * @test + * + * @covers ::__construct() + * @covers ::format() + * @covers ::render() + */ + public function formatShouldConvertAnyTwigException(): void + { + $formatter = new Twig($this->environment); + + $this->expectException(ContentCouldNotBeFormatted::class); + $this->expectExceptionMessage('An error occurred while formatting using twig'); + + $formatter->format(new PersonDto(1, 'Testing'), ['template' => 'no-template-at-all']); + } +}