JTPLV4 - Jotti's Template Engine version 4 -------------------------------------------- What is JTPLv4? ----------------- JTPLv4 is a multi-purpose markup language template engine, designed to generate and/or display e.g. HTML/XML documents in a convenient way. How does it work? ------------------- Create a new jtpl instance $template = new jtpl; fiddle around with variables, if blocks, case blocks, escapes, includes etc. and then $template->display(); Your document has been nicely formatted and will be displayed. What's needed to use JTPLv4? ----------------------------- A web server that speaks PHP5 or later. Include jtplv4.inc.php and you're ready to go. V4 is compatible with V3 in most respects, in cases where it is not, some minor modifications to your scripts are necessary. A compatibility layer is no longer offered. What can I do with the templates? ---------------------------------- -Read a template from a file $template->readtemplate("templatefile.tpl"); Will load templatefile.tpl as a template. -Assign a template from a string $template->assigntemplate("this is a template"); Will consider "this is a template" the template. -Assign variables. $template->assignvar("FOO", "bar"); Every instance of "{FOO}" in the document will be replaced by "bar". You can also use: $template->assignvarsfromarray($array); Every item in the array will be used as a template variable, capitalised by default. E.g. if you have an array $array with "foo" => "bar" and "foo2" => "bar2", JTPL will act like you entered: $template->assignvar("FOO", "bar"); $template->assignvar("FOO2", "bar2"); -Assign IF blocks $template->ifblock("FOO", false); Every instance of "{FOO:IF}true{FOO:ELSE}false{FOO:ENDIF}" will be replaced by "false". The "{FOO:ELSE}" part is optional. It's possible to use AND and/or OR statements in IF blocks. This is basically the idea: {FOO|BAR:IF}Foo or bar{FOO|BAR:ELSE}Not foo and not bar{FOO|BAR:ENDIF} and {FOO&BAR:IF}Foo and bar{FOO&BAR:ELSE}Not foo and bar{FOO&BAR:ENDIF} -Assign CASE blocks $template->caseblock("FOO", "YES"); Every instance of "{FOO:YES:CASE}yes{FOO:NO:CASE}no{FOO:DONTKNOW:CASE}don't know{FOO:CASE-END} will be replaced by "yes". If you include a possible {FOO:DEFAULT:CASE} section, this default will be used if you do not assign a case to FOO (you can also force the default by simply assigning "DEFAULT" to "FOO", as normally). -Escape variables for use with Javascript/HTML/OpenOffice.org/URLs Enter a variable name "{FOO}" as "{FOO;HTML}" instead and it will be htmlspecialcharred so HTML injection is not possible and you don't have to do an htmlspecialchars() in your script. Possible modifiers are: HTML: prevent HTML injection XML: escape content for use in XML documents JS: escape for use in Javascript functions NL2BR: convert newlines to HTML linebreaks OOO: escape for use in OpenOffice.org XML documents URL: urlencode for use in links TPL: escape { and } with their HTML entities so template content assignments will not be triggered LCASE: convert to lowercase characters UCASE: convert to uppercase characters UCFIRST: convert first character to uppercase INT: convert to integer (will result in 0 if not a number) MONEY: convert to 2 decimal number (2 will result in 2.00, 4.1 will result in 4.10, 5.2452 will result in 5.25 etc.) NOESCAPE: do nothing (this may sound utterly useless, more on this in the "default escapers" section below) For example, if you assign "I don't like this" to "FOO", entering {FOO;JS} in the template, will produce: "I don\'t like this". Multiple modifiers can be specified, e.g. {VAR;JS;HTML} or even e.g. double HTML escaping with {VAR;HTML;HTML} -Default escapers When working with HTML templates, it's common to escape (nearly) all variables by using the HTML modifier, which can become tiresome to do for every single variable. There is a way to treat every {FOO} variable as {FOO;HTML}. $template->defaultvarescape = "HTML"; Multiple modifiers can be specified, e.g. "JS;HTML". Be aware that the default escape setting ONLY applies to variables and ONLY to variables that have no explicit modifier set in the template! E.g. a template variable {FOO;JS} will NOT be HTML escaped, you will have to manually change it to {FOO;JS;HTML}. Should you need to inject plain HTML without escaping, there is a dedicated "void" escaper available. Simply use {FOO;NOESCAPE} in your template and JTPL will refrain from touching the content and keep his hands where you can see them. - Custom escapers If you want something escaped not provided by JTPL, you can assign custom escapers at runtime. For example, if you have a function: function removespaces($content) { return str_replace(" ", "", $content); } you can easily assign this function to JTPL, like this: $template->add_custom_escaper("REMOVESPACES", "removespaces"); this way, template contents: {BLA;REMOVESPACES} containing for examples "foo bar woot" will be displayed in the template as "foobarwoot" (removing spaces, as the function "removespaces" is supposed to do). -Repeat blocks A template with a block: {FOO:START}yes! {FOO:END} can be repeated by entering the FOO block level by entering: $template->enterblock("FOO"); invoking for every repeat: $template->startiteration(); and exiting the block afterwards by: $template->leaveblock(); Every block is a "level". They can have their own variables, if blocks, case blocks and escapes for that level and child levels (if you don't declare these variables in the child blocks - YES, repeat blocks can be nested!) -Nesting repeat blocks {FOO:START}yes! {BAR:START} really! {BAR:END} {FOO:END} First enter FOO, like described above. Perform an iteration and descend to BAR just like you did with FOO. Perform an iteration again. Leave FOO. Repeat this until every BAR and FOO iterations have been completed and leave BAR itself. This can of course be done with a virtually unlimited level of nested blocks, all of them with their own variables, if blocks, case blocks and variable modifiers. Be sure NOT to re-use names for repeat blocks on different levels. {FOO:START} {FOO:START} {FOO:END} {FOO:END} Will cause unexpected behaviour and severe headaches and/or other injuries related to the very profession of being a programmer. Show your doctor this document before taking medication. -Includes Entering: {tobeincluded.tpl:INCLUDE} Will include tobeincluded.tpl, read from the last known template directory, inline. These are called "dynamic includes". Entering: {../tobeincluded.tpl:INCLUDE} Will trigger an error. Upper directory (paths with two consecutive dots) includes are not allowed for security reasons by default. If $template->allowupperdirectoryincludes is set to true, the above INCLUDE token will include tobeincluded.tpl, read from one directory above the last known template directory, inline. Entering: {/some/directory/tobeincluded.tpl:INCLUDE} Will trigger an error. Absolute path includes are not allowed for security reasons by default. If $template->allowabsolutepathincludes is set to true, the above INCLUDE token will include tobeincluded.tpl, read from /some/directory (e.g., last known template directory is not used), inline. Includes can also take modifiers, e.g. {tobeincluded.tpl:INCLUDE;JS}. This works the same way as if the included file's contents had been content assigned to a variable escaped with ;JS. Also, multiple modifiers can be used at the same time, e.g.: {tobeincluded.tpl:INCLUDE;JS;HTML}. Also, entering: $template->includetemplate("included.tpl", "FOO"); Will replace {FOO} in the template by the contents of included.tpl. Template variable modifiers (e.g. {FOO;HTML}) are honoured. Note that the 'upper directory' and 'absolute path' include restrictions mentioned above are not applied here; if you intend to use user input to determine which file's contents you want {FOO} to be replaced with, it is your responsibility as a developer to make sure no sensitive data is allowed to be included. -Template comments Entering: {!-- comment! --} Will produce nothing. These are template comments. -Inline escapes Entering: {JS:ESCAPE-START}I don't know{JS:ESCAPE-END} Will produce: "I don\'t know" in the template. Very useful to keep DHTML readable for the designer, while still feeding it correctly to the browser. -Inline preservations, preventing parsing of template tokens Entering {PRESERVE-START} {WOOT} {PRESERVE-END} Will leave {WOOT} untouched, no matter how many times you use assignvar to give WOOT contents. If you want to parse the contents of preserved sections anyway, you may set the ignorepreserves option to true, like: $template->ignorepreserves = true; - Character sets Normally templates will be in UTF-8 encoding. If you want templates, for legacy applications, to utilise e.g. ISO-8859-1, you can modify the 'charset' variable, like: $template->charset = "ISO-8859-1"; This way e.g. HTML escapes will correctly escape the non-unicode characters. -Debugging Normally unassigned variables, if blocks, case blocks without a default and repeat blocks will be left empty if unassigned in the script, unnoticed. If you enabled debug like this: $template->debug = 1; JTPL will issue a warning about not using a variable, if block etc. or a repeat block that never iterates. -Returning $bla = $template->getdocument(); Will fill $bla with the parsed template. -Displaying $template->display(); Will echo the parsed template. -Parsetime tracking $template->getparsetime() will return the time needed to process the template after all declarations have been made and the document is retrieved. If no processing has been done yet (e.g. no ->display or ->getdocument has been called), it will return false; -Error handlers By default JTPL will emulate trigger_error by displaying a trigger_error like error message, honouring PHP's HTML error settings, using a backtrace. This ensures the proper line numbers and script names are stated instead of some routine in JTPL (which, obviously, is not the place to look for template errors). However, projects using a custom error handler will find this feature a pain, since the custom error handler is never initiated. The trigger_error emulation may be disabled as follows (be careful to use the American spelling): $template->honor_errorhandler = 1; Please note that accurate line numbers and script names will no longer be available this way.