diff --git a/src/Mustache/Compiler.php b/src/Mustache/Compiler.php index c34f992..50d335e 100644 --- a/src/Mustache/Compiler.php +++ b/src/Mustache/Compiler.php @@ -123,8 +123,8 @@ class Mustache_Compiler $code .= $this->parent( $node[Mustache_Tokenizer::NAME], isset($node[Mustache_Tokenizer::INDENT]) ? $node[Mustache_Tokenizer::INDENT] : '', - $level, - $node[Mustache_Tokenizer::NODES] + $node[Mustache_Tokenizer::NODES], + $level ); break; @@ -172,6 +172,7 @@ class Mustache_Compiler throw new Mustache_Exception_SyntaxException(sprintf('Unknown token type: %s', $node[Mustache_Tokenizer::TYPE]), $node); } } + return $code; } @@ -230,13 +231,26 @@ class Mustache_Compiler const BLOCK_VAR = ' $value = $this->resolveValue($context->findInBlock(%s), $context, $indent); - if($value && !is_array($value) && !is_object($value)) { + if ($value && !is_array($value) && !is_object($value)) { $buffer .= $value; } else { %s } '; + /** + * Generate Mustache Template inheritance block variable PHP source. + * + * @param array $nodes Array of child tokens + * @param string $id Section name + * @param int $start Section start offset + * @param int $end Section end offset + * @param string $otag Current Mustache opening tag + * @param string $ctag Current Mustache closing tag + * @param int $level + * + * @return string Generated PHP source code + */ private function blockVar($nodes, $id, $start, $end, $otag, $ctag, $level) { $id_str = var_export($id, true); @@ -250,6 +264,19 @@ class Mustache_Compiler $newContext[%s] = %s$value; '; + /** + * Generate Mustache Template inheritance block argument PHP source. + * + * @param array $nodes Array of child tokens + * @param string $id Section name + * @param int $start Section start offset + * @param int $end Section end offset + * @param string $otag Current Mustache opening tag + * @param string $ctag Current Mustache closing tag + * @param int $level + * + * @return string Generated PHP source code + */ private function blockArg($nodes, $id, $start, $end, $otag, $ctag, $level) { $key = $this->section($nodes, $id, $start, $end, $otag, $ctag, $level, true); @@ -338,6 +365,7 @@ class Mustache_Compiler } else { $method = $this->getFindMethod($id); $id = var_export($id, true); + return sprintf($this->prepare(self::SECTION_CALL, $level), $id, $method, $id, $filters, $key); } } @@ -397,6 +425,7 @@ class Mustache_Compiler } const PARENT = ' + %s if ($parent = $this->mustache->LoadPartial(%s)) { $context->pushBlockContext($newContext); @@ -405,24 +434,38 @@ class Mustache_Compiler } '; - private function parent($id, $indent, $level, $children) + /** + * Generate Mustache Template inheritance parent call PHP source. + * + * @param string $id Parent tag name + * @param string $indent Whitespace indent to apply to parent + * @param array $children Child nodes + * @param int $level + * + * @return string Generated PHP source code + */ + private function parent($id, $indent, array $children, $level) { - $block = ''; + $realChildren = array_filter($children, array(__CLASS__, 'onlyBlockArgs')); - $real_children = array_filter($children, array(__CLASS__, 'return_only_block_args')); - - $block = $this->walk($real_children, $level); - - return $block. sprintf( + return sprintf( $this->prepare(self::PARENT, $level), + $this->walk($realChildren, $level), var_export($id, true), var_export($indent, true) ); } - private static function return_only_block_args($child) + /** + * Helper method for filtering out non-block-arg tokens. + * + * @param array $node + * + * @return boolean True if $node is a block arg token. + */ + private static function onlyBlockArgs(array $node) { - return $child[Mustache_Tokenizer::TYPE] == Mustache_Tokenizer::T_BLOCK_ARG; + return $node[Mustache_Tokenizer::TYPE] === Mustache_Tokenizer::T_BLOCK_ARG; } const VARIABLE = ' @@ -590,6 +633,13 @@ class Mustache_Compiler const IS_CALLABLE = '!is_string(%s) && is_callable(%s)'; const STRICT_IS_CALLABLE = 'is_object(%s) && is_callable(%s)'; + /** + * Helper function to compile strict vs lax "is callable" logic. + * + * @param string $variable (default: '$value') + * + * @return string "is callable" logic + */ private function getCallable($variable = '$value') { $tpl = $this->strictCallables ? self::STRICT_IS_CALLABLE : self::IS_CALLABLE; diff --git a/src/Mustache/Context.php b/src/Mustache/Context.php index 2ec73b2..6918be4 100644 --- a/src/Mustache/Context.php +++ b/src/Mustache/Context.php @@ -133,7 +133,7 @@ class Mustache_Context public function findInBlock($id) { - foreach($this->block_stack as $context) { + foreach ($this->block_stack as $context) { if (array_key_exists($id, $context)) { return $context[$id]; } diff --git a/src/Mustache/Parser.php b/src/Mustache/Parser.php index a056dfc..f23f03a 100644 --- a/src/Mustache/Parser.php +++ b/src/Mustache/Parser.php @@ -235,14 +235,22 @@ class Mustache_Parser */ private function tokenIsWhitespace(array $token) { - if ($token[Mustache_Tokenizer::TYPE] == Mustache_Tokenizer::T_TEXT) { + if ($token[Mustache_Tokenizer::TYPE] === Mustache_Tokenizer::T_TEXT) { return preg_match('/^\s*$/', $token[Mustache_Tokenizer::VALUE]); } return false; } - private function checkIfTokenIsAllowedInParent($parent, $token) + /** + * Check whether a token is allowed inside a parent tag. + * + * @throws Mustache_Exception_SyntaxException if an invalid token is found inside a parent tag. + * + * @param array|null $parent + * @param array $token + */ + private function checkIfTokenIsAllowedInParent($parent, array $token) { if ($parent[Mustache_Tokenizer::TYPE] === Mustache_Tokenizer::T_PARENT) { throw new Mustache_Exception_SyntaxException('Illegal content in < parent tag', $token); diff --git a/src/Mustache/Tokenizer.php b/src/Mustache/Tokenizer.php index 8b0b805..eef1580 100644 --- a/src/Mustache/Tokenizer.php +++ b/src/Mustache/Tokenizer.php @@ -34,8 +34,8 @@ class Mustache_Tokenizer const T_UNESCAPED_2 = '&'; const T_TEXT = '_t'; const T_PRAGMA = '%'; - const T_BLOCK_VAR = '$'; - const T_BLOCK_ARG = '$arg'; + const T_BLOCK_VAR = '$'; + const T_BLOCK_ARG = '$arg'; // Valid token types private static $tagTypes = array( @@ -50,14 +50,14 @@ class Mustache_Tokenizer self::T_UNESCAPED => true, self::T_UNESCAPED_2 => true, self::T_PRAGMA => true, - self::T_BLOCK_VAR => true, + self::T_BLOCK_VAR => true, ); // Interpolated tags private static $interpolatedTags = array( - self::T_ESCAPED => true, - self::T_UNESCAPED => true, - self::T_UNESCAPED_2 => true, + self::T_ESCAPED => true, + self::T_UNESCAPED => true, + self::T_UNESCAPED_2 => true, ); // Token properties diff --git a/test/Mustache/Test/Functional/InheritanceTest.php b/test/Mustache/Test/Functional/InheritanceTest.php index 1f5dd97..0e61fdd 100644 --- a/test/Mustache/Test/Functional/InheritanceTest.php +++ b/test/Mustache/Test/Functional/InheritanceTest.php @@ -411,8 +411,6 @@ class Mustache_Test_Functional_InheritanceTest extends PHPUnit_Framework_TestCas $this->assertEquals('default content', $tpl->render($data)); } - - /** * @dataProvider getIllegalInheritanceExamples * @expectedException Mustache_Exception_SyntaxException