From 7030578bbe9e11c18b5becaf8b06e670e3c2e3cd Mon Sep 17 00:00:00 2001 From: Nils Adermann Date: Sun, 14 Jul 2013 01:32:34 -0400 Subject: [ticket/11698] Moving all autoloadable files to phpbb/ PHPBB3-11698 --- phpBB/phpbb/template/context.php | 389 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 389 insertions(+) create mode 100644 phpBB/phpbb/template/context.php (limited to 'phpBB/phpbb/template/context.php') diff --git a/phpBB/phpbb/template/context.php b/phpBB/phpbb/template/context.php new file mode 100644 index 0000000000..c5ce7422b9 --- /dev/null +++ b/phpBB/phpbb/template/context.php @@ -0,0 +1,389 @@ + $this->tpldata[block][iteration#][child][iteration#][child2][iteration#][variablename] == value + * if it's a root-level variable, it'll be like this: + * --> $this->tpldata[.][0][varname] == value + * + * @var array + */ + private $tpldata = array('.' => array(0 => array())); + + /** + * @var array Reference to template->tpldata['.'][0] + */ + private $rootref; + + public function __construct() + { + $this->clear(); + } + + /** + * Clears template data set. + */ + public function clear() + { + $this->tpldata = array('.' => array(0 => array())); + $this->rootref = &$this->tpldata['.'][0]; + } + + /** + * Assign a single scalar value to a single key. + * + * Value can be a string, an integer or a boolean. + * + * @param string $varname Variable name + * @param string $varval Value to assign to variable + */ + public function assign_var($varname, $varval) + { + $this->rootref[$varname] = $varval; + + return true; + } + + /** + * Append text to the string value stored in a key. + * + * Text is appended using the string concatenation operator (.). + * + * @param string $varname Variable name + * @param string $varval Value to append to variable + */ + public function append_var($varname, $varval) + { + $this->rootref[$varname] = (isset($this->rootref[$varname]) ? $this->rootref[$varname] : '') . $varval; + + return true; + } + + /** + * Returns a reference to template data array. + * + * This function is public so that template renderer may invoke it. + * Users should alter template variables via functions in phpbb_template. + * + * Note: modifying returned array will affect data stored in the context. + * + * @return array template data + */ + public function &get_data_ref() + { + // returning a reference directly is not + // something php is capable of doing + $ref = &$this->tpldata; + return $ref; + } + + /** + * Returns a reference to template root scope. + * + * This function is public so that template renderer may invoke it. + * Users should not need to invoke this function. + * + * Note: modifying returned array will affect data stored in the context. + * + * @return array template data + */ + public function &get_root_ref() + { + // rootref is already a reference + return $this->rootref; + } + + /** + * Assign key variable pairs from an array to a specified block + * + * @param string $blockname Name of block to assign $vararray to + * @param array $vararray A hash of variable name => value pairs + */ + public function assign_block_vars($blockname, array $vararray) + { + if (strpos($blockname, '.') !== false) + { + // Nested block. + $blocks = explode('.', $blockname); + $blockcount = sizeof($blocks) - 1; + + $str = &$this->tpldata; + for ($i = 0; $i < $blockcount; $i++) + { + $str = &$str[$blocks[$i]]; + $str = &$str[sizeof($str) - 1]; + } + + $s_row_count = isset($str[$blocks[$blockcount]]) ? sizeof($str[$blocks[$blockcount]]) : 0; + $vararray['S_ROW_COUNT'] = $vararray['S_ROW_NUM'] = $s_row_count; + + // Assign S_FIRST_ROW + if (!$s_row_count) + { + $vararray['S_FIRST_ROW'] = true; + } + + // Assign S_BLOCK_NAME + $vararray['S_BLOCK_NAME'] = $blocks[$blockcount]; + + // Now the tricky part, we always assign S_LAST_ROW and remove the entry before + // This is much more clever than going through the complete template data on display (phew) + $vararray['S_LAST_ROW'] = true; + if ($s_row_count > 0) + { + unset($str[$blocks[$blockcount]][($s_row_count - 1)]['S_LAST_ROW']); + } + + // Now we add the block that we're actually assigning to. + // We're adding a new iteration to this block with the given + // variable assignments. + $str[$blocks[$blockcount]][] = $vararray; + + // Set S_NUM_ROWS + foreach ($str[$blocks[$blockcount]] as &$mod_block) + { + $mod_block['S_NUM_ROWS'] = sizeof($str[$blocks[$blockcount]]); + } + } + else + { + // Top-level block. + $s_row_count = (isset($this->tpldata[$blockname])) ? sizeof($this->tpldata[$blockname]) : 0; + $vararray['S_ROW_COUNT'] = $vararray['S_ROW_NUM'] = $s_row_count; + + // Assign S_FIRST_ROW + if (!$s_row_count) + { + $vararray['S_FIRST_ROW'] = true; + } + + // Assign S_BLOCK_NAME + $vararray['S_BLOCK_NAME'] = $blockname; + + // We always assign S_LAST_ROW and remove the entry before + $vararray['S_LAST_ROW'] = true; + if ($s_row_count > 0) + { + unset($this->tpldata[$blockname][($s_row_count - 1)]['S_LAST_ROW']); + } + + // Add a new iteration to this block with the variable assignments we were given. + $this->tpldata[$blockname][] = $vararray; + + // Set S_NUM_ROWS + foreach ($this->tpldata[$blockname] as &$mod_block) + { + $mod_block['S_NUM_ROWS'] = sizeof($this->tpldata[$blockname]); + } + } + + return true; + } + + /** + * Change already assigned key variable pair (one-dimensional - single loop entry) + * + * An example of how to use this function: + * {@example alter_block_array.php} + * + * @param string $blockname the blockname, for example 'loop' + * @param array $vararray the var array to insert/add or merge + * @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 change or insert at directly given] + * + * If key is false the position is set to 0 + * If key is true the position is set to the last entry + * + * @param string $mode Mode to execute (valid modes are 'insert' and 'change') + * + * If insert, the vararray is inserted at the given position (position counting from zero). + * If change, the current block gets merged with the vararray (resulting in new key/value pairs be added and existing keys be replaced by the new value). + * + * Since counting begins by zero, inserting at the last position will result in this array: array(vararray, last positioned array) + * and inserting at position 1 will result in this array: array(first positioned array, vararray, following vars) + * + * @return bool false on error, true on success + */ + public function alter_block_array($blockname, array $vararray, $key = false, $mode = 'insert') + { + if (strpos($blockname, '.') !== false) + { + // Nested block. + $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 + } + else + { + // Top-level block. + $block = &$this->tpldata[$blockname]; + } + + // Change key to zero (change first position) if false and to last position if true + if ($key === false || $key === true) + { + $key = ($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); + + $key = NULL; + foreach ($block as $i => $val_ary) + { + if ($val_ary[$search_key] === $search_value) + { + $key = $i; + break; + } + } + + // key/value pair not found + if ($key === NULL) + { + return false; + } + } + + // Insert Block + if ($mode == 'insert') + { + // Make sure we are not exceeding the last iteration + if ($key >= sizeof($this->tpldata[$blockname])) + { + $key = sizeof($this->tpldata[$blockname]); + unset($this->tpldata[$blockname][($key - 1)]['S_LAST_ROW']); + $vararray['S_LAST_ROW'] = true; + } + else if ($key === 0) + { + unset($this->tpldata[$blockname][0]['S_FIRST_ROW']); + $vararray['S_FIRST_ROW'] = true; + } + + // Assign S_BLOCK_NAME + $vararray['S_BLOCK_NAME'] = $blockname; + + // Re-position template blocks + for ($i = sizeof($block); $i > $key; $i--) + { + $block[$i] = $block[$i-1]; + + $block[$i]['S_ROW_COUNT'] = $block[$i]['S_ROW_NUM'] = $i; + } + + // Insert vararray at given position + $block[$key] = $vararray; + $block[$key]['S_ROW_COUNT'] = $block[$key]['S_ROW_NUM'] = $key; + + // Set S_NUM_ROWS + foreach ($this->tpldata[$blockname] as &$mod_block) + { + $mod_block['S_NUM_ROWS'] = sizeof($this->tpldata[$blockname]); + } + + return true; + } + + // Which block to change? + if ($mode == 'change') + { + if ($key == sizeof($block)) + { + $key--; + } + + $block[$key] = array_merge($block[$key], $vararray); + + return true; + } + + return false; + } + + /** + * Reset/empty complete block + * + * @param string $blockname Name of block to destroy + */ + public function destroy_block_vars($blockname) + { + if (strpos($blockname, '.') !== false) + { + // Nested block. + $blocks = explode('.', $blockname); + $blockcount = sizeof($blocks) - 1; + + $str = &$this->tpldata; + for ($i = 0; $i < $blockcount; $i++) + { + $str = &$str[$blocks[$i]]; + $str = &$str[sizeof($str) - 1]; + } + + unset($str[$blocks[$blockcount]]); + } + else + { + // Top-level block. + unset($this->tpldata[$blockname]); + } + + return true; + } +} -- cgit v1.2.1 From b95fdacdd378877d277e261465da73deb06e50da Mon Sep 17 00:00:00 2001 From: Nils Adermann Date: Tue, 10 Sep 2013 14:01:09 +0200 Subject: [ticket/11700] Move all recent code to namespaces PHPBB3-11700 --- phpBB/phpbb/template/context.php | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) (limited to 'phpBB/phpbb/template/context.php') diff --git a/phpBB/phpbb/template/context.php b/phpBB/phpbb/template/context.php index c5ce7422b9..263f77a1b8 100644 --- a/phpBB/phpbb/template/context.php +++ b/phpBB/phpbb/template/context.php @@ -7,6 +7,8 @@ * */ +namespace phpbb\template; + /** * @ignore */ @@ -20,7 +22,7 @@ if (!defined('IN_PHPBB')) * * @package phpBB3 */ -class phpbb_template_context +class context { /** * variable that holds all the data we'll be substituting into @@ -86,7 +88,7 @@ class phpbb_template_context * Returns a reference to template data array. * * This function is public so that template renderer may invoke it. - * Users should alter template variables via functions in phpbb_template. + * Users should alter template variables via functions in \phpbb\template\template. * * Note: modifying returned array will affect data stored in the context. * @@ -158,7 +160,7 @@ class phpbb_template_context } // Now we add the block that we're actually assigning to. - // We're adding a new iteration to this block with the given + // We're adding a new \iteration to this block with the given // variable assignments. $str[$blocks[$blockcount]][] = $vararray; @@ -190,7 +192,7 @@ class phpbb_template_context unset($this->tpldata[$blockname][($s_row_count - 1)]['S_LAST_ROW']); } - // Add a new iteration to this block with the variable assignments we were given. + // Add a new \iteration to this block with the variable assignments we were given. $this->tpldata[$blockname][] = $vararray; // Set S_NUM_ROWS @@ -223,7 +225,7 @@ class phpbb_template_context * @param string $mode Mode to execute (valid modes are 'insert' and 'change') * * If insert, the vararray is inserted at the given position (position counting from zero). - * If change, the current block gets merged with the vararray (resulting in new key/value pairs be added and existing keys be replaced by the new value). + * If change, the current block gets merged with the vararray (resulting in new \key/value pairs be added and existing keys be replaced by the new \value). * * Since counting begins by zero, inserting at the last position will result in this array: array(vararray, last positioned array) * and inserting at position 1 will result in this array: array(first positioned array, vararray, following vars) -- cgit v1.2.1 From 390dc86344c23b658085bae4a719399e5eb579f0 Mon Sep 17 00:00:00 2001 From: Nils Adermann Date: Mon, 16 Sep 2013 05:00:18 +0200 Subject: [ticket/11700] And some last comments with backslashes PHPBB3-11700 --- phpBB/phpbb/template/context.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'phpBB/phpbb/template/context.php') diff --git a/phpBB/phpbb/template/context.php b/phpBB/phpbb/template/context.php index 263f77a1b8..f978f82d33 100644 --- a/phpBB/phpbb/template/context.php +++ b/phpBB/phpbb/template/context.php @@ -160,7 +160,7 @@ class context } // Now we add the block that we're actually assigning to. - // We're adding a new \iteration to this block with the given + // We're adding a new iteration to this block with the given // variable assignments. $str[$blocks[$blockcount]][] = $vararray; @@ -192,7 +192,7 @@ class context unset($this->tpldata[$blockname][($s_row_count - 1)]['S_LAST_ROW']); } - // Add a new \iteration to this block with the variable assignments we were given. + // Add a new iteration to this block with the variable assignments we were given. $this->tpldata[$blockname][] = $vararray; // Set S_NUM_ROWS -- cgit v1.2.1 From 06e7c842357fd26104efba6b7a0465d7c05c4493 Mon Sep 17 00:00:00 2001 From: Nils Adermann Date: Thu, 19 Sep 2013 15:27:03 +0200 Subject: [ticket/11700] Fix some more incorrectly changed comments PHPBB3-11700 --- phpBB/phpbb/template/context.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'phpBB/phpbb/template/context.php') diff --git a/phpBB/phpbb/template/context.php b/phpBB/phpbb/template/context.php index f978f82d33..24234c1e4a 100644 --- a/phpBB/phpbb/template/context.php +++ b/phpBB/phpbb/template/context.php @@ -225,7 +225,7 @@ class context * @param string $mode Mode to execute (valid modes are 'insert' and 'change') * * If insert, the vararray is inserted at the given position (position counting from zero). - * If change, the current block gets merged with the vararray (resulting in new \key/value pairs be added and existing keys be replaced by the new \value). + * If change, the current block gets merged with the vararray (resulting in new key/value pairs be added and existing keys be replaced by the new \value). * * Since counting begins by zero, inserting at the last position will result in this array: array(vararray, last positioned array) * and inserting at position 1 will result in this array: array(first positioned array, vararray, following vars) -- cgit v1.2.1 From 7f58a4572eaca75aecff2da889e67ea151616011 Mon Sep 17 00:00:00 2001 From: Marc Alexander Date: Mon, 28 Oct 2013 22:27:25 +0100 Subject: [ticket/11981] Fix code sniffer complaints PHPBB3-11981 --- phpBB/phpbb/template/context.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'phpBB/phpbb/template/context.php') diff --git a/phpBB/phpbb/template/context.php b/phpBB/phpbb/template/context.php index 24234c1e4a..decd1c7956 100644 --- a/phpBB/phpbb/template/context.php +++ b/phpBB/phpbb/template/context.php @@ -285,7 +285,7 @@ class context // Search array to get correct position list($search_key, $search_value) = @each($key); - $key = NULL; + $key = null; foreach ($block as $i => $val_ary) { if ($val_ary[$search_key] === $search_value) @@ -296,7 +296,7 @@ class context } // key/value pair not found - if ($key === NULL) + if ($key === null) { return false; } -- cgit v1.2.1 From 7aa8f6461f1e85cf91931f56b95384e54fec07c2 Mon Sep 17 00:00:00 2001 From: Andreas Fischer Date: Wed, 30 Oct 2013 13:05:28 +0100 Subject: [task/code-sniffer] Remove the IN_PHPBB check side-effect from class files. PHPBB3-11980 --- phpBB/phpbb/template/context.php | 8 -------- 1 file changed, 8 deletions(-) (limited to 'phpBB/phpbb/template/context.php') diff --git a/phpBB/phpbb/template/context.php b/phpBB/phpbb/template/context.php index decd1c7956..65c7d094a0 100644 --- a/phpBB/phpbb/template/context.php +++ b/phpBB/phpbb/template/context.php @@ -9,14 +9,6 @@ namespace phpbb\template; -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} - /** * Stores variables assigned to template. * -- cgit v1.2.1 From dda775c418593c254c463740636dd7fb4d352945 Mon Sep 17 00:00:00 2001 From: rxu Date: Sun, 23 Feb 2014 22:04:35 +0800 Subject: [ticket/12224] Add template wrapper method to assign block arrays Add one more wrapper template method for the function assign_block_vars() which takes a 2-dimensional array as a parameter and calls assign_block_vars() in a loop to assign the whole block loop at once. This can make the core a little bit more expendable from the point of developing extensions as it allows to pass the data to events before it's being assigned to template. PHPBB3-12224 --- phpBB/phpbb/template/context.php | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) (limited to 'phpBB/phpbb/template/context.php') diff --git a/phpBB/phpbb/template/context.php b/phpBB/phpbb/template/context.php index 65c7d094a0..af186c2215 100644 --- a/phpBB/phpbb/template/context.php +++ b/phpBB/phpbb/template/context.php @@ -197,6 +197,22 @@ class context return true; } + /** + * Assign key variable pairs from an array to a whole specified block loop + * + * @param string $blockname Name of block to assign $block_vars_array to + * @param array $block_vars_array An array of hashes of variable name => value pairs + */ + public function assign_block_vars_array($blockname, array $block_vars_array) + { + foreach ($block_vars_array as $vararray) + { + $this->assign_block_vars($blockname, $vararray); + } + + return true; + } + /** * Change already assigned key variable pair (one-dimensional - single loop entry) * -- cgit v1.2.1 From 5c3fc4840c6c5729b7144b8f268990684f151b12 Mon Sep 17 00:00:00 2001 From: Cesar G Date: Thu, 27 Feb 2014 19:29:02 -0800 Subject: [ticket/12232] Remove excessive calls to sizeof() in assign_block_vars() method The size of the template block array is calculated within a foreach loop iterating through the array, which is unnecessary. It only needs to be done once. In a block of 1000 rows, this results in 500,500 calls to sizeof() in this location. With this change, that's reduced to 1000. PHPBB3-12232 --- phpBB/phpbb/template/context.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'phpBB/phpbb/template/context.php') diff --git a/phpBB/phpbb/template/context.php b/phpBB/phpbb/template/context.php index 65c7d094a0..ef01034c52 100644 --- a/phpBB/phpbb/template/context.php +++ b/phpBB/phpbb/template/context.php @@ -186,11 +186,12 @@ class context // Add a new iteration to this block with the variable assignments we were given. $this->tpldata[$blockname][] = $vararray; + $s_num_rows = sizeof($this->tpldata[$blockname]); // Set S_NUM_ROWS foreach ($this->tpldata[$blockname] as &$mod_block) { - $mod_block['S_NUM_ROWS'] = sizeof($this->tpldata[$blockname]); + $mod_block['S_NUM_ROWS'] = $s_num_rows; } } -- cgit v1.2.1 From 99db2d91996c9beb40ff9b635c69497941a69ffb Mon Sep 17 00:00:00 2001 From: Cesar G Date: Thu, 27 Feb 2014 22:27:09 -0800 Subject: [ticket/12232] Fix a similar excessive pattern in the method. PHPBB3-12232 --- phpBB/phpbb/template/context.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'phpBB/phpbb/template/context.php') diff --git a/phpBB/phpbb/template/context.php b/phpBB/phpbb/template/context.php index ef01034c52..0b929f4934 100644 --- a/phpBB/phpbb/template/context.php +++ b/phpBB/phpbb/template/context.php @@ -155,11 +155,12 @@ class context // We're adding a new iteration to this block with the given // variable assignments. $str[$blocks[$blockcount]][] = $vararray; + $s_num_rows = sizeof($str[$blocks[$blockcount]]); // Set S_NUM_ROWS foreach ($str[$blocks[$blockcount]] as &$mod_block) { - $mod_block['S_NUM_ROWS'] = sizeof($str[$blocks[$blockcount]]); + $mod_block['S_NUM_ROWS'] = $s_num_rows; } } else -- cgit v1.2.1 From a759704b39fc1c1353f865a633759b1369589b67 Mon Sep 17 00:00:00 2001 From: Yuriy Rusko Date: Tue, 27 May 2014 20:18:06 +0200 Subject: [ticket/12594] Remove @package tags and update file headers PHPBB3-12594 --- phpBB/phpbb/template/context.php | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) (limited to 'phpBB/phpbb/template/context.php') diff --git a/phpBB/phpbb/template/context.php b/phpBB/phpbb/template/context.php index a222fbb69e..8df6c8b492 100644 --- a/phpBB/phpbb/template/context.php +++ b/phpBB/phpbb/template/context.php @@ -1,9 +1,13 @@ +* @license GNU General Public License, version 2 (GPL-2.0) +* +* For full copyright and license information, please see +* the docs/CREDITS.txt file. * */ @@ -11,8 +15,6 @@ namespace phpbb\template; /** * Stores variables assigned to template. -* -* @package phpBB3 */ class context { -- cgit v1.2.1 From 0d0113e6da590c113068a60864d44372a2fbccab Mon Sep 17 00:00:00 2001 From: Tristan Darricau Date: Sun, 15 Jun 2014 15:05:51 +0200 Subject: [ticket/12715] Cleanup comments in \phpbb\template\* PHPBB3-12715 --- phpBB/phpbb/template/context.php | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'phpBB/phpbb/template/context.php') diff --git a/phpBB/phpbb/template/context.php b/phpBB/phpbb/template/context.php index 8df6c8b492..0a32879943 100644 --- a/phpBB/phpbb/template/context.php +++ b/phpBB/phpbb/template/context.php @@ -55,6 +55,7 @@ class context * * @param string $varname Variable name * @param string $varval Value to assign to variable + * @return true */ public function assign_var($varname, $varval) { @@ -70,6 +71,7 @@ class context * * @param string $varname Variable name * @param string $varval Value to append to variable + * @return true */ public function append_var($varname, $varval) { @@ -117,6 +119,7 @@ class context * * @param string $blockname Name of block to assign $vararray to * @param array $vararray A hash of variable name => value pairs + * @return true */ public function assign_block_vars($blockname, array $vararray) { @@ -206,6 +209,7 @@ class context * * @param string $blockname Name of block to assign $block_vars_array to * @param array $block_vars_array An array of hashes of variable name => value pairs + * @return true */ public function assign_block_vars_array($blockname, array $block_vars_array) { @@ -374,6 +378,7 @@ class context * Reset/empty complete block * * @param string $blockname Name of block to destroy + * @return true */ public function destroy_block_vars($blockname) { -- cgit v1.2.1 From 831e9116ab46cd608065f4f664544c449ee95192 Mon Sep 17 00:00:00 2001 From: Joas Schilling Date: Fri, 25 Jul 2014 17:45:35 +0200 Subject: [ticket/12892] Do not set S_NUM_ROWS when adding a row to a template loop We do not set S_NUM_ROWS while adding a row, to reduce the complexity If we would set it on adding, each subsequent adding would cause n modifications, resulting in a O(n!) complexity, rather then O(n) PHPBB3-12892 --- phpBB/phpbb/template/context.php | 78 +++++++++++++++++++++++++++++----------- 1 file changed, 58 insertions(+), 20 deletions(-) (limited to 'phpBB/phpbb/template/context.php') diff --git a/phpBB/phpbb/template/context.php b/phpBB/phpbb/template/context.php index 0a32879943..4ee48205c8 100644 --- a/phpBB/phpbb/template/context.php +++ b/phpBB/phpbb/template/context.php @@ -34,6 +34,11 @@ class context */ private $rootref; + /** + * @var bool + */ + private $num_rows_is_set; + public function __construct() { $this->clear(); @@ -46,6 +51,7 @@ class context { $this->tpldata = array('.' => array(0 => array())); $this->rootref = &$this->tpldata['.'][0]; + $this->num_rows_is_set = false; } /** @@ -95,9 +101,58 @@ class context // returning a reference directly is not // something php is capable of doing $ref = &$this->tpldata; + + if (!$this->num_rows_is_set) + { + /* + * We do not set S_NUM_ROWS while adding a row, to reduce the complexity + * If we would set it on adding, each subsequent adding would cause + * n modifications, resulting in a O(n!) complexity, rather then O(n) + */ + foreach ($ref as $loop_name => &$loop_data) + { + if ($loop_name === '.') + { + continue; + } + + $this->set_num_rows($loop_data); + } + $this->num_rows_is_set = true; + } + return $ref; } + /** + * Set S_NUM_ROWS for each row in this template block + * + * @param array $loop_data + */ + protected function set_num_rows(&$loop_data) + { + $s_num_rows = sizeof($loop_data); + foreach ($loop_data as &$mod_block) + { + foreach ($mod_block as $sub_block_name => &$sub_block) + { + // If the key name is lowercase and the data is an array, + // it could be a template loop. So we set the S_NUM_ROWS there + // aswell. + if ($sub_block_name === strtolower($sub_block_name) && is_array($sub_block)) + { + $this->set_num_rows($sub_block); + } + } + + // Check whether we are inside a block before setting the variable + if (isset($mod_block['S_BLOCK_NAME'])) + { + $mod_block['S_NUM_ROWS'] = $s_num_rows; + } + } + } + /** * Returns a reference to template root scope. * @@ -123,6 +178,7 @@ class context */ public function assign_block_vars($blockname, array $vararray) { + $this->num_rows_is_set = false; if (strpos($blockname, '.') !== false) { // Nested block. @@ -160,13 +216,6 @@ class context // We're adding a new iteration to this block with the given // variable assignments. $str[$blocks[$blockcount]][] = $vararray; - $s_num_rows = sizeof($str[$blocks[$blockcount]]); - - // Set S_NUM_ROWS - foreach ($str[$blocks[$blockcount]] as &$mod_block) - { - $mod_block['S_NUM_ROWS'] = $s_num_rows; - } } else { @@ -192,13 +241,6 @@ class context // Add a new iteration to this block with the variable assignments we were given. $this->tpldata[$blockname][] = $vararray; - $s_num_rows = sizeof($this->tpldata[$blockname]); - - // Set S_NUM_ROWS - foreach ($this->tpldata[$blockname] as &$mod_block) - { - $mod_block['S_NUM_ROWS'] = $s_num_rows; - } } return true; @@ -250,6 +292,7 @@ class context */ public function alter_block_array($blockname, array $vararray, $key = false, $mode = 'insert') { + $this->num_rows_is_set = false; if (strpos($blockname, '.') !== false) { // Nested block. @@ -349,12 +392,6 @@ class context $block[$key] = $vararray; $block[$key]['S_ROW_COUNT'] = $block[$key]['S_ROW_NUM'] = $key; - // Set S_NUM_ROWS - foreach ($this->tpldata[$blockname] as &$mod_block) - { - $mod_block['S_NUM_ROWS'] = sizeof($this->tpldata[$blockname]); - } - return true; } @@ -382,6 +419,7 @@ class context */ public function destroy_block_vars($blockname) { + $this->num_rows_is_set = false; if (strpos($blockname, '.') !== false) { // Nested block. -- cgit v1.2.1 From d9991bdaf1aa9685437c4f4c298fa54f0c0f33f0 Mon Sep 17 00:00:00 2001 From: javiexin Date: Wed, 28 Dec 2016 12:37:53 +0100 Subject: [ticket/14943] Fix template loop access by index Allows inserting elements in a loop specified as 'outer[3].inner'. This was coded, but malfunctioning. PHPBB3-14943 --- phpBB/phpbb/template/context.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'phpBB/phpbb/template/context.php') diff --git a/phpBB/phpbb/template/context.php b/phpBB/phpbb/template/context.php index 4ee48205c8..8bf6c10e2d 100644 --- a/phpBB/phpbb/template/context.php +++ b/phpBB/phpbb/template/context.php @@ -365,15 +365,15 @@ class context if ($mode == 'insert') { // Make sure we are not exceeding the last iteration - if ($key >= sizeof($this->tpldata[$blockname])) + if ($key >= sizeof($block)) { - $key = sizeof($this->tpldata[$blockname]); - unset($this->tpldata[$blockname][($key - 1)]['S_LAST_ROW']); + $key = sizeof($block); + unset($block[($key - 1)]['S_LAST_ROW']); $vararray['S_LAST_ROW'] = true; } else if ($key === 0) { - unset($this->tpldata[$blockname][0]['S_FIRST_ROW']); + unset($block[0]['S_FIRST_ROW']); $vararray['S_FIRST_ROW'] = true; } -- cgit v1.2.1 From cff57f9076dd160b2185895f7298d4acbc5b5bb3 Mon Sep 17 00:00:00 2001 From: javiexin Date: Wed, 28 Dec 2016 12:55:26 +0100 Subject: [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/context.php | 71 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 71 insertions(+) (limited to 'phpBB/phpbb/template/context.php') 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) * -- cgit v1.2.1 From c656bd60ef99218a710882b6f640fea099e9c6e2 Mon Sep 17 00:00:00 2001 From: javiexin Date: Fri, 30 Dec 2016 18:03:09 +0100 Subject: [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. Remove unneeded references, do nothing for int keys. PHPBB3-14944 --- phpBB/phpbb/template/context.php | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'phpBB/phpbb/template/context.php') diff --git a/phpBB/phpbb/template/context.php b/phpBB/phpbb/template/context.php index e390c5a677..1617ca3d19 100644 --- a/phpBB/phpbb/template/context.php +++ b/phpBB/phpbb/template/context.php @@ -284,7 +284,7 @@ class context $blocks = explode('.', $blockname); $blockcount = sizeof($blocks) - 1; - $block = &$this->tpldata; + $block = $this->tpldata; for ($i = 0; $i < $blockcount; $i++) { if (($pos = strpos($blocks[$i], '[')) !== false) @@ -305,11 +305,11 @@ class context $name = $blocks[$i]; $index = sizeof($block[$name]) - 1; } - $block = &$block[$name]; - $block = &$block[$index]; + $block = $block[$name]; + $block = $block[$index]; } - $block = &$block[$blocks[$i]]; // Traverse the last block + $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) @@ -331,7 +331,7 @@ class context } } - return false; + return is_int($key) ? $key : false; } /** -- cgit v1.2.1 From 45ea013b111547ef684cc7c64dd91a6217935ab1 Mon Sep 17 00:00:00 2001 From: javiexin Date: Sun, 1 Jan 2017 21:22:29 +0100 Subject: [ticket/14943] Fix template loop access by index Allows inserting elements in a loop specified as 'outer[3].inner'. This was coded, but malfunctioning. Name incorrectly set on insert. PHPBB3-14943 --- phpBB/phpbb/template/context.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'phpBB/phpbb/template/context.php') diff --git a/phpBB/phpbb/template/context.php b/phpBB/phpbb/template/context.php index 8bf6c10e2d..f0bc4c859a 100644 --- a/phpBB/phpbb/template/context.php +++ b/phpBB/phpbb/template/context.php @@ -325,11 +325,13 @@ class context } $block = &$block[$blocks[$i]]; // Traverse the last block + $name = $blocks[$i]; } else { // Top-level block. $block = &$this->tpldata[$blockname]; + $name = $blockname; } // Change key to zero (change first position) if false and to last position if true @@ -378,7 +380,7 @@ class context } // Assign S_BLOCK_NAME - $vararray['S_BLOCK_NAME'] = $blockname; + $vararray['S_BLOCK_NAME'] = $name; // Re-position template blocks for ($i = sizeof($block); $i > $key; $i--) -- cgit v1.2.1 From 20c03cccdde2302412d1e14adda370e7eb57b8e8 Mon Sep 17 00:00:00 2001 From: javiexin Date: Sun, 8 Jan 2017 00:00:47 +0100 Subject: [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. Remove unneeded references, do nothing for int keys. Check out of bounds or wrong blockname errors. Added tests. PHPBB3-14944 --- phpBB/phpbb/template/context.php | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) (limited to 'phpBB/phpbb/template/context.php') diff --git a/phpBB/phpbb/template/context.php b/phpBB/phpbb/template/context.php index 1617ca3d19..8bfbd73f1a 100644 --- a/phpBB/phpbb/template/context.php +++ b/phpBB/phpbb/template/context.php @@ -305,16 +305,28 @@ class context $name = $blocks[$i]; $index = sizeof($block[$name]) - 1; } + if (!isset($block[$name])) + { + return false; + } $block = $block[$name]; + if (!isset($block[$index])) + { + return false; + } $block = $block[$index]; } + if (!isset($block[$blocks[$i]])) + { + return false; + } $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); + return ($key === false) ? 0 : sizeof($block) - 1; } // Get correct position if array given @@ -331,7 +343,7 @@ class context } } - return is_int($key) ? $key : false; + return (is_int($key) && ((0 <= $key) && ($key < sizeof($block)))) ? $key : false; } /** -- cgit v1.2.1 From d2ad751851c955c19d1688cbe511925489212121 Mon Sep 17 00:00:00 2001 From: javiexin Date: Thu, 12 Jan 2017 21:25:39 +0100 Subject: [ticket/14943] Fix template loop access by index Allows inserting elements in a loop specified as 'outer[3].inner'. This was coded, but malfunctioning. Name incorrectly set on insert. If block was empty, the insertion process should create it. Checking for out of bounds indexes. PHPBB3-14943 --- phpBB/phpbb/template/context.php | 69 +++++++++++++++++++++++----------------- 1 file changed, 39 insertions(+), 30 deletions(-) (limited to 'phpBB/phpbb/template/context.php') diff --git a/phpBB/phpbb/template/context.php b/phpBB/phpbb/template/context.php index f0bc4c859a..4235a8543e 100644 --- a/phpBB/phpbb/template/context.php +++ b/phpBB/phpbb/template/context.php @@ -293,47 +293,49 @@ class context public function alter_block_array($blockname, array $vararray, $key = false, $mode = 'insert') { $this->num_rows_is_set = false; - if (strpos($blockname, '.') !== false) - { - // Nested block. - $blocks = explode('.', $blockname); - $blockcount = sizeof($blocks) - 1; - $block = &$this->tpldata; - for ($i = 0; $i < $blockcount; $i++) + // 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) { - if (($pos = strpos($blocks[$i], '[')) !== false) + $name = substr($blocks[$i], 0, $pos); + + if (strpos($blocks[$i], '[]') === $pos) { - $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); - } + $index = sizeof($block[$name]) - 1; } else { - $name = $blocks[$i]; - $index = sizeof($block[$name]) - 1; + $index = min((int) substr($blocks[$i], $pos + 1, -1), sizeof($block[$name]) - 1); } - $block = &$block[$name]; - $block = &$block[$index]; } - - $block = &$block[$blocks[$i]]; // Traverse the last block - $name = $blocks[$i]; + else + { + $name = $blocks[$i]; + $index = sizeof($block[$name]) - 1; + } + $block = &$block[$name]; + $block = &$block[$index]; } - else + $name = $blocks[$i]; + + // If last block does not exist and we are inserting, and not searching for key, we create it empty; otherwise, nothing to do + if (!isset($block[$name])) { - // Top-level block. - $block = &$this->tpldata[$blockname]; - $name = $blockname; + if ($mode != 'insert' || is_array($key)) + { + return false; + } + $block[$name] = array(); } + $block = &$block[$name]; // Now we can traverse the last block + // Change key to zero (change first position) if false and to last position if true if ($key === false || $key === true) { @@ -373,8 +375,9 @@ class context unset($block[($key - 1)]['S_LAST_ROW']); $vararray['S_LAST_ROW'] = true; } - else if ($key === 0) + if ($key <= 0) { + $key = 0; unset($block[0]['S_FIRST_ROW']); $vararray['S_FIRST_ROW'] = true; } @@ -400,6 +403,12 @@ class context // Which block to change? if ($mode == 'change') { + // If key is out of bounds, do not change anything + if ($key > sizeof($block) || $key < 0) + { + return false; + } + if ($key == sizeof($block)) { $key--; -- cgit v1.2.1 From 849fd9df7d9b2e449801e14ef54584fc8e063d43 Mon Sep 17 00:00:00 2001 From: javiexin Date: Sat, 28 Jan 2017 21:34:08 +0100 Subject: [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. Remove unneeded references, do nothing for int keys. Check out of bounds or wrong blockname errors. Added tests. Remove default parameter value. PHPBB3-14944 --- phpBB/phpbb/template/context.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'phpBB/phpbb/template/context.php') diff --git a/phpBB/phpbb/template/context.php b/phpBB/phpbb/template/context.php index 8bfbd73f1a..e70d0574be 100644 --- a/phpBB/phpbb/template/context.php +++ b/phpBB/phpbb/template/context.php @@ -278,7 +278,7 @@ class context * * @return mixed false if not found, index position otherwise; be sure to test with === */ - public function find_key_index($blockname, $key = false) + public function find_key_index($blockname, $key) { // For nested block, $blockcount > 0, for top-level block, $blockcount == 0 $blocks = explode('.', $blockname); -- cgit v1.2.1