Skip to content

Commit

Permalink
Merge branch 'hanson-operators'
Browse files Browse the repository at this point in the history
  • Loading branch information
goetas committed May 22, 2014
2 parents 56d4126 + 90b1fbc commit 0d2eca1
Show file tree
Hide file tree
Showing 2 changed files with 108 additions and 16 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@ class FixHtmlEntitiesInExpressionSubscriber implements EventSubscriberInterface
public static function getSubscribedEvents()
{
return array(
'compiler.pre_dump' => 'addPlaceholder',
'compiler.pre_load' => 'addPlaceholderOnLoad',
//'compiler.pre_dump' => 'addPlaceholder',
'compiler.post_dump' => 'removePlaceholder'
);
}
Expand All @@ -33,27 +34,67 @@ public function __construct(array $placeholder = array())
$this->placeholder = $placeholder;
}
}

/**
* @param TemplateEvent $event
*
* @param SourceEvent $event
*/
public function addPlaceholder(TemplateEvent $event)
public function addPlaceholderOnLoad(SourceEvent $event)
{
$xp = new \DOMXPath($event->getTemplate()->getDocument());
$source = $event->getTemplate();
$exprs = array(
'{{' => '}}',
'{%' => '%}',
'{#' => '#}'
);
$offset = 0;
while(preg_match ("/".implode("|", array_map('preg_quote', array_keys($exprs)))."/" , $source , $matches , PREG_OFFSET_CAPTURE, $offset)){

foreach ($xp->query("//@*") as $node) {
if (preg_match_all("/(" . preg_quote("{{", "/") . ".*?" . preg_quote("}}", "/") . ")/", $node->value, $mch)) {
foreach ($mch[0] as $n => $m) {
$node->value = htmlspecialchars(str_replace($m, $this->placeholder[0] . $m . $this->placeholder[1], $node->value), ENT_COMPAT, 'UTF-8');
}
}
}
foreach ($xp->query("//text()") as $node) {
if (preg_match_all("/(" . preg_quote("{{", "/") . ".*?" . preg_quote("}}", "/") . ")/", $node->data, $mch)) {
foreach ($mch[0] as $n => $m) {
$node->data = str_replace($m, $this->placeholder[0] . $m . $this->placeholder[1], $node->data);
$source = substr($source, 0, $matches[0][1]).$this->placeholder[0].substr($source, $matches[0][1]);

$startoffset = $offset = $matches[0][1]+strlen($matches[0][0])+strlen($this->placeholder[0]);

do{
$matches2 = array();
if(preg_match ("/".preg_quote($exprs[$matches[0][0]])."/" , $source , $matches2 , PREG_OFFSET_CAPTURE, $offset)){

$offset = $matches2[0][1]+strlen($matches2[0][0]);

$inApex = false;
for ($i = $startoffset; $i <$offset; $i ++) {
$chr = $source[$i];

if ($chr == "'" || $chr == '"') {
$j = 1;
while ($i>=$j && $source[$i - $j] === '\\') {
$j ++;
}

if ($j % 2 !== 0) {
if (! $inApex) {
$inApex = $chr;
} elseif ($inApex === $chr) {
$inApex = false;
}
}
}
}
if(!$inApex){
$original = $offset-$startoffset;
$encoded = htmlspecialchars(substr($source, $startoffset, $offset-$startoffset), ENT_COMPAT, 'UTF-8');

$source = substr($source, 0, $startoffset). $encoded .$this->placeholder[1].substr($source, $offset);

$offset +=strlen($this->placeholder[1])+(strlen($encoded)-$original);

}
}else{
break;
}
}
} while($inApex && $offset<strlen($source));

}
$event->setTemplate($source);
}
/**
*
Expand All @@ -62,6 +103,7 @@ public function addPlaceholder(TemplateEvent $event)
public function removePlaceholder(SourceEvent $event)
{
$source = $event->getTemplate();

if (preg_match_all("/(" . preg_quote($this->placeholder[0], "/") . "(.*?)" . preg_quote($this->placeholder[1], "/") . ")/", $source, $mch)) {
foreach ($mch[0] as $n => $str) {
$source = str_replace($str, html_entity_decode($mch[2][$n], ENT_COMPAT, 'UTF-8'), $source);
Expand Down
50 changes: 50 additions & 0 deletions tests/Goetas/Twital/Tests/CoreTwigTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
<?php
namespace Goetas\Twital\Tests;

use Goetas\Twital\SourceAdapter\XHTMLAdapter;
use Goetas\Twital\SourceAdapter\XMLAdapter;
use Goetas\Twital\Twital;
use Goetas\Twital\SourceAdapter\HTML5Adapter;


class CoreTwigTest extends \PHPUnit_Framework_TestCase
{
private $twital;
private $sourceAdapter;

/**
* Prepares the environment before running a test.
*/
protected function setUp()
{
$this->twital = new Twital();
$this->sourceAdapter = new HTML5Adapter();
}

/**
* @dataProvider getData
*/
public function testTwigTemplate($source, $expected)
{
$compiled = $this->twital->compile($this->sourceAdapter, $source);
$this->assertEquals($expected, $compiled);
}

public function getData()
{
return array(
// operators

array('<div>{% if foo > 5 and bar < 8 and bar & 4 %}foo{% endif %}</div>', '<div>{% if foo > 5 and bar < 8 and bar & 4 %}foo{% endif %}</div>'),
array('<div>{{ foo > 5 and bar < 8 and bar & 4 ? "foo" }}</div>', '<div>{{ foo > 5 and bar < 8 and bar & 4 ? "foo" }}</div>'),
array('<div>{# foo > 5 and bar < 8 and bar & 4 ? "foo" #}</div>', '<div>{# foo > 5 and bar < 8 and bar & 4 ? "foo" #}</div>'),

array("<div>{% '{%' and '%}' and '{{' and '}}' and '{#' and '#}' %}</div>", "<div>{% '{%' and '%}' and '{{' and '}}' and '{#' and '#}' %}</div>"),
array("<div>{{ '{%' and '%}' and '{{' and '}}' and '{#' and '#}' }}</div>", "<div>{{ '{%' and '%}' and '{{' and '}}' and '{#' and '#}' }}</div>"),

array("<div>{# '{%' and '%}' and '{{' and '}}' and '{#' and '#}' #}</div>", "<div>{# '{%' and '%}' and '{{' and '}}' and '{#' and '#}' #}</div>"),
);
}
}


0 comments on commit 0d2eca1

Please sign in to comment.