You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
			
		
		
		
		
			
		
			
				
					
					
						
							483 lines
						
					
					
						
							17 KiB
						
					
					
				
			
		
		
	
	
							483 lines
						
					
					
						
							17 KiB
						
					
					
				| <?php
 | |
| /*****************************************************************************
 | |
|   $Id: yapter.php,v 1.24 2006/01/31 07:30:28 nvie Exp $
 | |
| 
 | |
|   Yapter 2.14b2 - Yet Another PHP Template Engine ®
 | |
|   Copyright (C) 2001-2003 Vincent Driessen
 | |
| 
 | |
|   This library is free software; you can redistribute it and/or
 | |
|   modify it under the terms of the GNU Lesser General Public
 | |
|   License as published by the Free Software Foundation; either
 | |
|   version 2.1 of the License, or (at your option) any later version.
 | |
| 
 | |
|   This library is distributed in the hope that it will be useful,
 | |
|   but WITHOUT ANY WARRANTY; without even the implied warranty of
 | |
|   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 | |
|   Lesser General Public License for more details.
 | |
| 
 | |
|   You should have received a copy of the GNU Lesser General Public
 | |
|   License along with this library; if not, write to the Free Software
 | |
|   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 | |
| 
 | |
|   For more information, visit http://yapter.sf.net/ or contact us at
 | |
|   nvie@users.sourceforge.net
 | |
|   The full terms of the GNU Lesser General Public License that apply to Yapter
 | |
|   can be found at http://yapter.sf.net/LICENSE
 | |
|  *****************************************************************************/
 | |
| 
 | |
| // Define Yapter's warning levels
 | |
| define('E_YAPTER_NONE',    		0);		// Be completely silent
 | |
| define('E_YAPTER_NOTICE',  		1);		// Report notices
 | |
| define('E_YAPTER_WARNING', 		2);		// Report warnings
 | |
| define('E_YAPTER_ERROR',   		4);		// Report errors
 | |
| define('E_YAPTER_DIE_ON_ERROR',		8);		// Die on errors
 | |
| define('E_YAPTER_ALL',     		15);	// Report errors, warnings and notices
 | |
| 
 | |
| // Define Yapter's ignore levels
 | |
| define('E_YAPTER_IGN_UNKNOWN_VARS',	16);	// Ignore unknown variables
 | |
| define('E_YAPTER_AUTO_HIDE_BLOCK',	32);	// Automaticly hide unparsed blocks
 | |
| 
 | |
| class Template {
 | |
| 	var $_ROOT = '__DOCUMENT_ROOT';
 | |
| 	var $parseUnknownVars = false;	// Defines whether unknown variables should be removed or left alone
 | |
| 	var $blox = array();		// $blox[blockname]['content']  holds the template's content
 | |
| 					// $blox[blockname]['numlines'] holds the number of lines in the block
 | |
| 					// $blox[blockname]['parsed']   holds an array with the parsed data
 | |
| 					// $blox[$_ROOT]                always holds the main template
 | |
| 	var $blockDefs = array();	// Keeps track of all block-definitions from which multiple blocks...
 | |
| 					// ...can be created instances of
 | |
| 
 | |
| 	var $vars = array();		// This array contains all variables. All are accessible from all blocks.
 | |
| 
 | |
| 	var $warningLevel;		// The level of verbosity Yapter complies with (see the E_* defines above)
 | |
| 	var $startTime;			// Holds the start time of the script, so that it can compare it to the...
 | |
| 					// ...end time to calculate the execution time. (For debugging purposes only.)
 | |
| 
 | |
| 	var $missing_list;		// List of variable names that are declared but never set.
 | |
| 
 | |
| 	/////////////////////////////////////////////////////////////////////
 | |
| 
 | |
| 	function error($msg)
 | |
| 	{
 | |
| 		if ($this->warningLevel & E_YAPTER_ERROR)
 | |
| 			if ($this->warningLevel & E_YAPTER_DIE_ON_ERROR )
 | |
| 				// if DIE_ON_ERROR is set, then do die on error!
 | |
| 				die("<br />\n<b>Yapter error</b>: ".$msg."<br />\n"); // Die here!
 | |
| 			else
 | |
| 				// else just barf out the message
 | |
| 				echo "<br />\n<b>Yapter error</b>: ".$msg."<br />\n";
 | |
| 	}
 | |
| 
 | |
| 	function warning($msg)
 | |
| 	{
 | |
| 		if ($this->warningLevel & E_YAPTER_WARNING)
 | |
| 			echo "<br />\n<b>Yapter warning</b>: ".$msg."<br />\n";
 | |
| 	}
 | |
| 
 | |
| 	function notice($msg)
 | |
| 	{
 | |
| 		if ($this->warningLevel & E_YAPTER_NOTICE)
 | |
| 			echo "<br />\n<b>Yapter notice</b>: ".$msg."<br />\n";
 | |
| 	}
 | |
| 
 | |
| 	function warn_var_not_set($varname)
 | |
| 	{
 | |
| 		if (!in_array($varname, $this->missing_list) && !($this->warningLevel & E_YAPTER_IGN_UNKNOWN_VARS)) {
 | |
| 			$this->missing_list[] = $varname;	// Add it to the list...
 | |
| 			// ...and print a warning once.
 | |
| 			$this->warning('Variable <b>'.htmlspecialchars($varname).'</b> found, but never assigned a value. (This message is shown only once for each variable.)');
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	/////////////////////////////////////////////////////////////////////
 | |
| 
 | |
| 	function Template($file, $level = E_YAPTER_ALL)
 | |
| 	{
 | |
| 		if (is_bool($level)) {
 | |
| 			//
 | |
| 			// Rationale:
 | |
| 			// =========
 | |
| 			// Older Yapter versions had the possibility of turning
 | |
| 			// on the so called "debug mode" with a bool parameter
 | |
| 			// as the second argument to this constructor.
 | |
| 			// However, since debug mode was dropped and the
 | |
| 			// warning level support was built in, it was a logical
 | |
| 			// step of replacing the second parameter.
 | |
| 			//
 | |
| 			// However, to prevent people from making mistakes,
 | |
| 			// we'll check if the user passed a boolean parameter.
 | |
| 			// If so, he or she is probably using debug mode, and
 | |
| 			// we'll issue a notice in these cases.
 | |
| 			//
 | |
| 			// Thanks to Ivo Koster.
 | |
| 			//
 | |
| 			$this->notice('Debug mode is not supported anymore since Yapter version 2.12.');
 | |
| 			$this->warningLevel = E_YAPTER_ALL;
 | |
| 		}
 | |
| 		else
 | |
| 			$this->warningLevel = (int)$level;
 | |
| 
 | |
| 		$this->startTime = $this->getmicrotime();
 | |
| 		$this->addBlockFromFile($this->_ROOT, $file);
 | |
| 		$this->missing_list = array();
 | |
| 	}
 | |
| 
 | |
| 	/* setParseMode(): specifies to parse unknown variables or not */
 | |
| 	function setParseMode($parseUnknownVars)
 | |
| 	{
 | |
| 		$this->parseUnknownVars = (bool)$parseUnknownVars;
 | |
| 	}
 | |
| 
 | |
| 	/* setWarningLevel(): sets the level of verbosity which Yapter should obey */
 | |
| 	function setWarningLevel($level)
 | |
| 	{
 | |
| 		$this->warningLevel = $level;
 | |
| 	}
 | |
| 
 | |
| 	/* addBlock(): adds a new block to the blox-array */
 | |
| 	function addBlock($blockname, $content)
 | |
| 	{
 | |
| 		$this->blox[$blockname]['content'] = $content;
 | |
| 		$this->blox[$blockname]['numlines'] = sizeof($this->blox[$blockname]['content']);
 | |
| 		$this->blox[$blockname]['parsed'] = '';
 | |
| 		$this->prepare($blockname);
 | |
| 	}
 | |
| 
 | |
| 	/* addBlockFromFile(): adds a new block, filling it with the specified's file contents */
 | |
| 	function addBlockFromFile($blockname, $file)
 | |
| 	{
 | |
| 		$content = @file($file) or $this->error('Cannot open template file <b>'.htmlspecialchars($file).'</b>!');
 | |
| 		//--- eliminate double block def mod -klp
 | |
| //		if ($blockname != $this->_ROOT)
 | |
| //			$this->addBlockDef($blockname, $content);
 | |
| 		$this->addBlock($blockname, $content);
 | |
| 	}
 | |
| 
 | |
| 	/* addBlockDef(): adds a block definition to the block-definition array from which other blocks can be copied */
 | |
| 	function addBlockDef($blockdef, $content)
 | |
| 	{
 | |
| /*		if (isset($this->blockDefs[$blockdef]))
 | |
| 			$this->error('Block "'.htmlspecialchars($blockdef).'" allready exists. I cannot create it twice.');
 | |
| 		else
 | |
| 			$this->blockDefs[$blockdef] = $content;
 | |
| */
 | |
| 		$this->blockDefs[$blockdef] = $content;
 | |
| 	}
 | |
| 
 | |
| 	/* addBlockFromDef(): copies a block from the block definition array */
 | |
| 	function addBlockFromDef($blockname, $blockdef)
 | |
| 	{
 | |
| 		$this->addBlock($blockname, $this->blockDefs[$blockdef]);
 | |
| 	}
 | |
| 
 | |
| 	/* prepare(): handles subprocessing of templates found in the main template file */
 | |
| 	function prepare($blockname)
 | |
| 	{
 | |
| 		$currblockcontents = array();
 | |
| 		$block = &$this->blox[$blockname];
 | |
| 		for ($i = 0; $i < $block['numlines']; $i++) {
 | |
| 			if (isset($block['content'][$i]))
 | |
| 				$line = $block['content'][$i];
 | |
| 			else
 | |
| 				continue;
 | |
| 
 | |
| 			// Try to find a tag-definition on this line
 | |
| 			if (preg_match('/\[(INCLUDE|BLOCK|END|REUSE|SET) ([A-Za-z0-9_.\/-]+)( AS ([A-Za-z0-9_-]+))?]/', $line, $matches)) {
 | |
| 				$type = $matches[1];
 | |
| 				$name = (!empty($matches[4])) ? $matches[4] : $matches[2];
 | |
| 				if ($type == 'END' && !isset($currblockdef))
 | |
| 					$this->error('"[END '.$name.']" found without matching "[BLOCK '.$name.']" or "[SET '.$name.']"');
 | |
| 				if ($type == 'END' && $matches[2] == $currblockdef) {
 | |
| 					if (isset($matches[4]))
 | |
| 						$this->error('Given "AS"-parameter not allowed in END-tags!');
 | |
| 
 | |
| 					// End the current block definition: add the block to the blox-array
 | |
| 					//--- if wrapper mod -klp
 | |
| 					if (isset($currblockdef) && isset($currblockcontents) && isset($currblockname)) {
 | |
| 						$this->addBlockDef($currblockdef, $currblockcontents);
 | |
| 						$this->addBlockFromDef($currblockname, $currblockdef);
 | |
| 					}
 | |
| 
 | |
| 					// Now, try to remove the block from the template definition, replacing it with a var
 | |
| 					for ($j = $i; $j >= $currblockstart; $j--) {
 | |
| 						if ($j == $currblockstart && $currblocktype == 'BLOCK')
 | |
| 							$block['content'][$j] = "{" .  $currblockname . "}";
 | |
| 						else
 | |
| 							unset($block['content'][$j]);
 | |
| 					}
 | |
| 
 | |
| 					// unset these thingies for further preparing
 | |
| 					unset($currblocktype);
 | |
| 					unset($currblockstart);
 | |
| 					unset($currblockname);
 | |
| 					unset($currblockdef);
 | |
| 					$currblockcontents = array();
 | |
| 
 | |
| 				} elseif (($type == 'SET' || $type == 'BLOCK') && !isset($currblockname)) {
 | |
| 
 | |
| 					if ($type == 'BLOCK') {
 | |
| 
 | |
| 						// Start block definition
 | |
| 						$currblocktype  = $type;
 | |
| 						$currblockstart = $i;
 | |
| 						$currblockname  = $name;
 | |
| 						$currblockdef   = $matches[2];
 | |
| 
 | |
| 					} else {		// SET-tag
 | |
| 
 | |
| 						// Start block definition
 | |
| 						if (isset($matches[4]))
 | |
| 							$this->error('Given "AS"-parameter not allowed in SET-tags!');
 | |
| 
 | |
| 						$currblocktype  = $type;
 | |
| 						$currblockstart = $i;
 | |
| 						$currblockname  = $matches[2];
 | |
| 						$currblockdef   = $matches[2];
 | |
| 
 | |
| 					}
 | |
| 
 | |
| 				} elseif ($type == 'INCLUDE' && !isset($currblockname)) {
 | |
| 
 | |
| 					// Make this line a variable...
 | |
| 					$block['content'][$i] = "{" . $name .  "}\n";
 | |
| 
 | |
| 					// ...and include the given file...
 | |
| 					$this->addBlockFromFile($name, $matches[2]);
 | |
| 
 | |
| 				} elseif ($type == 'REUSE' && !isset($currblockname)) {
 | |
| 
 | |
| 					if (!isset($matches[4]))
 | |
| 						$this->error('Missing "AS"-parameter in [REUSE <b>$name</b>] tag!');
 | |
| 
 | |
| 					// Make this line a variable...
 | |
| 					$block['content'][$i] = "{" .  $matches[4] . "}\n";
 | |
| 
 | |
| 					// ...and get this REUSE value from the block definition list...
 | |
| 					$this->addBlockFromDef($matches[4], $matches[2]);
 | |
| 
 | |
| 				} elseif ($currblockname != $name) {
 | |
| 					if ($currblockname)
 | |
| 						$currblockcontents[] = $line;
 | |
| 				}
 | |
| 
 | |
| 			} else {
 | |
| 				// No tag-definition... just normal text so do nothing here
 | |
| 				if (!empty($currblockname))
 | |
| 					$currblockcontents[] = $line;
 | |
| 			}
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	/* parse(): parses the specified block, filling variables and nested blockdefs */
 | |
| 	function parse($blockname = '')
 | |
| 	{
 | |
| 		if (!$blockname)
 | |
| 			$blockname = $this->_ROOT;
 | |
| 		if (!isset($this->blox[$blockname]))
 | |
| 			$this->error('Block "'.htmlspecialchars($blockname).'" does not exist.');
 | |
| 
 | |
| 		$block = &$this->blox[$blockname];
 | |
| 		$parsed = $block['content'];
 | |
| 
 | |
| 		// Loop through all the lines of the template and parse variables one-by-one
 | |
| 		for ($i = 0; $i < $block['numlines']; $i++) {
 | |
| 			if (!isset($parsed[$i]))
 | |
| 				continue;
 | |
| 			$line = $parsed[$i];
 | |
| 
 | |
| 			// Look for variables in this line, processing it character-by-character
 | |
| 			unset($start);
 | |
| 			unset($buffer);
 | |
| 			for ($j = 0; $j < strlen($line); $j++) {
 | |
| 				$char = $line[$j];
 | |
| 				if (!isset($start) && $char == '{')
 | |
| 					$start = $j;
 | |
| 				elseif (isset($start) && $char == '}') {
 | |
| 					// The sequence {} is not a valid variable value
 | |
| 					if (!isset($buffer)) {
 | |
| 						unset($start);
 | |
| 						continue;
 | |
| 					} else {
 | |
| 						// Gotcha! Now replace this variable with its contents
 | |
| 						// First, check to see if it's a variable or a block that has to be parsed
 | |
| 						if (isset($this->vars[$buffer]))
 | |
| 							$value = $this->vars[$buffer];
 | |
| 						elseif (isset($this->blox[$buffer])) {
 | |
| 							if ($this->blox[$buffer]['parsed']) {
 | |
| 								// The value must be filled with the parsed data from the $buffer block
 | |
| 								$value = @implode('', $this->blox[$buffer]['parsed']);
 | |
| 							} elseif ($this->warningLevel & E_YAPTER_AUTO_HIDE_BLOCK) {
 | |
| 								// Automaticly hide unparsed bloks
 | |
| 								$value = "";
 | |
| 							} else {
 | |
| 								// Make the recursive call now
 | |
| 								$value = @implode('', $this->parse($buffer));
 | |
| 							}
 | |
| 						} else {
 | |
| 							// No variable or block name found by the name of $buffer
 | |
| 
 | |
| 							// First, issue a warning!
 | |
| 							$this->warn_var_not_set($buffer);
 | |
| 
 | |
| 							if ($this->parseUnknownVars) {
 | |
| 								// Unable to find variable, replace this one with an empty
 | |
| 								// string silently.
 | |
| 								$value = '';
 | |
| 							} else {
 | |
| 								// Unable to find variable, leave this one alone...
 | |
| 								unset($start);
 | |
| 								unset($buffer);
 | |
| 								continue;
 | |
| 							}
 | |
| 						}
 | |
| 						$part1 = substr($line, 0, $start);
 | |
| 						$part2 = substr($line, $start + strlen($buffer) + 2);
 | |
| 						$line = $part1 . $value . $part2;
 | |
| 						$j += strlen($value) - (strlen($buffer) + 2);
 | |
| 						unset($start);
 | |
| 						unset($buffer);
 | |
| 					}
 | |
| 				} elseif (isset($start)) {
 | |
| 					// Check to see $char is a proper character (range: [A-Za-z0-9_./-])
 | |
| 					// In Yapter 2.13b2, I've added the '/' char as well, to support inclusion
 | |
| 					// from Unix paths, like '../../foo.tpl'
 | |
| 					if (($char >= 'a' && $char <= 'z') || ($char >= '0' && $char <= '9') || ($char >= 'A' && $char <= 'Z') || ($char == '_') || ($char == '.') || ($char == '-') || ($char == '/')) {
 | |
| 						if (!empty($buffer))
 | |
| 							$buffer .= $char;
 | |
| 						else
 | |
| 							$buffer = $char;
 | |
| 					} else {
 | |
| 						unset($start);
 | |
| 						unset($buffer);
 | |
| 					}
 | |
| 				}
 | |
| 			}
 | |
| 			$parsed[$i] = $line;
 | |
| 		}
 | |
| 
 | |
| 		if (is_array($this->blox[$blockname]['parsed'])) {
 | |
| 			$this->blox[$blockname]['parsed'] = array_merge($this->blox[$blockname]['parsed'], $parsed);
 | |
| 		} else {
 | |
| 			//--- array cast mod -klp
 | |
| 			$this->blox[$blockname]['parsed'] = (array) $parsed;
 | |
| 		}
 | |
| 		return $this->blox[$blockname]['parsed'];
 | |
| 	}
 | |
| 
 | |
| 	/* set(): assigns a value to a variabele inside curly brackets ('{' and '}') */
 | |
| 	function set($varname, $value)
 | |
| 	{
 | |
| 		if (isset($value))
 | |
| 			$this->vars[$varname] = $value;
 | |
| 		else
 | |
| 			$this->warning('Trying to set <b>'.htmlspecialchars($varname).'</b> to NULL. Variable not set.');
 | |
| 	}
 | |
| 
 | |
| 	/* setVars(): assigns values to variables for each element in the given array
 | |
| 	   Contributed by: Raniz
 | |
| 	 */
 | |
| 	function setVars($variables)
 | |
| 	{
 | |
| 		if (!is_array($variables))
 | |
| 			$this->error('Value passed to setVars is not an array.');
 | |
| 		foreach($variables as $varname => $value)
 | |
| 			$this->vars[$varname] = $value;
 | |
| 	}
 | |
| 
 | |
| 	/* setFile(): assigns the contents of a file to a variabele inside curly brackets ('{' and '}') */
 | |
| 	function setFile($varname, $filename)
 | |
| 	{
 | |
| 		if (!file_exists($filename))
 | |
| 			$this->error('Cannot open file "'.htmlspecialchars($filename).'" for inclusion in "'.htmlspecialchars($varname).'".');
 | |
| 		$value = implode('', file($filename));
 | |
| 		$this->set($varname, $value);
 | |
| 	}
 | |
| 
 | |
| 	/* getVar(): returns the value of the 'varname' variable */
 | |
| 	function getVar($varname)
 | |
| 	{
 | |
| 		if ($this->vars[$varname])
 | |
| 			return $this->vars[$varname];
 | |
| 		else
 | |
| 			return false;
 | |
| 	}
 | |
| 
 | |
| 	/* getBlock(): returns the content of the 'blockname' block */
 | |
| 	function getBlockContent($blockname)
 | |
| 	{
 | |
| 		if ($this->$blox[$blockname]['content'])
 | |
| 			return @implode('', $this->$blox[$blockname]['content']);
 | |
| 		else
 | |
| 			return false;
 | |
| 	}
 | |
| 
 | |
| 	/* replace(): replaces the content of one block by another */
 | |
| 	function replace($block, $byblock)
 | |
| 	{
 | |
| 		if (!isset($this->blox[$block]))
 | |
| 			$this->error('Block "'.htmlspecialchars($block).'" does not exist.');
 | |
| 		if (!isset($this->blox[$byblock]))
 | |
| 			$this->error('Block "'.htmlspecialchars($block).'" does not exist.');
 | |
| 		$this->blox[$block]['content'] = $this->blox[$byblock]['content'];
 | |
| 		$this->blox[$block]['numlines'] = $this->blox[$byblock]['numlines'];
 | |
| 	}
 | |
| 
 | |
| 	/* hide(): hides all the contents of the given block */
 | |
| 	function hide($block)
 | |
| 	{
 | |
| 		if (!isset($this->blox[$block]))
 | |
| 			$this->error('Block "'.htmlspecialchars($block).'" does not exist.');
 | |
| 		$this->blox[$block]['content'] = array();
 | |
| 		$this->blox[$block]['numlines'] = 0;
 | |
| 	}
 | |
| 
 | |
| 	/* clear(): resets the parsed data to an empty string again and defines the block as 'unparsed' */
 | |
| 	function clear($blockname)
 | |
| 	{
 | |
| 		if (!isset($this->blox[$blockname]))
 | |
| 			$this->error('Block "'.htmlspecialchars($blockname).'" does not exist.');
 | |
| 		$this->blox[$blockname]['parsed'] = '';
 | |
| 		unset($this->vars[$blockname]);	// often, a variabele is set whenever a block should be discarded...
 | |
| 						// ...now reset such a variable to make sure the block is not overriden
 | |
| 	}
 | |
| 
 | |
| 	/* getContents(): gets the final contents to be outputted on the screen */
 | |
| 	function getContents($blockname = '')
 | |
| 	{
 | |
| 		if ($blockname == '') $blockname = $this->_ROOT;
 | |
| 		$parsed = $this->blox[$blockname]['parsed'];
 | |
| 		if ($parsed)
 | |
| 			return implode('', $parsed);
 | |
| 		else
 | |
| 			return false;
 | |
| 	}
 | |
| 
 | |
| 	/* spit(): ouputs contents to screen */
 | |
| 	function spit()
 | |
| 	{
 | |
| 		echo $this->getContents();
 | |
| 	}
 | |
| 
 | |
| 	function getmicrotime()
 | |
| 	{
 | |
| 		/* I got this getmicrotime()-function from the PHP.net website, but it seems to be
 | |
| 		   buggy, while it sometimes displays a negative execution time when you substract
 | |
| 		   the current time with the starting time of the script... I only noticed it at
 | |
| 		   my Windows localhost machine, not on *nix servers. Is anybody familiar with this
 | |
| 		   behaviour? Any information about this is welcome at nvie@users.sourceforge.net
 | |
| 		   for your co-operation. */
 | |
| 		list($usec, $sec) = explode(' ', microtime());
 | |
| 		return ((float)$usec + (float)$sec);
 | |
| 	}
 | |
| 
 | |
| 	function execTime()
 | |
| 	{
 | |
| 		return round($this->getmicrotime() - $this->startTime, 5);
 | |
| 	}
 | |
| 
 | |
| 	function executionTime()
 | |
| 	{
 | |
| 		echo "<p>\n\nThe execution time is <b>".$this->execTime()."</b> seconds.<br>\n";
 | |
| 	}
 | |
| }
 | |
| ?>
 | |
| 
 |