Pārlūkot izejas kodu

Merge branch 'release/0.3.0'

Justin Hileman 15 gadi atpakaļ
vecāks
revīzija
8b1c9c113c

+ 11 - 13
Mustache.php

@@ -98,7 +98,7 @@ class Mustache {
 		self::PRAGMA_UNESCAPED
 	);
 
-	protected $_localPragmas;
+	protected $_localPragmas = array();
 
 	/**
 	 * Mustache class constructor.
@@ -130,7 +130,7 @@ class Mustache {
 	public function __clone() {
 		$this->_otag = '{{';
 		$this->_ctag = '}}';
-		$this->_localPragmas = null;
+		$this->_localPragmas = array();
 
 		if ($keys = array_keys($this->_context)) {
 			$last = array_pop($keys);
@@ -452,14 +452,12 @@ class Mustache {
 					return $this->_renderUnescaped($tag_name);
 				}
 				break;
-			case '':
-			default:
-				if ($this->_hasPragma(self::PRAGMA_UNESCAPED)) {
-					return $this->_renderUnescaped($tag_name);
-				} else {
-					return $this->_renderEscaped($tag_name);
-				}
-				break;
+		}
+
+		if ($this->_hasPragma(self::PRAGMA_UNESCAPED)) {
+			return $this->_renderUnescaped($modifier . $tag_name);
+		} else {
+			return $this->_renderEscaped($modifier . $tag_name);
 		}
 	}
 
@@ -605,10 +603,10 @@ class Mustache {
 	protected function _findVariableInContext($tag_name, $context) {
 		foreach ($context as $view) {
 			if (is_object($view)) {
-				if (isset($view->$tag_name)) {
-					return $view->$tag_name;
-				} else if (method_exists($view, $tag_name)) {
+				if (method_exists($view, $tag_name)) {
 					return $view->$tag_name();
+				} else if (isset($view->$tag_name)) {
+					return $view->$tag_name;
 				}
 			} else if (isset($view[$tag_name])) {
 				return $view[$tag_name];

+ 1 - 1
README.markdown

@@ -83,7 +83,7 @@ Known Issues
 
  * Sections don't respect delimiter changes -- `delimiters` example currently fails with an
    "unclosed section" exception.
- * Test coverage is incomplete.
+ * Mustache isn't always very good at whitespace.
 
 
 See Also

+ 3 - 27
examples/section_iterator_objects/SectionIteratorObjects.php

@@ -3,38 +3,14 @@
 class SectionIteratorObjects extends Mustache {
 	public $start = "It worked the first time.";
 
-	public function middle() {
-		return new IteratorObject();
-	}
-
-	public $final = "Then, surprisingly, it worked the final time.";
-}
-
-class IteratorObject implements Iterator {
-	protected $_position = 0;
-
 	protected $_data = array(
 		array('item' => 'And it worked the second time.'),
 		array('item' => 'As well as the third.'),
 	);
 
-	public function rewind() {
-		$this->_position = 0;
-	}
-
-	public function current() {
-		return $this->_data[$this->_position];
-	}
-
-	public function key() {
-		return $this->_position;
-	}
-
-	public function next() {
-		++$this->_position;
+	public function middle() {
+		return new ArrayIterator($this->_data);
 	}
 
-	public function valid() {
-		return isset($this->_data[$this->_position]);
-	}
+	public $final = "Then, surprisingly, it worked the final time.";
 }

+ 14 - 0
examples/sections_spaces/SectionsSpaces.php

@@ -0,0 +1,14 @@
+<?php
+
+class SectionsSpaces extends Mustache {
+	public $start = "It worked the first time.";
+
+	public function middle() {
+		return array(
+			array('item' => "And it worked the second time."),
+			array('item' => "As well as the third."),
+		);
+	}
+
+	public $final = "Then, surprisingly, it worked the final time.";
+}

+ 9 - 0
examples/sections_spaces/sections_spaces.mustache

@@ -0,0 +1,9 @@
+ * {{ start }}
+{{# middle }}
+ * {{ item }}
+{{/ middle }}
+ * {{ final }}
+
+ * {{ start }}
+{{# middle }} * {{ item }}{{/ middle }}
+ * {{ final }}

+ 9 - 0
examples/sections_spaces/sections_spaces.txt

@@ -0,0 +1,9 @@
+ * It worked the first time.
+ * And it worked the second time.
+ * As well as the third.
+ * Then, surprisingly, it worked the final time.
+
+ * It worked the first time.
+ * And it worked the second time.
+ * As well as the third.
+ * Then, surprisingly, it worked the final time.

+ 97 - 0
test/MustacheExceptionTest.php

@@ -0,0 +1,97 @@
+<?php
+
+require_once '../Mustache.php';
+
+class MustacheExceptionTest extends PHPUnit_Framework_TestCase {
+
+	const TEST_CLASS = 'Mustache';
+
+	protected $pickyMustache;
+	protected $slackerMustache;
+	
+	public function setUp() {
+		$this->pickyMustache      = new PickyMustache();
+		$this->slackerMustache    = new SlackerMustache();
+	}
+
+	/**
+	 * @expectedException MustacheException
+	 */
+	public function testThrowsUnknownVariableException() {
+		$this->pickyMustache->render('{{not_a_variable}}');
+	}
+
+	/**
+	 * @expectedException MustacheException
+	 */
+	public function testThrowsUnclosedSectionException() {
+		$this->pickyMustache->render('{{#unclosed}}');
+	}
+
+	/**
+	 * @expectedException MustacheException
+	 */
+	public function testThrowsUnexpectedCloseSectionException() {
+		$this->pickyMustache->render('{{/unopened}}');
+	}
+
+	/**
+	 * @expectedException MustacheException
+	 */
+	public function testThrowsUnknownPartialException() {
+		$this->pickyMustache->render('{{>impartial}}');
+	}
+
+	/**
+	 * @expectedException MustacheException
+	 */
+	public function testThrowsUnknownPragmaException() {
+		$this->pickyMustache->render('{{%SWEET-MUSTACHE-BRO}}');
+	}
+
+	public function testDoesntThrowUnclosedSectionException() {
+		$this->assertEquals('', $this->slackerMustache->render('{{#unclosed}}'));
+	}
+
+	public function testDoesntThrowUnexpectedCloseSectionException() {
+		$this->assertEquals('', $this->slackerMustache->render('{{/unopened}}'));
+	}
+
+	public function testDoesntThrowUnknownPartialException() {
+		$this->assertEquals('', $this->slackerMustache->render('{{>impartial}}'));
+	}
+
+	/**
+	 * @expectedException MustacheException
+	 */
+	public function testGetPragmaOptionsThrowsExceptionsIfItThinksYouHaveAPragmaButItTurnsOutYouDont() {
+		$mustache = new TestableMustache();
+		$mustache->testableGetPragmaOptions('PRAGMATIC');
+	}
+}
+
+class PickyMustache extends Mustache {
+	protected $_throwsExceptions = array(
+		MustacheException::UNKNOWN_VARIABLE         => true,
+		MustacheException::UNCLOSED_SECTION         => true,
+		MustacheException::UNEXPECTED_CLOSE_SECTION => true,
+		MustacheException::UNKNOWN_PARTIAL          => true,
+		MustacheException::UNKNOWN_PRAGMA           => true,
+	);
+}
+
+class SlackerMustache extends Mustache {
+	protected $_throwsExceptions = array(
+		MustacheException::UNKNOWN_VARIABLE         => false,
+		MustacheException::UNCLOSED_SECTION         => false,
+		MustacheException::UNEXPECTED_CLOSE_SECTION => false,
+		MustacheException::UNKNOWN_PARTIAL          => false,
+		MustacheException::UNKNOWN_PRAGMA           => false,
+	);
+}
+
+class TestableMustache extends Mustache {
+	public function testableGetPragmaOptions($pragma_name) {
+		return $this->_getPragmaOptions($pragma_name);
+	}
+}

+ 14 - 0
test/MustacheObjectSectionTest.php

@@ -17,6 +17,12 @@ class MustacheObjectSectionTest extends PHPUnit_Framework_TestCase {
 		$gamma = new Gamma();
 		$this->assertEquals('Foo', $gamma->render('{{#bar}}{{#foo}}{{name}}{{/foo}}{{/bar}}'));
 	}
+
+	public function testSectionObjectWithFunction() {
+		$alpha = new Alpha();
+		$alpha->foo = new Delta();
+		$this->assertEquals('Foo', $alpha->render('{{#foo}}{{name}}{{/foo}}'));
+	}
 }
 
 class Alpha extends Mustache {
@@ -53,4 +59,12 @@ class Gamma extends Mustache {
 	public function __construct() {
 		$this->bar = new Beta();
 	}
+}
+
+class Delta extends Mustache {
+	protected $_name = 'Foo';
+
+	public function name() {
+		return $this->_name;
+	}
 }

+ 0 - 1
test/MustachePragmaImplicitIteratorTest.php

@@ -1,7 +1,6 @@
 <?php
 
 require_once '../Mustache.php';
-require_once 'PHPUnit/Framework.php';
 
 class MustachePragmaImplicitIteratorTest extends PHPUnit_Framework_TestCase {
 

+ 36 - 12
test/MustacheTest.php

@@ -35,6 +35,11 @@ class MustacheTest extends PHPUnit_Framework_TestCase {
 
 	const TEST_CLASS = 'Mustache';
 
+	protected $knownIssues = array(
+		'Delimiters'     => "Known issue: sections don't respect delimiter changes",
+		'SectionsSpaces' => "Known issue: Mustache fails miserably at whitespace",
+	);
+
 	/**
 	 * Test Mustache constructor.
 	 *
@@ -136,6 +141,23 @@ class MustacheTest extends PHPUnit_Framework_TestCase {
 		$this->assertEquals('Zappa, Frank', $m->render('{{last_name}}, {{first_name}}', array('first_name' => 'Frank', 'last_name' => 'Zappa')));
 	}
 
+	public function testRenderWithPartials() {
+		$m = new Mustache('{{>stache}}', null, array('stache' => '{{first_name}} {{last_name}}'));
+		$this->assertEquals('Charlie Chaplin', $m->render(null, array('first_name' => 'Charlie', 'last_name' => 'Chaplin')));
+		$this->assertEquals('Zappa, Frank', $m->render('{{last_name}}, {{first_name}}', array('first_name' => 'Frank', 'last_name' => 'Zappa')));
+	}
+
+	/**
+	 * Mustache should allow newlines (and other whitespace) in comments and all other tags.
+	 *
+	 * @access public
+	 * @return void
+	 */
+	public function testNewlinesInComments() {
+		$m = new Mustache("{{! comment \n \t still a comment... }}");
+		$this->assertEquals('', $m->render());
+	}
+
 	/**
 	 * Mustache should return the same thing when invoked multiple times.
 	 *
@@ -166,10 +188,9 @@ class MustacheTest extends PHPUnit_Framework_TestCase {
 		$this->assertEquals($first, $second);
 	}
 
-
 	/**
 	 * Mustache should not use templates passed to the render() method for subsequent invocations.
-	 * 
+	 *
 	 * @access public
 	 * @return void
 	 */
@@ -177,7 +198,7 @@ class MustacheTest extends PHPUnit_Framework_TestCase {
 		$m = new Mustache('Sirve.');
 		$this->assertEquals('No sirve.', $m->render('No sirve.'));
 		$this->assertEquals('Sirve.', $m->render());
-		
+
 		$m2 = new Mustache();
 		$this->assertEquals('No sirve.', $m2->render('No sirve.'));
 		$this->assertEquals('', $m2->render());
@@ -186,14 +207,17 @@ class MustacheTest extends PHPUnit_Framework_TestCase {
 	/**
 	 * testClone function.
 	 *
+	 * @group examples
 	 * @dataProvider getExamples
 	 * @access public
+	 * @param string $class
+	 * @param string $template
+	 * @param string $output
 	 * @return void
 	 */
 	public function test__clone($class, $template, $output) {
-		if ($class == 'Delimiters') {
-			$this->markTestSkipped("Known issue: sections don't respect delimiter changes");
-			return;
+		if (isset($this->knownIssues[$class])) {
+			return $this->markTestSkipped($this->knownIssues[$class]);
 		}
 
 		$m = new $class;
@@ -214,17 +238,17 @@ class MustacheTest extends PHPUnit_Framework_TestCase {
 	/**
 	 * Test everything in the `examples` directory.
 	 *
+	 * @group examples
 	 * @dataProvider getExamples
 	 * @access public
-	 * @param mixed $class
-	 * @param mixed $template
-	 * @param mixed $output
+	 * @param string $class
+	 * @param string $template
+	 * @param string $output
 	 * @return void
 	 */
 	public function testExamples($class, $template, $output) {
-		if ($class == 'Delimiters') {
-			$this->markTestSkipped("Known issue: sections don't respect delimiter changes");
-			return;
+		if (isset($this->knownIssues[$class])) {
+			return $this->markTestSkipped($this->knownIssues[$class]);
 		}
 
 		$m = new $class;