From 537ebc44c8df4ba45f5a2f9c28887a47122b5c07 Mon Sep 17 00:00:00 2001 From: Justin Hileman Date: Wed, 28 Apr 2010 21:51:54 -0400 Subject: [PATCH] Initial work adding pragma detection to Mustache.php Currently stores pragmas and options, but does nothing with them. Also throws exceptions when it encounters unknown pragmas. Test coverage only for exceptions and pragma tag removal. --- Mustache.php | 66 +++++++++++++++++++++++++++++++++++-- test/MustachePragmaTest.php | 40 ++++++++++++++++++++++ 2 files changed, 104 insertions(+), 2 deletions(-) create mode 100644 test/MustachePragmaTest.php 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