diff --git a/Mustache.php b/Mustache.php index 88727c5..8d843c5 100644 --- a/Mustache.php +++ b/Mustache.php @@ -188,19 +188,25 @@ class Mustache { // regular section case '#': - if ($this->_varIsIterable($val)) { - foreach ($val as $local_context) { - $this->_pushContext($local_context); + if ($val) { + // higher order sections + if (is_callable($val)) { + $content = call_user_func($val, $content); $replace .= $this->_renderTemplate($content); - $this->_popContext(); - } - } else if ($val) { - if (is_array($val) || is_object($val)) { - $this->_pushContext($val); - $replace .= $this->_renderTemplate($content); - $this->_popContext(); + } else if ($this->_varIsIterable($val)) { + foreach ($val as $local_context) { + $this->_pushContext($local_context); + $replace .= $this->_renderTemplate($content); + $this->_popContext(); + } } else { - $replace .= $content; + if (is_array($val) || is_object($val)) { + $this->_pushContext($val); + $replace .= $this->_renderTemplate($content); + $this->_popContext(); + } else { + $replace .= $content; + } } } break; diff --git a/test/MustacheHigherOrderSectionsTest.php b/test/MustacheHigherOrderSectionsTest.php new file mode 100644 index 0000000..63b8d3b --- /dev/null +++ b/test/MustacheHigherOrderSectionsTest.php @@ -0,0 +1,117 @@ +foo = new Foo(); + } + + public function testAnonymousFunctionSectionCallback() { + if (version_compare(PHP_VERSION, '5.3.0', '<')) { + $this->markTestSkipped('Unable to test anonymous function section callbacks in PHP < 5.3'); + return; + } + + $this->foo->wrapper = function($text) { + return sprintf('
%s
', $text); + }; + + $this->assertEquals( + sprintf('
%s
', $this->foo->name), + $this->foo->render('{{#wrapper}}{{name}}{{/wrapper}}') + ); + } + + public function testSectionCallback() { + $this->assertEquals(sprintf('%s', $this->foo->name), $this->foo->render('{{name}}')); + $this->assertEquals(sprintf('%s', $this->foo->name), $this->foo->render('{{#wrap}}{{name}}{{/wrap}}')); + } + + public function testRuntimeSectionCallback() { + $this->foo->double_wrap = array($this->foo, 'wrapWithBoth'); + $this->assertEquals( + sprintf('%s', $this->foo->name), + $this->foo->render('{{#double_wrap}}{{name}}{{/double_wrap}}') + ); + } + + public function testFunctionSectionCallback() { + $this->foo->wrapper = 'make_my_logo_bigger'; + $this->assertEquals( + sprintf('

%s

', $this->foo->name), + $this->foo->render('{{#wrapper}}{{name}}{{/wrapper}}') + ); + } + + public function testStaticSectionCallback() { + $this->foo->trimmer = array(get_class($this->foo), 'staticTrim'); + $this->assertEquals($this->foo->name, $this->foo->render('{{#trimmer}} {{name}} {{/trimmer}}')); + + $this->foo->trimmer = 'Foo::staticTrim'; + $this->assertEquals($this->foo->lorem, $this->foo->render('{{#trimmer}} {{lorem}} {{/trimmer}}')); + } + + public function testViewArraySectionCallback() { + $data = array( + 'name' => 'Bob', + 'wrap' => 'make_my_logo_bigger', + 'trim' => array(get_class($this->foo), 'staticTrim'), + ); + $this->assertEquals( + sprintf('

%s

', $data['name']), + $this->foo->render('{{#wrap}}{{name}}{{/wrap}}', $data) + ); + $this->assertEquals($data['name'], $this->foo->render('{{#trim}} {{name}} {{/trim}}', $data)); + } + + public function testViewArrayAnonymousSectionCallback() { + if (version_compare(PHP_VERSION, '5.3.0', '<')) { + $this->markTestSkipped('Unable to test anonymous function section callbacks in PHP < 5.3'); + return; + } + $data = array( + 'name' => 'Bob', + 'wrap' => 'make_my_logo_bigger', + 'anonywrap' => function($text) { + return array('[[%s]]', $text); + } + ); + $this->assertEquals( + sprintf('

%s

', $data['name']), + $this->foo->render('{{#wrap}}{{name}}{{/wrap}}', $data) + ); + } +} + +class Foo extends Mustache { + public $name = 'Justin'; + public $lorem = 'Lorem ipsum dolor sit amet,'; + public $wrap; + + public function __construct($template = null, $view = null, $partials = null) { + $this->wrap = array($this, 'wrapWithEm'); + parent::__construct($template, $view, $partials); + } + + public function wrapWithEm($text) { + return sprintf('%s', $text); + } + + public function wrapWithStrong($text) { + return sprintf('%s', $text); + } + + public function wrapWithBoth($text) { + return self::wrapWithStrong(self::wrapWithEm($text)); + } + + public static function staticTrim($text) { + return trim($text); + } +} + +function make_my_logo_bigger($text) { + return sprintf('

%s

', $text); +} \ No newline at end of file