Skip to content

Commit

Permalink
feat(integrations): Add Twig and Plates extensions
Browse files Browse the repository at this point in the history
  • Loading branch information
dborsatto committed Sep 12, 2018
1 parent 5b26b93 commit 46a7f10
Show file tree
Hide file tree
Showing 12 changed files with 411 additions and 2 deletions.
2 changes: 1 addition & 1 deletion .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,6 @@ jobs:
- checkout
- run: { name: "Install dependencies", command: "sudo composer self-update && composer install -n --prefer-dist" }
- run: { name: "Test suite", command: "composer test-quick-fail" }
- run: { name: "Upload code coverage", command: "bash <(curl -s https://codecov.io/bash) -f build/logs/clover.xml" }

test72:
docker:
Expand All @@ -51,3 +50,4 @@ jobs:
- checkout
- run: { name: "Install dependencies", command: "sudo composer self-update && composer install -n --prefer-dist" }
- run: { name: "Test suite", command: "composer test-quick-fail" }
- run: { name: "Upload code coverage", command: "bash <(curl -s https://codecov.io/bash) -f build/logs/clover.xml" }
56 changes: 56 additions & 0 deletions src/Bridge/PlatesExtension.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
<?php

/**
* This file is part of the contentful/structured-text-renderer package.
*
* @copyright 2015-2018 Contentful GmbH
* @license MIT
*/

declare(strict_types=1);

namespace Contentful\StructuredText\Bridge;

use Contentful\StructuredText\Renderer;
use Contentful\StructuredText\RendererInterface;
use League\Plates\Engine;
use League\Plates\Extension\ExtensionInterface;

class PlatesExtension implements ExtensionInterface
{
/**
* @var RendererInterface
*/
private $renderer;

/**
* PlatesExtension constructor.
*
* @param RendererInterface|null $renderer
*/
public function __construct(RendererInterface $renderer = \null)
{
$this->renderer = $renderer ?: new Renderer();
}

/**
* {@inheritdoc}
*/
public function register(Engine $engine)
{
// The type annotations here make no sense.
// But they are needed to trick static analysis with PHPStan,
// as Plates wrongly defines the PHPDoc type of the second
// parameter of Engine::registerFunction() as "callback" (instead of callable),
// which does not exist and is resolved as the non-existent
// League\Plates\callback class ¯\_(ツ)_/¯

/** @var \League\Plates\callback $callback */
$callback = [$this->renderer, 'render'];
$engine->registerFunction('structuredTextRender', $callback);

/** @var \League\Plates\callback $callback */
$callback = [$this->renderer, 'renderCollection'];
$engine->registerFunction('structuredTextRenderCollection', $callback);
}
}
54 changes: 54 additions & 0 deletions src/Bridge/TwigExtension.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
<?php

/**
* This file is part of the contentful/structured-text-renderer package.
*
* @copyright 2015-2018 Contentful GmbH
* @license MIT
*/

declare(strict_types=1);

namespace Contentful\StructuredText\Bridge;

use Contentful\StructuredText\Renderer;
use Contentful\StructuredText\RendererInterface;
use Twig\Extension\AbstractExtension;
use Twig\TwigFunction;

class TwigExtension extends AbstractExtension
{
/**
* @var RendererInterface
*/
private $renderer;

/**
* TwigExtension constructor.
*
* @param RendererInterface|null $renderer
*/
public function __construct(RendererInterface $renderer = \null)
{
$this->renderer = $renderer ?: new Renderer();
}

/**
* {@inheritdoc}
*/
public function getFunctions()
{
return [
new TwigFunction(
'structured_text_render',
[$this->renderer, 'render'],
['is_safe' => ['html']]
),
new TwigFunction(
'structured_text_render_collection',
[$this->renderer, 'renderCollection'],
['is_safe' => ['html']]
),
];
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
The output is "<?php echo $this->structuredTextRenderCollection($nodes); ?>"
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
The output is "<?php echo $this->structuredTextRender($node); ?>"
1 change: 1 addition & 0 deletions tests/Fixtures/Integration/PlatesNodeRenderer/template.php
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
This is a node with type "<?php echo $this->e($name); ?>" with context var set to "<?php echo $this->e($contextVar); ?>".
55 changes: 55 additions & 0 deletions tests/Implementation/PlatesNodeRenderer.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
<?php

/**
* This file is part of the contentful/structured-text-renderer package.
*
* @copyright 2015-2018 Contentful GmbH
* @license MIT
*/

declare(strict_types=1);

namespace Contentful\Tests\StructuredText\Implementation;

use Contentful\StructuredText\Node\NodeInterface;
use Contentful\StructuredText\NodeRenderer\NodeRendererInterface;
use Contentful\StructuredText\RendererInterface;
use League\Plates\Engine;

/**
* Basic implementation of NodeRendererInterface for testing purposes.
*
* This implementation demonstrates how delegating
* to an actual templating engine might work.
*/
class PlatesNodeRenderer implements NodeRendererInterface
{
/**
* @var Engine
*/
private $plates;

public function __construct(Engine $plates)
{
$this->plates = $plates;
}

/**
* {@inheritdoc}
*/
public function supports(NodeInterface $node): bool
{
return \true;
}

/**
* {@inheritdoc}
*/
public function render(RendererInterface $renderer, NodeInterface $node, array $context = []): string
{
return $this->plates->render('template', [
'name' => $node->getType(),
'contextVar' => $context['contextVar'],
]);
}
}
66 changes: 66 additions & 0 deletions tests/Integration/PlatesNodeRendererTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
<?php

/**
* This file is part of the contentful/structured-text-renderer package.
*
* @copyright 2015-2018 Contentful GmbH
* @license MIT
*/

declare(strict_types=1);

namespace Contentful\Tests\StructuredText\Integration;

use Contentful\StructuredText\Bridge\PlatesExtension;
use Contentful\StructuredText\Renderer;
use Contentful\Tests\StructuredText\Implementation\Node;
use Contentful\Tests\StructuredText\Implementation\NodeRenderer;
use Contentful\Tests\StructuredText\Implementation\PlatesNodeRenderer;
use Contentful\Tests\StructuredText\TestCase;
use League\Plates\Engine;

class PlatesNodeRendererTest extends TestCase
{
public function testPlatesNodeRenderer()
{
$path = $this->convertClassToFixturePath(static::class);
// Create a Plates engine
$engine = new Engine($path);

// Create a custom node renderer which uses Plates
$platesNodeRenderer = new PlatesNodeRenderer($engine);
$renderer = new Renderer([$platesNodeRenderer]);

$rendered = $renderer->render(new Node('Some value'), [
'contextVar' => 'contextValue',
]);

$this->assertSame('This is a node with type "node" with context var set to "contextValue".'."\n", $rendered);
}

public function testPlatesExtension()
{
$path = $this->convertClassToFixturePath(static::class);
// Create a Plates engine
$engine = new Engine($path);

$renderer = new Renderer();
$renderer->pushNodeRenderer(new NodeRenderer());
$engine->loadExtension(new PlatesExtension($renderer));

$rendered = $engine->render('singleNode', [
'node' => new Node('Some text'),
]);

$this->assertSame('The output is "Some text"'."\n", $rendered);

$rendered = $engine->render('collectionNodes', [
'nodes' => [
new Node('First text -'),
new Node(' Second text'),
],
]);

$this->assertSame('The output is "First text - Second text"'."\n", $rendered);
}
}
70 changes: 70 additions & 0 deletions tests/Integration/TwigNodeRendererTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
<?php

/**
* This file is part of the contentful/structured-text-renderer package.
*
* @copyright 2015-2018 Contentful GmbH
* @license MIT
*/

declare(strict_types=1);

namespace Contentful\Tests\StructuredText\Integration;

use Contentful\StructuredText\Bridge\TwigExtension;
use Contentful\StructuredText\Renderer;
use Contentful\Tests\StructuredText\Implementation\Node;
use Contentful\Tests\StructuredText\Implementation\NodeRenderer;
use Contentful\Tests\StructuredText\Implementation\TwigNodeRenderer;
use Contentful\Tests\StructuredText\TestCase;
use Twig\Environment;
use Twig\Loader\ArrayLoader;

class TwigNodeRendererTest extends TestCase
{
public function testTwigNodeRenderer()
{
// Create a Twig environment
$loader = new ArrayLoader([]);
$twig = new Environment($loader);

// Create a custom node renderer which uses Twig
$twigNodeRenderer = new TwigNodeRenderer($twig);
$renderer = new Renderer([$twigNodeRenderer]);

$rendered = $renderer->render(new Node('Some value'), [
'contextVar' => 'contextValue',
]);

$this->assertSame('This is a node with type "node" with context var set to "contextValue".', $rendered);
}

public function testTwigExtension()
{
// Create a Twig environment
$loader = new ArrayLoader([]);
$twig = new Environment($loader);

$renderer = new Renderer();
$renderer->pushNodeRenderer(new NodeRenderer());
$extension = new TwigExtension($renderer);
$twig->addExtension($extension);

$template = $twig->createTemplate('The output is "{{ structured_text_render(node) }}"');
$rendered = $template->render([
'node' => new Node('Some text'),
]);

$this->assertSame('The output is "Some text"', $rendered);

$template = $twig->createTemplate('The output is "{{ structured_text_render_collection(nodes) }}"');
$rendered = $template->render([
'nodes' => [
new Node('First text -'),
new Node(' Second text'),
],
]);

$this->assertSame('The output is "First text - Second text"', $rendered);
}
}
2 changes: 1 addition & 1 deletion tests/TestCase.php
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ protected function getParsedFixture(string $file)
*
* @return string
*/
private function convertClassToFixturePath(string $class)
protected function convertClassToFixturePath(string $class)
{
$class = \str_replace(__NAMESPACE__.'\\', '', $class);
$class = \str_replace('\\', '/', $class);
Expand Down
54 changes: 54 additions & 0 deletions tests/Unit/Bridge/PlatesExtensionTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
<?php

/**
* This file is part of the contentful/structured-text-renderer package.
*
* @copyright 2015-2018 Contentful GmbH
* @license MIT
*/

declare(strict_types=1);

namespace Contentful\Tests\StructuredText\Unit\Bridge;

use Contentful\StructuredText\Bridge\PlatesExtension;
use Contentful\StructuredText\RendererInterface;
use Contentful\Tests\StructuredText\Implementation\Renderer;
use Contentful\Tests\StructuredText\TestCase;
use League\Plates\Engine;

class PlatesExtensionTest extends TestCase
{
public function testPlatesExtension()
{
$renderer = new Renderer();
$extension = new PlatesExtension($renderer);

$engine = $this->getMockBuilder(Engine::class)
->getMock()
;
$engine->method('registerFunction')
->willReturnCallback(function (string $name, callable $callback) {
switch ($name) {
case 'structuredTextRender':
$this->assertInternalType('array', $callback);
$this->assertInstanceOf(RendererInterface::class, $callback[0]);
$this->assertSame('render', $callback[1]);
break;
case 'structuredTextRenderCollection':
$this->assertInternalType('array', $callback);
$this->assertInstanceOf(RendererInterface::class, $callback[0]);
$this->assertSame('renderCollection', $callback[1]);
break;
default:
$this->fail(\sprintf(
'Unrecognized extension name "%s"',
$name
));
}
})
;

$extension->register($engine);
}
}
Loading

0 comments on commit 46a7f10

Please sign in to comment.