Modified template functions

This forum is now closed as part of retiring phpBB2.
Forum rules
READ: phpBB.com Board-Wide Rules and Regulations

This forum is now closed due to phpBB2.0 being retired.
Post Reply
Xore
Former Team Member
Posts: 2594
Joined: Wed Apr 16, 2003 7:42 pm
Location: the wastelands between insomnia and clairvoyance
Contact:

Modified template functions

Post by Xore »

after searching thru template.php and finding that the answer to my problem did not exist ( *sniffle* ) i set out to fix it.

It was surprisingly easy... only took me about a half hour, all told...

So, what is this? basically, i find it somewhat of a pain that block vars must be all assigned simultaneously. so, i added to the assign_block_vars an increment supresser so that if this flag is set, it will add the changes to the last block, rather than creating a new one

the other change was to the assign_var_from handle ... which is incapable of assigning values to block variables. so i changed that also (along with the supress_increment thingy.

i'm not so very knowledgeable in the way the assign_var_from_handle works... it might inherently be incapable of working from inside a loop, but i haven't had the opportunity to test.

i would like people's opinons on this, if possible, and the consequences thereof (note: this code is untested, it should work tho, it's 2:30 am right now tho and i'm not up for some pressure testing atm)

Code: Select all

	/**
	 * Inserts the uncompiled code for $handle as the
	 * value of $varname in the root-level. This can be used
	 * to effectively include a template in the middle of another
	 * template.
	 * Note that all desired assignments to the variables in $handle should be done
	 * BEFORE calling this function.
	 */
	function assign_var_from_handle($varname, $handle,$supress_block_increment = false)
	{
		if (!$this->loadfile($handle))
		{
			die("Template->assign_var_from_handle(): Couldn't load template file for handle $handle");
		}

		// Compile it, with the "no echo statements" option on.
		$_str = "";
		$code = $this->compile($this->uncompiled_code[$handle], true, '_str');

		// evaluate the variable assignment.
		eval($code);
		// assign the value of the generated variable to the given varname.
		if (strstr($varname, '.'))
		{
			$lastposition = strrpos($varname,'.');
			$blockname = substr($varname,0,$lastposition);
			$varname = substr($varname,$lastposition+1);
			$this->assign_block_vars($blockname,array($varname => $_str),$supress_block_increment);
		}
		else
		{
			$this->assign_var($varname, $_str);
		}

		return true;
	}
/*
//
// Old function:
//
	function assign_var_from_handle($varname, $handle)
	{
		if (!$this->loadfile($handle))
		{
			die("Template->assign_var_from_handle(): Couldn't load template file for handle $handle");
		}

		// Compile it, with the "no echo statements" option on.
		$_str = "";
		$code = $this->compile($this->uncompiled_code[$handle], true, '_str');

		// evaluate the variable assignment.
		eval($code);
		// assign the value of the generated variable to the given varname.
		$this->assign_var($varname, $_str);

		return true;
	}
*/

Code: Select all

	/**
	 * Block-level variable assignment. Adds a new block iteration with the given
	 * variable assignments. Note that this should only be called once per block
	 * iteration.
	 */
	function assign_block_vars($blockname, $vararray, $surpress_increment = false)
	{
		if ( !$surpress_increment )
		{
			if (strstr($blockname, '.'))
			{
				// Nested block.
				$blocks = explode('.', $blockname);
				$blockcount = sizeof($blocks) - 1;
				$str = '$this->_tpldata';
				for ($i = 0; $i < $blockcount; $i++)
				{
					$str .= '[\'' . $blocks[$i] . '.\']';
					eval('$lastiteration = sizeof(' . $str . ') - 1;');
					$str .= '[' . $lastiteration . ']';
				}
				// 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;';

				// Now we evaluate this assignment we've built up.
				eval($str);
			}
			else
			{
				// Top-level block.
				// Add a new iteration to this block with the variable assignments
				// we were given.
				$this->_tpldata[$blockname . '.'][] = $vararray;
			}
		}
		else
		{
			if (strstr($blockname, '.'))
			{
				// Nested block.
				$blocks = explode('.', $blockname);
				$blockcount = sizeof($blocks);
				$str = '$this->_tpldata';
				for ($i = 0; $i < $blockcount; $i++)
				{
					$str .= '[\'' . $blocks[$i] . '.\']';
					eval('$lastiteration = sizeof(' . $str . ') - 1;');
					$str .= '[' . $lastiteration . ']';
				}
				// Now we add the block that we're actually assigning to.
				reset ($vararray);
				while (list($key,$val) = each($vararray))
				{
					$current_string = $str . '[$key] = $val';
					// Now we evaluate this assignment we've built up.
					eval($current_string);
				}
			}
			else
			{
				// Top-level block.
				// Add a new iteration to this block with the variable assignments
				// we were given.
				$lastiteration = sizeof($this->_tpldata[$blockname . '.']) - 1;
				reset ($vararray);
				while (list($key,$val) = each($vararray))
				{
					$this->_tpldata[$blockname . '.'][$lastiteration][$key] = $val;
				}
			}
		}

		return true;
	}
/*
//
// Old function:
//
	function assign_block_vars($blockname, $vararray)
	{
		if (strstr($blockname, '.'))
		{
			// Nested block.
			$blocks = explode('.', $blockname);
			$blockcount = sizeof($blocks) - 1;
			$str = '$this->_tpldata';
			for ($i = 0; $i < $blockcount; $i++)
			{
				$str .= '[\'' . $blocks[$i] . '.\']';
				eval('$lastiteration = sizeof(' . $str . ') - 1;');
				$str .= '[' . $lastiteration . ']';
			}
			// 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;';

			// Now we evaluate this assignment we've built up.
			eval($str);
		}
		else
		{
			// Top-level block.
			// Add a new iteration to this block with the variable assignments
			// we were given.
			$this->_tpldata[$blockname . '.'][] = $vararray;
		}

		return true;
	}
*/
Edit: added some reset()s
Camels in the Mist
<noise type="random" source="camel" />
Cash Mod
Xore
Former Team Member
Posts: 2594
Joined: Wed Apr 16, 2003 7:42 pm
Location: the wastelands between insomnia and clairvoyance
Contact:

Post by Xore »

Ok, well i did some testing...

this 3rd function is necessary for clearing data when you (while in loop) re-include the same file, as it otherwise will continue accumulating data in rows, such that each pass will include both that loop's data, as well as the last loops data. this is a problem, so here is the fix...

Code: Select all

	/**
	 * Block-level variable clearing. Removes a block of data so it can be re-written
	 * fresh (for iterative file handled arrays, when different data is needed)
	 */
	function clear_block_vars($blockname)
	{
		if (strstr($blockname, '.'))
		{
			// i don't know how the heck this would be used, if ever.
			// i can't think of a situation where it would be useful personally
			// but, who knows... Only the top-level block makes sense to me
			// Nested block.
			$blocks = explode('.', $blockname);
			$blockcount = sizeof($blocks) - 1;
			$str = '$this->_tpldata';
			for ($i = 0; $i < $blockcount; $i++)
			{
				$str .= '[\'' . $blocks[$i] . '.\']';
				eval('$lastiteration = sizeof(' . $str . ') - 1;');
				$str .= '[' . $lastiteration . ']';
			}
			// 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] . '.\'] = array();';

			// Now we evaluate this assignment we've built up.
			eval($str);
		}
		else
		{
			// Top-level block.
			// Add a new iteration to this block with the variable assignments
			// we were given.
			$this->_tpldata[$blockname . '.'] = array();
		}

		return true;
	}
[/code]
Camels in the Mist
<noise type="random" source="camel" />
Cash Mod
Xore
Former Team Member
Posts: 2594
Joined: Wed Apr 16, 2003 7:42 pm
Location: the wastelands between insomnia and clairvoyance
Contact:

Post by Xore »

If a developer sees this.. is it possible that such functionality could be included in phpbb2.2 ? I looked through the most recent snapshot and it didn't have assign_var_from_handle() ... i haven't looked at 2.2 templates yet, so i don't know if this could be an issue or not, or if a similar functionality is now going by a different name.

cheers :-)
Camels in the Mist
<noise type="random" source="camel" />
Cash Mod
User avatar
Arty
Former Team Member
Posts: 16654
Joined: Wed Mar 06, 2002 2:36 pm
Name: Vjacheslav Trushkin
Contact:

Post by Arty »

Hi,

As you told in thread for eXtreme Styles mod this code has conflicts with my mod. So here is modified code that works with ALL versions of template.php and it is much faster than your code:

function assign_var_from_handle:

Code: Select all

	function assign_var_from_handle($varname, $handle, $surpress_block_increment = false)
	{
		ob_start();
		$res = $this->pparse($handle);
		if ($pos = strpos($varname, '.') !== false) 
		{
			$blockname = substr($varname, 0, $pos); 
			$varname = substr($varname, $pos + 1); 
			$this->assign_block_vars($blockname, array($varname => ob_get_contents()), $surpress_block_increment);
		}
		else
		{
			$this->_tpldata['.'][0][$varname] = ob_get_contents();
		}
		ob_end_clean();
		return $res;
	}
here is modified assign_block_vars:

Code: Select all

	function assign_block_vars($blockname, $vararray, $surpress_increment = false) 
	{
		if (strstr($blockname, '.'))
		{
			// 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]; 
			} 
			// 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. 
			if($surpress_increment)
			{
				$str = &$str[$blocks[$blockcount].'.'];
				$count = sizeof($str) - 1;
				if($count >= 0)
				{
					// adding only if there is at least one item
					$str[$count] = array_merge($str[$count], $vararray);
				}
			}
			else
			{
				$str[$blocks[$blockcount].'.'][] = $vararray;
			}
		}
		else
		{
			// Top-level block.
			// Add a new iteration to this block with the variable assignments
			// we were given.
			if($surpress_increment)
			{
				$str = &$this->_tpldata[$blockname.'.'];
				$count = sizeof($str) - 1;
				if($count >= 0)
				{
					// adding only if there is at least one item
					$str[$count] = array_merge($str[$count], $vararray);
				}
			}
			else
			{
				$this->_tpldata[$blockname.'.'][] = $vararray;
			}
		}
		return true;
	}
and here is faster version of clear_block_vars:

Code: Select all

	//
	// clears block vars
	//
	function clear_block_vars($blockname) 
	{
		if (strstr($blockname, '.'))
		{
			// 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]; 
			} 
			$str[$blocks[$blockcount].'.'] = array();
		}
		else
		{
			$this->_tpldata[$blockname.'.'] = array();
		}
		return true;
	}
I haven't tested this, but 90% that it is error-free. Please test it with your mod.
Vjacheslav Trushkin / Arty.
Free phpBB 3.1 styles | New project: Iconify - modern SVG framework
Xore
Former Team Member
Posts: 2594
Joined: Wed Apr 16, 2003 7:42 pm
Location: the wastelands between insomnia and clairvoyance
Contact:

Post by Xore »

much appreciated :-)

i'll probably be putting some stuff together later today
Camels in the Mist
<noise type="random" source="camel" />
Cash Mod
User avatar
Arty
Former Team Member
Posts: 16654
Joined: Wed Mar 06, 2002 2:36 pm
Name: Vjacheslav Trushkin
Contact:

Post by Arty »

..actually there is one bug - in both your and mine versions.

if function assign_var_from_handle is called with variable name that contains more than one dot then function will detect blockname incorrectly. instead of searching for first dot in string we should search for last one.

here is fixed function:

Code: Select all

	function assign_var_from_handle($varname, $handle, $surpress_block_increment = false)
	{
		ob_start();
		$res = $this->pparse($handle);
		$varrev = strrev($varname);
		if ($pos = strpos($varrev, '.') !== false) 
		{
			$blockname = strrev(substr($varrev, $pos + 1)); 
			$varname = strrev(substr($varrev, 0, $pos)); 
			$this->assign_block_vars($blockname, array($varname => ob_get_contents()), $surpress_block_increment);
		}
		else
		{
			$this->_tpldata['.'][0][$varname] = ob_get_contents();
		}
		ob_end_clean();
		return $res;
	}
Vjacheslav Trushkin / Arty.
Free phpBB 3.1 styles | New project: Iconify - modern SVG framework
Daijoubu
Registered User
Posts: 64
Joined: Wed Aug 21, 2002 4:31 pm
Location: Montreal QC Canada
Contact:

Post by Daijoubu »

Why use

Code: Select all

if ($pos = strpos($varname, '.') !== false)
I tried once and got some weird behavior, better simply use

Code: Select all

if ($pos = strpos($varname, '.') === true)
Xore
Former Team Member
Posts: 2594
Joined: Wed Apr 16, 2003 7:42 pm
Location: the wastelands between insomnia and clairvoyance
Contact:

Post by Xore »

CyberAlien wrote: ..actually there is one bug - in both your and mine versions.

if function assign_var_from_handle is called with variable name that contains more than one dot then function will detect blockname incorrectly. instead of searching for first dot in string we should search for last one.


Actually, if you look closely at my code, you'll notice that i used the strrpos() function rather than the strpos() function, which returns the last instance, rather than the first instance of needle in haystack

Code: Select all

$lastposition = strrpos($varname,'.');
Camels in the Mist
<noise type="random" source="camel" />
Cash Mod
User avatar
Arty
Former Team Member
Posts: 16654
Joined: Wed Mar 06, 2002 2:36 pm
Name: Vjacheslav Trushkin
Contact:

Post by Arty »

Ohh... then its just my error. Sorry about that.
Daijoubu wrote: if ($pos = strpos($varname, '.') === true)

This won't work - strpos returns number or false. So your if() will never be valid. And if you use == instead of === then your if will work but only when pos is > 0.
Vjacheslav Trushkin / Arty.
Free phpBB 3.1 styles | New project: Iconify - modern SVG framework
Post Reply

Return to “[2.0.x] MOD Writers Discussion”