Location: PHPKode > projects > ZenTrack - project/bug tracking software > zentrack_2.6.4/includes/zenTemplate.class.php
<?
if( !ZT_DEFINED ) { die("Illegal Access"); }


  /**
   **  TEMPLATE PROCESSING ENGINE
   **
   **  Essentially, the template engine works as follows
   **
   **  // get the template to process
   **  $tmp = new zenTemplate("/web/site/templates/template_name");
   **  // insert indexed array of values to be substituted
   **  $tmp->values($array_of_values);
   **  // get the results
   **  $text = $tmp->process();
   **
   **  A template file will look similar to the following:
   **
   **  <h3>{title}</h3>
   **  <form name="{name}" action="{action}">
   **  {list:array_name:"<input type='text' name='"+index+"' value='"+value+"'>"}
   **  </for>
   **
   ** Valid template entries are:
   **
   ** <ul> 
   **  <li>{varname} - inserts value of varname
   **  <li>{zen:varname} - inserts value of $zen->getSetting("varname")
   **  <li>{list:varname:"text"+index+"more text"+value} - loops through indexed array and prints name/value
   **  <li>{list:varname:"text"+index+"more text"+selected+"other text"+value} - loops through indexed array and print
   **                                                                            name/value (and " selected" when appropriate)
   **  <li>{list:varname:"text"+index+"more text"+checked+"other text"+value} - loops through indexed array and print
   **                                                                            name/value (and " checked" when appropriate)
   **  <li>{foreach:varname:"text"+value+"text"} - loops through array and prints values
   **  <li>{foreach:varname:"text"+selected+"more text"+value+"text"} - prints values and ' selected' if 
   **               field_selected exists and matches current value
   **  <li>{include:template_name} - inserts another template into this one
   **  <li>{if:field:"text to print"+field+"text to print"} - inserts text if field exists
   **  <li>{if:field=something:"text to print"+field+"more text"} - inserts text if field = something
   ** </ul>
   **
   */

class zenTemplate {

  /**
   ** invoke the template class
   **
   ** @param string $template is the path to the template file to load
   */
  function zenTemplate( $template ) {
    $this->_dir = dirname($template);
    $this->_template = $template;
    $this->_get();
    $this->_vars = array('rowcolor'=>'altCell', 'rowcolor_1'=>'cell', 'rowcolor_2'=>'altCell');
  }

  /**
   * load variables into the template engine for parsing
   *
   * @param array $vars indexed array of "name" => "value"
   */
  function values( $vars ) {
    foreach($vars as $k=>$v) {
      $this->_vars["$k"] = $v;
    }
  }

  /**
   * return a text string representing the parsed contents of the template
   *
   * @return string parsed template data, ready for use
   */
  function process() {
    return $this->_parse();
  }

  /**
   * <b>private</b>: get the template file and convert it to a text string
   */
  function _get() {
    if( file_exists($this->_template) ) {
      $this->_text = file($this->_template);
    }
    else {
      $this->_text = array("Template file {$this->_template} could not be found.");
    }
  }

  /**
   * <b>private</b>: returns a zen object
   *
   * @return object zen object
   */
  function _getZenObject() {    
    if( !is_object($this->_zen) ) {
      global $zen;
      $this->_zen = &$zen;
    }
    return $this->_zen;
  }

  /**
   * <b>private</b>: parse the contents of the template and insert values
   *
   * @return string parsed contents
   */
  function _parse() {
    $txt = $this->_text;
    for($i=0; $i<count($txt); $i++) {
      $txt[$i] = preg_replace("@[{]([^}]+)[}]@e", "''.\$this->_insert(\"\\1\").''",$txt[$i]);
    }
    return join("",$txt);
  }

  /**
   * <b>private</b>: parse the inserts in the template and return text for replacement
   *
   * @param string $text text to be replaced
   * @return string text to insert
   */
  function _insert( $text ) {
    $parts = explode(":", $text);
    $index = strtolower(trim($parts[0]));
    if( count($parts) == 1 ) {
      // {varname} - inserts value of varname
      return $this->_getVar($index);
    }    
    else {
      switch($index) {
      case "zen":
	{
	  // {zen:varname}
	  $zen = &$this->_getZenObject();
	  $n = trim($parts[1]);
	  return $zen->getSetting("$n")? $zen->getSetting("$n") : "";
	}
	break;
      case "list":
	{
	  // {list:varname:"text"+index+"more text"+value}
	  $vars = $this->_getVar(trim($parts[1]));
	  if( is_array($vars) ) {
	    $txt = "";
	    // make the string to show
	    $str = $this->_parseString($parts[2]);
	    // loop the list and make output text
	    foreach($vars as $k=>$v) {
              $this->_rowColor();
              if( preg_match('@^\\{include\\(([A-Za-z0-9/_.]+)\\)\\}$@', $str, $matches) ) {
                $txt .= $this->_inc($matches[1], $v, $k);
              }
              else {
                $fv = $this->_getVar("field_value");
                $fl = $this->_getVar("field_label");
                $tmp=$str;
                $_k = Zen::ffv($k);
                if($fv==$_k && strlen($fv) == strlen($_k) || is_array($fv) && in_array($_k, $fv) || 
                                       ( is_array($fv) && in_array($v,array_values($fv)) ) || 
                                       ( is_array($fl) && in_array($_k, $fl) ) ||
                                       (!is_array($fv) && !strlen($_k) && !strlen($fv))) {
                  $tmp = str_replace("{selected}", " selected", $tmp);
                  $tmp = str_replace("{checked}", " checked", $tmp);
                } else {
                  $tmp = str_replace("{selected}", "", $tmp);
                  $tmp = str_replace("{checked}", "", $tmp);
                }
                $tmp = str_replace("{index}", $k, $tmp);
                $txt .= str_replace("{value}", $v, $tmp);
              }
	    }
	    return $txt;
	  }
	  else {
	    return "";
	  }
	}
	break;
      case  "foreach":
	{
	  // {foreach:varname:"text"+value+"text"}
	  $vars = $this->_getVar(trim($parts[1]));
	  if( is_array($vars) ) {
            $sel = $this->_getVar("field_selected");
	    $txt = "";
	    // parse the string
	    $str = $this->_parseString($parts[2]);
	    // create the output text
	    foreach($vars as $v) {
        	$this->_rowColor();

	        $tmp=$str;
          	if($sel==$v && strlen($sel) == strlen($v) || is_array($sel) && in_array($v, $sel) || 
                                       ( is_array($sel) && in_array($v,array_values($sel)) ) || 
                                       ( !is_array($sel) && !strlen($v) && !strlen($sel) ) ||
                                       ( !is_array($sel) && $sel && $sel == $v && strlen($sel) == strlen($v) ) ) {
            		$selected = " selected";
          	} else {
            		$selected = "";
                }


        	//$selected = $sel && $sel == $v && strlen($sel) == strlen($v)? ' selected' : '';
        	if( preg_match('@^\\{include\\(([A-Za-z0-9/_.]+)\\)\\}$@', $str, $matches) ) {
          		$txt .= $this->_inc($matches[1], $v);
        	}
        	else {
          		$s = str_replace("{selected}", $selected, $str);
          		$s = str_replace("{value}", $v, $s);
          		$s = str_replace("{rowcolor}", $this->_vars['rowcolor'], $s);
		        $txt .= $s;
        	}
	    }
	    return $txt;
	  }
	  else {
	    return "";
	  }
	}
	break;
      case  "include":
	{
	  // {include:template_name}
	  return $this->_inc(trim($parts[1]));
	}
	break;
      case  "if":
	{
	  // {if:field:"text to print"+field+"text to print"}
	  // {if:field=something:"text to print"+field+"more text"}
	  $p = trim($parts[1]);
	  // determine if the if condition is true
	  if( strpos($p,"=") > 0 ) {
	    // there is an equals clause
	    list($key,$val) = explode("=",$parts[1]);
	    $key = trim($key);
	    $val = trim($val);
	    $tf = ($this->_getVar($key) == $val);
	  }
	  else {
	    $var = $this->_getVar($p);
	    $tf = ( (is_array($var) && count($var)) || (strlen($var) > 0) );
	  }
	  // execute the query if we met if condition
	  if( $tf ) {
	    return $this->_parseString($parts[2]);
	  }
	  else {
	    return "";
	  }
	}
	break;
      }
    }
    // return something generic if we fall through
    return "{invalid tag: $index}";
  }
  
  /**
   ** Return a value from an array based on match
   **/
  function _inc($file, $val = false, $key = false) {
    $tmp = new zenTemplate("{$this->_dir}/$file");
    $vals = $this->_vars;
    if( $val ) { $vals['curval'] = $val; }
    if( $key ) { $vals['curkey'] = $key; }
	  $tmp->values( $vals );
	  return $tmp->process();
  }
  
  /**
   * Alternate row colors
   */
  function _rowColor() {
    if( $this->_vars['rowcolor'] == $this->_vars['rowcolor_1'] ) { 
      $this->_vars['rowcolor'] = $this->_vars['rowcolor_2'];
    } 
    else { 
      $this->_vars['rowcolor'] = $this->_vars['rowcolor_1']; 
    }
  }

  /**
   ** <b>private</b>: parse a value string and return the results
   **
   ** this will replace variables with their values
   ** and the special keywords index and value
   ** with the text {index} and {value}
   **
   ** the value string should be in the format:
   **  "some text "+a_variable+"some more text"+another_variable... etc.
   **
   ** @param string $text the text string to parse
   ** @return string the parsed data
   **/
  function _parseString( $text, $curval = '', $curtext = '' ) {
    $text = str_replace('\\"', '"', $text);
    $text = str_replace("\\'", "'", $text);
    // parse the string to print
    $vals = explode("+",trim($text));
    $str = "";
    foreach($vals as $v) {
      $v = trim($v);
      // this is a string
      if( strpos($v,'"') === 0 ) {
        $str .= preg_replace('/^"/', "", preg_replace('/"$/', "", $v)); 
      }
      else if( preg_match('@^include\\(([A-Za-z0-9/_.]+)\\)$@', $v, $matches) ) {
        $str .= "\{$v}";
      }
      // this is the foreach key
      else if( $v == "index" ) {
        $str .= "{index}";
      }
      // this is the foreach value
      else if( $v == "value" ) {
        $str .= "{value}";
      }
      // this is used for list elements and is set to " selected" when the key equals the field_value
      else if( $v == "selected" ) {
        $str .= "{selected}";
      }
      // this is used for list elements and is set to " checked" when the key equals the field_value
      else if( $v == "checked" ) {
        $str .= "{checked}";
      }
      // used to alternate colors of rows
      else if( $v == 'rowcolor' ) {
        $str .= "{rowcolor}";
      }
      // this is another variable
      else {
        $str .= $this->_getVar($v);
      }
    }
    // fix return chars
    $str = str_replace('\n', "\n", $str);
    $str = str_replace('\t', "\t", $str);
    return $str;
  }
  
  /**
   ** <b>private</b>: returns a value recieved from the $this->values()
   **
   ** @param string $name the varname
   ** @return string the value of the varname
   **/
  function _getVar($name) {
    if( !is_array($this->_vars) ) { return ""; }
    if( preg_match("@^([a-zA-Z0-9_]+)\\[([a-zA-Z0-9_]+)\\]$@", $name, $matches) ) {
      $x = $matches[1];
      $y = $matches[2];
      if( array_key_exists($x, $this->_vars) && array_key_exists($y, $this->_vars[$x]) ) {
        return $this->_vars[$x][$y];
      }
      else {
        return "";
      }
    }
    if( !isset($this->_vars["$name"]) ) { return ""; }
    return $this->_vars["$name"];
  }

  var $_template; //the file we are using
  var $_zen;
  var $_text;  //the template data loaded and ready for parsing
  var $_vars;  //the variables to use for template parsing
  var $_dir;
}

?>
Return current item: ZenTrack - project/bug tracking software