diff --git a/Mustache.php b/Mustache.php index e1f69cd..6bdc6a4 100644 --- a/Mustache.php +++ b/Mustache.php @@ -30,6 +30,9 @@ class Mustache { protected $template = ''; protected $context = array(); protected $partials = array(); + protected $pragmas = array(); + + protected $pragmasImplemented = array('DOT-NOTATION'); /** * Mustache class constructor. @@ -101,6 +104,7 @@ class Mustache { * @return string Rendered Mustache template. */ protected function _render($template, &$context) { + $template = $this->renderPragmas($template, $context); $template = $this->renderSection($template, $context); return $this->renderTags($template, $context); } @@ -162,6 +166,60 @@ class Mustache { return $template; } + /** + * Initialize pragmas and remove all pragma tags. + * + * @access protected + * @param string $template + * @param array &$context + * @return string + */ + protected function renderPragmas($template, &$context) { + // no pragmas + if (strpos($template, $this->otag . '%') === false) { + return $template; + } + + $otag = $this->prepareRegEx($this->otag); + $ctag = $this->prepareRegEx($this->ctag); + $regex = '/' . $otag . '%([\\w_-]+)((?: [\\w]+=[\\w]+)*)' . $ctag . '\\n?/'; + return preg_replace_callback($regex, array($this, 'renderPragma'), $template); + } + + /** + * A preg_replace helper to remove {{%PRAGMA}} tags and enable requested pragma. + * + * @access protected + * @param mixed $matches + * @return void + * @throws MustacheException unknown pragma + */ + protected function renderPragma($matches) { + $pragma = $matches[0]; + $pragma_name = $matches[1]; + $options_string = $matches[2]; + + if (!in_array($pragma_name, $this->pragmasImplemented)) { + throw new MustacheException('Unknown pragma: ' . $pragma_name, MustacheException::UNKNOWN_PRAGMA); + } + + $options = array(); + foreach (explode(' ', trim($options_string)) as $o) { + if ($p = trim($o)) { + $p = explode('=', trim($p)); + $options[$p[0]] = $p[1]; + } + } + + if (empty($options)) { + $this->pragmas[$pragma_name] = true; + } else { + $this->pragmas[$pragma_name] = $options; + } + + return ''; + } + /** * Loop through and render individual Mustache tags. * @@ -175,8 +233,8 @@ class Mustache { return $template; } - $otag = $this->prepareRegEx($this->otag); - $ctag = $this->prepareRegEx($this->ctag); + $otag = $this->prepareRegEx($this->otag); + $ctag = $this->prepareRegEx($this->ctag); $this->tagRegEx = '/' . $otag . "(#|\/|=|!|>|\\{|&)?([^\/#]+?)\\1?" . $ctag . "+/"; $html = ''; $matches = array(); @@ -442,4 +500,8 @@ class MustacheException extends Exception { // with no associated partial. const UNKNOWN_PARTIAL = 3; + // An UNKNOWN_PRAGMA exception is thrown whenever a {{%PRAGMA}} tag appears + // which can't be handled by this Mustache instance. + const UNKNOWN_PRAGMA = 4; + } \ No newline at end of file diff --git a/test/MustachePragmaTest.php b/test/MustachePragmaTest.php new file mode 100644 index 0000000..49937d1 --- /dev/null +++ b/test/MustachePragmaTest.php @@ -0,0 +1,40 @@ +render('{{%I-HAVE-THE-GREATEST-MUSTACHE}}'); + } catch (Exception $e) { + $caught_exception = $e; + } + + $this->assertNotNull($caught_exception, 'No exception caught'); + $this->assertType('MustacheException', $caught_exception); + $this->assertEquals($caught_exception->getCode(), MustacheException::UNKNOWN_PRAGMA, 'Caught exception code was not MustacheException::UNKNOWN_PRAGMA'); + } + + public function testPragmaReplace() { + $m = new Mustache(); + $this->assertEquals($m->render('{{%DOT-NOTATION}}'), '', 'Pragma tag not removed'); + } + + public function testPragmaReplaceMultiple() { + $m = new Mustache(); + $this->assertEquals($m->render("{{%DOT-NOTATION}}\n{{%DOT-NOTATION}}"), '', 'Multiple pragma tags not removed'); + $this->assertEquals($m->render('{{%DOT-NOTATION}} {{%DOT-NOTATION}}'), ' ', 'Multiple pragma tags not removed'); + } + + public function testPragmaReplaceNewline() { + $m = new Mustache(); + $this->assertEquals($m->render("{{%DOT-NOTATION}}\n"), '', 'Trailing newline after pragma tag not removed'); + $this->assertEquals($m->render("\n{{%DOT-NOTATION}}\n"), "\n", 'Too many newlines removed with pragma tag'); + $this->assertEquals($m->render("1\n2{{%DOT-NOTATION}}\n3"), "1\n23", 'Wrong newline removed with pragma tag'); + } +} \ No newline at end of file