diff options
-rw-r--r-- | phpBB/includes/template/twig/extension.php | 40 | ||||
-rw-r--r-- | phpBB/includes/template/twig/lexer.php | 11 |
2 files changed, 46 insertions, 5 deletions
diff --git a/phpBB/includes/template/twig/extension.php b/phpBB/includes/template/twig/extension.php index 44d694ce1a..a952d70076 100644 --- a/phpBB/includes/template/twig/extension.php +++ b/phpBB/includes/template/twig/extension.php @@ -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); + } } diff --git a/phpBB/includes/template/twig/lexer.php b/phpBB/includes/template/twig/lexer.php index 95b9bd4630..9d348535a5 100644 --- a/phpBB/includes/template/twig/lexer.php +++ b/phpBB/includes/template/twig/lexer.php @@ -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); } /** |