diff --git a/src/Goetas/Twital/EventSubscriber/FixHtmlEntitiesInExpressionSubscriber.php b/src/Goetas/Twital/EventSubscriber/FixHtmlEntitiesInExpressionSubscriber.php index a066b9b..07c1d6e 100644 --- a/src/Goetas/Twital/EventSubscriber/FixHtmlEntitiesInExpressionSubscriber.php +++ b/src/Goetas/Twital/EventSubscriber/FixHtmlEntitiesInExpressionSubscriber.php @@ -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' ); } @@ -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 && $offsetsetTemplate($source); } /** * @@ -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); diff --git a/tests/Goetas/Twital/Tests/CoreTwigTest.php b/tests/Goetas/Twital/Tests/CoreTwigTest.php index a8c2b6f..2ce3b4f 100644 --- a/tests/Goetas/Twital/Tests/CoreTwigTest.php +++ b/tests/Goetas/Twital/Tests/CoreTwigTest.php @@ -34,9 +34,15 @@ public function getData() { return array( // operators + array('
{% if foo > 5 and bar < 8 and bar & 4 %}foo{% endif %}
', '
{% if foo > 5 and bar < 8 and bar & 4 %}foo{% endif %}
'), array('
{{ foo > 5 and bar < 8 and bar & 4 ? "foo" }}
', '
{{ foo > 5 and bar < 8 and bar & 4 ? "foo" }}
'), array('
{# foo > 5 and bar < 8 and bar & 4 ? "foo" #}
', '
{# foo > 5 and bar < 8 and bar & 4 ? "foo" #}
'), + + array("
{% '{%' and '%}' and '{{' and '}}' and '{#' and '#}' %}
", "
{% '{%' and '%}' and '{{' and '}}' and '{#' and '#}' %}
"), + array("
{{ '{%' and '%}' and '{{' and '}}' and '{#' and '#}' }}
", "
{{ '{%' and '%}' and '{{' and '}}' and '{#' and '#}' }}
"), + + array("
{# '{%' and '%}' and '{{' and '}}' and '{#' and '#}' #}
", "
{# '{%' and '%}' and '{{' and '}}' and '{#' and '#}' #}
"), ); } }