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 75bed4e
Show file tree
Hide file tree
Showing 14 changed files with 611 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" }
44 changes: 44 additions & 0 deletions src/Bridge/PlatesExtension.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
<?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)
{
$engine->registerFunction('structuredTextRender', [$this->renderer, 'render']);
$engine->registerFunction('structuredTextRenderCollection', [$this->renderer, 'renderCollection']);
}
}
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'],
]);
}
}
77 changes: 77 additions & 0 deletions tests/Integration/AllNodesHaveParserTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
<?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\NodeMapper\NodeMapperInterface;
use Contentful\StructuredText\Parser;
use Contentful\Tests\StructuredText\Implementation\LinkResolver;
use Contentful\Tests\StructuredText\TestCase;
use Symfony\Component\Finder\Finder;

class AllNodesHaveParserTest extends TestCase
{
/**
* @var NodeMapperInterface[]
*/
private $mappers;

public function setUp()
{
$parser = new Parser(new LinkResolver());

$object = new \ReflectionObject($parser);
$property = $object->getProperty('mappers');
$property->setAccessible(\true);

$this->mappers = $property->getValue($parser);
}

/**
* @dataProvider classFileProvider
*
* @param string $file
*/
public function testAllNodesHaveParser($file)
{
$file = \str_replace('.php', '', $file);
$nodeClass = '\\Contentful\\StructuredText\\Node\\'.$file;
$nodeMapperClass = '\\Contentful\\StructuredText\\NodeMapper\\'.$file;

if (!\class_exists($nodeMapperClass)) {
$this->fail(\sprintf(
'Node mapper "%s" does not exists',
$nodeMapperClass
));
}

$nodeType = \call_user_func([$nodeClass, 'getType']);
$this->assertArrayHasKey($nodeType, $this->mappers);
$this->assertInstanceOf($nodeMapperClass, $this->mappers[$nodeType]);
}

public function classFileProvider()
{
$iterator = Finder::create()
->files()
->name('*.php')
->in(__DIR__.'/../../src/Node')
;

foreach ($iterator as $file) {
if ('Interface.php' === \mb_substr($file->getFilename(), -13)) {
continue;
}

yield $file->getFilename() => [$file->getRelativePathname()];
}
}
}
135 changes: 135 additions & 0 deletions tests/Integration/AllNodesHaveRendererTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
<?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\Core\ResourceBuilder\ObjectHydrator;
use Contentful\StructuredText\Node\NodeInterface;
use Contentful\StructuredText\NodeRenderer\NodeRendererInterface;
use Contentful\StructuredText\Renderer;
use Contentful\Tests\StructuredText\Implementation\Node;
use Contentful\Tests\StructuredText\TestCase;
use Symfony\Component\Finder\Finder;

class AllNodesHaveRendererTest extends TestCase
{
/**
* @var NodeRendererInterface[]
*/
private $allNodeRenderers = [];

/**
* @var NodeRendererInterface[]
*/
private $defaultNodeRenderers = [];

public function setUp()
{
// This loads all available node renderers
$iterator = Finder::create()
->files()
->name('*.php')
->in(__DIR__.'/../../src/NodeRenderer')
;

foreach ($iterator as $file) {
if ('Interface.php' === \mb_substr($file->getFilename(), -13)) {
continue;
}

$nodeRendererClass = \str_replace('.php', '', $file->getRelativePathname());
$fqcn = '\\Contentful\\StructuredText\\NodeRenderer\\'.$nodeRendererClass;

$this->allNodeRenderers[$nodeRendererClass] = new $fqcn();
}

$this->defaultNodeRenderers = (new Renderer())
->getNodeRenderers()
;
}

/**
* @dataProvider classFileProvider
*
* @param string $class
*/
public function testAllNodesHaveRenderer($class)
{
$nodeClass = '\\Contentful\\StructuredText\\Node\\'.$class;
$nodeRendererClass = '\\Contentful\\StructuredText\\NodeRenderer\\'.$class;

if (!\class_exists($nodeRendererClass)) {
$this->fail(\sprintf(
'Node renderer "%s" does not exists',
$nodeRendererClass
));
}

$hydrator = new ObjectHydrator();
/** @var NodeInterface $node */
$node = $hydrator->hydrate($nodeClass, []);
foreach ($this->allNodeRenderers as $nodeRenderer) {
if ($nodeRenderer->supports($node)) {
$this->markTestAsPassed();

return;
}
}

$this->fail(\sprintf(
'No node renderer which supports node of class "%s" was found.',
$nodeClass
));
}

/**
* @dataProvider classFileProvider
*
* @param string $class
*/
public function testMainRendererCreatesAllNodeRenderers(string $class)
{
$nodeClass = '\\Contentful\\StructuredText\\Node\\'.$class;

$hydrator = new ObjectHydrator();
/** @var NodeInterface $node */
$node = $hydrator->hydrate($nodeClass, []);
foreach ($this->defaultNodeRenderers as $nodeRenderer) {
if ($nodeRenderer->supports($node)) {
$this->markTestAsPassed();

return;
}
}

$this->fail(\sprintf(
'No default node renderer which supports node of class "%s" was found.',
$nodeClass
));
}

public function classFileProvider()
{
$iterator = Finder::create()
->files()
->name('*.php')
->in(__DIR__.'/../../src/Node')
;

foreach ($iterator as $file) {
if ('Interface.php' === \mb_substr($file->getFilename(), -13)) {
continue;
}

yield $file->getFilename() => [\str_replace('.php', '', $file->getRelativePathname())];
}
}
}
Loading

0 comments on commit 75bed4e

Please sign in to comment.