1 | <?php |
||
2 | /** |
||
3 | * File MiniTemplator.class.php |
||
4 | * @package MiniTemplator |
||
5 | */ |
||
6 | |||
7 | /** |
||
8 | * A compact template engine for HTML files. |
||
9 | * |
||
10 | * Requires PHP 4.0.4 or newer. |
||
11 | * |
||
12 | * <pre> |
||
13 | * Template syntax: |
||
14 | * |
||
15 | * Variables: |
||
16 | * ${VariableName} |
||
17 | * |
||
18 | * Blocks: |
||
19 | * <!-- $BeginBlock BlockName --> |
||
20 | * ... block content ... |
||
21 | * <!-- $EndBlock BlockName --> |
||
22 | * |
||
23 | * Include a subtemplate: |
||
24 | * <!-- $Include RelativeFileName --> |
||
25 | * </pre> |
||
26 | * |
||
27 | * <pre> |
||
28 | * General remarks: |
||
29 | * - Variable names and block names are case-insensitive. |
||
30 | * - The same variable may be used multiple times within a template. |
||
31 | * - Blocks can be nested. |
||
32 | * - Multiple blocks with the same name may occur within a template. |
||
33 | * </pre> |
||
34 | * |
||
35 | * <pre> |
||
36 | * Public methods: |
||
37 | * readTemplateFromFile - Reads the template from a file. |
||
38 | * setTemplateString - Assigns a new template string. |
||
39 | * setVariable - Sets a template variable. |
||
40 | * setVariableEsc - Sets a template variable to an escaped string value. |
||
41 | * variableExists - Checks whether a template variable exists. |
||
42 | * addBlock - Adds an instance of a template block. |
||
43 | * blockExists - Checks whether a block exists. |
||
44 | * reset - Clears all variables and blocks. |
||
45 | * generateOutput - Generates the HTML page and writes it to the PHP output stream. |
||
46 | * generateOutputToFile - Generates the HTML page and writes it to a file. |
||
47 | * generateOutputToString - Generates the HTML page and writes it to a string. |
||
48 | * </pre> |
||
49 | * |
||
50 | * Home page: {@link http://www.source-code.biz/MiniTemplator}<br> |
||
51 | * License: This module is released under the GNU/LGPL license ({@link http://www.gnu.org/licenses/lgpl.html}).<br> |
||
52 | * Copyright 2003: Christian d'Heureuse, Inventec Informatik AG, Switzerland. All rights reserved.<br> |
||
53 | * This product is provided "as is" without warranty of any kind.<br> |
||
54 | * |
||
55 | * Version history:<br> |
||
56 | * 2001-10-24 Christian d'Heureuse (chdh): VBasic version created.<br> |
||
57 | * 2002-01-26 Markus Angst: ported to PHP4.<br> |
||
58 | * 2003-04-07 chdh: changes to adjust to Java version.<br> |
||
59 | * 2003-07-08 chdh: Method variableExists added. |
||
60 | * Method setVariable changed to trigger an error when the variable does not exist.<br> |
||
61 | * 2004-04-07 chdh: Parameter isOptional added to method setVariable. |
||
62 | * Licensing changed from GPL to LGPL.<br> |
||
63 | * 2004-04-18 chdh: Method blockExists added.<br> |
||
64 | * 2004-10-28 chdh:<br> |
||
65 | * Method setVariableEsc added.<br> |
||
66 | * Multiple blocks with the same name may now occur within a template.<br> |
||
67 | * No error ("unknown command") is generated any more, if a HTML comment starts with "${".<br> |
||
68 | * 2004-11-06 chdh:<br> |
||
69 | * "$Include" command implemented.<br> |
||
70 | * 2004-11-20 chdh:<br> |
||
71 | * "$Include" command changed so that the command text is not copied to the output file.<br> |
||
72 | */ |
||
73 | |||
74 | class MiniTemplator { |
||
75 | |||
76 | //--- public member variables --------------------------------------------------------------------------------------- |
||
77 | |||
78 | /** |
||
79 | * Base path for relative file names of subtemplates (for the $Include command). |
||
80 | * This path is prepended to the subtemplate file names. It must be set before |
||
81 | * readTemplateFromFile or setTemplateString. |
||
82 | * @access public |
||
83 | */ |
||
84 | var $subtemplateBasePath; |
||
85 | |||
86 | //--- private member variables -------------------------------------------------------------------------------------- |
||
87 | |||
88 | /**#@+ |
||
89 | * @access private |
||
90 | */ |
||
91 | |||
92 | var $maxNestingLevel = 50; // maximum number of block nestings |
||
93 | var $maxInclTemplateSize = 1000000; // maximum length of template string when including subtemplates |
||
94 | var $template; // Template file data |
||
95 | var $varTab; // variables table, array index is variable no |
||
96 | // Fields: |
||
97 | // varName // variable name |
||
98 | // varValue // variable value |
||
99 | var $varTabCnt; // no of entries used in VarTab |
||
100 | var $varNameToNoMap; // maps variable names to variable numbers |
||
101 | var $varRefTab; // variable references table |
||
102 | // Contains an entry for each variable reference in the template. Ordered by TemplatePos. |
||
103 | // Fields: |
||
104 | // varNo // variable no |
||
105 | // tPosBegin // template position of begin of variable reference |
||
106 | // tPosEnd // template position of end of variable reference |
||
107 | // blockNo // block no of the (innermost) block that contains this variable reference |
||
108 | // blockVarNo // block variable no. Index into BlockInstTab.BlockVarTab |
||
109 | var $varRefTabCnt; // no of entries used in VarRefTab |
||
110 | var $blockTab; // Blocks table, array index is block no |
||
111 | // Contains an entry for each block in the template. Ordered by TPosBegin. |
||
112 | // Fields: |
||
113 | // blockName // block name |
||
114 | // nextWithSameName; // block no of next block with same name or -1 (blocks are backward linked in relation to template position) |
||
115 | // tPosBegin // template position of begin of block |
||
116 | // tPosContentsBegin // template pos of begin of block contents |
||
117 | // tPosContentsEnd // template pos of end of block contents |
||
118 | // tPosEnd // template position of end of block |
||
119 | // nestingLevel // block nesting level |
||
120 | // parentBlockNo // block no of parent block |
||
121 | // definitionIsOpen // true while $BeginBlock processed but no $EndBlock |
||
122 | // instances // number of instances of this block |
||
123 | // firstBlockInstNo // block instance no of first instance of this block or -1 |
||
124 | // lastBlockInstNo // block instance no of last instance of this block or -1 |
||
125 | // currBlockInstNo // current block instance no, used during generation of output file |
||
126 | // blockVarCnt // no of variables in block |
||
127 | // blockVarNoToVarNoMap // maps block variable numbers to variable numbers |
||
128 | // firstVarRefNo // variable reference no of first variable of this block or -1 |
||
129 | var $blockTabCnt; // no of entries used in BlockTab |
||
130 | var $blockNameToNoMap; // maps block names to block numbers |
||
131 | var $openBlocksTab; |
||
132 | // During parsing, this table contains the block numbers of the open parent blocks (nested outer blocks). |
||
133 | // Indexed by the block nesting level. |
||
134 | var $blockInstTab; // block instances table |
||
135 | // This table contains an entry for each block instance that has been added. |
||
136 | // Indexed by BlockInstNo. |
||
137 | // Fields: |
||
138 | // blockNo // block number |
||
139 | // instanceLevel // instance level of this block |
||
140 | // InstanceLevel is an instance counter per block. |
||
141 | // (In contrast to blockInstNo, which is an instance counter over the instances of all blocks) |
||
142 | // parentInstLevel // instance level of parent block |
||
143 | // nextBlockInstNo // pointer to next instance of this block or -1 |
||
144 | // Forward chain for instances of same block. |
||
145 | // blockVarTab // block instance variables |
||
146 | var $blockInstTabCnt; // no of entries used in BlockInstTab |
||
147 | |||
148 | var $currentNestingLevel; // Current block nesting level during parsing. |
||
149 | var $templateValid; // true if a valid template is prepared |
||
150 | var $outputMode; // 0 = to PHP output stream, 1 = to file, 2 = to string |
||
151 | var $outputFileHandle; // file handle during writing of output file |
||
152 | var $outputError; // true when an output error occurred |
||
153 | var $outputString; // string buffer for the generated HTML page |
||
154 | |||
155 | /**#@-*/ |
||
156 | |||
157 | //--- constructor --------------------------------------------------------------------------------------------------- |
||
158 | |||
159 | /** |
||
160 | * Constructs a MiniTemplator object. |
||
161 | * @access public |
||
162 | */ |
||
163 | function __construct() { |
||
0 ignored issues
–
show
|
|||
164 | $this->templateValid = false; } |
||
165 | |||
166 | //--- template string handling -------------------------------------------------------------------------------------- |
||
167 | |||
168 | /** |
||
169 | * Reads the template from a file. |
||
170 | * @param string $fileName name of the file that contains the template. |
||
171 | * @return boolean true on success, false on error. |
||
172 | * @access public |
||
173 | */ |
||
174 | function readTemplateFromFile($fileName) { |
||
0 ignored issues
–
show
|
|||
175 | if (!$this->readFileIntoString($fileName, $s)) { |
||
176 | $this->triggerError("Error while reading template file ".$fileName."."); |
||
177 | return false; } |
||
178 | if (!$this->setTemplateString($s)) { |
||
179 | return false; |
||
180 | } |
||
181 | return true; } |
||
182 | |||
183 | /** |
||
184 | * Assigns a new template string. |
||
185 | * @param string $templateString contents of the template file. |
||
186 | * @return boolean true on success, false on error. |
||
187 | * @access public |
||
188 | */ |
||
189 | function setTemplateString($templateString) { |
||
0 ignored issues
–
show
|
|||
190 | $this->templateValid = false; |
||
191 | $this->template = $templateString; |
||
192 | if (!$this->parseTemplate()) { |
||
193 | return false; |
||
194 | } |
||
195 | $this->reset(); |
||
196 | $this->templateValid = true; |
||
197 | return true; } |
||
198 | |||
199 | /** |
||
200 | * Loads the template string for a subtemplate (used for the $Include command). |
||
201 | * @return boolean true on success, false on error. |
||
202 | * @access private |
||
203 | */ |
||
204 | function loadSubtemplate($subtemplateName, &$s) { |
||
0 ignored issues
–
show
|
|||
205 | $subtemplateFileName = $this->combineFileSystemPath($this->subtemplateBasePath, $subtemplateName); |
||
206 | if (!$this->readFileIntoString($subtemplateFileName, $s)) { |
||
207 | $this->triggerError("Error while reading subtemplate file ".$subtemplateFileName."."); |
||
208 | return false; } |
||
209 | return true; } |
||
210 | |||
211 | //--- template parsing ---------------------------------------------------------------------------------------------- |
||
212 | |||
213 | /** |
||
214 | * Parses the template. |
||
215 | * @return boolean true on success, false on error. |
||
216 | * @access private |
||
217 | */ |
||
218 | function parseTemplate() { |
||
0 ignored issues
–
show
|
|||
219 | $this->initParsing(); |
||
220 | $this->beginMainBlock(); |
||
221 | if (!$this->parseTemplateCommands()) { |
||
222 | return false; |
||
223 | } |
||
224 | $this->endMainBlock(); |
||
225 | if (!$this->checkBlockDefinitionsComplete()) { |
||
226 | return false; |
||
227 | } |
||
228 | if (!$this->parseTemplateVariables()) { |
||
229 | return false; |
||
230 | } |
||
231 | $this->associateVariablesWithBlocks(); |
||
232 | return true; } |
||
233 | |||
234 | /** |
||
235 | * @access private |
||
236 | */ |
||
237 | function initParsing() { |
||
0 ignored issues
–
show
|
|||
238 | $this->varTab = array(); |
||
239 | $this->varTabCnt = 0; |
||
240 | $this->varNameToNoMap = array(); |
||
241 | $this->varRefTab = array(); |
||
242 | $this->varRefTabCnt = 0; |
||
243 | $this->blockTab = array(); |
||
244 | $this->blockTabCnt = 0; |
||
245 | $this->blockNameToNoMap = array(); |
||
246 | $this->openBlocksTab = array(); } |
||
247 | |||
248 | /** |
||
249 | * Registers the main block. |
||
250 | * The main block is an implicitly defined block that covers the whole template. |
||
251 | * @access private |
||
252 | */ |
||
253 | function beginMainBlock() { |
||
0 ignored issues
–
show
|
|||
254 | $blockNo = 0; |
||
255 | $this->registerBlock('@@InternalMainBlock@@', $blockNo); |
||
256 | $bte = & $this->blockTab[$blockNo]; |
||
257 | $bte['tPosBegin'] = 0; |
||
258 | $bte['tPosContentsBegin'] = 0; |
||
259 | $bte['nestingLevel'] = 0; |
||
260 | $bte['parentBlockNo'] = -1; |
||
261 | $bte['definitionIsOpen'] = true; |
||
262 | $this->openBlocksTab[0] = $blockNo; |
||
263 | $this->currentNestingLevel = 1; } |
||
264 | |||
265 | /** |
||
266 | * Completes the main block registration. |
||
267 | * @access private |
||
268 | */ |
||
269 | function endMainBlock() { |
||
0 ignored issues
–
show
|
|||
270 | $bte = & $this->blockTab[0]; |
||
271 | $bte['tPosContentsEnd'] = strlen($this->template); |
||
272 | $bte['tPosEnd'] = strlen($this->template); |
||
273 | $bte['definitionIsOpen'] = false; |
||
274 | $this->currentNestingLevel -= 1; } |
||
275 | |||
276 | /** |
||
277 | * Parses commands within the template in the format "<!-- $command parameters -->". |
||
278 | * @return boolean true on success, false on error. |
||
279 | * @access private |
||
280 | */ |
||
281 | function parseTemplateCommands() { |
||
0 ignored issues
–
show
|
|||
282 | $p = 0; |
||
283 | while (true) { |
||
284 | $p0 = strpos($this->template, '<!--', $p); |
||
285 | if ($p0 === false) { |
||
286 | break; |
||
287 | } |
||
288 | $p = strpos($this->template, '-->', $p0); |
||
289 | if ($p === false) { |
||
290 | $this->triggerError("Invalid HTML comment in template at offset $p0."); |
||
291 | return false; } |
||
292 | $p += 3; |
||
293 | $cmdL = substr($this->template, $p0 + 4, $p - $p0 - 7); |
||
294 | if (!$this->processTemplateCommand($cmdL, $p0, $p, $resumeFromStart)) { |
||
295 | return false; |
||
296 | } |
||
297 | if ($resumeFromStart) { |
||
298 | $p = $p0; |
||
299 | } |
||
300 | } |
||
301 | return true; } |
||
302 | |||
303 | /** |
||
304 | * @return boolean true on success, false on error. |
||
305 | * @access private |
||
306 | */ |
||
307 | function processTemplateCommand($cmdL, $cmdTPosBegin, $cmdTPosEnd, &$resumeFromStart) { |
||
0 ignored issues
–
show
|
|||
308 | $resumeFromStart = false; |
||
309 | $p = 0; |
||
310 | $cmd = ''; |
||
311 | if (!$this->parseWord($cmdL, $p, $cmd)) { |
||
312 | return true; |
||
313 | } |
||
314 | $parms = substr($cmdL, $p); |
||
315 | switch (strtoupper($cmd)) { |
||
316 | case '$BEGINBLOCK': |
||
317 | if (!$this->processBeginBlockCmd($parms, $cmdTPosBegin, $cmdTPosEnd)) { |
||
318 | return false; |
||
319 | } |
||
320 | break; |
||
321 | case '$ENDBLOCK': |
||
322 | if (!$this->processEndBlockCmd($parms, $cmdTPosBegin, $cmdTPosEnd)) { |
||
323 | return false; |
||
324 | } |
||
325 | break; |
||
326 | case '$INCLUDE': |
||
327 | if (!$this->processincludeCmd($parms, $cmdTPosBegin, $cmdTPosEnd)) { |
||
328 | return false; |
||
329 | } |
||
330 | $resumeFromStart = true; |
||
331 | break; |
||
332 | default: |
||
333 | if ($cmd{0} == '$' && !(strlen($cmd) >= 2 && $cmd{1} == '{')) { |
||
334 | $this->triggerError("Unknown command \"$cmd\" in template at offset $cmdTPosBegin."); |
||
335 | return false; }} |
||
336 | return true; } |
||
337 | |||
338 | /** |
||
339 | * Processes the $BeginBlock command. |
||
340 | * @return boolean true on success, false on error. |
||
341 | * @access private |
||
342 | */ |
||
343 | function processBeginBlockCmd($parms, $cmdTPosBegin, $cmdTPosEnd) { |
||
0 ignored issues
–
show
|
|||
344 | $p = 0; |
||
345 | if (!$this->parseWord($parms, $p, $blockName)) { |
||
346 | $this->triggerError("Missing block name in \$BeginBlock command in template at offset $cmdTPosBegin."); |
||
347 | return false; } |
||
348 | if (trim(substr($parms, $p)) != '') { |
||
349 | $this->triggerError("Extra parameter in \$BeginBlock command in template at offset $cmdTPosBegin."); |
||
350 | return false; } |
||
351 | $this->registerBlock($blockName, $blockNo); |
||
352 | $btr = & $this->blockTab[$blockNo]; |
||
353 | $btr['tPosBegin'] = $cmdTPosBegin; |
||
354 | $btr['tPosContentsBegin'] = $cmdTPosEnd; |
||
355 | $btr['nestingLevel'] = $this->currentNestingLevel; |
||
356 | $btr['parentBlockNo'] = $this->openBlocksTab[$this->currentNestingLevel - 1]; |
||
357 | $this->openBlocksTab[$this->currentNestingLevel] = $blockNo; |
||
358 | $this->currentNestingLevel += 1; |
||
359 | if ($this->currentNestingLevel > $this->maxNestingLevel) { |
||
360 | $this->triggerError("Block nesting overflow in template at offset $cmdTPosBegin."); |
||
361 | return false; } |
||
362 | return true; } |
||
363 | |||
364 | /** |
||
365 | * Processes the $EndBlock command. |
||
366 | * @return boolean true on success, false on error. |
||
367 | * @access private |
||
368 | */ |
||
369 | function processEndBlockCmd($parms, $cmdTPosBegin, $cmdTPosEnd) { |
||
0 ignored issues
–
show
|
|||
370 | $p = 0; |
||
371 | if (!$this->parseWord($parms, $p, $blockName)) { |
||
372 | $this->triggerError("Missing block name in \$EndBlock command in template at offset $cmdTPosBegin."); |
||
373 | return false; } |
||
374 | if (trim(substr($parms, $p)) != '') { |
||
375 | $this->triggerError("Extra parameter in \$EndBlock command in template at offset $cmdTPosBegin."); |
||
376 | return false; } |
||
377 | if (!$this->lookupBlockName($blockName, $blockNo)) { |
||
378 | $this->triggerError("Undefined block name \"$blockName\" in \$EndBlock command in template at offset $cmdTPosBegin."); |
||
379 | return false; } |
||
380 | $this->currentNestingLevel -= 1; |
||
381 | $btr = & $this->blockTab[$blockNo]; |
||
382 | if (!$btr['definitionIsOpen']) { |
||
383 | $this->triggerError("Multiple \$EndBlock command for block \"$blockName\" in template at offset $cmdTPosBegin."); |
||
384 | return false; } |
||
385 | if ($btr['nestingLevel'] != $this->currentNestingLevel) { |
||
386 | $this->triggerError("Block nesting level mismatch at \$EndBlock command for block \"$blockName\" in template at offset $cmdTPosBegin."); |
||
387 | return false; } |
||
388 | $btr['tPosContentsEnd'] = $cmdTPosBegin; |
||
389 | $btr['tPosEnd'] = $cmdTPosEnd; |
||
390 | $btr['definitionIsOpen'] = false; |
||
391 | return true; } |
||
392 | |||
393 | /** |
||
394 | * @access private |
||
395 | */ |
||
396 | function registerBlock($blockName, &$blockNo) { |
||
0 ignored issues
–
show
|
|||
397 | $blockNo = $this->blockTabCnt++; |
||
398 | $btr = & $this->blockTab[$blockNo]; |
||
399 | $btr = array(); |
||
400 | $btr['blockName'] = $blockName; |
||
401 | if (!$this->lookupBlockName($blockName, $btr['nextWithSameName'])) { |
||
402 | $btr['nextWithSameName'] = -1; |
||
403 | } |
||
404 | $btr['definitionIsOpen'] = true; |
||
405 | $btr['instances'] = 0; |
||
406 | $btr['firstBlockInstNo'] = -1; |
||
407 | $btr['lastBlockInstNo'] = -1; |
||
408 | $btr['blockVarCnt'] = 0; |
||
409 | $btr['firstVarRefNo'] = -1; |
||
410 | $btr['blockVarNoToVarNoMap'] = array(); |
||
411 | $this->blockNameToNoMap[strtoupper($blockName)] = $blockNo; } |
||
412 | |||
413 | /** |
||
414 | * Checks that all block definitions are closed. |
||
415 | * @return boolean true on success, false on error. |
||
416 | * @access private |
||
417 | */ |
||
418 | function checkBlockDefinitionsComplete() { |
||
0 ignored issues
–
show
|
|||
419 | for ($blockNo = 0; $blockNo < $this->blockTabCnt; $blockNo++) { |
||
420 | $btr = & $this->blockTab[$blockNo]; |
||
421 | if ($btr['definitionIsOpen']) { |
||
422 | $this->triggerError("Missing \$EndBlock command in template for block ".$btr['blockName']."."); |
||
423 | return false; }} |
||
424 | if ($this->currentNestingLevel != 0) { |
||
425 | $this->triggerError("Block nesting level error at end of template."); |
||
426 | return false; } |
||
427 | return true; } |
||
428 | |||
429 | /** |
||
430 | * Processes the $Include command. |
||
431 | * @return boolean true on success, false on error. |
||
432 | * @access private |
||
433 | */ |
||
434 | function processIncludeCmd($parms, $cmdTPosBegin, $cmdTPosEnd) { |
||
0 ignored issues
–
show
|
|||
435 | $p = 0; |
||
436 | if (!$this->parseWordOrQuotedString($parms, $p, $subtemplateName)) { |
||
437 | $this->triggerError("Missing or invalid subtemplate name in \$Include command in template at offset $cmdTPosBegin."); |
||
438 | return false; } |
||
439 | if (trim(substr($parms, $p)) != '') { |
||
440 | $this->triggerError("Extra parameter in \$include command in template at offset $cmdTPosBegin."); |
||
441 | return false; } |
||
442 | return $this->insertSubtemplate($subtemplateName, $cmdTPosBegin, $cmdTPosEnd); } |
||
443 | |||
444 | /** |
||
445 | * Processes the $Include command. |
||
446 | * @return boolean true on success, false on error. |
||
447 | * @access private |
||
448 | */ |
||
449 | function insertSubtemplate($subtemplateName, $tPos1, $tPos2) { |
||
0 ignored issues
–
show
|
|||
450 | if (strlen($this->template) > $this->maxInclTemplateSize) { |
||
451 | $this->triggerError("Subtemplate include aborted because the internal template string is longer than $this->maxInclTemplateSize characters."); |
||
452 | return false; } |
||
453 | if (!$this->loadSubtemplate($subtemplateName, $subtemplate)) { |
||
454 | return false; |
||
455 | } |
||
456 | // (Copying the template to insert a subtemplate is a bit slow. In a future implementation of MiniTemplator, |
||
457 | // a table could be used that contains references to the string fragments.) |
||
458 | $this->template = substr($this->template, 0, $tPos1).$subtemplate.substr($this->template, $tPos2); |
||
459 | return true; } |
||
460 | |||
461 | /** |
||
462 | * Parses variable references within the template in the format "${VarName}". |
||
463 | * @return boolean true on success, false on error. |
||
464 | * @access private |
||
465 | */ |
||
466 | function parseTemplateVariables() { |
||
0 ignored issues
–
show
|
|||
467 | $p = 0; |
||
468 | while (true) { |
||
469 | $p = strpos($this->template, '${', $p); |
||
470 | if ($p === false) { |
||
471 | break; |
||
472 | } |
||
473 | $p0 = $p; |
||
474 | $p = strpos($this->template, '}', $p); |
||
475 | if ($p === false) { |
||
476 | $this->triggerError("Invalid variable reference in template at offset $p0."); |
||
477 | return false; } |
||
478 | $p += 1; |
||
479 | $varName = trim(substr($this->template, $p0 + 2, $p - $p0 - 3)); |
||
480 | if (strlen($varName) == 0) { |
||
481 | $this->triggerError("Empty variable name in template at offset $p0."); |
||
482 | return false; } |
||
483 | $this->registerVariableReference($varName, $p0, $p); } |
||
484 | return true; } |
||
485 | |||
486 | /** |
||
487 | * @access private |
||
488 | */ |
||
489 | function registerVariableReference($varName, $tPosBegin, $tPosEnd) { |
||
0 ignored issues
–
show
|
|||
490 | if (!$this->lookupVariableName($varName, $varNo)) { |
||
491 | $this->registerVariable($varName, $varNo); |
||
492 | } |
||
493 | $varRefNo = $this->varRefTabCnt++; |
||
494 | $vrtr = & $this->varRefTab[$varRefNo]; |
||
495 | $vrtr = array(); |
||
496 | $vrtr['tPosBegin'] = $tPosBegin; |
||
497 | $vrtr['tPosEnd'] = $tPosEnd; |
||
498 | $vrtr['varNo'] = $varNo; } |
||
499 | |||
500 | /** |
||
501 | * @access private |
||
502 | */ |
||
503 | function registerVariable($varName, &$varNo) { |
||
0 ignored issues
–
show
|
|||
504 | $varNo = $this->varTabCnt++; |
||
505 | $vtr = & $this->varTab[$varNo]; |
||
506 | $vtr = array(); |
||
507 | $vtr['varName'] = $varName; |
||
508 | $vtr['varValue'] = ''; |
||
509 | $this->varNameToNoMap[strtoupper($varName)] = $varNo; } |
||
510 | |||
511 | /** |
||
512 | * Associates variable references with blocks. |
||
513 | * @access private |
||
514 | */ |
||
515 | function associateVariablesWithBlocks() { |
||
0 ignored issues
–
show
|
|||
516 | $varRefNo = 0; |
||
517 | $activeBlockNo = 0; |
||
518 | $nextBlockNo = 1; |
||
519 | while ($varRefNo < $this->varRefTabCnt) { |
||
520 | $vrtr = & $this->varRefTab[$varRefNo]; |
||
521 | $varRefTPos = $vrtr['tPosBegin']; |
||
522 | $varNo = $vrtr['varNo']; |
||
523 | if ($varRefTPos >= $this->blockTab[$activeBlockNo]['tPosEnd']) { |
||
524 | $activeBlockNo = $this->blockTab[$activeBlockNo]['parentBlockNo']; |
||
525 | continue; } |
||
526 | if ($nextBlockNo < $this->blockTabCnt) { |
||
527 | if ($varRefTPos >= $this->blockTab[$nextBlockNo]['tPosBegin']) { |
||
528 | $activeBlockNo = $nextBlockNo; |
||
529 | $nextBlockNo += 1; |
||
530 | continue; }} |
||
531 | $btr = & $this->blockTab[$activeBlockNo]; |
||
532 | if ($varRefTPos < $btr['tPosBegin']) { |
||
533 | $this->programLogicError(1); |
||
534 | } |
||
535 | $blockVarNo = $btr['blockVarCnt']++; |
||
536 | $btr['blockVarNoToVarNoMap'][$blockVarNo] = $varNo; |
||
537 | if ($btr['firstVarRefNo'] == -1) { |
||
538 | $btr['firstVarRefNo'] = $varRefNo; |
||
539 | } |
||
540 | $vrtr['blockNo'] = $activeBlockNo; |
||
541 | $vrtr['blockVarNo'] = $blockVarNo; |
||
542 | $varRefNo += 1; }} |
||
543 | |||
544 | //--- build up (template variables and blocks) ---------------------------------------------------------------------- |
||
545 | |||
546 | /** |
||
547 | * Clears all variables and blocks. |
||
548 | * This method can be used to produce another HTML page with the same |
||
549 | * template. It is faster than creating another MiniTemplator object, |
||
550 | * because the template does not have to be parsed again. |
||
551 | * All variable values are cleared and all added block instances are deleted. |
||
552 | * @access public |
||
553 | */ |
||
554 | function reset() { |
||
0 ignored issues
–
show
|
|||
555 | for ($varNo = 0; $varNo < $this->varTabCnt; $varNo++) { |
||
556 | $this->varTab[$varNo]['varValue'] = ''; |
||
557 | } |
||
558 | for ($blockNo = 0; $blockNo < $this->blockTabCnt; $blockNo++) { |
||
559 | $btr = & $this->blockTab[$blockNo]; |
||
560 | $btr['instances'] = 0; |
||
561 | $btr['firstBlockInstNo'] = -1; |
||
562 | $btr['lastBlockInstNo'] = -1; } |
||
563 | $this->blockInstTab = array(); |
||
564 | $this->blockInstTabCnt = 0; } |
||
565 | |||
566 | /** |
||
567 | * Sets a template variable. |
||
568 | * For variables that are used in blocks, the variable value |
||
569 | * must be set before {@link addBlock} is called. |
||
570 | * @param string $variableName the name of the variable to be set. |
||
571 | * @param string $variableValue the new value of the variable. |
||
572 | * @param boolean $isOptional Specifies whether an error should be |
||
573 | * generated when the variable does not exist in the template. If |
||
574 | * $isOptional is false and the variable does not exist, an error is |
||
575 | * generated. |
||
576 | * @return boolean true on success, or false on error (e.g. when no |
||
577 | * variable with the specified name exists in the template and |
||
578 | * $isOptional is false). |
||
579 | * @access public |
||
580 | */ |
||
581 | function setVariable($variableName, $variableValue, $isOptional = false) { |
||
0 ignored issues
–
show
|
|||
582 | if (!$this->templateValid) {$this->triggerError("Template not valid."); return false; } |
||
583 | if (!$this->lookupVariableName($variableName, $varNo)) { |
||
584 | if ($isOptional) { |
||
585 | return true; |
||
586 | } |
||
587 | $this->triggerError("Variable \"$variableName\" not defined in template."); |
||
588 | return false; } |
||
589 | $this->varTab[$varNo]['varValue'] = $variableValue; |
||
590 | return true; } |
||
591 | |||
592 | /** |
||
593 | * Sets a template variable to an escaped string. |
||
594 | * This method is identical to (@link setVariable), except that |
||
595 | * the characters <, >, &, ' and " of variableValue are |
||
596 | * replaced by their corresponding HTML/XML character entity codes. |
||
597 | * For variables that are used in blocks, the variable value |
||
598 | * must be set before {@link addBlock} is called. |
||
599 | * @param string $variableName the name of the variable to be set. |
||
600 | * @param string $variableValue the new value of the variable. Special HTML/XML characters are escaped. |
||
601 | * @param boolean $isOptional Specifies whether an error should be |
||
602 | * generated when the variable does not exist in the template. If |
||
603 | * $isOptional is false and the variable does not exist, an error is |
||
604 | * generated. |
||
605 | * @return boolean true on success, or false on error (e.g. when no |
||
606 | * variable with the specified name exists in the template and |
||
607 | * $isOptional is false). |
||
608 | * @access public |
||
609 | */ |
||
610 | function setVariableEsc($variableName, $variableValue, $isOptional = false) { |
||
0 ignored issues
–
show
|
|||
611 | return $this->setVariable($variableName, htmlspecialchars($variableValue, ENT_QUOTES), $isOptional); } |
||
612 | |||
613 | /** |
||
614 | * Checks whether a variable with the specified name exists within the template. |
||
615 | * @param string $variableName the name of the variable. |
||
616 | * @return boolean true if the variable exists, or false when no |
||
617 | * variable with the specified name exists in the template. |
||
618 | * @access public |
||
619 | */ |
||
620 | function variableExists($variableName) { |
||
0 ignored issues
–
show
|
|||
621 | if (!$this->templateValid) {$this->triggerError("Template not valid."); return false; } |
||
622 | return $this->lookupVariableName($variableName, $varNo); } |
||
623 | |||
624 | /** |
||
625 | * Adds an instance of a template block. |
||
626 | * If the block contains variables, these variables must be set |
||
627 | * before the block is added. |
||
628 | * If the block contains subblocks (nested blocks), the subblocks |
||
629 | * must be added before this block is added. |
||
630 | * If multiple blocks exist with the specified name, an instance |
||
631 | * is added for each block occurence. |
||
632 | * @param string blockName the name of the block to be added. |
||
0 ignored issues
–
show
The type
blockName was not found. Maybe you did not declare it correctly or list all dependencies?
The issue could also be caused by a filter entry in the build configuration.
If the path has been excluded in your configuration, e.g. filter:
dependency_paths: ["lib/*"]
For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths ![]() |
|||
633 | * @return boolean true on success, false on error (e.g. when no |
||
634 | * block with the specified name exists in the template). |
||
635 | * @access public |
||
636 | */ |
||
637 | function addBlock($blockName) { |
||
0 ignored issues
–
show
|
|||
638 | if (!$this->templateValid) {$this->triggerError("Template not valid."); return false; } |
||
639 | if (!$this->lookupBlockName($blockName, $blockNo)) { |
||
640 | $this->triggerError("Block \"$blockName\" not defined in template."); |
||
641 | return false; } |
||
642 | while ($blockNo != -1) { |
||
643 | $this->addBlockByNo($blockNo); |
||
644 | $blockNo = $this->blockTab[$blockNo]['nextWithSameName']; } |
||
645 | return true; } |
||
646 | |||
647 | /** |
||
648 | * @access private |
||
649 | */ |
||
650 | function addBlockByNo($blockNo) { |
||
0 ignored issues
–
show
|
|||
651 | $btr = & $this->blockTab[$blockNo]; |
||
652 | $this->registerBlockInstance($blockInstNo); |
||
653 | $bitr = & $this->blockInstTab[$blockInstNo]; |
||
654 | if ($btr['firstBlockInstNo'] == -1) { |
||
655 | $btr['firstBlockInstNo'] = $blockInstNo; |
||
656 | } |
||
657 | if ($btr['lastBlockInstNo'] != -1) { |
||
658 | $this->blockInstTab[$btr['lastBlockInstNo']]['nextBlockInstNo'] = $blockInstNo; |
||
659 | } |
||
660 | // set forward pointer of chain |
||
661 | $btr['lastBlockInstNo'] = $blockInstNo; |
||
662 | $parentBlockNo = $btr['parentBlockNo']; |
||
663 | $blockVarCnt = $btr['blockVarCnt']; |
||
664 | $bitr['blockNo'] = $blockNo; |
||
665 | $bitr['instanceLevel'] = $btr['instances']++; |
||
666 | if ($parentBlockNo == -1) { |
||
667 | $bitr['parentInstLevel'] = -1; |
||
668 | } else { |
||
669 | $bitr['parentInstLevel'] = $this->blockTab[$parentBlockNo]['instances']; |
||
670 | } |
||
671 | $bitr['nextBlockInstNo'] = -1; |
||
672 | $bitr['blockVarTab'] = array(); |
||
673 | // copy instance variables for this block |
||
674 | for ($blockVarNo = 0; $blockVarNo < $blockVarCnt; $blockVarNo++) { |
||
675 | $varNo = $btr['blockVarNoToVarNoMap'][$blockVarNo]; |
||
676 | $bitr['blockVarTab'][$blockVarNo] = $this->varTab[$varNo]['varValue']; }} |
||
677 | |||
678 | /** |
||
679 | * @access private |
||
680 | */ |
||
681 | function registerBlockInstance(&$blockInstNo) { |
||
0 ignored issues
–
show
|
|||
682 | $blockInstNo = $this->blockInstTabCnt++; } |
||
683 | |||
684 | /** |
||
685 | * Checks whether a block with the specified name exists within the template. |
||
686 | * @param string $blockName the name of the block. |
||
687 | * @return boolean true if the block exists, or false when no |
||
688 | * block with the specified name exists in the template. |
||
689 | * @access public |
||
690 | */ |
||
691 | function blockExists($blockName) { |
||
0 ignored issues
–
show
|
|||
692 | if (!$this->templateValid) {$this->triggerError("Template not valid."); return false; } |
||
693 | return $this->lookupBlockName($blockName, $blockNo); } |
||
694 | |||
695 | //--- output generation --------------------------------------------------------------------------------------------- |
||
696 | |||
697 | /** |
||
698 | * Generates the HTML page and writes it to the PHP output stream. |
||
699 | * @return boolean true on success, false on error. |
||
700 | * @access public |
||
701 | */ |
||
702 | function generateOutput() { |
||
0 ignored issues
–
show
|
|||
703 | $this->outputMode = 0; |
||
704 | if (!$this->generateOutputPage()) { |
||
705 | return false; |
||
706 | } |
||
707 | return true; } |
||
708 | |||
709 | /** |
||
710 | * Generates the HTML page and writes it to a file. |
||
711 | * @param string $fileName name of the output file. |
||
712 | * @return boolean true on success, false on error. |
||
713 | * @access public |
||
714 | */ |
||
715 | function generateOutputToFile($fileName) { |
||
0 ignored issues
–
show
|
|||
716 | $fh = fopen($fileName, "wb"); |
||
717 | if ($fh === false) { |
||
718 | return false; |
||
719 | } |
||
720 | $this->outputMode = 1; |
||
721 | $this->outputFileHandle = $fh; |
||
722 | $ok = $this->generateOutputPage(); |
||
723 | fclose($fh); |
||
724 | return $ok; } |
||
725 | |||
726 | /** |
||
727 | * Generates the HTML page and writes it to a string. |
||
728 | * @param string $outputString variable that receives |
||
729 | * the contents of the generated HTML page. |
||
730 | * @return boolean true on success, false on error. |
||
731 | * @access public |
||
732 | */ |
||
733 | function generateOutputToString(&$outputString) { |
||
0 ignored issues
–
show
|
|||
734 | $outputString = "Error"; |
||
735 | $this->outputMode = 2; |
||
736 | $this->outputString = ""; |
||
737 | if (!$this->generateOutputPage()) { |
||
738 | return false; |
||
739 | } |
||
740 | $outputString = $this->outputString; |
||
741 | return true; } |
||
742 | |||
743 | /** |
||
744 | * @access private |
||
745 | * @return boolean true on success, false on error. |
||
746 | */ |
||
747 | function generateOutputPage() { |
||
0 ignored issues
–
show
|
|||
748 | if (!$this->templateValid) {$this->triggerError("Template not valid."); return false; } |
||
749 | if ($this->blockTab[0]['instances'] == 0) { |
||
750 | $this->addBlockByNo(0); |
||
751 | } |
||
752 | // add main block |
||
753 | for ($blockNo = 0; $blockNo < $this->blockTabCnt; $blockNo++) { |
||
754 | $btr = & $this->blockTab[$blockNo]; |
||
755 | $btr['currBlockInstNo'] = $btr['firstBlockInstNo']; } |
||
756 | $this->outputError = false; |
||
757 | $this->writeBlockInstances(0, -1); |
||
758 | if ($this->outputError) { |
||
759 | return false; |
||
760 | } |
||
761 | return true; } |
||
762 | |||
763 | /** |
||
764 | * Writes all instances of a block that are contained within a specific |
||
765 | * parent block instance. |
||
766 | * Called recursively. |
||
767 | * @access private |
||
768 | */ |
||
769 | function writeBlockInstances($blockNo, $parentInstLevel) { |
||
0 ignored issues
–
show
|
|||
770 | $btr = & $this->blockTab[$blockNo]; |
||
771 | while (!$this->outputError) { |
||
772 | $blockInstNo = $btr['currBlockInstNo']; |
||
773 | if ($blockInstNo == -1) { |
||
774 | break; |
||
775 | } |
||
776 | $bitr = & $this->blockInstTab[$blockInstNo]; |
||
777 | if ($bitr['parentInstLevel'] < $parentInstLevel) { |
||
778 | $this->programLogicError(2); |
||
779 | } |
||
780 | if ($bitr['parentInstLevel'] > $parentInstLevel) { |
||
781 | break; |
||
782 | } |
||
783 | $this->writeBlockInstance($blockInstNo); |
||
784 | $btr['currBlockInstNo'] = $bitr['nextBlockInstNo']; }} |
||
785 | |||
786 | /** |
||
787 | * @access private |
||
788 | */ |
||
789 | function writeBlockInstance($blockInstNo) { |
||
0 ignored issues
–
show
|
|||
790 | $bitr = & $this->blockInstTab[$blockInstNo]; |
||
791 | $blockNo = $bitr['blockNo']; |
||
792 | $btr = & $this->blockTab[$blockNo]; |
||
793 | $tPos = $btr['tPosContentsBegin']; |
||
794 | $subBlockNo = $blockNo + 1; |
||
795 | $varRefNo = $btr['firstVarRefNo']; |
||
796 | while (!$this->outputError) { |
||
797 | $tPos2 = $btr['tPosContentsEnd']; |
||
798 | $kind = 0; // assume end-of-block |
||
799 | if ($varRefNo != -1 && $varRefNo < $this->varRefTabCnt) { // check for variable reference |
||
800 | $vrtr = & $this->varRefTab[$varRefNo]; |
||
801 | if ($vrtr['tPosBegin'] < $tPos) { |
||
802 | $varRefNo += 1; |
||
803 | continue; } |
||
804 | if ($vrtr['tPosBegin'] < $tPos2) { |
||
805 | $tPos2 = $vrtr['tPosBegin']; |
||
806 | $kind = 1; }} |
||
807 | if ($subBlockNo < $this->blockTabCnt) { // check for subblock |
||
808 | $subBtr = & $this->blockTab[$subBlockNo]; |
||
809 | if ($subBtr['tPosBegin'] < $tPos) { |
||
810 | $subBlockNo += 1; |
||
811 | continue; } |
||
812 | if ($subBtr['tPosBegin'] < $tPos2) { |
||
813 | $tPos2 = $subBtr['tPosBegin']; |
||
814 | $kind = 2; }} |
||
815 | if ($tPos2 > $tPos) { |
||
816 | $this->writeString(substr($this->template, $tPos, $tPos2 - $tPos)); |
||
817 | } |
||
818 | switch ($kind) { |
||
819 | case 0: // end of block |
||
820 | return; |
||
821 | case 1: // variable |
||
822 | $vrtr = & $this->varRefTab[$varRefNo]; |
||
823 | if ($vrtr['blockNo'] != $blockNo) { |
||
824 | $this->programLogicError(4); |
||
825 | } |
||
826 | $variableValue = $bitr['blockVarTab'][$vrtr['blockVarNo']]; |
||
827 | $this->writeString($variableValue); |
||
828 | $tPos = $vrtr['tPosEnd']; |
||
829 | $varRefNo += 1; |
||
830 | break; |
||
831 | case 2: // sub block |
||
832 | $subBtr = & $this->blockTab[$subBlockNo]; |
||
833 | if ($subBtr['parentBlockNo'] != $blockNo) { |
||
834 | $this->programLogicError(3); |
||
835 | } |
||
836 | $this->writeBlockInstances($subBlockNo, $bitr['instanceLevel']); // recursive call |
||
837 | $tPos = $subBtr['tPosEnd']; |
||
838 | $subBlockNo += 1; |
||
839 | break; }}} |
||
840 | |||
841 | /** |
||
842 | * @access private |
||
843 | */ |
||
844 | function writeString($s) { |
||
0 ignored issues
–
show
|
|||
845 | if ($this->outputError) { |
||
846 | return; |
||
847 | } |
||
848 | switch ($this->outputMode) { |
||
849 | case 0: |
||
850 | print($s); |
||
851 | break; |
||
852 | case 1: |
||
853 | $rc = fwrite($this->outputFileHandle, $s); |
||
854 | if ($rc === false) { |
||
855 | $this->outputError = true; |
||
856 | } |
||
857 | break; |
||
858 | case 2: |
||
859 | $this->outputString .= $s; |
||
860 | break; |
||
861 | } |
||
862 | } |
||
863 | |||
864 | //--- name lookup routines ------------------------------------------------------------------------------------------ |
||
865 | |||
866 | /** |
||
867 | * Maps variable name to variable number. |
||
868 | * @return boolean true on success, false if the variable is not found. |
||
869 | * @access private |
||
870 | */ |
||
871 | function lookupVariableName($varName, &$varNo) { |
||
0 ignored issues
–
show
|
|||
872 | $x = & $this->varNameToNoMap[strtoupper($varName)]; |
||
873 | if (!isset($x)) { |
||
874 | return false; |
||
875 | } |
||
876 | $varNo = $x; |
||
877 | return true; } |
||
878 | |||
879 | /** |
||
880 | * Maps block name to block number. |
||
881 | * If there are multiple blocks with the same name, the block number of the last |
||
882 | * registered block with that name is returned. |
||
883 | * @return boolean true on success, false when the block is not found. |
||
884 | * @access private |
||
885 | */ |
||
886 | function lookupBlockName($blockName, &$blockNo) { |
||
0 ignored issues
–
show
|
|||
887 | $x = & $this->blockNameToNoMap[strtoupper($blockName)]; |
||
888 | if (!isset($x)) { |
||
889 | return false; |
||
890 | } |
||
891 | $blockNo = $x; |
||
892 | return true; } |
||
893 | |||
894 | //--- general utility routines ----------------------------------------------------------------------------------------- |
||
895 | |||
896 | /** |
||
897 | * Reads a file into a string. |
||
898 | * @return boolean true on success, false on error. |
||
899 | * @access private |
||
900 | */ |
||
901 | function readFileIntoString($fileName, &$s) { |
||
0 ignored issues
–
show
|
|||
902 | if (function_exists('version_compare') && version_compare(phpversion(), "4.3.0", ">=")) { |
||
903 | $s = file_get_contents($fileName); |
||
904 | if ($s === false) { |
||
905 | return false; |
||
906 | } |
||
907 | return true; } |
||
908 | $fh = fopen($fileName, "rb"); |
||
909 | if ($fh === false) { |
||
910 | return false; |
||
911 | } |
||
912 | $fileSize = filesize($fileName); |
||
913 | if ($fileSize === false) {fclose($fh); return false; } |
||
914 | $s = fread($fh, $fileSize); |
||
915 | fclose($fh); |
||
916 | if (strlen($s) != $fileSize) { |
||
917 | return false; |
||
918 | } |
||
919 | return true; } |
||
920 | |||
921 | /** |
||
922 | * @access private |
||
923 | * @return boolean true on success, false when the end of the string is reached. |
||
924 | */ |
||
925 | function parseWord($s, &$p, &$w) { |
||
0 ignored issues
–
show
|
|||
926 | $sLen = strlen($s); |
||
927 | while ($p < $sLen && ord($s{$p}) <= 32) { |
||
928 | $p++; |
||
929 | } |
||
930 | if ($p >= $sLen) { |
||
931 | return false; |
||
932 | } |
||
933 | $p0 = $p; |
||
934 | while ($p < $sLen && ord($s{$p}) > 32) { |
||
935 | $p++; |
||
936 | } |
||
937 | $w = substr($s, $p0, $p - $p0); |
||
938 | return true; } |
||
939 | |||
940 | /** |
||
941 | * @access private |
||
942 | * @return boolean true on success, false on error. |
||
943 | */ |
||
944 | function parseQuotedString($s, &$p, &$w) { |
||
0 ignored issues
–
show
|
|||
945 | $sLen = strlen($s); |
||
946 | while ($p < $sLen && ord($s{$p}) <= 32) { |
||
947 | $p++; |
||
948 | } |
||
949 | if ($p >= $sLen) { |
||
950 | return false; |
||
951 | } |
||
952 | if (substr($s, $p, 1) != '"') { |
||
953 | return false; |
||
954 | } |
||
955 | $p++; $p0 = $p; |
||
956 | while ($p < $sLen && $s{$p} != '"') { |
||
957 | $p++; |
||
958 | } |
||
959 | if ($p >= $sLen) { |
||
960 | return false; |
||
961 | } |
||
962 | $w = substr($s, $p0, $p - $p0); |
||
963 | $p++; |
||
964 | return true; } |
||
965 | |||
966 | /** |
||
967 | * @access private |
||
968 | * @return boolean true on success, false on error. |
||
969 | */ |
||
970 | function parseWordOrQuotedString($s, &$p, &$w) { |
||
0 ignored issues
–
show
|
|||
971 | $sLen = strlen($s); |
||
972 | while ($p < $sLen && ord($s{$p}) <= 32) { |
||
973 | $p++; |
||
974 | } |
||
975 | if ($p >= $sLen) { |
||
976 | return false; |
||
977 | } |
||
978 | if (substr($s, $p, 1) == '"') { |
||
979 | return $this->parseQuotedString($s, $p, $w); |
||
980 | } else { |
||
981 | return $this->parseWord($s, $p, $w); |
||
982 | } |
||
983 | } |
||
984 | |||
985 | /** |
||
986 | * Combine two file system paths. |
||
987 | * @access private |
||
988 | */ |
||
989 | function combineFileSystemPath($path1, $path2) { |
||
0 ignored issues
–
show
|
|||
990 | if ($path1 == '' || $path2 == '') { |
||
991 | return $path2; |
||
992 | } |
||
993 | $s = $path1; |
||
994 | if (substr($s, -1) != '\\' && substr($s, -1) != '/') { |
||
995 | $s = $s."/"; |
||
996 | } |
||
997 | if (substr($path2, 0, 1) == '\\' || substr($path2, 0, 1) == '/') { |
||
998 | $s = $s.substr($path2, 1); |
||
999 | } else { |
||
1000 | $s = $s.$path2; |
||
1001 | } |
||
1002 | return $s; } |
||
1003 | |||
1004 | /** |
||
1005 | * @access private |
||
1006 | */ |
||
1007 | function triggerError($msg) { |
||
0 ignored issues
–
show
|
|||
1008 | trigger_error("MiniTemplator error: $msg", E_USER_ERROR); } |
||
1009 | |||
1010 | /** |
||
1011 | * @access private |
||
1012 | */ |
||
1013 | function programLogicError($errorId) { |
||
0 ignored issues
–
show
|
|||
1014 | die ("MiniTemplator: Program logic error $errorId.\n"); } |
||
0 ignored issues
–
show
|
|||
1015 | |||
1016 | } |
||
1017 | ?> |
||
0 ignored issues
–
show
It is not recommended to use PHP's closing tag
?> in files other than templates.
Using a closing tag in PHP files that only contain PHP code is not recommended as you might accidentally add whitespace after the closing tag which would then be output by PHP. This can cause severe problems, for example headers cannot be sent anymore. A simple precaution is to leave off the closing tag as it is not required, and it also has no negative effects whatsoever. ![]() |
|||
1018 |
Adding explicit visibility (
private
,protected
, orpublic
) is generally recommend to communicate to other developers how, and from where this method is intended to be used.