diff --git a/Mustache.php b/Mustache.php index d0ff274..c97cd12 100644 --- a/Mustache.php +++ b/Mustache.php @@ -14,7 +14,7 @@ */ class Mustache { - const VERSION = '0.9.0'; + const VERSION = '1.0.0'; const SPEC_VERSION = '1.1.2'; /** @@ -94,6 +94,15 @@ class Mustache { * 'pragmas' => array( * Mustache::PRAGMA_UNESCAPED => true * ), + * + * // an array of thrown exceptions to enable/disable + * 'throws_exceptions' => array( + * MustacheException::UNKNOWN_VARIABLE => false, + * MustacheException::UNCLOSED_SECTION => true, + * MustacheException::UNEXPECTED_CLOSE_SECTION => true, + * MustacheException::UNKNOWN_PARTIAL => false, + * MustacheException::UNKNOWN_PRAGMA => true, + * ), * ); * * @access public @@ -139,6 +148,12 @@ class Mustache { } $this->_pragmas = $options['pragmas']; } + + if (isset($options['throws_exceptions'])) { + foreach ($options['throws_exceptions'] as $exception => $value) { + $this->_throwsExceptions[$exception] = $value; + } + } } /** @@ -189,7 +204,7 @@ class Mustache { } $template = $this->_renderPragmas($template); - $template = $this->_renderTemplate($template, $this->_context); + $template = $this->_renderTemplate($template); $this->_otag = $otag_orig; $this->_ctag = $ctag_orig; @@ -403,7 +418,11 @@ class Mustache { $options_string = $matches['options_string']; if (!in_array($pragma_name, $this->_pragmasImplemented)) { - throw new MustacheException('Unknown pragma: ' . $pragma_name, MustacheException::UNKNOWN_PRAGMA); + if ($this->_throwsException(MustacheException::UNKNOWN_PRAGMA)) { + throw new MustacheException('Unknown pragma: ' . $pragma_name, MustacheException::UNKNOWN_PRAGMA); + } else { + return ''; + } } $options = array(); @@ -448,7 +467,9 @@ class Mustache { */ protected function _getPragmaOptions($pragma_name) { if (!$this->_hasPragma($pragma_name)) { - throw new MustacheException('Unknown pragma: ' . $pragma_name, MustacheException::UNKNOWN_PRAGMA); + if ($this->_throwsException(MustacheException::UNKNOWN_PRAGMA)) { + throw new MustacheException('Unknown pragma: ' . $pragma_name, MustacheException::UNKNOWN_PRAGMA); + } } return (is_array($this->_localPragmas[$pragma_name])) ? $this->_localPragmas[$pragma_name] : array(); @@ -767,7 +788,7 @@ class Mustache { $first = array_shift($chunks); $ret = $this->_findVariableInContext($first, $this->_context); - while ($next = array_shift($chunks)) { + foreach ($chunks as $next) { // Slice off a chunk of context for dot notation traversal. $c = array($ret); $ret = $this->_findVariableInContext($next, $c); diff --git a/README.markdown b/README.markdown index 730264f..989ff97 100644 --- a/README.markdown +++ b/README.markdown @@ -9,73 +9,79 @@ Usage A quick example: - render('Hello {{planet}}', array('planet' => 'World!')); - // "Hello World!" - ?> +```php +render('Hello {{planet}}', array('planet' => 'World!')); +// "Hello World!" +``` And a more in-depth example--this is the canonical Mustache template: - Hello {{name}} - You have just won ${{value}}! - {{#in_ca}} - Well, ${{taxed_value}}, after taxes. - {{/in_ca}} +``` +Hello {{name}} +You have just won ${{value}}! +{{#in_ca}} +Well, ${{taxed_value}}, after taxes. +{{/in_ca}} +``` Along with the associated Mustache class: - value - ($this->value * 0.4); - } - - public $in_ca = true; + public function taxed_value() { + return $this->value - ($this->value * 0.4); } + public $in_ca = true; +} +``` + Render it like so: - render($template); - ?> +```php +render($template); +``` Here's the same thing, a different way: Create a view object--which could also be an associative array, but those don't do functions quite as well: - value - ($this->value * 0.4); - } - - public $in_ca = true; +```php +value - ($this->value * 0.4); } - ?> + + public $in_ca = true; +} +``` And render it: - render($template, $chris); - ?> - - +```php +render($template, $chris); +``` Known Issues diff --git a/examples/dot_notation/DotNotation.php b/examples/dot_notation/DotNotation.php index 0274e19..7dd0a4e 100644 --- a/examples/dot_notation/DotNotation.php +++ b/examples/dot_notation/DotNotation.php @@ -9,10 +9,11 @@ class DotNotation extends Mustache { public $person = array( 'name' => array('first' => 'Chris', 'last' => 'Firescythe'), 'age' => 24, + 'hobbies' => array('Cycling', 'Fishing'), 'hometown' => array( - 'city' => 'Cincinnati', + 'city' => 'Cincinnati', 'state' => 'OH', - ) + ), ); public $normal = 'Normal'; diff --git a/examples/dot_notation/dot_notation.mustache b/examples/dot_notation/dot_notation.mustache index 0566867..0135a2a 100644 --- a/examples/dot_notation/dot_notation.mustache +++ b/examples/dot_notation/dot_notation.mustache @@ -1,4 +1,5 @@ * {{person.name.first}} {{person.name.last}} * {{person.age}} +* {{person.hobbies.0}}, {{person.hobbies.1}} * {{person.hometown.city}}, {{person.hometown.state}} -* {{normal}} \ No newline at end of file +* {{normal}} diff --git a/examples/dot_notation/dot_notation.txt b/examples/dot_notation/dot_notation.txt index f8cf1fa..e5c1ed9 100644 --- a/examples/dot_notation/dot_notation.txt +++ b/examples/dot_notation/dot_notation.txt @@ -1,4 +1,5 @@ * Chris Firescythe * 24 +* Cycling, Fishing * Cincinnati, OH -* Normal \ No newline at end of file +* Normal diff --git a/test/MustacheCallTest.php b/test/MustacheCallTest.php new file mode 100644 index 0000000..366d2c4 --- /dev/null +++ b/test/MustacheCallTest.php @@ -0,0 +1,24 @@ +name = 'Bob'; + + $template = '{{# foo }}{{ label }}: {{ name }}{{/ foo }}'; + $data = array('label' => 'name', 'foo' => $foo); + $m = new Mustache($template, $data); + + $this->assertEquals('name: Bob', $m->render()); + } +} + +class ClassWithCall { + public $name; + public function __call($method, $args) { + return 'unknown value'; + } +} diff --git a/test/MustacheExceptionTest.php b/test/MustacheExceptionTest.php index 98bddce..2a40223 100644 --- a/test/MustacheExceptionTest.php +++ b/test/MustacheExceptionTest.php @@ -8,7 +8,7 @@ class MustacheExceptionTest extends PHPUnit_Framework_TestCase { protected $pickyMustache; protected $slackerMustache; - + public function setUp() { $this->pickyMustache = new PickyMustache(); $this->slackerMustache = new SlackerMustache(); @@ -91,6 +91,34 @@ class MustacheExceptionTest extends PHPUnit_Framework_TestCase { $mustache = new TestableMustache(); $mustache->testableGetPragmaOptions('PRAGMATIC'); } + + public function testOverrideThrownExceptionsViaConstructorOptions() { + $exceptions = array( + MustacheException::UNKNOWN_VARIABLE, + MustacheException::UNCLOSED_SECTION, + MustacheException::UNEXPECTED_CLOSE_SECTION, + MustacheException::UNKNOWN_PARTIAL, + MustacheException::UNKNOWN_PRAGMA, + ); + + $one = new TestableMustache(null, null, null, array( + 'throws_exceptions' => array_fill_keys($exceptions, true) + )); + + $thrownExceptions = $one->getThrownExceptions(); + foreach ($exceptions as $exception) { + $this->assertTrue($thrownExceptions[$exception]); + } + + $two = new TestableMustache(null, null, null, array( + 'throws_exceptions' => array_fill_keys($exceptions, false) + )); + + $thrownExceptions = $two->getThrownExceptions(); + foreach ($exceptions as $exception) { + $this->assertFalse($thrownExceptions[$exception]); + } + } } class PickyMustache extends Mustache { @@ -117,4 +145,8 @@ class TestableMustache extends Mustache { public function testableGetPragmaOptions($pragma_name) { return $this->_getPragmaOptions($pragma_name); } -} \ No newline at end of file + + public function getThrownExceptions() { + return $this->_throwsExceptions; + } +} diff --git a/test/MustachePragmaTest.php b/test/MustachePragmaTest.php index 7952b03..c00441c 100644 --- a/test/MustachePragmaTest.php +++ b/test/MustachePragmaTest.php @@ -20,6 +20,20 @@ class MustachePragmaTest extends PHPUnit_Framework_TestCase { $this->fail('Mustache should have thrown an unknown pragma exception'); } + public function testSuppressUnknownPragmaException() { + $m = new LessWhinyMustache(); + + try { + $this->assertEquals('', $m->render('{{%I-HAVE-THE-GREATEST-MUSTACHE}}')); + } catch (MustacheException $e) { + if ($e->getCode() == MustacheException::UNKNOWN_PRAGMA) { + $this->fail('Mustache should have thrown an unknown pragma exception'); + } else { + throw $e; + } + } + } + public function testPragmaReplace() { $m = new Mustache(); $this->assertEquals('', $m->render('{{%UNESCAPED}}'), 'Pragma tag not removed'); @@ -47,4 +61,14 @@ class MustachePragmaTest extends PHPUnit_Framework_TestCase { $this->assertEquals('>>>', $m->render('{{%UNESCAPED}}{{symbol}}')); $this->assertEquals('>>>', $m->render('{{{symbol}}}')); } +} + +class LessWhinyMustache extends Mustache { + protected $_throwsExceptions = array( + MustacheException::UNKNOWN_VARIABLE => false, + MustacheException::UNCLOSED_SECTION => true, + MustacheException::UNEXPECTED_CLOSE_SECTION => true, + MustacheException::UNKNOWN_PARTIAL => false, + MustacheException::UNKNOWN_PRAGMA => false, + ); } \ No newline at end of file