Rev 4986 Rev 4987
1 <?php 1 <?php
2   2  
3 // Template Engine 3 // Template Engine
4 // --------------- 4 // ---------------
5 // 5 //
6 // Tento modul zpracovává tmplejty a strká do nich dynamicky geenrované 6 // Tento modul zpracovává tmplejty a strká do nich dynamicky geenrované
7 // informace a vytváří tak dynamické HTML stránky s oddělenou logikou 7 // informace a vytváří tak dynamické HTML stránky s oddělenou logikou
8 // programu a vzhledu. 8 // programu a vzhledu.
9 // 9 //
10 // Více viz popis činnosti v konentáři na začátku templejtu 10 // Více viz popis činnosti v konentáři na začátku templejtu
11 // 11 //
12 // (c)miho www.mlab.cz 2007, free software 12 // (c)miho www.mlab.cz 2007, free software
13 // 13 //
14 // Typické použití objektu je toto: 14 // Typické použití objektu je toto:
15 // 15 //
16 // - Založ objekt templejtu (new) 16 // - Založ objekt templejtu (new)
17 // - $Template = new TemplateEngine(); 17 // - $Template = new TemplateEngine();
18 // 18 //
19 // - Načti templejt ze souboru do objektu (ošetři chybu!) 19 // - Načti templejt ze souboru do objektu (ošetři chybu!)
20 // - $error = $Template->LoadTemplate($TemplateFile); 20 // - $error = $Template->LoadTemplate($TemplateFile);
21 // 21 //
22 // - Tady se provádí generování masa, je možné použít proměnné, 22 // - Tady se provádí generování masa, je možné použít proměnné,
23 // - modifikovat proměnné a nechat provéstsubstituce v proměnných 23 // - modifikovat proměnné a nechat provéstsubstituce v proměnných
24 // - do řetězců. 24 // - do řetězců.
25 // 25 //
26 // $Template->SetVariable('InfoTitle','Generovaný seznam'); 26 // $Template->SetVariable('InfoTitle','Generovaný seznam');
27 // - první parametr je jméno proměnné, druhý je jeho nový obsah 27 // - první parametr je jméno proměnné, druhý je jeho nový obsah
28 // 28 //
29 // $Line = $Template->SetVariable('InfoLine') 29 // $Line = $Template->SetVariable('InfoLine')
30 // - vrací obsah proměnné nebo prázdný řetězec 30 // - vrací obsah proměnné nebo prázdný řetězec
31 // 31 //
32 // - Připrav si proměnné, které se budou strkat do vzorového řetězce 32 // - Připrav si proměnné, které se budou strkat do vzorového řetězce
33 // $Variables[InfoName] = 'nějaká informace pro proměnnou InfoName'; 33 // $Variables[InfoName] = 'nějaká informace pro proměnnou InfoName';
34 // $Variables[InfoPicture] = 'jiná informace pro proměnnou InfoPicture'; 34 // $Variables[InfoPicture] = 'jiná informace pro proměnnou InfoPicture';
35 // - aplikuj (nahraď) proměnné na vzorový řetězec z propměnné 'InfoLine' 35 // - aplikuj (nahraď) proměnné na vzorový řetězec z propměnné 'InfoLine'
36 // $Line = $Template->Substitute($Variables, $Template->GetVariable('InfoLine')); 36 // $Line = $Template->Substitute($Variables, $Template->GetVariable('InfoLine'));
37 // 37 //
38 // - Nakonec se aplikují proměnné do nataženého templejtu a výsledek 38 // - Nakonec se aplikují proměnné do nataženého templejtu a výsledek
39 // - se pošle klientovi 39 // - se pošle klientovi
40 // echo $Template->GetPage(); 40 // echo $Template->GetPage();
41 // 41 //
42   42  
43   43  
44 // Objekt pro zpracování templejtu 44 // Objekt pro zpracování templejtu
45 class TemplateEngine 45 class TemplateEngine
46 { 46 {
47   47  
48 private $Page; // Sem se načte templejt a zde se provádí substituce 48 private $Page; // Sem se načte templejt a zde se provádí substituce
49 private $Info; // Sem se načtou z templejtu proměnné 49 private $Info; // Sem se načtou z templejtu proměnné
50   50  
51   51  
52 function ListInfo(): void 52 function ListInfo(): void
53 // Vypíše nalezené proměnné a jejich hodnoty 53 // Vypíše nalezené proměnné a jejich hodnoty
54 // Pouze pro ladění 54 // Pouze pro ladění
55 { 55 {
56 echo "[ ListInfo:\n"; 56 echo "[ ListInfo:\n";
57 print_r($this->Info); 57 print_r($this->Info);
58 echo ']'; 58 echo ']';
59 } 59 }
60   60  
61   61  
62 function LoadTemplate($TemplateFileName, $Lang) 62 function LoadTemplate($TemplateFileName, $Lang)
63 // Načte templejt ze souboru, při chybě vrací chybový řetězec 63 // Načte templejt ze souboru, při chybě vrací chybový řetězec
64 // Snaží se rozumně využít informaci o jazyku k otevření správné verze 64 // Snaží se rozumně využít informaci o jazyku k otevření správné verze
65 // templejtu. Cesta se zadává bez jazykové části ale s příponou. 65 // templejtu. Cesta se zadává bez jazykové části ale s příponou.
66 { 66 {
67 // Vlož zadaný jazyk do názvu souboru 67 // Vlož zadaný jazyk do názvu souboru
68 $TemplateFileName = LangFile($TemplateFileName, $Lang); 68 $TemplateFileName = LangFile($TemplateFileName, $Lang);
69   69  
70 // Načti template ze souboru (po řádcích do pole) 70 // Načti template ze souboru (po řádcích do pole)
71 $this->Page = @file($TemplateFileName); 71 $this->Page = @file($TemplateFileName);
72 if ($this->Page=='') 72 if ($this->Page=='')
73 return 'Unable Open Template File'; 73 return 'Unable Open Template File';
74   74  
75 // Sestav z pole jeden retězec 75 // Sestav z pole jeden retězec
76 $this->Page = implode($this->Page); 76 $this->Page = implode('', $this->Page);
77   77  
78   78  
79 // Definice regulárních výrazů pro hledání 79 // Definice regulárních výrazů pro hledání
80 // --------------------------------------- 80 // ---------------------------------------
81   81  
82 // Definice vzoru pro hledání komentáře ve tvaru <!-- --> 82 // Definice vzoru pro hledání komentáře ve tvaru <!-- -->
83 // Komentář je nepojmenované pole 83 // Komentář je nepojmenované pole
84 // Před a za koentářem mohou být bílé znaky 84 // Před a za koentářem mohou být bílé znaky
85 // Uvnitř komentáře nesmí být znak > 85 // Uvnitř komentáře nesmí být znak >
86 $PatternComment = '(?:\s*<!--[^>]*--\s*>\s*)'; 86 $PatternComment = '(?:\s*<!--[^>]*--\s*>\s*)';
87 // (?: nepojemnované pole 87 // (?: nepojemnované pole
88 // \s* volitelné bílé znaky před 88 // \s* volitelné bílé znaky před
89 // <!-- začátek komentáře 89 // <!-- začátek komentáře
90 // [^>]* vniřek komentáře (neobsahuje >) 90 // [^>]* vniřek komentáře (neobsahuje >)
91 // --\s*> konec komentáře 91 // --\s*> konec komentáře
92 // \s* volitelné bílé znaky za komentářem 92 // \s* volitelné bílé znaky za komentářem
93 // ) tady končí komentář 93 // ) tady končí komentář
94   94  
95 // Definice vzoru pro hledání proměnných ve tvaru $InfoXXX 95 // Definice vzoru pro hledání proměnných ve tvaru $InfoXXX
96 $PatternVar ='\$(?P<VarName>Info[a-z,A-Z,0-9,\-\_]+)'; 96 $PatternVar ='\$(?P<VarName>Info[a-z,A-Z,0-9,\-\_]+)';
97 // \$ na začátku $ 97 // \$ na začátku $
98 // (?P<VarName> pojmenované pole VarName je (jméno proměnné bez dolaru) 98 // (?P<VarName> pojmenované pole VarName je (jméno proměnné bez dolaru)
99 // Info[a-z,A-Z,0-9,\-\_]+ proměnná začíná Info a pak jsou písmena, 99 // Info[a-z,A-Z,0-9,\-\_]+ proměnná začíná Info a pak jsou písmena,
100 // ) číslice, mínus a podtržítko 100 // ) číslice, mínus a podtržítko
101   101  
102 // Definice vzoru pro hledání hodnot proměnných ve tvaru = " Hodnota " 102 // Definice vzoru pro hledání hodnot proměnných ve tvaru = " Hodnota "
103 // Definice hodnot je ve tvaru $InfoXXX="YYY" a mohou být víceřádkové 103 // Definice hodnot je ve tvaru $InfoXXX="YYY" a mohou být víceřádkové
104 // ( a mohou obsahovat uvnitř další substituce uvozené $, které program 104 // ( a mohou obsahovat uvnitř další substituce uvozené $, které program
105 // zpracovává ale ne tady) 105 // zpracovává ale ne tady)
106 $PatternValue = '\s*=\s*"(?P<VarValue>[^"]*)"'; 106 $PatternValue = '\s*=\s*"(?P<VarValue>[^"]*)"';
107 // \s*=\s* rovná se volitelnými bílými znaky okolo 107 // \s*=\s* rovná se volitelnými bílými znaky okolo
108 // " hodnota v uvozovkách 108 // " hodnota v uvozovkách
109 // (?P<VarValue> parametr s názvem VarValue 109 // (?P<VarValue> parametr s názvem VarValue
110 // [^"]* hodnota nesmí obsahovat uvozovky 110 // [^"]* hodnota nesmí obsahovat uvozovky
111 // ) vracíme hodnotu bez uvozovek 111 // ) vracíme hodnotu bez uvozovek
112 // " konec uvozovek 112 // " konec uvozovek
113   113  
114 // Zparacování vzoru 114 // Zparacování vzoru
115 // ----------------- 115 // -----------------
116   116  
117 // Najdi na začátku stránky komentář a vykousni ho 117 // Najdi na začátku stránky komentář a vykousni ho
118 $pattern = '/^' .$PatternComment. '+/su'; 118 $pattern = '/^' .$PatternComment. '+/su';
119 $this->Page = preg_replace($pattern, '', $this->Page); 119 $this->Page = preg_replace($pattern, '', $this->Page);
120 // / oddělovač 120 // / oddělovač
121 // ^ od začátku řetězce (jen komentáře na začátku souboru) 121 // ^ od začátku řetězce (jen komentáře na začátku souboru)
122 // $PatternComment komentář (<!-- -->) s bílými znaky okolo 122 // $PatternComment komentář (<!-- -->) s bílými znaky okolo
123 // + alespoň jeden komentář 123 // + alespoň jeden komentář
124 // /su modifikátor, . zastupuje i odřádkování, utf8 124 // /su modifikátor, . zastupuje i odřádkování, utf8
125   125  
126   126  
127 // Najdi v templejtu substutuční proměnné a vytvoř v poli $Info 127 // Najdi v templejtu substutuční proměnné a vytvoř v poli $Info
128 // prázdné položky pro každou použitou proměnnou. Dělá se to proto, 128 // prázdné položky pro každou použitou proměnnou. Dělá se to proto,
129 // aby se na konci nepoužité proměnné nahradily prázdným řetězcem. 129 // aby se na konci nepoužité proměnné nahradily prázdným řetězcem.
130 $pattern = '/' .$PatternVar. '/su'; 130 $pattern = '/' .$PatternVar. '/su';
131 preg_match_all($pattern, $this->Page, $temp); 131 preg_match_all($pattern, $this->Page, $temp);
132 // / oddělovač 132 // / oddělovač
133 // .$PatternVar. proměnná ( $InfoXXX ) - parametr VarName 133 // .$PatternVar. proměnná ( $InfoXXX ) - parametr VarName
134 // /su modifikátor zajistí, že . zastupuje i odřádkování, utf8 134 // /su modifikátor zajistí, že . zastupuje i odřádkování, utf8
135 foreach($temp['VarName'] as $key => $value) 135 foreach($temp['VarName'] as $key => $value)
136 $this->Info[$value] = ''; 136 $this->Info[$value] = '';
137 unset($temp); 137 unset($temp);
138   138  
139 // Vytáhni proměnné a jejich hodnoty do pole $Info 139 // Vytáhni proměnné a jejich hodnoty do pole $Info
140 $pattern = '/' .$PatternVar.$PatternValue. '/su'; 140 $pattern = '/' .$PatternVar.$PatternValue. '/su';
141 // / oddělovač 141 // / oddělovač
142 // .$PatternVar. proměnná ( $InfoXXX ) - parametr VarName 142 // .$PatternVar. proměnná ( $InfoXXX ) - parametr VarName
143 // .$PatternValue. přiřazení ( = " Hodnota " ) - parametr VarValue 143 // .$PatternValue. přiřazení ( = " Hodnota " ) - parametr VarValue
144 // /su modifikátor, . zastupuje i odřádkování, UTF8 144 // /su modifikátor, . zastupuje i odřádkování, UTF8
145 preg_match_all($pattern, $this->Page, $temp); 145 preg_match_all($pattern, $this->Page, $temp);
146 foreach($temp['VarName'] as $key => $value) 146 foreach($temp['VarName'] as $key => $value)
147 $this->Info[$value] = $temp['VarValue'][$key]; 147 $this->Info[$value] = $temp['VarValue'][$key];
148 unset($temp); 148 unset($temp);
149   149  
150 // Vykousej zpracované definice proměnných (a komentáře před nimi) 150 // Vykousej zpracované definice proměnných (a komentáře před nimi)
151 $pattern = '/' .$PatternComment.'?'.$PatternVar.$PatternValue. '/su'; 151 $pattern = '/' .$PatternComment.'?'.$PatternVar.$PatternValue. '/su';
152 // / oddělovač 152 // / oddělovač
153 // .$PatternComment.'?' volitelný komentář před definicí 153 // .$PatternComment.'?' volitelný komentář před definicí
154 // .$PatternVar. proměnná ( $InfoXXX ) 154 // .$PatternVar. proměnná ( $InfoXXX )
155 // .$PatternValue. přiřazení ( = " Hodnota " ) 155 // .$PatternValue. přiřazení ( = " Hodnota " )
156 // /su modifikátor, . zastupuje i odřádkování, UTF8 156 // /su modifikátor, . zastupuje i odřádkování, UTF8
157 $this->Page = preg_replace($pattern, '', $this->Page); 157 $this->Page = preg_replace($pattern, '', $this->Page);
158 } 158 }
159 159
160 function Indent($StringData, $Indent) 160 function Indent($StringData, $Indent)
161 // Všechna odřádkování v řetězci $StringData odsadí o hodnotu $Indent pokud je 161 // Všechna odřádkování v řetězci $StringData odsadí o hodnotu $Indent pokud je
162 // $Indent číslo nebo o déllku řetězce $Indent pokud je to řetězec 162 // $Indent číslo nebo o déllku řetězce $Indent pokud je to řetězec
163 { 163 {
164 // Velikost odsazení (vyrob číslo) 164 // Velikost odsazení (vyrob číslo)
165 if (is_string($Indent)) 165 if (is_string($Indent))
166 $Num = mb_strlen($Indent,'utf-8'); 166 $Num = mb_strlen($Indent,'utf-8');
167 else 167 else
168 $Num = 0+$Indent; 168 $Num = 0+$Indent;
169   169  
170 // Odsazení 170 // Odsazení
171 return $StringData = $Indent.str_replace("\n", "\n".str_repeat(' ', $Num), $StringData); 171 return $StringData = $Indent.str_replace("\n", "\n".str_repeat(' ', $Num), $StringData);
172 } 172 }
173   173  
174   174  
175 /* 175 /*
176 function Substitute($Variables, $String) 176 function Substitute($Variables, $String)
177 // Nahradí proměnné v řetězci $String obsahem proměnných z pole $Variables 177 // Nahradí proměnné v řetězci $String obsahem proměnných z pole $Variables
178 // a vrátí výsledný řetězec 178 // a vrátí výsledný řetězec
179 { 179 {
180 if (is_array($Variables)) 180 if (is_array($Variables))
181 { 181 {
182 foreach($Variables as $Key => $Value) 182 foreach($Variables as $Key => $Value)
183 { 183 {
184 // Hledací vzor (hledáme proměnnou s názvem v $Key) 184 // Hledací vzor (hledáme proměnnou s názvem v $Key)
185 $Pattern = '\$'.$Key.'(?=[^a-z,A-Z,0-9,\-\_])'; 185 $Pattern = '\$'.$Key.'(?=[^a-z,A-Z,0-9,\-\_])';
186 // \$$Key hledáme $JmenoProměnné 186 // \$$Key hledáme $JmenoProměnné
187 // (?= následuje něco, co nemůže být jménem 187 // (?= následuje něco, co nemůže být jménem
188 // [^a-z,A-Z,0-9,\-\_] a nezajímá nás 188 // [^a-z,A-Z,0-9,\-\_] a nezajímá nás
189 // ) 189 // )
190   190  
191 // Vkládáme více řádek? 191 // Vkládáme více řádek?
192 $IsMultiline = !(strpos($Value, "\n") === FALSE); 192 $IsMultiline = !(strpos($Value, "\n") === FALSE);
193 193
194 if (!$IsMultiline) 194 if (!$IsMultiline)
195 { 195 {
196 // Vkládáme jednoduchý řetězec 196 // Vkládáme jednoduchý řetězec
197 $String = preg_replace('/'.$Pattern.'/su', $Value, $String); 197 $String = preg_replace('/'.$Pattern.'/su', $Value, $String);
198 // /su víceřádkové v UTF8 198 // /su víceřádkové v UTF8
199 } 199 }
200 else 200 else
201 { 201 {
202 // Vkládáme řetezec s odřádkováním - je třeba odsazovat 202 // Vkládáme řetezec s odřádkováním - je třeba odsazovat
203 $String = preg_replace('/(.*)'.$Pattern.'/ue', 203 $String = preg_replace('/(.*)'.$Pattern.'/ue',
204 "\$this->Indent(\$Value, '\\1')", 204 "\$this->Indent(\$Value, '\\1')",
205 $String); 205 $String);
206 // (.*) hledáme cokoli před vzorem -> první parametr 206 // (.*) hledáme cokoli před vzorem -> první parametr
207 // .$Pattern. proměnná 207 // .$Pattern. proměnná
208 // /ue UTF8, náhrada je php skriptem 208 // /ue UTF8, náhrada je php skriptem
209 } 209 }
210 } 210 }
211 } 211 }
212 212
213 return $String; 213 return $String;
214 } 214 }
215 */ 215 */
216   216  
217   217  
218 function Substitute($Variables, $String) 218 function Substitute($Variables, $String)
219 // Nahradí proměnné v řetězci $String obsahem proměnných z pole $Variables 219 // Nahradí proměnné v řetězci $String obsahem proměnných z pole $Variables
220 // a vrátí výsledný řetězec 220 // a vrátí výsledný řetězec
221 { 221 {
222 // Hledací vzor 222 // Hledací vzor
223 $Pattern = '/(.*?)\$(Info[a-z,A-Z,0-9,\-\_]+)(?=[^a-z,A-Z,0-9,\-\_])/ue'; 223 $Pattern = '/(.*?)\$(Info[a-z,A-Z,0-9,\-\_]+)(?=[^a-z,A-Z,0-9,\-\_])/ue';
224   224  
225 // Náhrada s kusem php kódu (nezapomeň, že preg_replace s přepínačem /e vrací oescapované řetězce) 225 // Náhrada s kusem php kódu (nezapomeň, že preg_replace s přepínačem /e vrací oescapované řetězce)
226 $String = preg_replace($Pattern, 226 $String = preg_replace($Pattern,
227 'isset($Variables[\'\2\']) 227 'isset($Variables[\'\2\'])
228 ? $this->Indent($Variables[\'\2\'], stripslashes(\'\1\')) 228 ? $this->Indent($Variables[\'\2\'], stripslashes(\'\1\'))
229 : stripslashes(\'\1\') 229 : stripslashes(\'\1\')
230 ', 230 ',
231 $String); 231 $String);
232 return $String; 232 return $String;
233 } 233 }
234   234  
235   235  
236 function SetVariable($VarName, $VarValue, $Wrap=0): void 236 function SetVariable($VarName, $VarValue, $Wrap=0): void
237 // Nastaví hodnotu proměnné 237 // Nastaví hodnotu proměnné
238 // Volitelně provede zálámání na zadaný počet znaků a odstranění nadbytečných mezer 238 // Volitelně provede zálámání na zadaný počet znaků a odstranění nadbytečných mezer
239 { 239 {
240 // Volitelné zalámání a odstranění bílých znaků 240 // Volitelné zalámání a odstranění bílých znaků
241 if ($Wrap!=0) 241 if ($Wrap!=0)
242 $VarValue = WrapString($VarValue, $Wrap); 242 $VarValue = WrapString($VarValue, $Wrap);
243 243
244 // Uložení do proměnných 244 // Uložení do proměnných
245 $this->Info[$VarName] = $VarValue; 245 $this->Info[$VarName] = $VarValue;
246 } 246 }
247 247
248   248  
249 function GetVariable($VarName) 249 function GetVariable($VarName)
250 // Vrátí hodnotu proměnné tak, jak je, včetně mezer a odřádkování 250 // Vrátí hodnotu proměnné tak, jak je, včetně mezer a odřádkování
251 { 251 {
252 if (isset($this->Info[$VarName])) 252 if (isset($this->Info[$VarName]))
253 return $this->Info[$VarName]; 253 return $this->Info[$VarName];
254 else 254 else
255 return ''; 255 return '';
256 } 256 }
257 257
258   258  
259 function GetString($VarName) 259 function GetString($VarName)
260 // Vrátí parametr jako jeden řetězec s redukovanými bílými znaky 260 // Vrátí parametr jako jeden řetězec s redukovanými bílými znaky
261 // Tedy bez odřádkování a nadbytečných mezer 261 // Tedy bez odřádkování a nadbytečných mezer
262 { 262 {
263 return WrapString($this->GetVariable($VarName), 0); 263 return WrapString($this->GetVariable($VarName), 0);
264 } 264 }
265   265  
266 266
267 function GetPage() 267 function GetPage()
268 // Provede substituce ve stránce a vrátí ji jako řetězec 268 // Provede substituce ve stránce a vrátí ji jako řetězec
269 // Substituce bere z proměnné $Info 269 // Substituce bere z proměnné $Info
270 { 270 {
271 // Proveď ve stránce substituce proměnných a vrať výsledek 271 // Proveď ve stránce substituce proměnných a vrať výsledek
272 return $this->Substitute($this->Info, $this->Page); 272 return $this->Substitute($this->Info, $this->Page);
273 } 273 }
274 } 274 }
275   275  
276   276  
277 ?> 277 ?>