From cff57f9076dd160b2185895f7298d4acbc5b5bb3 Mon Sep 17 00:00:00 2001 From: javiexin Date: Wed, 28 Dec 2016 12:55:26 +0100 Subject: [PATCH] [ticket/14944] Add possibility to search for template loop indexes by key Adds a new function to the template interface, and implements it in the context class. The function returns the ordinal index for a specified key, with the same structure that the key for alter_block_array. Reuses same code. PHPBB3-14944 --- phpBB/phpbb/template/base.php | 8 ++++ phpBB/phpbb/template/context.php | 71 +++++++++++++++++++++++++++++++ phpBB/phpbb/template/template.php | 17 ++++++++ 3 files changed, 96 insertions(+) diff --git a/phpBB/phpbb/template/base.php b/phpBB/phpbb/template/base.php index 9a40702ba8..bc0f022cc4 100644 --- a/phpBB/phpbb/template/base.php +++ b/phpBB/phpbb/template/base.php @@ -132,6 +132,14 @@ abstract class base implements template return $this->context->alter_block_array($blockname, $vararray, $key, $mode); } + /** + * {@inheritdoc} + */ + public function find_key_index($blockname, $key = false) + { + return $this->context->find_key_index($blockname, $key); + } + /** * Calls hook if any is defined. * diff --git a/phpBB/phpbb/template/context.php b/phpBB/phpbb/template/context.php index 4ee48205c8..e390c5a677 100644 --- a/phpBB/phpbb/template/context.php +++ b/phpBB/phpbb/template/context.php @@ -263,6 +263,77 @@ class context return true; } + /** + * Find the index for a specified key in the innermost specified block + * + * @param string $blockname the blockname, for example 'loop' + * @param mixed $key Key to search for + * + * array: KEY => VALUE [the key/value pair to search for within the loop to determine the correct position] + * + * int: Position [the position to search for] + * + * If key is false the position is set to 0 + * If key is true the position is set to the last entry + * + * @return mixed false if not found, index position otherwise; be sure to test with === + */ + public function find_key_index($blockname, $key = false) + { + // For nested block, $blockcount > 0, for top-level block, $blockcount == 0 + $blocks = explode('.', $blockname); + $blockcount = sizeof($blocks) - 1; + + $block = &$this->tpldata; + for ($i = 0; $i < $blockcount; $i++) + { + if (($pos = strpos($blocks[$i], '[')) !== false) + { + $name = substr($blocks[$i], 0, $pos); + + if (strpos($blocks[$i], '[]') === $pos) + { + $index = sizeof($block[$name]) - 1; + } + else + { + $index = min((int) substr($blocks[$i], $pos + 1, -1), sizeof($block[$name]) - 1); + } + } + else + { + $name = $blocks[$i]; + $index = sizeof($block[$name]) - 1; + } + $block = &$block[$name]; + $block = &$block[$index]; + } + + $block = &$block[$blocks[$i]]; // Traverse the last block + + // Change key to zero (change first position) if false and to last position if true + if ($key === false || $key === true) + { + return ($key === false) ? 0 : sizeof($block); + } + + // Get correct position if array given + if (is_array($key)) + { + // Search array to get correct position + list($search_key, $search_value) = @each($key); + foreach ($block as $i => $val_ary) + { + if ($val_ary[$search_key] === $search_value) + { + return $i; + } + } + } + + return false; + } + /** * Change already assigned key variable pair (one-dimensional - single loop entry) * diff --git a/phpBB/phpbb/template/template.php b/phpBB/phpbb/template/template.php index 041ecb12e4..b5a6ab32dc 100644 --- a/phpBB/phpbb/template/template.php +++ b/phpBB/phpbb/template/template.php @@ -172,6 +172,23 @@ interface template */ public function alter_block_array($blockname, array $vararray, $key = false, $mode = 'insert'); + /** + * Find the index for a specified key in the innermost specified block + * + * @param string $blockname the blockname, for example 'loop' + * @param mixed $key Key to search for + * + * array: KEY => VALUE [the key/value pair to search for within the loop to determine the correct position] + * + * int: Position [the position to search for] + * + * If key is false the position is set to 0 + * If key is true the position is set to the last entry + * + * @return mixed false if not found, index position otherwise; be sure to test with === + */ + public function find_key_index($blockname, $key = false); + /** * Get path to template for handle (required for BBCode parser) *