Move filter logic from the compiler to the parser.
This commit is contained in:
+29
-45
@@ -60,7 +60,7 @@ class Mustache_Compiler
|
|||||||
*
|
*
|
||||||
* @internal Users should set global pragmas in Mustache_Engine, not here :)
|
* @internal Users should set global pragmas in Mustache_Engine, not here :)
|
||||||
*
|
*
|
||||||
* @param array $pragmas
|
* @param string[] $pragmas
|
||||||
*/
|
*/
|
||||||
public function setPragmas(array $pragmas)
|
public function setPragmas(array $pragmas)
|
||||||
{
|
{
|
||||||
@@ -95,6 +95,7 @@ class Mustache_Compiler
|
|||||||
$code .= $this->section(
|
$code .= $this->section(
|
||||||
$node[Mustache_Tokenizer::NODES],
|
$node[Mustache_Tokenizer::NODES],
|
||||||
$node[Mustache_Tokenizer::NAME],
|
$node[Mustache_Tokenizer::NAME],
|
||||||
|
isset($node[Mustache_Tokenizer::FILTERS]) ? $node[Mustache_Tokenizer::FILTERS] : array(),
|
||||||
$node[Mustache_Tokenizer::INDEX],
|
$node[Mustache_Tokenizer::INDEX],
|
||||||
$node[Mustache_Tokenizer::END],
|
$node[Mustache_Tokenizer::END],
|
||||||
$node[Mustache_Tokenizer::OTAG],
|
$node[Mustache_Tokenizer::OTAG],
|
||||||
@@ -107,6 +108,7 @@ class Mustache_Compiler
|
|||||||
$code .= $this->invertedSection(
|
$code .= $this->invertedSection(
|
||||||
$node[Mustache_Tokenizer::NODES],
|
$node[Mustache_Tokenizer::NODES],
|
||||||
$node[Mustache_Tokenizer::NAME],
|
$node[Mustache_Tokenizer::NAME],
|
||||||
|
isset($node[Mustache_Tokenizer::FILTERS]) ? $node[Mustache_Tokenizer::FILTERS] : array(),
|
||||||
$level
|
$level
|
||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
@@ -154,14 +156,24 @@ class Mustache_Compiler
|
|||||||
|
|
||||||
case Mustache_Tokenizer::T_UNESCAPED:
|
case Mustache_Tokenizer::T_UNESCAPED:
|
||||||
case Mustache_Tokenizer::T_UNESCAPED_2:
|
case Mustache_Tokenizer::T_UNESCAPED_2:
|
||||||
$code .= $this->variable($node[Mustache_Tokenizer::NAME], false, $level);
|
$code .= $this->variable(
|
||||||
|
$node[Mustache_Tokenizer::NAME],
|
||||||
|
isset($node[Mustache_Tokenizer::FILTERS]) ? $node[Mustache_Tokenizer::FILTERS] : array(),
|
||||||
|
false,
|
||||||
|
$level
|
||||||
|
);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case Mustache_Tokenizer::T_COMMENT:
|
case Mustache_Tokenizer::T_COMMENT:
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case Mustache_Tokenizer::T_ESCAPED:
|
case Mustache_Tokenizer::T_ESCAPED:
|
||||||
$code .= $this->variable($node[Mustache_Tokenizer::NAME], true, $level);
|
$code .= $this->variable(
|
||||||
|
$node[Mustache_Tokenizer::NAME],
|
||||||
|
isset($node[Mustache_Tokenizer::FILTERS]) ? $node[Mustache_Tokenizer::FILTERS] : array(),
|
||||||
|
true,
|
||||||
|
$level
|
||||||
|
);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case Mustache_Tokenizer::T_TEXT:
|
case Mustache_Tokenizer::T_TEXT:
|
||||||
@@ -279,7 +291,7 @@ class Mustache_Compiler
|
|||||||
*/
|
*/
|
||||||
private function blockArg($nodes, $id, $start, $end, $otag, $ctag, $level)
|
private function blockArg($nodes, $id, $start, $end, $otag, $ctag, $level)
|
||||||
{
|
{
|
||||||
$key = $this->section($nodes, $id, $start, $end, $otag, $ctag, $level, true);
|
$key = $this->section($nodes, $id, array(), $start, $end, $otag, $ctag, $level, true);
|
||||||
$id = var_export($id, true);
|
$id = var_export($id, true);
|
||||||
|
|
||||||
return sprintf($this->prepare(self::BLOCK_ARG, $level), $id, $key, $id, $this->flushIndent());
|
return sprintf($this->prepare(self::BLOCK_ARG, $level), $id, $key, $id, $this->flushIndent());
|
||||||
@@ -322,6 +334,7 @@ class Mustache_Compiler
|
|||||||
*
|
*
|
||||||
* @param array $nodes Array of child tokens
|
* @param array $nodes Array of child tokens
|
||||||
* @param string $id Section name
|
* @param string $id Section name
|
||||||
|
* @param string[] $filters Array of filters
|
||||||
* @param int $start Section start offset
|
* @param int $start Section start offset
|
||||||
* @param int $end Section end offset
|
* @param int $end Section end offset
|
||||||
* @param string $otag Current Mustache opening tag
|
* @param string $otag Current Mustache opening tag
|
||||||
@@ -331,14 +344,8 @@ class Mustache_Compiler
|
|||||||
*
|
*
|
||||||
* @return string Generated section PHP source code
|
* @return string Generated section PHP source code
|
||||||
*/
|
*/
|
||||||
private function section($nodes, $id, $start, $end, $otag, $ctag, $level, $arg = false)
|
private function section($nodes, $id, $filters, $start, $end, $otag, $ctag, $level, $arg = false)
|
||||||
{
|
{
|
||||||
$filters = '';
|
|
||||||
|
|
||||||
if (isset($this->pragmas[Mustache_Engine::PRAGMA_FILTERS])) {
|
|
||||||
list($id, $filters) = $this->getFilters($id, $level);
|
|
||||||
}
|
|
||||||
|
|
||||||
$source = var_export(substr($this->source, $start, $end - $start), true);
|
$source = var_export(substr($this->source, $start, $end - $start), true);
|
||||||
$callable = $this->getCallable();
|
$callable = $this->getCallable();
|
||||||
|
|
||||||
@@ -359,6 +366,7 @@ class Mustache_Compiler
|
|||||||
} else {
|
} else {
|
||||||
$method = $this->getFindMethod($id);
|
$method = $this->getFindMethod($id);
|
||||||
$id = var_export($id, true);
|
$id = var_export($id, true);
|
||||||
|
$filters = $this->getFilters($filters, $level);
|
||||||
|
|
||||||
return sprintf($this->prepare(self::SECTION_CALL, $level), $id, $method, $id, $filters, $key);
|
return sprintf($this->prepare(self::SECTION_CALL, $level), $id, $method, $id, $filters, $key);
|
||||||
}
|
}
|
||||||
@@ -376,20 +384,16 @@ class Mustache_Compiler
|
|||||||
*
|
*
|
||||||
* @param array $nodes Array of child tokens
|
* @param array $nodes Array of child tokens
|
||||||
* @param string $id Section name
|
* @param string $id Section name
|
||||||
|
* @param string[] $filters Array of filters
|
||||||
* @param int $level
|
* @param int $level
|
||||||
*
|
*
|
||||||
* @return string Generated inverted section PHP source code
|
* @return string Generated inverted section PHP source code
|
||||||
*/
|
*/
|
||||||
private function invertedSection($nodes, $id, $level)
|
private function invertedSection($nodes, $id, $filters, $level)
|
||||||
{
|
{
|
||||||
$filters = '';
|
|
||||||
|
|
||||||
if (isset($this->pragmas[Mustache_Engine::PRAGMA_FILTERS])) {
|
|
||||||
list($id, $filters) = $this->getFilters($id, $level);
|
|
||||||
}
|
|
||||||
|
|
||||||
$method = $this->getFindMethod($id);
|
$method = $this->getFindMethod($id);
|
||||||
$id = var_export($id, true);
|
$id = var_export($id, true);
|
||||||
|
$filters = $this->getFilters($filters, $level);
|
||||||
|
|
||||||
return sprintf($this->prepare(self::INVERTED_SECTION, $level), $id, $method, $id, $filters, $this->walk($nodes, $level));
|
return sprintf($this->prepare(self::INVERTED_SECTION, $level), $id, $method, $id, $filters, $this->walk($nodes, $level));
|
||||||
}
|
}
|
||||||
@@ -478,42 +482,22 @@ class Mustache_Compiler
|
|||||||
* Generate Mustache Template variable interpolation PHP source.
|
* Generate Mustache Template variable interpolation PHP source.
|
||||||
*
|
*
|
||||||
* @param string $id Variable name
|
* @param string $id Variable name
|
||||||
|
* @param string[] $filters Array of filters
|
||||||
* @param boolean $escape Escape the variable value for output?
|
* @param boolean $escape Escape the variable value for output?
|
||||||
* @param int $level
|
* @param int $level
|
||||||
*
|
*
|
||||||
* @return string Generated variable interpolation PHP source
|
* @return string Generated variable interpolation PHP source
|
||||||
*/
|
*/
|
||||||
private function variable($id, $escape, $level)
|
private function variable($id, $filters, $escape, $level)
|
||||||
{
|
{
|
||||||
$filters = '';
|
|
||||||
|
|
||||||
if (isset($this->pragmas[Mustache_Engine::PRAGMA_FILTERS])) {
|
|
||||||
list($id, $filters) = $this->getFilters($id, $level);
|
|
||||||
}
|
|
||||||
|
|
||||||
$method = $this->getFindMethod($id);
|
$method = $this->getFindMethod($id);
|
||||||
$id = ($method !== 'last') ? var_export($id, true) : '';
|
$id = ($method !== 'last') ? var_export($id, true) : '';
|
||||||
|
$filters = $this->getFilters($filters, $level);
|
||||||
$value = $escape ? $this->getEscape() : '$value';
|
$value = $escape ? $this->getEscape() : '$value';
|
||||||
|
|
||||||
return sprintf($this->prepare(self::VARIABLE, $level), $method, $id, $filters, $this->flushIndent(), $value);
|
return sprintf($this->prepare(self::VARIABLE, $level), $method, $id, $filters, $this->flushIndent(), $value);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Generate Mustache Template variable filtering PHP source.
|
|
||||||
*
|
|
||||||
* @param string $id Variable name
|
|
||||||
* @param int $level
|
|
||||||
*
|
|
||||||
* @return string Generated variable filtering PHP source
|
|
||||||
*/
|
|
||||||
private function getFilters($id, $level)
|
|
||||||
{
|
|
||||||
$filters = array_map('trim', explode('|', $id));
|
|
||||||
$id = array_shift($filters);
|
|
||||||
|
|
||||||
return array($id, $this->getFilter($filters, $level));
|
|
||||||
}
|
|
||||||
|
|
||||||
const FILTER = '
|
const FILTER = '
|
||||||
$filter = $context->%s(%s);
|
$filter = $context->%s(%s);
|
||||||
if (!(%s)) {
|
if (!(%s)) {
|
||||||
@@ -523,14 +507,14 @@ class Mustache_Compiler
|
|||||||
';
|
';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generate PHP source for a single filter.
|
* Generate Mustache Template variable filtering PHP source.
|
||||||
*
|
*
|
||||||
* @param array $filters
|
* @param string[] $filters Array of filters
|
||||||
* @param int $level
|
* @param int $level
|
||||||
*
|
*
|
||||||
* @return string Generated filter PHP source
|
* @return string Generated filter PHP source
|
||||||
*/
|
*/
|
||||||
private function getFilter(array $filters, $level)
|
private function getFilters(array $filters, $level)
|
||||||
{
|
{
|
||||||
if (empty($filters)) {
|
if (empty($filters)) {
|
||||||
return '';
|
return '';
|
||||||
@@ -542,7 +526,7 @@ class Mustache_Compiler
|
|||||||
$callable = $this->getCallable('$filter');
|
$callable = $this->getCallable('$filter');
|
||||||
$msg = var_export($name, true);
|
$msg = var_export($name, true);
|
||||||
|
|
||||||
return sprintf($this->prepare(self::FILTER, $level), $method, $filter, $callable, $msg, $this->getFilter($filters, $level));
|
return sprintf($this->prepare(self::FILTER, $level), $method, $filter, $callable, $msg, $this->getFilters($filters, $level));
|
||||||
}
|
}
|
||||||
|
|
||||||
const LINE = '$buffer .= "\n";';
|
const LINE = '$buffer .= "\n";';
|
||||||
|
|||||||
+57
-5
@@ -21,6 +21,9 @@ class Mustache_Parser
|
|||||||
private $pragmas;
|
private $pragmas;
|
||||||
private $defaultPragmas = array();
|
private $defaultPragmas = array();
|
||||||
|
|
||||||
|
private $pragmaFilters;
|
||||||
|
private $pragmaBlocks;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Process an array of Mustache tokens and convert them into a parse tree.
|
* Process an array of Mustache tokens and convert them into a parse tree.
|
||||||
*
|
*
|
||||||
@@ -34,6 +37,9 @@ class Mustache_Parser
|
|||||||
$this->lineTokens = 0;
|
$this->lineTokens = 0;
|
||||||
$this->pragmas = $this->defaultPragmas;
|
$this->pragmas = $this->defaultPragmas;
|
||||||
|
|
||||||
|
$this->pragmaFilters = isset($this->pragmas[Mustache_Engine::PRAGMA_FILTERS]);
|
||||||
|
$this->pragmaBlocks = isset($this->pragmas[Mustache_Engine::PRAGMA_BLOCKS]);
|
||||||
|
|
||||||
return $this->buildTree($tokens);
|
return $this->buildTree($tokens);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -43,13 +49,13 @@ class Mustache_Parser
|
|||||||
*
|
*
|
||||||
* @internal Users should set global pragmas in Mustache_Engine, not here :)
|
* @internal Users should set global pragmas in Mustache_Engine, not here :)
|
||||||
*
|
*
|
||||||
* @param array $pragmas
|
* @param string[] $pragmas
|
||||||
*/
|
*/
|
||||||
public function setPragmas(array $pragmas)
|
public function setPragmas(array $pragmas)
|
||||||
{
|
{
|
||||||
$this->pragmas = array();
|
$this->pragmas = array();
|
||||||
foreach ($pragmas as $pragma) {
|
foreach ($pragmas as $pragma) {
|
||||||
$this->pragmas[$pragma] = true;
|
$this->enablePragma($pragma);
|
||||||
}
|
}
|
||||||
$this->defaultPragmas = $this->pragmas;
|
$this->defaultPragmas = $this->pragmas;
|
||||||
}
|
}
|
||||||
@@ -78,6 +84,14 @@ class Mustache_Parser
|
|||||||
$this->lineTokens = 0;
|
$this->lineTokens = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ($this->pragmaFilters && isset($token[Mustache_Tokenizer::NAME])) {
|
||||||
|
list($name, $filters) = $this->getNameAndFilters($token[Mustache_Tokenizer::NAME]);
|
||||||
|
if (!empty($filters)) {
|
||||||
|
$token[Mustache_Tokenizer::NAME] = $name;
|
||||||
|
$token[Mustache_Tokenizer::FILTERS] = $filters;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
switch ($token[Mustache_Tokenizer::TYPE]) {
|
switch ($token[Mustache_Tokenizer::TYPE]) {
|
||||||
case Mustache_Tokenizer::T_DELIM_CHANGE:
|
case Mustache_Tokenizer::T_DELIM_CHANGE:
|
||||||
$this->checkIfTokenIsAllowedInParent($parent, $token);
|
$this->checkIfTokenIsAllowedInParent($parent, $token);
|
||||||
@@ -133,7 +147,7 @@ class Mustache_Parser
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case Mustache_Tokenizer::T_BLOCK_VAR:
|
case Mustache_Tokenizer::T_BLOCK_VAR:
|
||||||
if (isset($this->pragmas[Mustache_Engine::PRAGMA_BLOCKS])) {
|
if ($this->pragmaBlocks) {
|
||||||
// BLOCKS pragma is enabled, let's do this!
|
// BLOCKS pragma is enabled, let's do this!
|
||||||
if ($parent[Mustache_Tokenizer::TYPE] === Mustache_Tokenizer::T_PARENT) {
|
if ($parent[Mustache_Tokenizer::TYPE] === Mustache_Tokenizer::T_PARENT) {
|
||||||
$token[Mustache_Tokenizer::TYPE] = Mustache_Tokenizer::T_BLOCK_ARG;
|
$token[Mustache_Tokenizer::TYPE] = Mustache_Tokenizer::T_BLOCK_ARG;
|
||||||
@@ -150,7 +164,7 @@ class Mustache_Parser
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case Mustache_Tokenizer::T_PRAGMA:
|
case Mustache_Tokenizer::T_PRAGMA:
|
||||||
$this->pragmas[$token[Mustache_Tokenizer::NAME]] = true;
|
$this->enablePragma($token[Mustache_Tokenizer::NAME]);
|
||||||
// no break
|
// no break
|
||||||
|
|
||||||
case Mustache_Tokenizer::T_COMMENT:
|
case Mustache_Tokenizer::T_COMMENT:
|
||||||
@@ -184,7 +198,7 @@ class Mustache_Parser
|
|||||||
* @param array $nodes Parsed nodes.
|
* @param array $nodes Parsed nodes.
|
||||||
* @param array $tokens Tokens to be parsed.
|
* @param array $tokens Tokens to be parsed.
|
||||||
*
|
*
|
||||||
* @return array Resulting indent token, if any.
|
* @return array|null Resulting indent token, if any.
|
||||||
*/
|
*/
|
||||||
private function clearStandaloneLines(array &$nodes, array &$tokens)
|
private function clearStandaloneLines(array &$nodes, array &$tokens)
|
||||||
{
|
{
|
||||||
@@ -265,4 +279,42 @@ class Mustache_Parser
|
|||||||
throw new Mustache_Exception_SyntaxException('Illegal content in < parent tag', $token);
|
throw new Mustache_Exception_SyntaxException('Illegal content in < parent tag', $token);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Split a tag name into name and filters.
|
||||||
|
*
|
||||||
|
* @param string $name
|
||||||
|
*
|
||||||
|
* @return array {
|
||||||
|
* @type string Tag name
|
||||||
|
* @type string[] Array of filters
|
||||||
|
* }
|
||||||
|
*/
|
||||||
|
private function getNameAndFilters($name)
|
||||||
|
{
|
||||||
|
$filters = array_map('trim', explode('|', $name));
|
||||||
|
$name = array_shift($filters);
|
||||||
|
|
||||||
|
return array($name, $filters);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Enable a pragma.
|
||||||
|
*
|
||||||
|
* @param string $name
|
||||||
|
*/
|
||||||
|
private function enablePragma($name)
|
||||||
|
{
|
||||||
|
$this->pragmas[$name] = true;
|
||||||
|
|
||||||
|
switch ($name) {
|
||||||
|
case Mustache_Engine::PRAGMA_BLOCKS:
|
||||||
|
$this->pragmaBlocks = true;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Mustache_Engine::PRAGMA_FILTERS:
|
||||||
|
$this->pragmaFilters = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -71,6 +71,7 @@ class Mustache_Tokenizer
|
|||||||
const INDENT = 'indent';
|
const INDENT = 'indent';
|
||||||
const NODES = 'nodes';
|
const NODES = 'nodes';
|
||||||
const VALUE = 'value';
|
const VALUE = 'value';
|
||||||
|
const FILTERS = 'filters';
|
||||||
|
|
||||||
private $state;
|
private $state;
|
||||||
private $tagType;
|
private $tagType;
|
||||||
|
|||||||
Reference in New Issue
Block a user