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