2 Replies - 2417 Views - Last Post: 23 August 2012 - 04:12 AM

#1 RudiVisser   User is offline

  • .. does not guess solutions
  • member icon

Reputation: 1010
  • View blog
  • Posts: 3,566
  • Joined: 05-June 09

Template Engine

Posted 09 June 2009 - 02:34 PM

Description: Supports Conditionals, Blocks (repeated data), PHP Variables, Simple (Evaluated) IF statements, built in variables, and basic "compression" of the output.

Taken directly from source code of MageBB v2.
<?php
	/*#NOTICE:1#*/
	
	/**
	* Styles class.
	*
	* Produces templated versions of MageBB in a procedural style taken from the style.config file in the style directory.
	* Will fallback to style 'magebb' when there is no style set in the Administration Panel.
	*
	* Will automatically replace variables in the template files which are accessed by $magebb{varname}.
	*
	* Blocks are accessed via $openBlock{blockname} and from there on $blockItem{varname} for the variable values (Translates into a for loop).
	**/
	class Styles {
		
		/**
		* Stores the single replacement variables (named) -> $variables['varname'] = 'replacement';
		*
		* @var	array	Variables
		**/
		private $Variables;
		
		/**
		* Stores the blocks of data (named) -> $blocks['name'][0]['varname'] = 'replacement';
		*
		* @var	array	Blocks
		**/
		private $Blocks;
		
		/**
		* Style Data such as copyright, name, etc.
		*
		* @var	array	StyleData
		**/
		public $StyleData;
		
		/**
		* Template names -> $templates['header'] = 'header.inc';
		*
		* @var	array	Templates
		**/
		private $Templates;
		
		/**
		* Reference to the active MageBB object
		*
		* @var	object	MageBB
		**/
		private $MageBB;
		
		/**
		* Setup and parse the style from $MageBB->Settings
		*
		* @param	object	MageBB
		**/
		public function __construct(&$MageBB) {
			$this->MageBB = $MageBB;
			// Now all done from Session
			//$styleName = $this->MageBB->Settings->AllSettings['style_name'];
			$styleName = $this->MageBB->Sessions->CurrentData['style'];
			if(!file_exists(ROOT . "styles/" . $styleName . "/style.config")) $styleName = "magebb";
			if(!file_exists(ROOT . "styles/" . $styleName . "/style.config")) triggerCritical(CRIT_FILESTRUCTURE, "Style '" . $styleName . "'s style.config file does not exist.");
			$configContents = file_get_contents(ROOT . "styles/" . $styleName . "/style.config");
			$xml = new SimpleXMLElement($configContents);
			$this->StyleData = array();
			$this->StyleData['FolderName'] = $this->MageBB->Settings->AllSettings['style_name'];
			$this->StyleData['Name'] = (string)$xml->name;
			$this->StyleData['Copyright'] = (string)$xml->copyright;
			$this->StyleData['Site'] = (string)$xml->site;
			$this->StyleData['Version'] = (int)$xml->version;
			$this->StyleData['ForBuild'] = (int)$xml->magebbBuild;
			$this->StyleData['StyleSheet'] = (string)$xml->stylesheet;
			// Now parse templates
			$this->Templates = array();
			foreach($xml->templates->template As $template) {
				$this->Templates[(string)$template->name] = array('RealName' => (string)$template->realName, 'FileName' => (string)$template->fileName);
			}
			$this->initialiseParser();
		}
		
		/**
		* Setup replacement variable parser
		**/
		private function initialiseParser() {
			// From settings
			$this->Variables['boardtitle'] = $this->MageBB->Settings->AllSettings['board_name'];
			$this->Variables['pagetitle'] = $this->MageBB->Settings->AllSettings['board_name'];
			$this->Variables['date'] = date($this->MageBB->Settings->AllSettings['date_format']);
			$this->Variables['genseconds'] = 0;
			$this->Variables['querycount'] = &$this->MageBB->Database->queryCount;
			$this->Variables['stylesheet'] = "styles/".$this->StyleData['FolderName']."/".$this->StyleData['StyleSheet'];
			$this->Variables['imagedir'] = "styles/".$this->StyleData['FolderName']."/images/";
			$this->Variables['bbjs'] = "includes/js/javascriptinclude.php";
			// We might aswell generate the generic style variables here
			$this->Variables['copyrightnotice'] = "Powered by <a href="http://www.magebb.com/">MageBB</a> Version ".$this->MageBB->Version.".
Copyright © 2002-2008 <a href="http://www.mageuk.com/">Mage UK Ltd</a>.";
			$avgs = $this->MageBB->Compat->LoadAverages();
			$this->Variables['loadavg'] = $avgs[0] . ", " . $avgs[1] . ", " . $avgs[2];
			$this->Variables['loadavg0'] = $avgs[0];
			$this->Variables['loadavg1'] = $avgs[1];
			$this->Variables['loadavg2'] = $avgs[2];
			$this->Variables['onlineusers'] = $this->MageBB->State->Output['onlineusers'];
			$this->Variables['onlineguests'] = $this->MageBB->State->Output['onlineguests'];
			$this->Variables['onlinemembers'] = $this->MageBB->State->Output['onlinemembers'];
			$this->Variables['loggedin'] = ($this->MageBB->Users->LoggedIn()?"true":"false");
			
			$menuNum = 1; // For dynamic menu items
			$this->Blocks['menuitems'][0]['link'] = "index.php";
			$this->Blocks['menuitems'][0]['title'] = "Home";
			if( !$this->MageBB->Users->LoggedIn() && $this->MageBB->Settings->AllSettings['allow_registration']) {
				$this->Blocks['menuitems'][$menuNum]['link'] = "register.php";
				$this->Blocks['menuitems'][$menuNum]['title'] = "Register";
				$menuNum++;
			}
			if( $this->MageBB->Users->LoggedIn() ) {
				$this->Blocks['menuitems'][$menuNum]['link'] = "accountcenter.php";
				$this->Blocks['menuitems'][$menuNum]['title'] = "Account Center";
				$menuNum++;
			}
			if( $this->MageBB->Settings->AllSettings['enable_memberlist'] && ($this->MageBB->Users->LoggedIn() || $this->MageBB->Settings->AllSettings['guestview_memberlist'])) {
				$this->Blocks['menuitems'][$menuNum]['link'] = "register.php";
				$this->Blocks['menuitems'][$menuNum]['title'] = "Member Listing";
				$menuNum++;
			}
			$this->Blocks['breadcrumbs'][0]['link'] = "index.php";
			$this->Blocks['breadcrumbs'][0]['title'] = $this->Variables['boardtitle'];
			$this->Blocks['breadcrumbs'][0]['post'] = "";
		}
		
		/**
		* Change or set a variable's value for the specific page
		*
		* @param	string	name
		* @param	string	value
		**/
		public function setVariable($name, $value) {
			$this->Variables[$name] = $value;
		}
		
		/**
		* Change or set a block's array value for the specific page
		*
		* @param	string	name
		* @param	array	values
		**/
		public function setBlock($name, $values) {
			$this->Blocks[$name] = $values;
		}
		
		/**
		* Add a block item to a specified block for the specific page
		*
		* @param	string	name
		* @param	array	values
		**/
		public function addBlockItem($name, $values) {
			$this->Blocks[$name][] = $values;
		}
		
		/**
		* Parse the $sysvar (Straight from PHP) variables in templates, contain generic data
		*
		* @param	string	toParse
		* @param	bool	failToFalse
		**/
		private function parseSystemVariables($toParse, $failToFalse=false) {
			// System Variable parsing
			preg_match_all('/$sysvar{(.*?)}/i', $toParse, $varMatches);
			$replaceme = array();
			$replacements = array();
			foreach($varMatches[1] As $key => $matchName) {
				$InFail = str_replace("$","",$matchName);
				if(isset($$matchName))
					{ $replaceme[$key] = $varMatches[0][$key]; $replacements[$key] = $$matchName; }
				else if(isset($$InFail))
					{ $replaceme[$key] = $varMatches[0][$key]; $replacements[$key] = $$InFail; }
				else if(function_exists($matchName))
					{ $replaceme[$key] = $varMatches[0][$key]; $replacements[$key] = $matchName(); }
				else
					{ $replaceme[$key] = $varMatches[0][$key]; if(!$failToFalse) { $replacements[$key] = "Style error: ".$varMatches[0][$key]." is undefined."; } else { $replacements[$key] = "false"; } }
			}
			return str_replace($replaceme, $replacements, $toParse);
		}
		
		/**
		* Parse the $mbbsetting variables in templates, contain generic data
		*
		* @param	string	toParse
		* @param	bool	failToFalse
		**/
		private function parseTemplateIncludes($toParse, $failToFalse=false) {
			// String template replacements
			preg_match_all('/$template{(.*?)}/i', $toParse, $varMatches);
			$replaceme = array();
			$replacements = array();
			foreach($varMatches[1] As $key => $matchName) {
				$replaceme[$key] = $varMatches[0][$key];
				$replacements[$key] = $this->outputTemplate($matchName, true);
			}
			return str_replace($replaceme, $replacements, $this->parseSystemVariables($toParse, $failToFalse));
		}
		
		/**
		* Parse the $mbbsetting variables in templates, contain generic data
		*
		* @param	string	toParse
		* @param	bool	failToFalse
		**/
		private function parseSettingVariables($toParse, $failToFalse=false) {
			// String template replacements
			preg_match_all('/$mbbsetting{(.*?)}/i', $toParse, $varMatches);
			$replaceme = array();
			$replacements = array();
			foreach($varMatches[1] As $key => $matchName) {
				if(isset($this->MageBB->Settings->AllSettings[$matchName]))
					{ $replaceme[$key] = $varMatches[0][$key]; $replacements[$key] = $this->MageBB->Settings->AllSettings[$matchName]; }
				else
					{ $replaceme[$key] = $varMatches[0][$key];if(!$failToFalse) { $replacements[$key] = "Style error: ".$varMatches[0][$key]." is undefined."; } else { $replacements[$key] = "false"; } }
			}
			return str_replace($replaceme, $replacements, $this->parseTemplateIncludes($toParse, $failToFalse));
		}
		
		/**
		* Parse the $magebb variables in templates, contain generic data
		*
		* @param	string	toParse
		* @param	bool	failToFalse
		**/
		private function parseVariables($toParse, $failToFalse=false) {
			// String template replacements
			preg_match_all('/$magebb{(.*?)}/i', $toParse, $varMatches);
			$replaceme = array();
			$replacements = array();
			foreach($varMatches[1] As $key => $matchName) {
				if(isset($this->Variables[$matchName]))
					{ $replaceme[$key] = $varMatches[0][$key]; $replacements[$key] = $this->Variables[$matchName]; }
				else if(strpos($matchName, "[") !== false) {
					preg_match("/(.*?)[(.*?)]$/", $matchName, $matches);
					if(isset($this->Variables[$matches[1]][$matches[2]]))
					{ $replaceme[$key] = $varMatches[0][$key]; $replacements[$key] = $this->Variables[$matches[1]][$matches[2]]; }
					else
					{ $replaceme[$key] = $varMatches[0][$key];if(!$failToFalse) { $replacements[$key] = "Style error: ".$varMatches[0][$key]." is undefined."; } else { $replacements[$key] = "false"; } }
				}
				else
					{ $replaceme[$key] = $varMatches[0][$key];if(!$failToFalse) { $replacements[$key] = "Style error: ".$varMatches[0][$key]." is undefined."; } else { $replacements[$key] = "false"; } }
			}
			return str_replace($replaceme, $replacements, $this->parseSettingVariables($toParse, $failToFalse));
		}
		
		/**
		* Parse simple ($coutput{CONDITION?ONTRUE?ONFALSE}) conditional statements
		*
		* @param	string	toParse
		**/
		private function simpleConditional($toParse) {
			// Conditional template replacements
			preg_match_all('/$coutput{(.*?)?(.*?)?(.*?)}/si', $toParse, $varMatches);
			$replaceme = array();
			$replacements = array();
			foreach($varMatches[1] As $key => $matchName) {
				$evalMe = $this->parseVariables($varMatches[1][$key], true);
				if(eval("if(".$evalMe.") { return true; } else { return false; }"))
					{ $replaceme[$key] = $varMatches[0][$key]; $replacements[$key] = $varMatches[2][$key]; }
				else
					{ $replaceme[$key] = $varMatches[0][$key]; $replacements[$key] = $varMatches[3][$key]; }
			}
			return str_replace($replaceme, $replacements, $toParse);
		}
		
		/**
		* Parse full $if{condition} dowhatever $else dowhatever $endif conditional statements
		*
		* @param	string	toParse
		**/
		private function fullConditional($toParse) {
			// Conditional template replacements
			preg_match_all('/$if{"(.*?)"}(.*?)(|$else(.*?))$endif/si', $toParse, $varMatches);
			$replaceme = array();
			$replacements = array();
			foreach($varMatches[1] As $key => $matchName) {
				$evalMe = $this->parseVariables($varMatches[1][$key], true);
				if(eval("if(".$evalMe.") { return true; } else { return false; }"))
					{ $replaceme[$key] = $varMatches[0][$key]; $replacements[$key] = $varMatches[2][$key]; }
				else
					{ $replaceme[$key] = $varMatches[0][$key]; $replacements[$key] = $varMatches[4][$key]; }
			}
			return str_replace($replaceme, $replacements, $toParse);
		}
		
		private function ParseBlocks($toParse) {
			preg_match_all('/$openBlock{(.*?)}(.*)$closeBlock{(.*?)}/si', $toParse, $blockMatches);
			if(count($blockMatches[0]) < 1) return $toParse;
			foreach($blockMatches[1] As $key => $matchName) {
				if(isset($this->Blocks[$matchName])) {
					$replacementHTML = "";
					preg_match_all('/$blockItem{(.*?)}/i', $blockMatches[2][$key], $itemMatches);
					foreach($this->Blocks[$matchName] As $block) {
						$replaceme = array();
						$replacements = array();
						foreach($itemMatches[1] As $itemKey => $itemMatchName) {
							if(isset($block[$itemMatchName]))
								{ $replaceme[$itemKey] = $itemMatches[0][$itemKey]; $replacements[$itemKey] = $block[$itemMatchName]; }
							else
								{ $replaceme[$itemKey] = $itemMatches[0][$itemKey]; $replacements[$itemKey] = "Style error: ".$itemMatches[0][$itemKey]." is undefined in block ".$matchName."."; }
						}
						$replacementHTML .= str_replace($replaceme, $replacements, $blockMatches[2][$key]);
					}
					$toParse = str_replace($blockMatches[0], $replacementHTML, $toParse);
				} else { $toParse = str_replace($blockMatches[0][$key], "Style error: Block '".$matchName."' is undefined.", $toParse); }
			}
			return $toParse;
		}
		
		/**
		* Parse the style's template
		*
		* @param	string	templateName
		*
		* @returns	string	Parsed Template Contents
		**/
		private function parseTemplate($templateName) {
			// Read file
			$templateContents = file_get_contents(ROOT . "styles/" . $this->StyleData['FolderName'] . "/" . $this->Templates[$templateName]['FileName']);
			$templateContents = $this->simpleConditional($templateContents);
			$templateContents = $this->fullConditional($templateContents);
			$templateContents = $this->parseVariables($templateContents);
			$templateContents = $this->parseBlocks($templateContents);
			return $templateContents;
		}
		
		/**
		* Output template with appropriate finalisation
		*
		* @param	string	templateName
		**/
		public function outputTemplate($templateName, $return=false) {
			// 01/06/2008, Rudi - Added finalisation
			if(!isset($this->Templates[$templateName])) {
				if($return)
					return "Style error: Template $templateName does not exist.";
				echo "Style error: Template $templateName does not exist.";
				return;
			}
			$parsed = $this->parseTemplate($templateName);
			if((boolean)$this->MageBB->Settings->AllSettings['compress_style'] == true) {
				/* Note: This will work as long as there are no preformatted paragraphs as whitespace such as tabs are
						stripped. Add note to theme developer guide. */
				$working = $parsed;
				// Strip tabs
				$working = str_replace("t", "", $working);
				// Strip double spaces
				$working = str_replace("  ", "", $working);
				// Strip empty lines
				$working = preg_replace("@(^[rn]*|[rn]+)[st]*[rn][email protected]", "n", $working);
				// Put closing tags together working from MAX_LINE_EMPTY_TAGS
				preg_match_all("@(</.*>[rn]*){1,".MAX_LINE_EMPTY_TAGS."}@", $working, $matches);
				$working = str_replace($matches[0], preg_replace("@[rn]*@", "", $matches[0]), $working);
				// Put tag-only lines together working from MAX_LINE_EMPTY_TAGS
				preg_match_all("@(<.*>[rn]*){1,".MAX_LINE_EMPTY_TAGS."}@", $working, $matches);
				$working = str_replace($matches[0], preg_replace("@[rn]*@", "", $matches[0]), $working);
				$finalTemplate = $working;
			} else $finalTemplate = $parsed;
			if($return) return $finalTemplate;
			else echo $finalTemplate;
		}
	}
	
?>



/**** EXAMPLE TEMPLATE ****/
$if{"$magebb{loadavg0} > $mbbsetting{max_load}"}
	<div id="badnotice_tl">
		High Server Load Detected
	</div>
$endif
<div id="mainBody">
	<div id="header">
    	<img src="$magebb{imagedir}magebb_logo.png" alt="$magebb{boardtitle}'s Logo" id="logo" />
		<div id="right">
			$template{menu}
			$if{"$magebb{loggedin}"}
				Logged in
			$else
				$coutput{$mbbsetting{usejs}?
					<a href="" id="showlogin" class="smalltext">Show Login Form</a>
					<div id="loginform">
				?}
					<form action="login.php" method="post" class="smalltext">
						Username: <input type="text" name="username" />
						Password: <input type="password" name="password" /> <input type="submit" name="submit_dologin" value="Login" />
						$coutput{$mbbsetting{usejs}?[<a href="" id="hidelogin">Hide</a>]?}
					</form>
				$coutput{$mbbsetting{usejs}?</div>?}
			$endif
		</div>
		<div style="clear:both"></div>
	</div>
	<div id="maincontent">
		$template{breadcrumbs}


Is This A Good Question/Topic? 0
  • +

Replies To: Template Engine

#2 mrtuan   User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 6
  • Joined: 06-December 11

Re: Template Engine

Posted 05 December 2011 - 11:57 PM

ok
Was This Post Helpful? 0
  • +
  • -

#3 itsall4u   User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 1
  • Joined: 22-August 12

Re: Template Engine

Posted 23 August 2012 - 04:12 AM

Hay This is what i was searching for.... Great job Thanks
Was This Post Helpful? 0
  • +
  • -

Page 1 of 1