Merge branch 'dev' into feature/higher-order-sections

Conflicts:
	Mustache.php
This commit is contained in:
Justin Hileman
2011-03-05 12:13:27 -05:00
8 changed files with 20 additions and 221 deletions
+9 -58
View File
@@ -38,38 +38,6 @@ class Mustache {
* will change in the future. * will change in the future.
*/ */
/**
* The {{%DOT-NOTATION}} pragma allows context traversal via dots. Given the following context:
*
* $context = array('foo' => array('bar' => array('baz' => 'qux')));
*
* One could access nested properties using dot notation:
*
* {{%DOT-NOTATION}}{{foo.bar.baz}}
*
* Which would render as `qux`.
*/
const PRAGMA_DOT_NOTATION = 'DOT-NOTATION';
/**
* The {{%IMPLICIT-ITERATOR}} pragma allows access to non-associative array data in an
* iterable section:
*
* $context = array('items' => array('foo', 'bar', 'baz'));
*
* With this template:
*
* {{%IMPLICIT-ITERATOR}}{{#items}}{{.}}{{/items}}
*
* Would render as `foobarbaz`.
*
* {{%IMPLICIT-ITERATOR}} accepts an optional 'iterator' argument which allows implicit
* iterator tags other than {{.}} ...
*
* {{%IMPLICIT-ITERATOR iterator=i}}{{#items}}{{i}}{{/items}}
*/
const PRAGMA_IMPLICIT_ITERATOR = 'IMPLICIT-ITERATOR';
/** /**
* The {{%UNESCAPED}} pragma swaps the meaning of the {{normal}} and {{{unescaped}}} * The {{%UNESCAPED}} pragma swaps the meaning of the {{normal}} and {{{unescaped}}}
* Mustache tags. That is, once this pragma is activated the {{normal}} tag will not be * Mustache tags. That is, once this pragma is activated the {{normal}} tag will not be
@@ -99,8 +67,6 @@ class Mustache {
protected $_pragmas = array(); protected $_pragmas = array();
protected $_pragmasImplemented = array( protected $_pragmasImplemented = array(
self::PRAGMA_DOT_NOTATION,
self::PRAGMA_IMPLICIT_ITERATOR,
self::PRAGMA_UNESCAPED self::PRAGMA_UNESCAPED
); );
@@ -128,9 +94,7 @@ class Mustache {
* *
* // an array of pragmas to enable * // an array of pragmas to enable
* 'pragmas' => array( * 'pragmas' => array(
* Mustache::PRAGMA_UNESCAPED, * Mustache::PRAGMA_UNESCAPED
* Mustache::PRAGMA_DOT_NOTATION,
* Mustache::PRAGMA_IMPLICIT_ITERATOR
* ), * ),
* ); * );
* *
@@ -279,30 +243,13 @@ class Mustache {
// regular section // regular section
case '#': case '#':
// higher order sections // higher order sections
if ($this->_varIsCallable($val)) { if ($this->_varIsCallable($val)) {
$content = call_user_func($val, $content); $content = call_user_func($val, $content);
$replace .= $this->_renderTemplate($content); $replace .= $this->_renderTemplate($content);
} else if ($this->_varIsIterable($val)) { } else if ($this->_varIsIterable($val)) {
if ($this->_hasPragma(self::PRAGMA_IMPLICIT_ITERATOR)) {
if ($opt = $this->_getPragmaOptions(self::PRAGMA_IMPLICIT_ITERATOR)) {
$iterator = $opt['iterator'];
} else {
$iterator = '.';
}
} else {
$iterator = false;
}
foreach ($val as $local_context) { foreach ($val as $local_context) {
if ($iterator) { $this->_pushContext($local_context);
$iterator_context = array($iterator => $local_context);
$this->_pushContext($iterator_context);
} else {
$this->_pushContext($local_context);
}
$replace .= $this->_renderTemplate($content); $replace .= $this->_renderTemplate($content);
$this->_popContext(); $this->_popContext();
} }
@@ -685,8 +632,10 @@ class Mustache {
*/ */
protected function _renderPartial($tag_name, $whitespace = '') { protected function _renderPartial($tag_name, $whitespace = '') {
$view = clone($this); $view = clone($this);
return $whitespace . preg_replace('/\n(?!$)/s', "\n" . $whitespace, $view->render($this->_getPartial($tag_name))); $partial = $whitespace . preg_replace('/\n(?!$)/s', "\n" . $whitespace, $this->_getPartial($tag_name));
return $view->render($partial);
} }
/** /**
@@ -755,7 +704,9 @@ class Mustache {
* @return string * @return string
*/ */
protected function _getVariable($tag_name) { protected function _getVariable($tag_name) {
if ($tag_name != '.' && strpos($tag_name, '.') !== false && $this->_hasPragma(self::PRAGMA_DOT_NOTATION)) { if ($tag_name === '.') {
return $this->_context[0];
} else if (strpos($tag_name, '.') !== false) {
$chunks = explode('.', $tag_name); $chunks = explode('.', $tag_name);
$first = array_shift($chunks); $first = array_shift($chunks);
@@ -1,4 +1,3 @@
{{%DOT-NOTATION}}
* {{person.name.first}} {{person.name.last}} * {{person.name.first}} {{person.name.last}}
* {{person.age}} * {{person.age}}
* {{person.hometown.city}}, {{person.hometown.state}} * {{person.hometown.city}}, {{person.hometown.state}}
@@ -1,4 +1,3 @@
{{%IMPLICIT-ITERATOR}}
{{#data}} {{#data}}
* {{.}} * {{.}}
{{/data}} {{/data}}
-63
View File
@@ -1,63 +0,0 @@
<?php
require_once '../Mustache.php';
/**
* @group pragmas
*/
class MustachePragmaDotNotationTest extends PHPUnit_Framework_TestCase {
public function testDotTraversal() {
$m = new Mustache('', array('foo' => array('bar' => 'this worked')));
$this->assertEquals($m->render('{{foo.bar}}'), '',
'Dot notation not enabled, variable should have been replaced with nothing');
$this->assertEquals($m->render('{{%DOT-NOTATION}}{{foo.bar}}'), 'this worked',
'Dot notation enabled, variable should have been replaced by "this worked"');
}
public function testDeepTraversal() {
$data = array(
'foo' => array('bar' => array('baz' => array('qux' => array('quux' => 'WIN!')))),
'a' => array('b' => array('c' => array('d' => array('e' => 'abcs')))),
'one' => array(
'one' => 'one-one',
'two' => 'one-two',
'three' => 'one-three',
),
);
$m = new Mustache('', $data);
$this->assertEquals($m->render('{{%DOT-NOTATION}}{{foo.bar.baz.qux.quux}}'), 'WIN!');
$this->assertEquals($m->render('{{%DOT-NOTATION}}{{a.b.c.d.e}}'), 'abcs');
$this->assertEquals($m->render('{{%DOT-NOTATION}}{{one.one}}|{{one.two}}|{{one.three}}'), 'one-one|one-two|one-three');
}
public function testDotNotationContext() {
$data = array('parent' => array('items' => array(
array('item' => array('index' => 1)),
array('item' => array('index' => 2)),
array('item' => array('index' => 3)),
array('item' => array('index' => 4)),
array('item' => array('index' => 5)),
)));
$m = new Mustache('', $data);
$this->assertEquals('12345', $m->render('{{%DOT-NOTATION}}{{#parent}}{{#items}}{{item.index}}{{/items}}{{/parent}}'));
}
public function testDotNotationSectionNames() {
$data = array('parent' => array('items' => array(
array('item' => array('index' => 1)),
array('item' => array('index' => 2)),
array('item' => array('index' => 3)),
array('item' => array('index' => 4)),
array('item' => array('index' => 5)),
)));
$m = new Mustache('', $data);
$this->assertEquals('.....', $m->render('{{%DOT-NOTATION}}{{#parent.items}}.{{/parent.items}}'));
$this->assertEquals('12345', $m->render('{{%DOT-NOTATION}}{{#parent.items}}{{item.index}}{{/parent.items}}'));
$this->assertEquals('12345', $m->render('{{%DOT-NOTATION}}{{#parent.items}}{{#item}}{{index}}{{/item}}{{/parent.items}}'));
}
}
@@ -1,87 +0,0 @@
<?php
require_once '../Mustache.php';
/**
* @group pragmas
*/
class MustachePragmaImplicitIteratorTest extends PHPUnit_Framework_TestCase {
public function testEnablePragma() {
$m = $this->getMock('Mustache', array('_renderPragma'), array('{{%IMPLICIT-ITERATOR}}'));
$m->expects($this->exactly(1))
->method('_renderPragma')
->with(array(
0 => '{{%IMPLICIT-ITERATOR}}',
1 => 'IMPLICIT-ITERATOR', 'pragma_name' => 'IMPLICIT-ITERATOR',
2 => null, 'options_string' => null
));
$m->render();
}
public function testImplicitIterator() {
$m1 = new Mustache('{{%IMPLICIT-ITERATOR}}{{#items}}{{.}}{{/items}}', array('items' => array('a', 'b', 'c')));
$this->assertEquals('abc', $m1->render());
$m2 = new Mustache('{{%IMPLICIT-ITERATOR}}{{#items}}{{.}}{{/items}}', array('items' => array(1, 2, 3)));
$this->assertEquals('123', $m2->render());
}
public function testDotNotationCollision() {
$m = new Mustache(null, array('items' => array('foo', 'bar', 'baz')));
$this->assertEquals('foobarbaz', $m->render('{{%IMPLICIT-ITERATOR}}{{%DOT-NOTATION}}{{#items}}{{.}}{{/items}}'));
$this->assertEquals('foobarbaz', $m->render('{{%DOT-NOTATION}}{{%IMPLICIT-ITERATOR}}{{#items}}{{.}}{{/items}}'));
}
public function testCustomIterator() {
$m = new Mustache(null, array('items' => array('foo', 'bar', 'baz')));
$this->assertEquals('foobarbaz', $m->render('{{%IMPLICIT-ITERATOR}}{{#items}}{{.}}{{/items}}'));
$this->assertEquals('foobarbaz', $m->render('{{%IMPLICIT-ITERATOR iterator=i}}{{#items}}{{i}}{{/items}}'));
$this->assertEquals('foobarbaz', $m->render('{{%IMPLICIT-ITERATOR iterator=items}}{{#items}}{{items}}{{/items}}'));
}
public function testDotNotationContext() {
$m = new Mustache(null, array('items' => array(
array('index' => 1, 'name' => 'foo'),
array('index' => 2, 'name' => 'bar'),
array('index' => 3, 'name' => 'baz'),
)));
$this->assertEquals('foobarbaz', $m->render('{{%IMPLICIT-ITERATOR}}{{#items}}{{#.}}{{name}}{{/.}}{{/items}}'));
$this->assertEquals('123', $m->render('{{%IMPLICIT-ITERATOR iterator=i}}{{%DOT-NOTATION}}{{#items}}{{i.index}}{{/items}}'));
$this->assertEquals('foobarbaz', $m->render('{{%IMPLICIT-ITERATOR iterator=i}}{{%DOT-NOTATION}}{{#items}}{{i.name}}{{/items}}'));
}
/**
* @dataProvider recursiveSectionData
*/
public function testRecursiveSections($template, $view, $result) {
$m = new Mustache();
$this->assertEquals($result, $m->render($template, $view));
}
public function recursiveSectionData() {
return array(
array(
'{{%IMPLICIT-ITERATOR}}{{#items}}{{#.}}{{.}}{{/.}}{{/items}}',
array('items' => array(array('a', 'b', 'c'), array('d', 'e', 'f'))),
'abcdef'
),
array(
'{{%IMPLICIT-ITERATOR}}{{#items}}{{#.}}{{#.}}{{.}}{{/.}}{{/.}}{{/items}}',
array('items' => array(array(array('a', 'b'), array('c')), array(array('d'), array('e', 'f')))),
'abcdef'
),
array(
'{{%IMPLICIT-ITERATOR}}{{#items}}{{#.}}{{#items}}{{.}}{{/items}}{{/.}}{{/items}}',
array('items' => array(
array('items' => array('a', 'b', 'c')),
array('items' => array('d', 'e', 'f')),
)),
'abcdef'
),
);
}
}
+8 -8
View File
@@ -22,23 +22,23 @@ class MustachePragmaTest extends PHPUnit_Framework_TestCase {
public function testPragmaReplace() { public function testPragmaReplace() {
$m = new Mustache(); $m = new Mustache();
$this->assertEquals('', $m->render('{{%DOT-NOTATION}}'), 'Pragma tag not removed'); $this->assertEquals('', $m->render('{{%UNESCAPED}}'), 'Pragma tag not removed');
} }
public function testPragmaReplaceMultiple() { public function testPragmaReplaceMultiple() {
$m = new Mustache(); $m = new Mustache();
$this->assertEquals('', $m->render('{{% DOT-NOTATION }}'), 'Pragmas should allow whitespace'); $this->assertEquals('', $m->render('{{% UNESCAPED }}'), 'Pragmas should allow whitespace');
$this->assertEquals('', $m->render('{{% DOT-NOTATION foo=bar }}'), 'Pragmas should allow whitespace'); $this->assertEquals('', $m->render('{{% UNESCAPED foo=bar }}'), 'Pragmas should allow whitespace');
$this->assertEquals('', $m->render("{{%DOT-NOTATION}}\n{{%DOT-NOTATION}}"), 'Multiple pragma tags not removed'); $this->assertEquals('', $m->render("{{%UNESCAPED}}\n{{%UNESCAPED}}"), 'Multiple pragma tags not removed');
$this->assertEquals(' ', $m->render('{{%DOT-NOTATION}} {{%DOT-NOTATION}}'), 'Multiple pragma tags not removed'); $this->assertEquals(' ', $m->render('{{%UNESCAPED}} {{%UNESCAPED}}'), 'Multiple pragma tags not removed');
} }
public function testPragmaReplaceNewline() { public function testPragmaReplaceNewline() {
$m = new Mustache(); $m = new Mustache();
$this->assertEquals('', $m->render("{{%DOT-NOTATION}}\n"), 'Trailing newline after pragma tag not removed'); $this->assertEquals('', $m->render("{{%UNESCAPED}}\n"), 'Trailing newline after pragma tag not removed');
$this->assertEquals("\n", $m->render("\n{{%DOT-NOTATION}}\n"), 'Too many newlines removed with pragma tag'); $this->assertEquals("\n", $m->render("\n{{%UNESCAPED}}\n"), 'Too many newlines removed with pragma tag');
$this->assertEquals("1\n23", $m->render("1\n2{{%DOT-NOTATION}}\n3"), 'Wrong newline removed with pragma tag'); $this->assertEquals("1\n23", $m->render("1\n2{{%UNESCAPED}}\n3"), 'Wrong newline removed with pragma tag');
} }
public function testPragmaReset() { public function testPragmaReset() {
+2 -2
View File
@@ -104,11 +104,11 @@ class MustacheTest extends PHPUnit_Framework_TestCase {
array( array(
'charset' => 'cp866', 'charset' => 'cp866',
'delimiters' => array('[[[[', ']]]]'), 'delimiters' => array('[[[[', ']]]]'),
'pragmas' => array(Mustache::PRAGMA_DOT_NOTATION, Mustache::PRAGMA_IMPLICIT_ITERATOR) 'pragmas' => array(Mustache::PRAGMA_UNESCAPED)
), ),
'cp866', 'cp866',
array('[[[[', ']]]]'), array('[[[[', ']]]]'),
array(Mustache::PRAGMA_DOT_NOTATION, Mustache::PRAGMA_IMPLICIT_ITERATOR), array(Mustache::PRAGMA_UNESCAPED),
), ),
); );
} }