Skip to content

Instantly share code, notes, and snippets.

@jakzal
Created February 20, 2012 13:43
Show Gist options
  • Save jakzal/1869254 to your computer and use it in GitHub Desktop.
Save jakzal/1869254 to your computer and use it in GitHub Desktop.
Twig extension to render parts of content as actions
<?php
namespace PSS\Bundle\ContentBundle\Twig\Extension;
use Symfony\Bundle\FrameworkBundle\Templating\Helper\ActionsHelper;
class BlockActionExtension extends \Twig_Extension
{
/**
* @var \Symfony\Bundle\FrameworkBundle\Templating\Helper\ActionsHelper $actionsHelper
*/
private $actionsHelper = null;
/**
* @var array $actions
*/
private $actions = array();
/**
* @param \Symfony\Bundle\FrameworkBundle\Templating\Helper\ActionsHelper $actionsHelper
* @param array $actions
*
* @return null
*/
public function __construct(ActionsHelper $actionsHelper, array $actions = array())
{
$this->actionsHelper = $actionsHelper;
$this->actions = $actions;
}
/**
* @return array
*/
public function getFilters()
{
return array(
'render_action_blocks' => new \Twig_Filter_Method($this, 'renderActionBlocks', array('is_safe' => array('html')))
);
}
/**
* @param string $text
*
* @return string
*/
public function renderActionBlocks($text)
{
foreach ($this->actions as $placeHolder => $action) {
if (false !== strpos($text, $placeHolder)) {
$block = $this->actionsHelper->render($action);
$text = str_replace($placeHolder, $block, $text);
}
}
return $text;
}
/**
* @return string
*/
public function getName()
{
return 'block_action';
}
}
<?php
namespace PSS\Bundle\ContentBundle\Tests\Twig\Extension;
use PSS\Bundle\ContentBundle\Twig\Extension\BlockActionExtension;
class BlockActionExtensionTest extends \PHPUnit_Framework_TestCase
{
/**
* @var \Symfony\Bundle\FrameworkBundle\Templating\Helper\ActionsHelper $actionsHelper
*/
private $actionsHelper = null;
public function setUp()
{
$this->actionsHelper = $this->getMockBuilder('Symfony\Bundle\FrameworkBundle\Templating\Helper\ActionsHelper')
->disableOriginalConstructor()
->getMock();
}
public function testThatActionsAreCalledAndRenderedIntoString()
{
$this->actionsHelper->expects($this->once())
->method('render')
->will($this->returnCallback(function ($action) {
if ('MyBundle:Block:show' == $action) {
return 'Rendered show action.';
}
}));
$blockExtension = new BlockActionExtension($this->actionsHelper, array(
'{MyBlock}' => 'MyBundle:Block:show'
));
$result = $blockExtension->renderActionBlocks('Lorem lipsum. {MyBlock} Lorem lipsum.');
$this->assertEquals('Lorem lipsum. Rendered show action. Lorem lipsum.', $result);
}
public function testThatNotRecognizedBlocksAreIgnored()
{
$this->actionsHelper->expects($this->never())->method('render');
$blockExtension = new BlockActionExtension($this->actionsHelper, array(
'{MyBlock}' => 'MyBundle:Block:show'
));
$result = $blockExtension->renderActionBlocks('Lorem lipsum. {NotDefinedBlock} Lorem lipsum.');
$this->assertEquals('Lorem lipsum. {NotDefinedBlock} Lorem lipsum.', $result);
}
public function testThatMultipleBlocksAreRenderedIntoString()
{
$this->actionsHelper->expects($this->any())
->method('render')
->will($this->returnCallback(function ($action) {
if ('MyBundle:Block:show' == $action) {
return 'Rendered show action.';
} else if ('MyBundle:Block:form' == $action) {
return 'Rendered form action.';
}
}));
$blockExtension = new BlockActionExtension($this->actionsHelper, array(
'{MyBlock}' => 'MyBundle:Block:show',
'{AnotherBlock}' => 'MyBundle:Block:form'
));
$result = $blockExtension->renderActionBlocks(
'{MyBlock} Lorem lipsum. {AnotherBlock} {MyBlock} Lorem lipsum.'
);
$this->assertEquals('Rendered show action. Lorem lipsum. Rendered form action. Rendered show action. Lorem lipsum.', $result);
}
public function testThatFiltersAreExposed()
{
$blockExtension = new BlockActionExtension($this->actionsHelper, array());
$filters = $blockExtension->getFilters();
$this->assertEquals('block_action', $blockExtension->getName());
$this->assertArrayHasKey('render_action_blocks', $filters);
$this->assertInstanceOf('Twig_Filter_method', $filters['render_action_blocks']);
}
}
{{ page.body | render_action_blocks }}
<container xmlns="http://symfony.com/schema/dic/services"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd">
<parameters>
<parameter key="pss_content.block.actions" type="collection">
<parameter key="{ContactUsForm}">PSSContentBundle:Block:contactUsForm</parameter>
<parameter key="{FeedbackForm}">PSSContentBundle:Block:feedbackForm</parameter>
</parameter>
</parameters>
<services>
<service id="pss_content.twig.extension.block_action" class="PSS\Bundle\ContentBundle\Twig\Extension\BlockActionExtension" public="false">
<argument type="service" id="templating.helper.actions" />
<argument>%pss_content.block.actions%</argument>
<tag name="twig.extension" />
</service>
</services>
</container>
@stloyd
Copy link

stloyd commented Feb 20, 2012

Add is_safe into getFilters() and you can skip raw filter in template.

@stloyd
Copy link

stloyd commented Feb 20, 2012

new \Twig_Filter_Method($this, 'renderActionBlocks', array('is_safe' => array('html')))

@jakzal
Copy link
Author

jakzal commented Feb 20, 2012

Thanks for the tip!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment