<?php
// Template Engine
// ---------------
//
// Tento modul zpracovává tmplejty a strká do nich dynamicky geenrované
// informace a vytváří tak dynamické HTML stránky s oddělenou logikou
// programu a vzhledu.
//
// Více viz popis činnosti v konentáři na začátku templejtu
//
// (c)miho www.mlab.cz 2007, free software
//
// Typické použití objektu je toto:
//
// - Založ objekt templejtu (new)
// - $Template = new TemplateEngine();
//
// - Načti templejt ze souboru do objektu (ošetři chybu!)
// - $error = $Template->LoadTemplate($TemplateFile);
//
// - Tady se provádí generování masa, je možné použít proměnné,
// - modifikovat proměnné a nechat provéstsubstituce v proměnných
// - do řetězců.
//
// $Template->SetVariable('InfoTitle','Generovaný seznam');
// - první parametr je jméno proměnné, druhý je jeho nový obsah
//
// $Line = $Template->SetVariable('InfoLine')
// - vrací obsah proměnné nebo prázdný řetězec
//
// - Připrav si proměnné, které se budou strkat do vzorového řetězce
// $Variables[InfoName] = 'nějaká informace pro proměnnou InfoName';
// $Variables[InfoPicture] = 'jiná informace pro proměnnou InfoPicture';
// - aplikuj (nahraď) proměnné na vzorový řetězec z propměnné 'InfoLine'
// $Line = $Template->Substitute($Variables, $Template->GetVariable('InfoLine'));
//
// - Nakonec se naaplikují proměnné do nataženého templejtu a výsledek
// - se pošle klientovi
// echo $Template->GetPage();
//
// Objekt pro zpracování templejtu
class TemplateEngine
{
private $Page; // Sem se načte templejt a zde se provádí substituce
private $Info; // Sem se načtou z templejtu proměnné
function ListInfo()
// Vypíše nalezené proměnné a jejich hodnoty
// Pouze pro ladění
{
echo "[ ListInfo:\n";
print_r($this->Info);
echo ']';
}
function LoadTemplate($TemplateFileName, $Lang)
// Načte templejt ze souboru, při chybě vrací chybový řetězec
// Snaží se rozumně využít informaci o jazyku k otevření správné verze
// templejtu. Cesta se zadává bez jazykové části ale s příponou.
{
// Vlož zadaný jazyk do názvu souboru
$TemplateFileName = LangFile($TemplateFileName, $Lang);
// Načti template ze souboru (po řádcích do pole)
$this->Page = @file($TemplateFileName);
if ($this->Page=='')
return 'Unable Open Template File';
// Sestav z pole jeden retězec
$this->Page = implode($this->Page);
// Definice regulárních výrazů pro hledání
// ---------------------------------------
// Definice vzoru pro hledání komentáře ve tvaru <!-- -->
// Komentář je nepojmenované pole
// Před a za koentářem mohou být bílé znaky
// Uvnitř komentáře nesmí být znak >
$PatternComment = '(?:\s*<!--[^>]*--\s*>\s*)';
// (?: nepojemnované pole
// \s* volitelné bílé znaky před
// <!-- začátek komentáře
// [^>]* vniřek komentáře (neobsahuje >)
// --\s*> konec komentáře
// \s* volitelné bílé znaky za komentářem
// ) tady končí komentář
// Definice vzoru pro hledání proměnných ve tvaru $InfoXXX
$PatternVar ='\$(?P<VarName>Info[a-z,A-Z,0-9,\-\_]+)';
// \$ na začátku $
// (?P<VarName> pojmenované pole VarName je (jméno proměnné bez dolaru)
// Info[a-z,A-Z,0-9,\-\_]+ proměnná začíná Info a pak jsou písmena,
// ) číslice, mínus a podtržítko
// Definice vzoru pro hledání hodnot proměnných ve tvaru = " Hodnota "
// Definice hodnot je ve tvaru $InfoXXX="YYY" a mohou být víceřádkové
// ( a mohou obsahovat uvnitř další substituce uvozené $, které program
// zpracovává ale ne tady)
$PatternValue = '\s*=\s*"(?P<VarValue>[^"]*)"';
// \s*=\s* rovná se volitelnými bílými znaky okolo
// " hodnota v uvozovkách
// (?P<VarValue> parametr s názvem VarValue
// [^"]* hodnota nesmí obsahovat uvozovky
// ) vracíme hodnotu bez uvozovek
// " konec uvozovek
// Zparacování vzoru
// -----------------
// Najdi na začátku stránky komentář a vykousni ho
$pattern = '/^' .$PatternComment. '+/su';
$this->Page = preg_replace($pattern, '', $this->Page);
// / oddělovač
// ^ od začátku řetězce (jen komentáře na začátku souboru)
// $PatternComment komentář (<!-- -->) s bílými znaky okolo
// + alespoň jeden komentář
// /su modifikátor, . zastupuje i odřádkování, utf8
// Najdi v templejtu substutuční proměnné a vytvoř v poli $Info
// prázdné položky pro každou použitou proměnnou. Dělá se to proto,
// aby se na konci nepoužité proměnné nahradily prázdným řetězcem.
$pattern = '/' .$PatternVar. '/su';
preg_match_all($pattern, $this->Page, $temp);
// / oddělovač
// .$PatternVar. proměnná ( $InfoXXX ) - parametr VarName
// /su modifikátor zajistí, že . zastupuje i odřádkování, utf8
foreach($temp['VarName'] as $key => $value)
$this->Info[$value] = '';
unset($temp);
// Vytáhni proměnné a jejich hodnoty do pole $Info
$pattern = '/' .$PatternVar.$PatternValue. '/su';
// / oddělovač
// .$PatternVar. proměnná ( $InfoXXX ) - parametr VarName
// .$PatternValue. přiřazení ( = " Hodnota " ) - parametr VarValue
// /su modifikátor, . zastupuje i odřádkování, UTF8
preg_match_all($pattern, $this->Page, $temp);
foreach($temp['VarName'] as $key => $value)
$this->Info[$value] = $temp['VarValue'][$key];
unset($temp);
// Vykousej zpracované definice proměnných (a komentáře před nimi)
$pattern = '/' .$PatternComment.'?'.$PatternVar.$PatternValue. '/su';
// / oddělovač
// .$PatternComment.'?' volitelný komentář před definicí
// .$PatternVar. proměnná ( $InfoXXX )
// .$PatternValue. přiřazení ( = " Hodnota " )
// /su modifikátor, . zastupuje i odřádkování, UTF8
$this->Page = preg_replace($pattern, '', $this->Page);
}
function Indent($StringData, $Indent)
// Všechna odřádkování v řetězci $StringData odsadí o hodnotu $Indent pokud je
// $Indent číslo nebo o déllku řetězce $Indent pokud je to řetězec
{
// Velikost odsazení (vyrob číslo)
if (is_string($Indent))
$Num = mb_strlen($Indent,'utf-8');
else
$Num = 0+$Indent;
// Odsazení
return $StringData = $Indent.str_replace("\n", "\n".str_repeat(' ', $Num), $StringData);
}
/*
function Substitute($Variables, $String)
// Nahradí proměnné v řetězci $String obsahem proměnných z pole $Variables
// a vrátí výsledný řetězec
{
if (is_array($Variables))
{
foreach($Variables as $Key => $Value)
{
// Hledací vzor (hledáme proměnnou s názvem v $Key)
$Pattern = '\$'.$Key.'(?=[^a-z,A-Z,0-9,\-\_])';
// \$$Key hledáme $JmenoProměnné
// (?= následuje něco, co nemůže být jménem
// [^a-z,A-Z,0-9,\-\_] a nezajímá nás
// )
// Vkládáme více řádek?
$IsMultiline = !(strpos($Value, "\n") === FALSE);
if (!$IsMultiline)
{
// Vkládáme jednoduchý řetězec
$String = preg_replace('/'.$Pattern.'/su', $Value, $String);
// /su víceřádkové v UTF8
}
else
{
// Vkládáme řetezec s odřádkováním - je třeba odsazovat
$String = preg_replace('/(.*)'.$Pattern.'/ue',
"\$this->Indent(\$Value, '\\1')",
$String);
// (.*) hledáme cokoli před vzorem -> první parametr
// .$Pattern. proměnná
// /ue UTF8, náhrada je php skriptem
}
}
}
return $String;
}
*/
function Substitute($Variables, $String)
// Nahradí proměnné v řetězci $String obsahem proměnných z pole $Variables
// a vrátí výsledný řetězec
{
// Hledací vzor
$Pattern = '/(.*?)\$(Info[a-z,A-Z,0-9,\-\_]+)(?=[^a-z,A-Z,0-9,\-\_])/ue';
// Náhrada s kusem php kódu (nezapomeň, že preg_replace s přepínačem /e vrací oescapované řetězce)
$String = preg_replace($Pattern,
'isset($Variables[\'\2\'])
? $this->Indent($Variables[\'\2\'], stripslashes(\'\1\'))
: stripslashes(\'\1\')
',
$String);
return $String;
}
function SetVariable($VarName, $VarValue, $Wrap=0)
// Nastaví hodnotu proměnné
// Volitelně provede zálámání na zadaný počet znaků a odstranění nadbytečných mezer
{
// Volitelné zalámání a odstranění bílých znaků
if ($Wrap!=0)
$VarValue = WrapString($VarValue, $Wrap);
// Uložení do proměnných
$this->Info[$VarName] = $VarValue;
}
function GetVariable($VarName)
// Vrátí hodnotu proměnné tak, jak je, včetně mezer a odřádkování
{
if (isset($this->Info[$VarName]))
return $this->Info[$VarName];
else
return '';
}
function GetString($VarName)
// Vrátí parametr jako jeden řetězec s redukovanými bílými znaky
// Tedy bez odřádkování a nadbytečných mezer
{
return WrapString($this->GetVariable($VarName), 0);
}
function GetPage()
// Provede substituce ve stránce a vrátí ji jako řetězec
// Substituce bere z proměnné $Info
{
// Proveď ve stránce substituce proměnných a vrať výsledek
return $this->Substitute($this->Info, $this->Page);
}
}
?>