Ich stelle meine Frage in Englisch damit ich mich nicht zu sehr blamiere . Nach dem ich aber die Funktionalität sowie so brauche habe ich auch gleich eine geänderte class.template.php beigefügt mit der entsprechende Erweiterung. Ich muss noch die regex Beschreibung anpassen nach dem es endlich funktioniert - morgen weiß ich wieder nicht warum es überhaupt funktioniert (siehe templateParseConditionalsRecursive und variable $regex).
Grüße, Simon
I often have the situation that I have content which only should be displayed if one of the variables has been set. An example would be to display a small icon of a telephone if a record contains a telephone number, otherwise not to display anything. Currently it is necessary to code this in php and and insert this as needed to the template as a variable.
What I have coded is the following:
Consider the following template:
Code: Alles auswählen
Conditional statustrainer <!-- CONDITIONAL statustrainer -->evaluated to true<!-- /CONDITIONAL --><br>
Conditional statusteacher <!-- CONDITIONAL statusteacher -->evaluated to true<!-- /CONDITIONAL --><br>
Conditional statusgroup <!-- CONDITIONAL statusgroup -->evaluated to true<!-- /CONDITIONAL --><br>
setting statusteacher to "true" (or in fact any non empty string) results in:
Code: Alles auswählen
Conditional statustrainer <br>
Conditional statusteacher evaluated to true<br>
Conditional statusgroup <br>
Code: Alles auswählen
Conditional statustrainer <!-- CONDITIONAL statustrainer -->evaluated to true<br>
----------> Conditional statusteacher <!-- CONDITIONAL statusteacher -->evaluated to true<br>
---------------------> Conditional statusgroup <!-- CONDITIONAL statusgroup -->evaluated to true<br>
<!-- /CONDITIONAL -->
<!-- /CONDITIONAL -->
<!-- /CONDITIONAL -->
I use this code standalone at the moment so it is not possible to just drop this onto the contenido distribution. My hope is that this or something similar could be included in an official release.
Here is my (slightly castrated) class.template.php file an example template file for testing and example php code:
Code: Alles auswählen
<?php
/* The following template class is based almost entirely on the template class used in contenido */
/* Modified by Simon Woods */
/*****************************************
*
* $Id: class.template.php,v 1.17 2005/08/30 09:24:34 timo.hummel Exp $
*
* File : $RCSfile: class.template.php,v $
* Project : Contenido
* Descr : Contenido Template Engine
*
* Author : $Author: timo.hummel $
* Modified : $Date: 2005/08/30 09:24:34 $
*
* © four for business AG, www.4fb.de
******************************************/
/**
* templateConditionalsArray
* @array
*/
$templateConditionalsArray;
/**
* class Template
*
* Light template mechanism
*
* @author Jan Lengowski <Jan.Lengowski@4fb.de>
* @copyright four for business <http://www.4fb.de>
* @author Stefan Jelner (Optimizations)
* @version 1.0
*/
class Template
{
/**
* Needles (static)
* @var array
*/
var $needles = array ();
/**
* Replacements (static)
* @var array
*/
var $replacements = array ();
/**
* Conditionals (static)
* @var array
*/
var $conditionals = array ();
/**
* Dyn_Needles (dynamic)
* @var array
*/
var $Dyn_needles = array ();
/**
* Dyn_Replacements (dynamic)
* @var array
*/
var $Dyn_replacements = array ();
/**
* Dyn_Conditionals (dynamic)
* @var array
*/
var $Dyn_conditionals = array ();
/**
* Template cache
* @var array
*/
var $tplcache;
/**
* Template name cache
* @var array
*/
var $tplnamecache;
/**
* Dynamic counter
* @var int
*/
var $dyn_cnt = 0;
/**
* Tags array (for dynamic blocks);
* @var array
*/
var $tags = array ('static' => '{%s}', 'start' => '<!-- BEGIN:BLOCK -->', 'end' => '<!-- END:BLOCK -->');
/**
* Constructor function
* @return void
*/
function Template($tags = false)
{
$this->tplcache = Array ();
$this->tplnamecache = Array ();
if (is_array($tags))
{
$this->tags = $tags;
}
$this->setEncoding("");
$this->setDomain("contenido");
} // end function
/**
* setDomain
*
* Sets the gettext domain to use for translations in a template
*
* @param $sDomain string Sets the domain to use for template translations
* @return none
*/
function setDomain ($sDomain)
{
$this->_sDomain = $sDomain;
}
/**
* Set Templates placeholders and values
*
* With this method you can replace the placeholders
* in the static templates with dynamic data.
*
* @param $which String 's' for Static or else dynamic
* @param $needle String Placeholder
* @param $replacement String Replacement String
*
* @return void
*/
function set($which = 's', $needle, $replacement)
{
if ($which == 's')
{ // static
$this->needles[] = sprintf($this->tags['static'], $needle);
$this->replacements[] = $replacement;
if (strlen($replacement) > 0)
{
$this->conditionals[$needle] = true;
}
} else
{ // dynamic
$this->Dyn_needles[$this->dyn_cnt][] = sprintf($this->tags['static'], $needle);
$this->Dyn_replacements[$this->dyn_cnt][] = $replacement;
if (strlen($replacement) > 0)
{
$this->Dyn_conditionals[$this->dyn_cnt][$needle] = true;
}
}
}
/**
* Sets an encoding for the template's head block.
*
* @param $encoding string Encoding to set
*/
function setEncoding ($encoding)
{
$this->_encoding = $encoding;
}
/**
* Iterate internal counter by one
*
* @return void
*/
function next()
{
$this->dyn_cnt++;
}
/**
* Reset template data
*
* @return void
*/
function reset()
{
$this->dyn_cnt = 0;
$this->needles = array ();
$this->replacements = array ();
$this->conditionals = array ();
$this->Dyn_needles = array ();
$this->Dyn_replacements = array ();
$this->Dyn_conditionals = array ();
}
/**
* Generate the template and
* print/return it. (do translations sequentially to save memory!!!)
*
* @param $template string/file Template
* @param $return bool Return or print template
* @param $note bool Echo "Generated by ... " Comment
*
* @return string complete Template string
*/
function generate($template, $return = 0, $note = 1)
{
//check if the template is a file or a string
if (!@ file_exists($template))
$content = & $template; //template is a string (it is a reference to save memory!!!)
else
$content = implode("", file($template)); //template is a file
$content = (($note) ? "<!-- Generated by Contenido Template file -->\n" : "").$content;
$pieces = array();
//if content has dynamic blocks
if (preg_match("/^.*".preg_quote($this->tags['start'], "/").".*?".preg_quote($this->tags['end'], "/").".*$/s", $content))
{
//split everything into an array
preg_match_all("/^(.*)".preg_quote($this->tags['start'], "/")."(.*?)".preg_quote($this->tags['end'], "/")."(.*)$/s", $content, $pieces);
//safe memory
array_shift($pieces);
$content = "";
//now combine pieces together
//start block
// Check for conditional blocks
$pieces[0][0] = $this->parseConditionals($pieces[0][0], $this->conditionals);
// Now replace the variables
$pieces[0][0] = str_replace($this->needles, $this->replacements, $pieces[0][0]);
$this->replacei18n($pieces[0][0], "i18n");
$this->replacei18n($pieces[0][0], "trans");
$content .= $pieces[0][0];
unset ($pieces[0][0]);
//generate dynamic blocks
for ($a = 0; $a < $this->dyn_cnt; $a ++)
{
// Check for conditional blocks
$temp = $this->parseConditionals($pieces[1][0], $this->Dyn_conditionals[$a]);
$temp = str_replace($this->Dyn_needles[$a], $this->Dyn_replacements[$a], $temp);
$this->replacei18n($temp, "i18n");
$this->replacei18n($temp, "trans");
$content .= $temp;
}
unset ($temp);
//end block
// Check for conditional blocks
$pieces[2][0] = $this->parseConditionals($pieces[2][0], $this->conditionals);
$pieces[2][0] = str_replace($this->needles, $this->replacements, $pieces[2][0]);
$this->replacei18n($pieces[2][0], "i18n");
$this->replacei18n($pieces[2][0], "trans");
$content .= $pieces[2][0];
unset ($pieces[2][0]);
} else
{
$content = str_replace($this->needles, $this->replacements, $content);
$this->replacei18n($content, "i18n");
$this->replacei18n($content, "trans");
}
if ($this->_encoding != "")
{
$content = str_replace("</head>", '<meta http-equiv="Content-Type" content="text/html; charset='.$this->_encoding.'">'."\n".'</head>', $content);
}
if ($return)
return $content;
else
echo $content;
} # end function
/**
* replacei18n()
*
* Replaces a named function with the translated variant
*
* @param $template string Contents of the template to translate (it is reference to save memory!!!)
* @param $functionName string Name of the translation function (e.g. i18n)
*/
function replacei18n(& $template, $functionName)
{
/*
//if template contains functionName + parameter store all matches
preg_match_all("/".preg_quote($functionName, "/")."\\(([\\\"\\'])(.*?)\\1\\)/s", $template, $matches);
$matches = array_values(array_unique($matches[2]));
for ($a = 0; $a < count($matches); $a ++)
{
$template = preg_replace("/".preg_quote($functionName, "/")."\\([\\\"\\']".preg_quote($matches[$a], "/")."[\\\"\\']\\)/s", i18n($matches[$a], $this->_sDomain), $template);
}
*/
}
/**
* parseConditionals()
*
* Prepare the conditionals list prior to calling the templateParseConditionalsRecursive function
* Conditional blocks are defined by <!-- CONDITIONAL varname --> this is the text <!-- /CONDITIONAL -->
* Currently if a variable is defined and is non empty the condition evaluates to true.
* Defined but empty variables evaluate to false
* Static variable are only evaluated outside BLOCK statements, dynamic variables only in BLOCK statements
*
* @param $input string Text part which is to be searched for conditional blocks (it is reference to save memory!!!)
* @param $conditionals array Associative array of conditionals
*/
function parseConditionals(& $input, $conditionals)
{
// Ideally we would store this information in a static varibale in the class
// and read this in the templateParseConditionalsRecursive static function. Was however
// unable to get this to work in php4 (should work in php5 though).
global $templateConditionalsArray;
$templateConditionalsArray = $conditionals;
return($this->templateParseConditionalsRecursive($input));
}
/**
* templateParseConditionalsRecursive()
*
* Process the conditional blocks in the text piece. Conditional blocks are removed if the variables are not set
*
* @param $input string Text part which is to be searched for conditional blocks
*/
function templateParseConditionalsRecursive($input)
{
global $templateConditionalsArray;
# I keep forgetting how this works so here again as a reminder
# <!--\ CONDITIONAL\ (\w*)\ --> - This is the start of a match string with a word in the middle which is put in [1]
# The next bit is ((?:[^<]|<(?!<!--\ /?CONDITIONAL\ -->])|(?R))+) which gets put in [2] for further processing
# <!--\ /CONDITIONAL\ --> is then the end tag
# The trick is in the middle bit to allow nested blocks but to stop when the close block is present
#
# To break down (?:[^<]|<(?!<!--\ /?CONDITIONAL\ -->])|(?R))+)
# ( (?: [^<] | < (?!<!--\ /?CONDITIONAL\ -->]) | (?R) )+ )
#
#
$regex = '#<!--\sCONDITIONAL\s(\w*)\s-->((?:[^<]|<(?!!--\s/?CONDITIONAL(\s\w*)?\s-->)|(?R))+)<!--\s/CONDITIONAL\s-->#';
if (is_array($input))
{
// [0] is the unfiltered input
// [1] is the conditional variable name
// [2] is the body inside the conditional
// If the variable specified in the conditional exists and has content then we include the inner html
// Otherwise it is ignored
if (isset($templateConditionalsArray[ltrim($input[1])]))
{
$input = $input[2];
}
else
{
$input = "";
}
}
return preg_replace_callback($regex, Array('Template', 'templateParseConditionalsRecursive'), $input);
}
} # end class
?>
Code: Alles auswählen
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<title>Test Template</title>
</head>
<body>
<!-- Template: TestTemplate -->
Test sequential conditionals with no text in between : <br>
<!-- CONDITIONAL statustrainer -->Conditional statustrainer evaluated to true<br><!-- /CONDITIONAL --><!-- CONDITIONAL statusteacher -->Conditional statusteacher evaluated to true<br><!-- /CONDITIONAL -->
<!-- CONDITIONAL statusgroup -->Conditional statusgroup evaluated to true<br><!-- /CONDITIONAL -->
<br>
Test sequential conditionals with text in between : <br>
Conditional statustrainer <!-- CONDITIONAL statustrainer -->evaluated to true<!-- /CONDITIONAL --><br>
Conditional statusteacher <!-- CONDITIONAL statusteacher -->evaluated to true<!-- /CONDITIONAL --><br>
Conditional statusgroup <!-- CONDITIONAL statusgroup -->evaluated to true<!-- /CONDITIONAL --><br>
<br>
Test nested conditionals with text in between : <br>
Conditional statustrainer <!-- CONDITIONAL statustrainer -->evaluated to true<br>
----------> Conditional statusteacher <!-- CONDITIONAL statusteacher -->evaluated to true<br>
---------------------> Conditional statusgroup <!-- CONDITIONAL statusgroup -->evaluated to true<br>
<!-- /CONDITIONAL -->
<!-- /CONDITIONAL -->
<!-- /CONDITIONAL -->
<!-- BEGIN:BLOCK -->
<!-- END:BLOCK -->
</body>
</html>
Example php code:
Code: Alles auswählen
<?php
require_once($_SERVER["DOCUMENT_ROOT"] . "/somewhere_over_the_rainbow/class.template.php");
$testTemplate = new Template;
$testTemplate->reset();
$testTemplate->set("s", "statustrainer", "true");
$testTemplate->set("s", "statusteacher", "true");
// $testTemplate->set("s", "statusgroup", "true");
echo $testTemplate->generate("testTemplate.html", 1);
echo "<br>";
?>