[feature/twig] New Twig filter, subset

This filter grabs a subset of a loop for output (according to past
functionality).

PHPBB3-11598
This commit is contained in:
Nathaniel Guse 2013-06-28 15:40:30 -05:00
parent 09ed0dd7bc
commit abb7901edb
2 changed files with 46 additions and 5 deletions

View file

@ -35,12 +35,19 @@ class phpbb_template_twig_extension extends Twig_Extension
);
}
public function getFilters()
{
return array(
new Twig_SimpleFilter('subset', array($this, 'loop_subset'), array('needs_environment' => true)),
);
}
public function getOperators()
{
return array(
array(),
array(
// @todo check if all these are needed (or others)
// @todo check if all these are needed (or others) and set precedence correctly
'eq' => array('precedence' => 20, 'class' => 'Twig_Node_Expression_Binary_Equal', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT),
'ne' => array('precedence' => 20, 'class' => 'Twig_Node_Expression_Binary_NotEqual', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT),
@ -60,4 +67,35 @@ class phpbb_template_twig_extension extends Twig_Extension
),
);
}
/**
* Grabs a subset of a loop
*
* @param Twig_Environment $env A Twig_Environment instance
* @param mixed $item A variable
* @param integer $start Start of the subset
* @param integer $end End of the subset
* @param Boolean $preserveKeys Whether to preserve key or not (when the input is an array)
*
* @return mixed The sliced variable
*/
function loop_subset(Twig_Environment $env, $item, $start, $end = null, $preserveKeys = false)
{
// We do almost the same thing as array_slice, except when $end is positive
if ($end >= 1)
{
// When end is > 1, subset will end on the last item in an array with the specified $end
// This is different from slice in that it is the number we end on rather than the number
// of items to grab (length)
// Start must always be the actual starting number for this calculation (not negative)
$start = ($start < 0) ? sizeof($item) + $start : $start;
$end = $end - $start;
}
// We always include the last element (this was the past design)
$end = ($end == -1 || $end === null) ? null : $end + 1;
return twig_slice($env, $item, $start, $end, $preserveKeys);
}
}

View file

@ -78,7 +78,7 @@ class phpbb_template_twig_lexer extends Twig_Lexer
$callback = function ($matches) use ($parent_class, $parent_nodes)
{
$name = $matches[1];
$slice = $matches[2];
$subset = trim(substr($matches[2], 1, -1)); // Remove parenthesis
$body = $matches[3];
// Is the designer wanting to call another loop in a loop?
@ -118,16 +118,19 @@ class phpbb_template_twig_lexer extends Twig_Lexer
array_pop($parent_nodes);
$parent = (!empty($parent_nodes)) ? end($parent_nodes) . '_loop_element.' : '';
$slice = ($slice) ? '|slice(' . $slice . ')' : '';
if ($subset !== '')
{
$subset = '|subset(' . $subset . ')';
}
// Turn into a Twig for loop, using (loop name)_loop_element for each child
return "{% for {$name}_loop_element in {$parent}{$name}{$slice} %}{$body}{% endfor %}";
return "{% for {$name}_loop_element in {$parent}{$name}{$subset} %}{$body}{% endfor %}";
};
// Replace <!-- BEGINELSE --> correctly, only needs to be done once
$code = str_replace('<!-- BEGINELSE -->', '{% else %}', $code);
return preg_replace_callback('#<!-- BEGIN ([!a-zA-Z0-9_]+)\(?([0-9,]+)?\)? -->(.+?)<!-- END \1 -->#s', $callback, $code);
return preg_replace_callback('#<!-- BEGIN ([!a-zA-Z0-9_]+)(\([0-9,\-]+\))? -->(.+?)<!-- END \1 -->#s', $callback, $code);
}
/**