Date: 12/01/00
- Next message: uw: "[phplib-dev] cvs commit"
- Previous message: Max Derkachev: "[phplib-dev] Re: [phplib] PHPlib session using PHP4 sessions implementation: the code"
- Next in thread: uw: "[phplib-dev] cvs commit"
- Maybe reply: uw: "[phplib-dev] cvs commit"
- Maybe reply: max: "[phplib-dev] cvs commit"
- Maybe reply: max: "[phplib-dev] cvs commit"
- Maybe reply: max: "[phplib-dev] cvs commit"
- Maybe reply: max: "[phplib-dev] cvs commit"
- Maybe reply: max: "[phplib-dev] cvs commit"
- Maybe reply: uw: "[phplib-dev] cvs commit"
- Maybe reply: uw: "[phplib-dev] cvs commit"
- Maybe reply: uw: "[phplib-dev] cvs commit"
- Maybe reply: uw: "[phplib-dev] cvs commit"
- Maybe reply: uw: "[phplib-dev] cvs commit"
- Maybe reply: uw: "[phplib-dev] cvs commit"
- Maybe reply: uw: "[phplib-dev] cvs commit"
- Maybe reply: uw: "[phplib-dev] cvs commit"
- Maybe reply: uw: "[phplib-dev] cvs commit"
- Maybe reply: negro: "[phplib-dev] cvs commit"
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]
From: uw
Date: Fri Dec 1 10:16:44 2000
Modified files:
php-lib/php/ext/integratedtemplate.inc
php-lib/php/ext/integratedtemplateextension.inc
Log message:
IT:
- some minor bugfixes
Cleaned up default values.
- added a PHP4 workaround
Some PHP4 version prior to 4.04dev(?) have problems with
preg_replace(array(), "", "some text"). The returned string shows
a negative strlen() value...
- added "touchable blocks"
"touchable blocks" are blocks without any placeholder which get not
automatically removed although $removeEmptyBlocks = true if you call
touchBlock(). I use such blocks to place error messages in the templates.
If the block gets not touched the error message will not be shown. If it
gets touched the message will be shown. That means I can avoid different template
files (noerror.tpl, error.tpl) and the error message is not in
my source code. It's for my special customer...
ITX:
- function call recognition
Some rather simple CMS allow users to place function calls ("module calls",
modules such as guestbooks, contact forms etc.) in their template. Added
some functions to grep these function calls and to define callback functions
for this "module calls".
The current implementation is quite simple and not very powerful.
Nevertheless it gives me all I need ;-).
Index: php-lib/php/ext/integratedtemplate.inc
diff -u php-lib/php/ext/integratedtemplate.inc:1.5 php-lib/php/ext/integratedtemplate.inc:1.6
--- php-lib/php/ext/integratedtemplate.inc:1.5 Tue Oct 10 14:31:31 2000
+++ php-lib/php/ext/integratedtemplate.inc Fri Dec 1 10:16:41 2000
@@ -1,724 +1,862 @@
-<?php
-/**
-* Integrated Template - IT
-*
-* Well there's not much to say about it. I needed a template class that
-* supports a single template file with multiple (nested) blocks inside and
-* a simple block API.
-*
-* The Isotemplate API is somewhat tricky for a beginner although it is the best
-* one you can build. template::parse() [phplib template = Isotemplate] requests
-* you to name a source and a target where the current block gets parsed into.
-* Source and target can be block names or even handler names. This API gives you
-* a maximum of fexibility but you always have to know what you do which is
-* quite unusual for php skripter like me.
-*
-* I noticed that I do not any control on which block gets parsed into which one.
-* If all blocks are within one file, the script knows how they are nested and in
-* which way you have to parse them. IT knows that inner1 is a child of block2, there's
-* no need to tell him about this.
-*
-* <table border>
-* <tr>
-* <td colspan=2>
-* __global__
-* <p>
-* (hidden and automatically added)
-* </td>
-* </tr>
-* <tr>
-* <td>block1</td>
-* <td>
-* <table border>
-* <tr>
-* <td colspan=2>block2</td>
-* </tr>
-* <tr>
-* <td>inner1</td>
-* <td>inner2</td>
-* </tr>
-* </table>
-* </td>
-* </tr>
-* </table>
-*
-* To add content to block1 you simply type:
-* <code>$tpl->setCurrentBlock("block1");</code>
-* and repeat this as often as needed:
-* <code>
-* $tpl->setVariable(...);
-* $tpl->parseCurrentBlock();
-* </code>
-*
-* To add content to block2 you would type something like:
-* <code>
-* $tpl->setCurrentBlock("inner1");
-* $tpl->setVariable(...);
-* $tpl->parseCurrentBlock();
-*
-* $tpl->setVariable(...);
-* $tpl->parseCurrentBlock();
-*
-* $tpl->parse("block1");
-* </code>
-*
-* This will result in one repition of block1 which contains two repitions
-* of inner1. inner2 will be removed if $removeEmptyBlock is set to true which is the default.
-*
-* Usage:
-* <code>
-* $tpl = new IntegratedTemplate( [string filerootdir] );
-*
-* // load a template or set it with setTemplate()
-* $tpl->loadTemplatefile( string filename [, boolean removeUnknownVariables, boolean removeEmptyBlocks] )
-*
-* // set "global" Variables meaning variables not beeing within a (inner) block
-* $tpl->setVariable( string variablename, mixed value );
-*
-* // like with the Isotemplates there's a second way to use setVariable()
-* $tpl->setVariable( array ( string varname => mixed value ) );
-*
-* // Let's use any block, even a deeply nested one
-* $tpl->setCurrentBlock( string blockname );
-*
-* // repeat this as often as you need it.
-* $tpl->setVariable( array ( string varname => mixed value ) );
-* $tpl->parseCurrentBlock();
-*
-* // get the parsed template or print it: $tpl->show()
-* $tpl->get();
-* </code>
-*
-* <email protected> Ulf Wendel <uw <email protected>>
-* <email protected> 1.2 10/10/00
-* <email protected> public
-*/
-class IntegratedTemplate {
-
- /**
- * Contains the error objects
- * <email protected> array
- * <email protected> public
- * <email protected> halt(), $printError, $haltOnError
- */
- var $err = array();
-
- /**
- * Print error messages?
- * <email protected> boolean
- * <email protected> public
- * <email protected> halt(), $haltOnError, $err
- */
- var $printError = false;
-
- /**
- * Call die() on error?
- * <email protected> boolean
- * <email protected> public
- * <email protected> halt(), $printError, $err
- */
- var $haltOnError = false;
-
- /**
- * Clear cache on get()?
- * <email protected> boolean
- */
- var $clearCache = false;
-
- /**
- * First character of a variable placeholder ( _{_VARIABLE} ).
- * <email protected> string
- * <email protected> public
- * <email protected> $closingDelimiter, $blocknameRegExp, $variablenameRegExp
- */
- var $openingDelimiter = "{";
-
- /**
- * Last character of a variable placeholder ( {VARIABLE_}_ ).
- * <email protected> string
- * <email protected> public
- * <email protected> $openingDelimiter, $blocknameRegExp, $variablenameRegExp
- */
- var $closingDelimiter = "}";
-
- /**
- * RegExp matching a block in the template.
- * Per default "sm" is used as the regexp modifier, "i" is missing.
- * That means a case sensitive search is done.
- * <email protected> string
- * <email protected> public
- * <email protected> $variablenameRegExp, $openingDelimiter, $closingDelimiter
- */
- var $blocknameRegExp = "[0-9A-Za-z_-]+";
-
- /**
- * RegExp matching a variable placeholder in the template.
- * Per default "sm" is used as the regexp modifier, "i" is missing.
- * That means a case sensitive search is done.
- * <email protected> string
- * <email protected> public
- * <email protected> $blocknameRegExp, $openingDelimiter, $closingDelimiter
- */
- var $variablenameRegExp = "[0-9A-Za-z_-]+";
-
- /**
- * Full RegExp used to find variable placeholder, filled by the constructor.
- * <email protected> string Looks somewhat like @(delimiter varname delimiter)@
- * <email protected> public
- * <email protected> IntegratedTemplate()
- */
- var $variablesRegExp = "";
-
- /**
- * Controls the handling of unknown variables, default is remove.
- * <email protected> boolean
- * <email protected> public
- */
- var $removeUnknownVariables = true;
-
- /**
- * Controls the handling of empty blocks, default is remove.
- * <email protected> boolean
- * <email protected> public
- */
- var $removeEmptyBlocks = true;
-
- /**
- * Full RegExp used to find blocks an their content, filled by the constructor.
- * <email protected> string
- * <email protected> IntegratedTemplate()
- */
- var $blockRegExp = "";
-
- /**
- * Name of the current block.
- * <email protected> string
- */
- var $currentBlock = "__global__";
-
- /**
- * Content of the template.
- * <email protected> string
- */
- var $template = "";
-
- /**
- * Array of all blocks and their content.
- *
- * <email protected> array
- * <email protected> findBlocks()
- */
- var $blocklist = array();
-
- /**
- * Array with the parsed content of a block.
- *
- * <email protected> array
- */
- var $blockdata = array();
-
- /**
- * Array of variables in a block.
- * <email protected> array
- */
- var $blockvariables = array();
-
- /**
- * Array of inner blocks of a block.
- * <email protected> array
- */
- var $blockinner = array();
-
- /**
- * Future versions will use this...
- * <email protected> array
- */
- var $blocktypes = array();
-
- /**
- * Variable cache.
- *
- * Variables get cached before any replacement is done.
- * Advantage: empty blocks can be removed automatically.
- * Disadvantage: might take some more memory
- *
- * <email protected> array
- * <email protected> setVariable(), $clearCacheOnParse
- */
- var $variableCache = array();
-
- /**
- * <email protected> boolean
- */
- var $clearCacheOnParse = true;
-
- /**
- * Root directory for all file operations.
- * The string gets prefixed to all filenames given.
- * <email protected> string
- * <email protected> IntegratedTemplate(), setRoot()
- */
- var $fileRoot = "";
-
- /**
- * Internal flag indicating that a blockname was used multiple times.
- * <email protected> boolean
- */
- var $flagBlocktrouble = false;
-
- /**
- * Flag indicating that the global block was parsed.
- * <email protected> boolean
- */
- var $flagGlobalParsed = false;
-
- /**
- * Builds some complex regular expressions and optinally sets the file root directory.
- *
- * Make sure that you call this constructor if you derive your template
- * class from this one.
- *
- * <email protected> string File root directory, prefix for all filenames given to the object.
- * <email protected> setRoot()
- */
- function IntegratedTemplate($root = "") {
-
- $this->variablesRegExp = "@".$this->openingDelimiter."(".$this->variablenameRegExp.")".$this->closingDelimiter." <email protected>";
- $this->blockRegExp = '@!--\s+BEGIN\s+('.$this->blocknameRegExp.')\s+-->(.*)<!--\s+END\s+\1\s+--> <email protected>';
-
- $this->setRoot($root);
- } // end constructor
-
- /**
- * Print a certain block with all replacements done.
- * <email protected> get()
- */
- function show($block = "__global__") {
- print $this->get($block);
- } // end func show
-
- /**
- * Returns a block with all replacements done.
- *
- * <email protected> string name of the block
- * <email protected> string
- * <email protected> public
- * <email protected> show()
- */
- function get($block = "__global__") {
-
- if ("__global__" == $block && !$this->flagGlobalParsed)
- $this->parse("__global__");
-
- if (!isset($this->blocklist[$block])) {
- $this->halt("The block '$block' was not found in the template.", __FILE__, __LINE__);
- return true;
- }
-
- if ($this->clearCache) {
-
- $data = (isset($this->blockdata[$block])) ? $this->blockdata[$block] : "";
- unset($this->blockdata[$block]);
- return $data;
-
- } else {
-
- return (isset($this->blockdata[$block])) ? $this->blockdata[$block] : "";
-
- }
-
- } // end func get()
-
- /**
- * Parses the given block.
- *
- * <email protected> string name of the block to be parsed
- * <email protected> public
- * <email protected> parseCurrentBlock()
- */
- function parse($block = "__global__", $flag_recursion = false) {
-
- if (!isset($this->blocklist[$block])) {
- $this->halt("The block '$block' was not found in the template.", __FILE__, __LINE__);
- return false;
- }
-
- if ("__global__" == $block)
- $this->flagGlobalParsed = true;
-
- $regs = array();
- $values = array();
-
- if ($this->clearCacheOnParse) {
-
- reset($this->variableCache);
- while (list($name, $value)=each($this->variableCache)) {
- $regs[] = "@".$this->openingDelimiter.$name.$this->closingDelimiter."@";
- $values[] = $value;
- }
- $this->variableCache = array();
-
- } else {
-
- reset($this->blockvariables[$block]);
- while (list($k, $allowedvar)=each($this->blockvariables[$block])) {
-
- if (isset($this->variableCache[$allowedvar])) {
- $regs[] = "@".$this->openingDelimiter.$allowedvar.$this->closingDelimiter."@";
- $values[] = $this->variableCache[$allowedvar];
- unset($this->variableCache[$allowedvar]);
- }
-
- }
-
- }
-
- $outer = preg_replace($regs, $values, $this->blocklist[$block]);
- $empty = (0==count($values)) ? true : false;
-
- if (isset($this->blockinner[$block])) {
-
- reset($this->blockinner[$block]);
- while (list($k, $innerblock)=each($this->blockinner[$block])) {
-
- $this->parse($innerblock, true);
- if (""!=$this->blockdata[$innerblock])
- $empty = false;
-
- $placeholder = $this->openingDelimiter."__".$innerblock."__".$this->closingDelimiter;
- $outer = str_replace($placeholder, $this->blockdata[$innerblock], $outer);
- $this->blockdata[$innerblock] = "";
- }
- }
-
- if ($this->removeUnknownVariables)
- $outer = preg_replace($this->variablesRegExp, "", $outer);
-
- if ($empty) {
-
- if (!$this->removeEmptyBlocks)
- $this->blockdata[$block].= $outer;
-
- } else {
-
- $this->blockdata[$block].= $outer;
-
- }
-
- return $empty;
- } // end func parse
-
- /**
- * Parses the current block
- * <email protected> parse(), setCurrentBlock(), $currentBlock
- * <email protected> public
- */
- function parseCurrentBlock() {
- return $this->parse($this->currentBlock);
- } // end func parseCurrentBlock
-
- /**
- * Sets a variable value.
- *
- * The function can be used eighter like setVariable( "varname", "value")
- * or with one array $variables["varname"] = "value" given setVariable($variables)
- * quite like phplib templates set_var().
- *
- * <email protected> mixed string with the variable name or an array %variables["varname"] = "value"
- * <email protected> string value of the variable or empty if $variable is an array.
- * <email protected> string prefix for variable names
- * <email protected> public
- */
- function setVariable($variable, $value="") {
-
- if (is_array($variable)) {
-
- reset($variable);
- while (list($var, $value)=each($variable))
- $this->variableCache[$var] = $value;
-
- } else {
-
- $this->variableCache[$variable] = $value;
-
- }
-
- } // end func setVariable
-
- /**
- * Sets the name of the current block that is the block where variables are added.
- *
- * <email protected> string name of the block
- * <email protected> boolean false on failure otherwise true
- * <email protected> public
- */
- function setCurrentBlock($block = "__global__") {
-
- if (!isset($this->blocklist[$block])) {
- $this->halt("Can't find the block '$block' in the template.", __FILE__, __LINE__);
- return false;
- }
-
- $this->currentBlock = $block;
-
- return true;
- } // end func setCurrentBlock
-
- /**
- * Clears all datafields of the object and rebuild the internal blocklist
- *
- * LoadTemplatefile() and setTemplate() automatically call this function
- * when a new template is given. Don't use this function
- * unless you know what you're doing.
- *
- * <email protected> public
- * <email protected> free()
- */
- function init() {
-
- $this->free();
- $this->findBlocks($this->template);
- $this->buildBlockvariablelist();
-
- } // end func init
-
- /**
- * Clears all datafields of the object.
- *
- * Don't use this function unless you know what you're doing.
- *
- * <email protected> public
- * <email protected> init()
- */
- function free() {
-
- $this->err[] = "";
-
- $this->currentBlock = "__global__";
-
- $this->variableCache = array();
- $this->blocklist = array();
- $this->blockvariables = array();
- $this->blockinner = array();
- $this->blockdata = array();
- $this->blocklookup = array();
- $this->blocktypes = array();
-
- $this->flagBlocktrouble = false;
- $this->flagGlobalParsed = false;
-
- } // end func free
-
- /**
- * Sets the template.
- *
- * You can eighter load a template file from disk with LoadTemplatefile() or set the
- * template manually using this function.
- *
- * <email protected> string template content
- * <email protected> boolean Unbekannte, nicht ersetzte Platzhalter entfernen?
- * <email protected> boolean remove unknown/unused variables?
- * <email protected> boolean remove empty blocks?
- * <email protected> LoadTemplatefile(), $template
- * <email protected> public
- */
- function setTemplate($template, $removeUnknownVariables = true, $removeEmptyBlocks = false) {
- if (""==$template) {
- $this->halt("The given string is empty.", __FILE__, __LINE__);
- return false;
- }
-
- $this->removeUnknownVariables = $removeUnknownVariables;
- $this->removeEmptyBlocks = $removeEmptyBlocks;
-
- $this->template = '<!-- BEGIN __global__ -->'.$template.'<!-- END __global__ -->';
- $this->init();
-
- if ($this->flagBlocktrouble)
- return false;
-
- return true;
- } // end func setTemplate
-
- /**
- * Reads a template file from the disk.
- *
- * <email protected> string name of the template file
- * <email protected> mixed How to handle unknown variables. true = remove, false = keep,
- * empty string = fallback to class default $removeUnknownVariables.
- * <email protected> mixed How to handle empty blocks. true = remove, false = keep,
- * empty string = fallback to class default $removeEmptyBlocks
- * <email protected> public
- * <email protected> boolean false on failure, otherwise true
- * <email protected> $template, setTemplate(), $removeUnknownVariables, $removeEmptyBlocks
- */
- function loadTemplatefile($filename, $removeUnknownVariables = "", $removeEmptyBlocks = "") {
-
- $template = $this->getfile($filename);
-
- if (""!=$removeUnknownVariables)
- $this->removeUnknownVariables = ($removeUnknownVariables) ? true : false;
- if (""!=$removeEmptyBlocks)
- $this->removeEmptyBlocks = ($removeEmptyBlocks) ? true : false;
-
- return $this->setTemplate($this->getFile($filename), $removeUnknownVariables, $removeEmptyBlocks);
- } // end func LoadTemplatefile
-
- /**
- * Sets the file root. The file root gets prefixed to all filenames passed to the object.
- *
- * Make sure that you override this function when using the class
- * on windows.
- *
- * <email protected> string
- * <email protected> IntegratedTemplate()
- * <email protected> public
- */
- function setRoot($root) {
-
- if (""!=$root && "/"!= substr($root, -1))
- $root.="/";
-
- $this->fileRoot = $root;
-
- } // end func setRoot
-
- /**
- * Build a list of all variables within a block
- */
- function buildBlockvariablelist() {
-
- reset($this->blocklist);
- while (list($name, $content)=each($this->blocklist)) {
- preg_match_all( $this->variablesRegExp, $content, $regs );
- $this->blockvariables[$name] = $regs[1];
- }
-
- } // end func buildBlockvariablelist
-
- /**
- * Returns a list of all
- */
- function getGlobalvariables() {
-
- $regs = array();
- $values = array();
-
- reset($this->blockvariables["__global__"]);
- while (list($k, $allowedvar)=each($this->blockvariables["__global__"])) {
-
- if (isset($this->variableCache[$allowedvar])) {
- $regs[] = "@".$this->openingDelimiter.$allowedvar.$this->closingDelimiter."@";
- $values[] = $this->variableCache[$allowedvar];
- unset($this->variableCache[$allowedvar]);
- }
-
- }
-
- return array($regs, $values);
- } // end func getGlobalvariables
-
- /**
- * Recusively builds a list of all blocks within the template.
- *
- * <email protected> string string that gets scanned
- * <email protected> private
- * <email protected> $blocklist
- */
- function findBlocks($string) {
-
- $blocklist = array();
-
- if (preg_match_all($this->blockRegExp, $string, $regs, PREG_SET_ORDER)) {
-
- reset($regs);
- while (list($k, $match)=each($regs)) {
-
- $blockname = $match[1];
- $blockcontent = $match[2];
-
- if (isset($this->blocklist[$blockname])) {
- $this->halt("The name of a block must be unique within a template. Found '$blockname' twice. Unpredictable results may appear.", __FILE__, __LINE__);
- $this->flagBlocktrouble = true;
- }
-
- $this->blocklist[$blockname] = $blockcontent;
- $this->blockdata[$blockname] = "";
-
- $blocklist[] = $blockname;
-
- $inner = $this->findBlocks($blockcontent);
- reset($inner);
- while (list($k, $name)=each($inner)) {
-
- $pattern = sprintf('@<!--\s+BEGIN\s+%s\s+-->(.*)<!--\s+END\s+%s\s+--> <email protected>',
- $name,
- $name
- );
-
- $this->blocklist[$blockname] = preg_replace( $pattern,
- $this->openingDelimiter."__".$name."__".$this->closingDelimiter,
- $this->blocklist[$blockname]
- );
- $this->blockinner[$blockname][] = $name;
- $this->blockparents[$name] = $blockname;
-
- }
-
- }
-
- }
-
- return $blocklist;
- } // end func findBlocks
-
- /**
- * Reads a file from disk and returns its content.
- * <email protected> string Filename
- * <email protected> string Filecontent
- */
- function getFile($filename) {
-
- if ("/" == substr($filename, 0, 1))
- $filename = substr($filename, 1);
-
- $filename = $this->fileRoot.$filename;
-
- if ( !($fh = <email protected>($filename, "r")) ) {
- $this->halt("Can't read '$filename'.", __FILE__, __LINE__);
- return "";
- }
-
- $content = fread($fh, filesize($filename));
- fclose($fh);
-
- return $content;
- } // end func getFile
-
- /**
- * Error Handling function.
- * <email protected> string error message
- * <email protected> mixed File where the error occured
- * <email protected> int Line where the error occured
- * <email protected> $err
- */
- function halt($message, $file="", $line=0) {
-
- $message = sprintf("IntegratedTemplate Error: %s [File: %s, Line: %d]",
- $message,
- $file,
- $line
- );
-
- $this->err[] = $message;
-
- if ($this->printError)
- print $message;
-
- if ($this->haltOnError)
- die($message);
-
- } // end func halt
-
-} // end class IntegratedTemplate
+<?php
+/**
+* Integrated Template - IT
+*
+* Well there's not much to say about it. I needed a template class that
+* supports a single template file with multiple (nested) blocks inside and
+* a simple block API.
+*
+* The Isotemplate API is somewhat tricky for a beginner although it is the best
+* one you can build. template::parse() [phplib template = Isotemplate] requests
+* you to name a source and a target where the current block gets parsed into.
+* Source and target can be block names or even handler names. This API gives you
+* a maximum of fexibility but you always have to know what you do which is
+* quite unusual for php skripter like me.
+*
+* I noticed that I do not any control on which block gets parsed into which one.
+* If all blocks are within one file, the script knows how they are nested and in
+* which way you have to parse them. IT knows that inner1 is a child of block2, there's
+* no need to tell him about this.
+*
+* <table border>
+* <tr>
+* <td colspan=2>
+* __global__
+* <p>
+* (hidden and automatically added)
+* </td>
+* </tr>
+* <tr>
+* <td>block1</td>
+* <td>
+* <table border>
+* <tr>
+* <td colspan=2>block2</td>
+* </tr>
+* <tr>
+* <td>inner1</td>
+* <td>inner2</td>
+* </tr>
+* </table>
+* </td>
+* </tr>
+* </table>
+*
+* To add content to block1 you simply type:
+* <code>$tpl->setCurrentBlock("block1");</code>
+* and repeat this as often as needed:
+* <code>
+* $tpl->setVariable(...);
+* $tpl->parseCurrentBlock();
+* </code>
+*
+* To add content to block2 you would type something like:
+* <code>
+* $tpl->setCurrentBlock("inner1");
+* $tpl->setVariable(...);
+* $tpl->parseCurrentBlock();
+*
+* $tpl->setVariable(...);
+* $tpl->parseCurrentBlock();
+*
+* $tpl->parse("block1");
+* </code>
+*
+* This will result in one repition of block1 which contains two repitions
+* of inner1. inner2 will be removed if $removeEmptyBlock is set to true which is the default.
+*
+* Usage:
+* <code>
+* $tpl = new IntegratedTemplate( [string filerootdir] );
+*
+* // load a template or set it with setTemplate()
+* $tpl->loadTemplatefile( string filename [, boolean removeUnknownVariables, boolean removeEmptyBlocks] )
+*
+* // set "global" Variables meaning variables not beeing within a (inner) block
+* $tpl->setVariable( string variablename, mixed value );
+*
+* // like with the Isotemplates there's a second way to use setVariable()
+* $tpl->setVariable( array ( string varname => mixed value ) );
+*
+* // Let's use any block, even a deeply nested one
+* $tpl->setCurrentBlock( string blockname );
+*
+* // repeat this as often as you need it.
+* $tpl->setVariable( array ( string varname => mixed value ) );
+* $tpl->parseCurrentBlock();
+*
+* // get the parsed template or print it: $tpl->show()
+* $tpl->get();
+* </code>
+*
+* <email protected> Ulf Wendel <uw <email protected>>
+* <email protected> 1.2 10/10/00
+* <email protected> public
+*/
+class IntegratedTemplate {
+
+ /**
+ * Contains the error objects
+ * <email protected> array
+ * <email protected> public
+ * <email protected> halt(), $printError, $haltOnError
+ */
+ var $err = array();
+
+ /**
+ * Print error messages?
+ * <email protected> boolean
+ * <email protected> public
+ * <email protected> halt(), $haltOnError, $err
+ */
+ var $printError = false;
+
+ /**
+ * Call die() on error?
+ * <email protected> boolean
+ * <email protected> public
+ * <email protected> halt(), $printError, $err
+ */
+ var $haltOnError = false;
+
+ /**
+ * Clear cache on get()?
+ * <email protected> boolean
+ */
+ var $clearCache = false;
+
+ /**
+ * First character of a variable placeholder ( _{_VARIABLE} ).
+ * <email protected> string
+ * <email protected> public
+ * <email protected> $closingDelimiter, $blocknameRegExp, $variablenameRegExp
+ */
+ var $openingDelimiter = "{";
+
+ /**
+ * Last character of a variable placeholder ( {VARIABLE_}_ ).
+ * <email protected> string
+ * <email protected> public
+ * <email protected> $openingDelimiter, $blocknameRegExp, $variablenameRegExp
+ */
+ var $closingDelimiter = "}";
+
+ /**
+ * RegExp matching a block in the template.
+ * Per default "sm" is used as the regexp modifier, "i" is missing.
+ * That means a case sensitive search is done.
+ * <email protected> string
+ * <email protected> public
+ * <email protected> $variablenameRegExp, $openingDelimiter, $closingDelimiter
+ */
+ var $blocknameRegExp = "[0-9A-Za-z_-]+";
+
+ /**
+ * RegExp matching a variable placeholder in the template.
+ * Per default "sm" is used as the regexp modifier, "i" is missing.
+ * That means a case sensitive search is done.
+ * <email protected> string
+ * <email protected> public
+ * <email protected> $blocknameRegExp, $openingDelimiter, $closingDelimiter
+ */
+ var $variablenameRegExp = "[0-9A-Za-z_-]+";
+
+ /**
+ * RegExp used to find variable placeholder, filled by the constructor.
+ * <email protected> string Looks somewhat like @(delimiter varname delimiter)@
+ * <email protected> public
+ * <email protected> IntegratedTemplate()
+ */
+ var $variablesRegExp = "";
+
+ /**
+ * RegExp used to strip unused variable placeholder.
+ * <email protected> $variablesRegExp
+ */
+ var $removeVariablesRegExp = "";
+
+ /**
+ * Controls the handling of unknown variables, default is remove.
+ * <email protected> boolean
+ * <email protected> public
+ */
+ var $removeUnknownVariables = true;
+
+ /**
+ * Controls the handling of empty blocks, default is remove.
+ * <email protected> boolean
+ * <email protected> public
+ */
+ var $removeEmptyBlocks = true;
+
+ /**
+ * RegExp used to find blocks an their content, filled by the constructor.
+ * <email protected> string
+ * <email protected> IntegratedTemplate()
+ */
+ var $blockRegExp = "";
+
+ /**
+ * Name of the current block.
+ * <email protected> string
+ */
+ var $currentBlock = "__global__";
+
+ /**
+ * Content of the template.
+ * <email protected> string
+ */
+ var $template = "";
+
+ /**
+ * Array of all blocks and their content.
+ *
+ * <email protected> array
+ * <email protected> findBlocks()
+ */
+ var $blocklist = array();
+
+ /**
+ * Array with the parsed content of a block.
+ *
+ * <email protected> array
+ */
+ var $blockdata = array();
+
+ /**
+ * Array of variables in a block.
+ * <email protected> array
+ */
+ var $blockvariables = array();
+
+ /**
+ * Array of inner blocks of a block.
+ * <email protected> array
+ */
+ var $blockinner = array();
+
+ /**
+ * List of blocks to preverse even if they are "empty".
+ *
+ * This is something special. Sometimes you have blocks that
+ * should be preserved although they are empty (no placeholder replaced).
+ * Think of a shopping basket. If it's empty you have to drop a message to
+ * the user. If it's filled you have to show the contents of the shopping baseket.
+ * Now where do you place the message that the basket is empty? It's no good
+ * idea to place it in you applications as customers tend to like unecessary minor
+ * text changes. Having another template file for an empty basket means that it's
+ * very likely that one fine day the filled and empty basket templates have different
+ * layout. I decided to introduce blocks that to not contain any placeholder but only
+ * text such as the message "Your shopping basked is empty".
+ *
+ * Now if there is no replacement done in such a block the block will be recognized
+ * as "empty" and by default ($removeEmptyBlocks = true) be stripped off. To avoid this
+ * you can now call touchBlock() to avoid this.
+ *
+ * The array $touchedBlocks stores a list of touched block which must not be removed even
+ * if they are empty.
+ *
+ * <email protected> array $touchedBlocks
+ * <email protected> touchBlock(), $removeEmptyBlocks
+ */
+ var $touchedBlocks = array();
+
+ /**
+ * Variable cache.
+ *
+ * Variables get cached before any replacement is done.
+ * Advantage: empty blocks can be removed automatically.
+ * Disadvantage: might take some more memory
+ *
+ * <email protected> array
+ * <email protected> setVariable(), $clearCacheOnParse
+ */
+ var $variableCache = array();
+
+ /**
+ * Clear the variable cache on parse?
+ *
+ * If you're not an expert just leave the default false.
+ * True reduces memory consumption somewhat if you tend to
+ * add lots of values for unknown placeholder.
+ *
+ * <email protected> boolean
+ */
+ var $clearCacheOnParse = false;
+
+ /**
+ * Root directory for all file operations.
+ * The string gets prefixed to all filenames given.
+ * <email protected> string
+ * <email protected> IntegratedTemplate(), setRoot()
+ */
+ var $fileRoot = "";
+
+ /**
+ * Internal flag indicating that a blockname was used multiple times.
+ * <email protected> boolean
+ */
+ var $flagBlocktrouble = false;
+
+ /**
+ * Flag indicating that the global block was parsed.
+ * <email protected> boolean
+ */
+ var $flagGlobalParsed = false;
+
+ /**
+ * Builds some complex regular expressions and optinally sets the file root directory.
+ *
+ * Make sure that you call this constructor if you derive your template
+ * class from this one.
+ *
+ * <email protected> string File root directory, prefix for all filenames given to the object.
+ * <email protected> setRoot()
+ */
+ function IntegratedTemplate($root = "") {
+
+ $this->variablesRegExp = "@".$this->openingDelimiter."(".$this->variablenameRegExp.")".$this->closingDelimiter." <email protected>";
+ $this->removeVariablesRegExp = "@".$this->openingDelimiter."\s*(".$this->variablenameRegExp.")\s*".$this->closingDelimiter." <email protected>";
+
+ $this->blockRegExp = '@<!--\s+BEGIN\s+('.$this->blocknameRegExp.')\s+-->(.*)<!--\s+END\s+\1\s+--> <email protected>';
+
+ $this->setRoot($root);
+ } // end constructor
+
+ /**
+ * Print a certain block with all replacements done.
+ * <email protected> get()
+ */
+ function show($block = "__global__") {
+ print $this->get($block);
+ } // end func show
+
+ /**
+ * Returns a block with all replacements done.
+ *
+ * <email protected> string name of the block
+ * <email protected> string
+ * <email protected> public
+ * <email protected> show()
+ */
+ function get($block = "__global__") {
+
+ if ("__global__" == $block && !$this->flagGlobalParsed)
+ $this->parse("__global__");
+
+ if (!isset($this->blocklist[$block])) {
+ $this->halt("The block '$block' was not found in the template.", __FILE__, __LINE__);
+ return true;
+ }
+
+ if ($this->clearCache) {
+
+ $data = (isset($this->blockdata[$block])) ? $this->blockdata[$block] : "";
+ unset($this->blockdata[$block]);
+ return $data;
+
+ } else {
+
+ return (isset($this->blockdata[$block])) ? $this->blockdata[$block] : "";
+
+ }
+
+ } // end func get()
+
+ /**
+ * Parses the given block.
+ *
+ * <email protected> string name of the block to be parsed
+ * <email protected> public
+ * <email protected> parseCurrentBlock()
+ */
+ function parse($block = "__global__", $flag_recursion = false) {
+
+ if (!isset($this->blocklist[$block])) {
+ $this->halt("The block '$block' was not found in the template.", __FILE__, __LINE__);
+ return false;
+ }
+
+ if ("__global__" == $block)
+ $this->flagGlobalParsed = true;
+
+ $regs = array();
+ $values = array();
+
+ if ($this->clearCacheOnParse) {
+
+ reset($this->variableCache);
+ while (list($name, $value)=each($this->variableCache)) {
+ $regs[] = "@".$this->openingDelimiter.$name.$this->closingDelimiter."@";
+ $values[] = $value;
+ }
+ $this->variableCache = array();
+
+ } else {
+
+ reset($this->blockvariables[$block]);
+ while (list($allowedvar, $k) = each($this->blockvariables[$block])) {
+
+ if (isset($this->variableCache[$allowedvar])) {
+ $regs[] = "@".$this->openingDelimiter.$allowedvar.$this->closingDelimiter."@";
+ $values[] = $this->variableCache[$allowedvar];
+ unset($this->variableCache[$allowedvar]);
+ }
+
+ }
+
+ }
+
+ $outer = (0 == count($regs)) ? $this->blocklist[$block] : preg_replace($regs, $values, $this->blocklist[$block]);
+ $empty = (0 == count($values)) ? true : false;
+
+ if (isset($this->blockinner[$block])) {
+
+ reset($this->blockinner[$block]);
+ while (list($k, $innerblock) = each($this->blockinner[$block])) {
+
+ $this->parse($innerblock, true);
+ if (""!=$this->blockdata[$innerblock])
+ $empty = false;
+
+ $placeholder = $this->openingDelimiter."__".$innerblock."__".$this->closingDelimiter;
+ $outer = str_replace($placeholder, $this->blockdata[$innerblock], $outer);
+ $this->blockdata[$innerblock] = "";
+ }
+ }
+
+ if ($this->removeUnknownVariables)
+ $outer = preg_replace($this->removeVariablesRegExp, "", $outer);
+
+
+ if ($empty) {
+
+ if (!$this->removeEmptyBlocks) {
+
+ $this->blockdata[$block].= $outer;
+
+ } else {
+
+ if (isset($this->touchedBlocks[$block]))
+ $this->blockdata[$block].= $outer;
+
+ }
+
+ } else {
+
+ $this->blockdata[$block].= $outer;
+
+ }
+
+ return $empty;
+ } // end func parse
+
+ /**
+ * Parses the current block
+ * <email protected> parse(), setCurrentBlock(), $currentBlock
+ * <email protected> public
+ */
+ function parseCurrentBlock() {
+ return $this->parse($this->currentBlock);
+ } // end func parseCurrentBlock
+
+ /**
+ * Sets a variable value.
+ *
+ * The function can be used eighter like setVariable( "varname", "value")
+ * or with one array $variables["varname"] = "value" given setVariable($variables)
+ * quite like phplib templates set_var().
+ *
+ * <email protected> mixed string with the variable name or an array %variables["varname"] = "value"
+ * <email protected> string value of the variable or empty if $variable is an array.
+ * <email protected> string prefix for variable names
+ * <email protected> public
+ */
+ function setVariable($variable, $value="") {
+
+ if (is_array($variable)) {
+
+ reset($variable);
+ while (list($var, $value)=each($variable))
+ $this->variableCache[$var] = $value;
+
+ } else {
+
+ $this->variableCache[$variable] = $value;
+
+ }
+
+ } // end func setVariable
+
+ /**
+ * Sets the name of the current block that is the block where variables are added.
+ *
+ * <email protected> string name of the block
+ * <email protected> boolean false on failure, otherwise true
+ * <email protected> public
+ */
+ function setCurrentBlock($block = "__global__") {
+
+ if (!isset($this->blocklist[$block])) {
+ $this->halt("Can't find the block '$block' in the template.", __FILE__, __LINE__);
+ return false;
+ }
+
+ $this->currentBlock = $block;
+
+ return true;
+ } // end func setCurrentBlock
+
+ /**
+ * Preserves an empty block even if removeEmptyBlocks is true.
+ *
+ * <email protected> string name of the block
+ * <email protected> boolean false on false, otherwise true
+ * <email protected> public
+ * <email protected> $removeEmptyBlocks
+ */
+ function touchBlock($block) {
+
+ if (!isset($this->blocklist[$block])) {
+ $this->halt("Can't find the block '$block' in the template.", __FILE__, __LINE__);
+ return false;
+ }
+
+ $this->touchedBlocks[$block] = true;
+
+ return true;
+ } // end func touchBlock
+
+ /**
+ * Clears all datafields of the object and rebuild the internal blocklist
+ *
+ * LoadTemplatefile() and setTemplate() automatically call this function
+ * when a new template is given. Don't use this function
+ * unless you know what you're doing.
+ *
+ * <email protected> public
+ * <email protected> free()
+ */
+ function init() {
+
+ $this->free();
+ $this->findBlocks($this->template);
+ $this->buildBlockvariablelist();
+
+ } // end func init
+
+ /**
+ * Clears all datafields of the object.
+ *
+ * Don't use this function unless you know what you're doing.
+ *
+ * <email protected> public
+ * <email protected> init()
+ */
+ function free() {
+
+ $this->err[] = "";
+
+ $this->currentBlock = "__global__";
+
+ $this->variableCache = array();
+ $this->blocklist = array();
+ $this->blockvariables = array();
+ $this->blockinner = array();
+ $this->blockdata = array();
+ $this->blocklookup = array();
+ $this->touchedBlocks = array();
+
+ $this->flagBlocktrouble = false;
+ $this->flagGlobalParsed = false;
+
+ } // end func free
+
+ /**
+ * Sets the template.
+ *
+ * You can eighter load a template file from disk with LoadTemplatefile() or set the
+ * template manually using this function.
+ *
+ * <email protected> string template content
+ * <email protected> boolean Unbekannte, nicht ersetzte Platzhalter entfernen?
+ * <email protected> boolean remove unknown/unused variables?
+ * <email protected> boolean remove empty blocks?
+ * <email protected> LoadTemplatefile(), $template
+ * <email protected> public
+ */
+ function setTemplate($template, $removeUnknownVariables = true, $removeEmptyBlocks = true) {
+ if (""==$template) {
+ $this->halt("The given string is empty.", __FILE__, __LINE__);
+ return false;
+ }
+
+ $this->removeUnknownVariables = $removeUnknownVariables;
+ $this->removeEmptyBlocks = $removeEmptyBlocks;
+
+ $this->template = '<!-- BEGIN __global__ -->'.$template.'<!-- END __global__ -->';
+ $this->init();
+
+ if ($this->flagBlocktrouble)
+ return false;
+
+ return true;
+ } // end func setTemplate
+
+ /**
+ * Reads a template file from the disk.
+ *
+ * <email protected> string name of the template file
+ * <email protected> bool How to handle unknown variables.
+ * <email protected> bool How to handle empty blocks.
+ * <email protected> public
+ * <email protected> boolean false on failure, otherwise true
+ * <email protected> $template, setTemplate(), $removeUnknownVariables, $removeEmptyBlocks
+ */
+ function loadTemplatefile($filename, $removeUnknownVariables = true, $removeEmptyBlocks = true) {
+
+ $template = $this->getfile($filename);
+
+ return $this->setTemplate($this->getFile($filename), $removeUnknownVariables, $removeEmptyBlocks);
+ } // end func LoadTemplatefile
+
+ /**
+ * Sets the file root. The file root gets prefixed to all filenames passed to the object.
+ *
+ * Make sure that you override this function when using the class
+ * on windows.
+ *
+ * <email protected> string
+ * <email protected> IntegratedTemplate()
+ * <email protected> public
+ */
+ function setRoot($root) {
+
+ if (""!=$root && "/"!= substr($root, -1))
+ $root.="/";
+
+ $this->fileRoot = $root;
+
+ } // end func setRoot
+
+ /**
+ * Build a list of all variables within a block
+ */
+ function buildBlockvariablelist() {
+
+ reset($this->blocklist);
+ while (list($name, $content)=each($this->blocklist)) {
+ preg_match_all( $this->variablesRegExp, $content, $regs );
+
+ if (0 != count($regs[1])) {
+
+ reset($regs[1]);
+ while (list($k, $var) = each($regs[1]))
+ $this->blockvariables[$name][$var] = true;
+
+ } else {
+
+ $this->blockvariables[$name] = array();
+
+ }
+
+ }
+
+ } // end func buildBlockvariablelist
+
+ /**
+ * Returns a list of all
+ */
+ function getGlobalvariables() {
+
+ $regs = array();
+ $values = array();
+
+ reset($this->blockvariables["__global__"]);
+ while (list($allowedvar, $v) = each($this->blockvariables["__global__"])) {
+
+ if (isset($this->variableCache[$allowedvar])) {
+ $regs[] = "@".$this->openingDelimiter.$allowedvar.$this->closingDelimiter."@";
+ $values[] = $this->variableCache[$allowedvar];
+ unset($this->variableCache[$allowedvar]);
+ }
+
+ }
+
+ return array($regs, $values);
+ } // end func getGlobalvariables
+
+ /**
+ * Recusively builds a list of all blocks within the template.
+ *
+ * <email protected> string string that gets scanned
+ * <email protected> private
+ * <email protected> $blocklist
+ */
+ function findBlocks($string) {
+
+ $blocklist = array();
+
+ if (preg_match_all($this->blockRegExp, $string, $regs, PREG_SET_ORDER)) {
+
+ reset($regs);
+ while (list($k, $match)=each($regs)) {
+
+ $blockname = $match[1];
+ $blockcontent = $match[2];
+
+ if (isset($this->blocklist[$blockname])) {
+ $this->halt("The name of a block must be unique within a template. Found '$blockname' twice. Unpredictable results may appear.", __FILE__, __LINE__);
+ $this->flagBlocktrouble = true;
+ }
+
+ $this->blocklist[$blockname] = $blockcontent;
+ $this->blockdata[$blockname] = "";
+
+ $blocklist[] = $blockname;
+
+ $inner = $this->findBlocks($blockcontent);
+ reset($inner);
+ while (list($k, $name)=each($inner)) {
+
+ $pattern = sprintf('@<!--\s+BEGIN\s+%s\s+-->(.*)<!--\s+END\s+%s\s+--> <email protected>',
+ $name,
+ $name
+ );
+
+ $this->blocklist[$blockname] = preg_replace( $pattern,
+ $this->openingDelimiter."__".$name."__".$this->closingDelimiter,
+ $this->blocklist[$blockname]
+ );
+ $this->blockinner[$blockname][] = $name;
+ $this->blockparents[$name] = $blockname;
+
+ }
+
+ }
+
+ }
+
+ return $blocklist;
+ } // end func findBlocks
+
+ /**
+ * Reads a file from disk and returns its content.
+ * <email protected> string Filename
+ * <email protected> string Filecontent
+ */
+ function getFile($filename) {
+
+ if ("/" == substr($filename, 0, 1))
+ $filename = substr($filename, 1);
+
+ $filename = $this->fileRoot.$filename;
+
+ if ( !($fh = <email protected>($filename, "r")) ) {
+ $this->halt("Can't read '$filename'.", __FILE__, __LINE__);
+ return "";
+ }
+
+ $content = fread($fh, filesize($filename));
+ fclose($fh);
+
+ return $content;
+ } // end func getFile
+
+ /**
+ * Error Handling function.
+ * <email protected> string error message
+ * <email protected> mixed File where the error occured
+ * <email protected> int Line where the error occured
+ * <email protected> $err
+ */
+ function halt($message, $file="", $line=0) {
+
+ $message = sprintf("IntegratedTemplate Error: %s [File: %s, Line: %d]",
+ $message,
+ $file,
+ $line
+ );
+
+ $this->err[] = $message;
+
+ if ($this->printError)
+ print $message;
+
+ if ($this->haltOnError)
+ die($message);
+
+ } // end func halt
+
+ function introspection($title="", $data = "", $userfunction=true) {
+
+ if (""==$data)
+ $data = $this;
+
+ printf('<table border="1" cellspacing="4" cellpadding="4" bordercolor="Silver">%s',
+ $this->CR_HTML
+ );
+
+ if (""!=$title)
+ printf('<tr>%s<td colspan=4><b>%s</b></td>%s</tr>%s',
+ $this->CR_HTML,
+ $title,
+ $this->CR_HTML,
+ $this->CR_HTML
+ );
+
+ reset($data);
+ while (list($k, $v)=each($data)) {
+
+ if ("user function"==gettype($v) && !$userfunction)
+ continue;
+
+ if (is_array($v) || is_object($v)) {
+
+
+ $color="navy";
+
+ printf('<tr>
+ <td align="left" valign="top">
+ <font color="%s"><pre><b>%s</b></pre></font>
+ </td>
+ <td align="left" valign="top"><font color="%s"><pre>=></pre></font></td>
+ <td align="left" valign="top" colspan=2>',
+ $color,
+ $k,
+ $color,
+ str_replace("<", "<", $v)
+ );
+
+ $this->introspection("", $v, $userfunction);
+
+ printf('</td>%s</tr>%s', $this->CR_HTML, $this->CR_HTML);
+
+ } else {
+
+ $color="black";
+
+ printf('<tr>
+ <td align="left" valign="top">
+ <font color="%s"><pre><b>%s</b></pre></font>
+ </td>
+ <td align="left" valign="top"><pre><font color="%s">=></pre></font></td>
+ <td align="left" valign="top"><pre><font color="%s">[%s]</font></pre></td>
+ <td align="left" valign="top"><pre><font color="%s">"%s"</font></pre></td>
+ </tr>',
+ $color,
+ $k,
+ $color,
+ $color,
+ gettype($v),
+ $color,
+ str_replace("<", "<", $v)
+ );
+ }
+ }
+ print '</table>'.$this->CR_HTML;
+ } // end func introspection
+ var $CR_HTML = "\n";
+
+} // end class IntegratedTemplate
?>
Index: php-lib/php/ext/integratedtemplateextension.inc
diff -u php-lib/php/ext/integratedtemplateextension.inc:1.1 php-lib/php/ext/integratedtemplateextension.inc:1.2
--- php-lib/php/ext/integratedtemplateextension.inc:1.1 Fri Sep 22 13:42:02 2000
+++ php-lib/php/ext/integratedtemplateextension.inc Fri Dec 1 10:16:42 2000
@@ -1,292 +1,569 @@
-<?php
-/**
-* Integrated Template Extension - ITX
-*
-* With this class you get the full power of the phplib template class.
-* You may have one file with blocks in it but you have as well one main file
-* and multiple files one for each block. This is quite usefull when you have
-* user configurable websites. Using blocks not in the main template allows
-* you to some parts of your layout easily.
-*
-* Note that you can replace an existing block and add new blocks add runtime.
-* Adding new blocks means changing a variable placeholder to a block.
-*
-* <email protected> Ulf Wendel <uw <email protected>>
-* <email protected> public
-* <email protected> 1.0 22/09/00
-*/
-class IntegratedTemplateExtension extends IntegratedTemplate {
-
- /**
- * Array with all warnings.
- * <email protected> array
- * <email protected> public
- * <email protected> $printWarning, $haltOnWarning, warning()
- */
- var $warn = array();
-
- /**
- * Print warnings?
- * <email protected> array
- * <email protected> public
- * <email protected> $haltOnWarning, $warn, warning()
- */
- var $printWarning = false;
-
- /**
- * Call die() on warning?
- * <email protected> boolean
- * <email protected> public
- * <email protected> $warn, $printWarning, warning()
- */
- var $haltOnWarning = false;
-
- /**
- * RegExp used to test for a valid blockname.
- * <email protected> string
- */
- var $checkblocknameRegExp = "";
-
- /**
- * Builds some complex regexps and calls the constructor of the parent class.
- *
- * Make sure that you call this constructor if you derive you own
- * template class from this one.
- *
- * <email protected> IntegratedTemplate()
- */
- function IntegratedTemplateExtension() {
-
- $this->checkblocknameRegExp = "@".$this->blocknameRegExp."@";
- $this->IntegratedTemplate();
-
- } // end func IntegratedTemplateExtension
-
- /**
- * Replaces an existing block with new content. Warning: not implemented yet.
- *
- * The Replacement does not affect previously added variables. All data is cached.
- * In case the new block does contain less or other variable placeholder the previously
- * passed data that is no longer referenced will be deleted. The internal list
- * of allowed variables gets updated as well.
- *
- * In case the original block contains other blocks it must eighter have placeholder
- * for the inner blocks or contain them. If you want to use placeholder the placeholder must
- * look like openingDelimiter."__".blockname."__".closingDelimiter .
- *
- * Due to the cache updates replaceBlock() and replaceBlockfile() are "expensive" operations
- * which means extensive usage will slow down your script. So try to avoid them and if
- * you can't do so try to use them before you pass lots of variables to the block you're
- * replacing.
- *
- * <email protected> string Blockname
- * <email protected> string Blockcontent
- * <email protected> boolean
- * <email protected> replaceBlockfile(), addBlock(), addBlockfile()
- * <email protected> public
- */
- function replaceBlock($block, $template) {
- if (!isset($this->blocklist[$block])) {
- $this->halt("The block '$block' does not exist in the template and thus it can't be replaced.", __FILE__, __LINE__);
- return false;
- }
- if (""==$template) {
- $this->halt("No block content given.", __FILE__, __LINE__);
- return false;
- }
-
- print "This function has not been coded yet.";
-
- // find inner blocks
- // add to variablelist
- // compare variable list
- // update caches
-
- return true;
- } // end func replaceBlock
-
- /**
- * Replaces an existing block with new content from a file. Warning: not implemented yet.
- * <email protected> replaceBlock()
- * <email protected> string Blockname
- * <email protected> string Name of the file that contains the blockcontent
- */
- function replaceBlockfile($block, $filename) {
- return $this->replaceBlock($block, $this->getFile($filename));
- } // end func replaceBlockfile
-
- /**
- * Adds a block to the template changing a variable placeholder to a block placeholder.
- *
- * Add means "replace a variable placeholder by a new block".
- * This is different to PHPLibs templates. The function loads a
- * block, creates a handle for it and assigns it to a certain
- * variable placeholder. To to the same with PHPLibs templates you would
- * call set_file() to create the handle and parse() to assign the
- * parsed block to a variable. By this PHPLibs templates assume that you tend
- * to assign a block to more than one one placeholder. To assign a parsed block
- * to more than only the placeholder you specify in this function you have
- * to use a combination of getBlock() and setVariable().
- *
- * As no updates to cached data is necessary addBlock() and addBlockfile()
- * are rather "cheap" meaning quick operations.
- *
- * The block content must not start with <!-- BEGIN blockname --> and end with
- * <!-- END blockname --> this would cause overhead and produce an error.
- *
- * <email protected> string Name of the variable placeholder, the name must be unique within the template.
- * <email protected> string Name of the block to be added
- * <email protected> string Content of the block
- * <email protected> boolean
- * <email protected> addBlockfile()
- * <email protected> public
- */
- function addBlock($placeholder, $blockname, $template) {
-
- // Don't trust any user even if it's a programmer or yourself...
- if (""==$placeholder) {
-
- $this->halt("No variable placeholder given.", __FILE__, __LINE__);
- return false;
-
- } else if (""==$blockname || !preg_match($this->checkblocknameRegExp, $blockname) ) {
-
- print $this->checkblocknameRegExp;
- $this->halt("No or invalid blockname '$blockname' given.", __FILE__, __LINE__);
- return false;
-
- } else if (""==$template) {
-
- $this->halt("No block content given.", __FILE__, __LINE__);
- return false;
-
- } else if (isset($this->blocklist[$blockname])) {
-
- $this->halt("The block already exists.", __FILE__, __LINE__);
- return false;
-
- }
-
- // Hmm, we should do some more tests.
- $parents = $this->findPlaceholderBlocks($placeholder);
- if (0==count($parents)) {
-
- $this->halt("The variable placeholder '$placeholder' was not found in the template.", __FILE__, __LINE__);
- return false;
-
- } else if ( count($parents)>1 ) {
-
- reset($parents);
- while (list($k, $parent)=each($parents))
- $msg.= "$parent, ";
- $msg = substr($parent, -2);
-
- $this->halt("The variable placeholder '$placeholder' must be unique, found in multiple blocks '$msg'.", __FILE__, __LINE__);
- return false;
-
- }
-
- $template = "<!-- BEGIN $blockname -->".$template."<!-- END $blockname -->";
- $this->findBlocks($template);
- if ($this->flagBlocktrouble)
- return false; // findBlocks() already throws an exception
-
- $this->blockinner[$parents[0]][] = $blockname;
- $this->blocklist[$parents[0]] = preg_replace( "@".$this->openingDelimiter.$placeholder.$this->closingDelimiter."@",
- $this->openingDelimiter."__".$blockname."__".$this->closingDelimiter,
- $this->blocklist[$parents[0]]
- );
-
- $this->deleteFromBlockvariablelist($parents[0], $placeholder);
- $this->updateBlockvariablelist($blockname);
-
- return true;
- } // end func addBlock
-
- /**
- * Adds a block taken from a file to the template changing a variable placeholder to a block placeholder.
- *
- * <email protected> string Name of the variable placeholder to be converted
- * <email protected> string Name of the block to be added
- * <email protected> string File that contains the block
- * <email protected> addBlock()
- */
- function addBlockfile($placeholder, $blockname, $filename) {
- return $this->addBlock($placeholder, $blockname, $this->getFile($filename));
- } // end func addBlockfile
-
- /**
- * Deletes one or many variables from the block variable list.
- * <email protected> string Blockname
- * <email protected> mixed Name of one variable or array of variables ( array ( name => true ) ) to be stripped.
- */
- function deleteFromBlockvariablelist($block, $variables) {
-
- if (!is_array($variables))
- $variables = array( $variables => true);
-
- reset($this->blockvariables[$block]);
- while (list($k, $varname)=each($this->blockvariables[$block]))
- if (isset($variables[$varname]))
- unset($this->blockvariables[$block][$k]);
-
- } // end deleteFromBlockvariablelist
-
- /**
- * Updates the variable list of a block.
- * <email protected> string Blockname
- */
- function updateBlockvariablelist($block) {
-
- preg_match_all( $this->variablesRegExp, $this->blocklist[$block], $regs );
- $this->blockvariables[$block] = $regs[1];
-
- } // end func updateBlockvariablelist
-
- /**
- * Returns an array of blocknames where the given variable placeholder is used.
- * <email protected> string Variable placeholder
- * <email protected> array $parents parents[0..n] = blockname
- */
- function findPlaceholderBlocks($variable) {
-
- $parents = array();
-
- reset($this->blocklist);
- while (list($blockname, $content)=each($this->blocklist)) {
-
- reset($this->blockvariables[$blockname]);
- while (list($k, $varname)=each($this->blockvariables[$blockname]))
- if ($variable == $varname)
- $parents[] = $blockname;
- }
-
- return $parents;
- } // end func findPlaceholderBlocks
-
- /**
- * Handles warnings, saves them to $warn and prints them or calls die() depending on the flags
- * <email protected> string Warning
- * <email protected> string File where the warning occured
- * <email protected> int Linenumber where thr warning occured
- * <email protected> $warn, $printWarning, $haltOnWarning
- */
- function warning($message, $file="", $line=0) {
-
- $message = sprintf("IntegratedTemplateExtension Warning: %s [File: %s, Line: %d]",
- $message,
- $file,
- $line );
-
- $this->warn[] = $message;
-
- if ($this->printWarning)
- print $message;
-
- if ($this->haltOnError)
- die($message);
-
- } // end func warning
-
-} // end class IntegratedTemplateExtension
-?>
\ No newline at end of file
+<?php
+/**
+* Integrated Template Extension - ITX
+*
+* With this class you get the full power of the phplib template class.
+* You may have one file with blocks in it but you have as well one main file
+* and multiple files one for each block. This is quite usefull when you have
+* user configurable websites. Using blocks not in the main template allows
+* you to some parts of your layout easily.
+*
+* Note that you can replace an existing block and add new blocks add runtime.
+* Adding new blocks means changing a variable placeholder to a block.
+*
+* <email protected> Ulf Wendel <uw <email protected>>
+* <email protected> public
+* <email protected> 1.0 22/09/00
+*/
+class IntegratedTemplateExtension extends IntegratedTemplate {
+
+ /**
+ * Array with all warnings.
+ * <email protected> array
+ * <email protected> public
+ * <email protected> $printWarning, $haltOnWarning, warning()
+ */
+ var $warn = array();
+
+ /**
+ * Print warnings?
+ * <email protected> array
+ * <email protected> public
+ * <email protected> $haltOnWarning, $warn, warning()
+ */
+ var $printWarning = false;
+
+ /**
+ * Call die() on warning?
+ * <email protected> boolean
+ * <email protected> public
+ * <email protected> $warn, $printWarning, warning()
+ */
+ var $haltOnWarning = false;
+
+ /**
+ * RegExp used to test for a valid blockname.
+ * <email protected> string
+ */
+ var $checkblocknameRegExp = "";
+
+ /**
+ * Functionnameprefix used when searching function calls in the template.
+ * <email protected> string
+ */
+ var $functionPrefix = "func_";
+
+ /**
+ * Functionname RegExp.
+ * <email protected> string
+ */
+ var $functionnameRegExp = "[_a-zA-Z]+[A-Za-z_0-9]*";
+
+ /**
+ * RegExp used to grep function calls in the template.
+ *
+ * The variable gets set by the constructor.
+ *
+ * <email protected> string
+ * <email protected> IntegratedTemplateExtension()
+ */
+ var $functionRegExp = "";
+
+ /**
+ * List of functions found in the template.
+ *
+ * <email protected> array
+ */
+ var $functions = array();
+
+ /**
+ * List of callback functions specified by the user.
+ *
+ * <email protected> array
+ */
+ var $callback = array();
+
+ /**
+ * Builds some complex regexps and calls the constructor of the parent class.
+ *
+ * Make sure that you call this constructor if you derive you own
+ * template class from this one.
+ *
+ * <email protected> IntegratedTemplate()
+ */
+ function IntegratedTemplateExtension() {
+
+ $this->checkblocknameRegExp = "@".$this->blocknameRegExp."@";
+ $this->functionRegExp = "@".$this->functionPrefix."(".$this->functionnameRegExp.")\s*\( <email protected>";
+
+ $this->IntegratedTemplate();
+
+ } // end func IntegratedTemplateExtension
+
+ function init() {
+
+ $this->free();
+ $this->buildFunctionlist();
+ $this->findBlocks($this->template);
+ $this->buildBlockvariablelist();
+
+ } // end func init
+
+
+ /**
+ * Replaces an existing block with new content. Warning: not implemented yet.
+ *
+ * The Replacement does not affect previously added variables. All data is cached.
+ * In case the new block does contain less or other variable placeholder the previously
+ * passed data that is no longer referenced will be deleted. The internal list
+ * of allowed variables gets updated as well.
+ *
+ * In case the original block contains other blocks it must eighter have placeholder
+ * for the inner blocks or contain them. If you want to use placeholder the placeholder must
+ * look like openingDelimiter."__".blockname."__".closingDelimiter .
+ *
+ * Due to the cache updates replaceBlock() and replaceBlockfile() are "expensive" operations
+ * which means extensive usage will slow down your script. So try to avoid them and if
+ * you can't do so try to use them before you pass lots of variables to the block you're
+ * replacing.
+ *
+ * <email protected> string Blockname
+ * <email protected> string Blockcontent
+ * <email protected> boolean
+ * <email protected> replaceBlockfile(), addBlock(), addBlockfile()
+ * <email protected> public
+ */
+ function replaceBlock($block, $template) {
+ if (!isset($this->blocklist[$block])) {
+ $this->halt("The block '$block' does not exist in the template and thus it can't be replaced.", __FILE__, __LINE__);
+ return false;
+ }
+ if (""==$template) {
+ $this->halt("No block content given.", __FILE__, __LINE__);
+ return false;
+ }
+
+ print "This function has not been coded yet.";
+
+ // find inner blocks
+ // add to variablelist
+ // compare variable list
+ // update caches
+
+ return true;
+ } // end func replaceBlock
+
+ /**
+ * Replaces an existing block with new content from a file. Warning: not implemented yet.
+ * <email protected> replaceBlock()
+ * <email protected> string Blockname
+ * <email protected> string Name of the file that contains the blockcontent
+ */
+ function replaceBlockfile($block, $filename) {
+ return $this->replaceBlock($block, $this->getFile($filename));
+ } // end func replaceBlockfile
+
+ /**
+ * Adds a block to the template changing a variable placeholder to a block placeholder.
+ *
+ * Add means "replace a variable placeholder by a new block".
+ * This is different to PHPLibs templates. The function loads a
+ * block, creates a handle for it and assigns it to a certain
+ * variable placeholder. To to the same with PHPLibs templates you would
+ * call set_file() to create the handle and parse() to assign the
+ * parsed block to a variable. By this PHPLibs templates assume that you tend
+ * to assign a block to more than one one placeholder. To assign a parsed block
+ * to more than only the placeholder you specify in this function you have
+ * to use a combination of getBlock() and setVariable().
+ *
+ * As no updates to cached data is necessary addBlock() and addBlockfile()
+ * are rather "cheap" meaning quick operations.
+ *
+ * The block content must not start with <!-- BEGIN blockname --> and end with
+ * <!-- END blockname --> this would cause overhead and produce an error.
+ *
+ * <email protected> string Name of the variable placeholder, the name must be unique within the template.
+ * <email protected> string Name of the block to be added
+ * <email protected> string Content of the block
+ * <email protected> boolean
+ * <email protected> addBlockfile()
+ * <email protected> public
+ */
+ function addBlock($placeholder, $blockname, $template) {
+
+ // Don't trust any user even if it's a programmer or yourself...
+ if ("" == $placeholder) {
+
+ $this->halt("No variable placeholder given.", __FILE__, __LINE__);
+ return false;
+
+ } else if ("" == $blockname || !preg_match($this->checkblocknameRegExp, $blockname) ) {
+
+ print $this->checkblocknameRegExp;
+ $this->halt("No or invalid blockname '$blockname' given.", __FILE__, __LINE__);
+ return false;
+
+ } else if ("" == $template) {
+
+ $this->halt("No block content given.", __FILE__, __LINE__);
+ return false;
+
+ } else if (isset($this->blocklist[$blockname])) {
+
+ $this->halt("The block already exists.", __FILE__, __LINE__);
+ return false;
+
+ }
+
+ // Hmm, we should do some more tests.
+ $parents = $this->findPlaceholderBlocks($placeholder);
+ if (0 == count($parents)) {
+
+ $this->halt("The variable placeholder '$placeholder' was not found in the template.", __FILE__, __LINE__);
+ return false;
+
+ } else if ( count($parents) > 1 ) {
+
+ reset($parents);
+ while (list($k, $parent)=each($parents))
+ $msg.= "$parent, ";
+ $msg = substr($parent, -2);
+
+ $this->halt("The variable placeholder '$placeholder' must be unique, found in multiple blocks '$msg'.", __FILE__, __LINE__);
+ return false;
+
+ }
+
+ $template = "<!-- BEGIN $blockname -->".$template."<!-- END $blockname -->";
+ $this->findBlocks($template);
+ if ($this->flagBlocktrouble)
+ return false; // findBlocks() already throws an exception
+
+ $this->blockinner[$parents[0]][] = $blockname;
+ $this->blocklist[$parents[0]] = preg_replace( "@".$this->openingDelimiter.$placeholder.$this->closingDelimiter."@",
+ $this->openingDelimiter."__".$blockname."__".$this->closingDelimiter,
+ $this->blocklist[$parents[0]]
+ );
+
+ $this->deleteFromBlockvariablelist($parents[0], $placeholder);
+ $this->updateBlockvariablelist($blockname);
+
+ return true;
+ } // end func addBlock
+
+ /**
+ * Adds a block taken from a file to the template changing a variable placeholder to a block placeholder.
+ *
+ * <email protected> string Name of the variable placeholder to be converted
+ * <email protected> string Name of the block to be added
+ * <email protected> string File that contains the block
+ * <email protected> addBlock()
+ */
+ function addBlockfile($placeholder, $blockname, $filename) {
+ return $this->addBlock($placeholder, $blockname, $this->getFile($filename));
+ } // end func addBlockfile
+
+ /**
+ * Returns the name of the (first) block that contains the specified placeholder.
+ *
+ * <email protected> string Name of the placeholder you're searching
+ * <email protected> string Name of the block to scan. If left out (default) all blocks are scanned.
+ * <email protected> string Name of the (first) block that contains the specified placeholder.
+ * If the placeholder was not found or an error occured an empty string is returned.
+ * <email protected> public
+ */
+ function placeholderExists($placeholder, $block = "") {
+
+ if ("" == $placeholder) {
+ $this->halt("No placeholder name given.", __FILE__, __LINE__);
+ return "";
+ }
+
+ if ("" != $block && !isset($this->blocklist[$block])) {
+ $this->halt("Unknown block '$block'.", __FILE__, __LINE__);
+ return "";
+ }
+
+
+ // name of the block where the given placeholder was found
+ $found = "";
+
+ if ( "" != $block) {
+
+ if (is_array($variables = $this->blockvariables[$block])) {
+
+ // search the value in the list of blockvariables
+ reset($variables);
+ while (list($k, $variable) = each($variables))
+ if ($variable == $placeholder) {
+ $found = $block;
+ break;
+ }
+
+ }
+
+ } else {
+
+ // search all blocks and return the name of the first block that
+ // contains the placeholder
+ reset($this->blockvariables);
+ while (list($blockname, $variables) = each($this->blockvariables)) {
+
+ reset($variables);
+ while (list($k, $variable) = each($variables))
+ if ($variable == $placeholder) {
+ $found = $blockname;
+ break 2;
+ }
+
+ }
+
+ }
+
+ return $found;
+ } // end func placeholderExists
+
+ function performCallback() {
+
+ reset($this->functions);
+ while (list($func_id, $function) = each($this->functions)) {
+
+ if (isset($this->callback[$function["name"]])) {
+
+ if ("" != $this->callback[$function["name"]]["object"])
+ $this->setFunctioncontent( $func_id,
+ call_user_method(
+ $this->callback[$function["name"]]["function"],
+ $GLOBALS[$this->callback[$function["name"]]["object"]],
+ $function["args"]
+ )
+ );
+ else
+ $this->setFunctioncontent( $func_id,
+ call_user_func(
+ $this->callback[$function["name"]]["function"],
+ $function["args"]
+ )
+ );
+
+ }
+
+ }
+
+ } // end func performCallback
+
+ /**
+ * Returns a list of all function calls in the current template.
+ *
+ * <email protected> array
+ * <email protected> public
+ */
+ function getFunctioncalls() {
+
+ return $this->functions;
+
+ } // end func getFunctioncalls
+
+ /**
+ * Replaces a function call with the given replacement.
+ *
+ * <email protected> int Function ID
+ * <email protected> string Replacement
+ * <email protected> public
+ */
+ function setFunctioncontent($functionID, $replacement) {
+
+ $this->variableCache["__function".$functionID."__"] = $replacement;
+
+ } // end func setFunctioncontent
+
+ /**
+ * Sets a callback function.
+ *
+ * <email protected> string Function name in the template
+ * <email protected> string Name of the callback function
+ * <email protected> string Name of the callback object
+ * <email protected> boolean False on failure.
+ * <email protected> public
+ */
+ function setCallbackFunction($tplfunction, $callbackfunction, $callbackobject = "") {
+
+ if ("" == $tplfunction || "" == $callbackfunction) {
+ $this->halt("No template function name ('$tplfunction') and/or no callback function name ('$callback') given.", __FILE__, __LINE__);
+ return false;
+ }
+
+ $this->callback[$tplfunction] = array(
+ "function" => $callbackfunction,
+ "object" => $callbackobject
+ );
+
+ return true;
+ } // end func setCallbackFunction
+
+ /**
+ * Sets the Callback function lookup table
+ *
+ * <email protected> array function table - array[templatefunction] = array( "function" => userfunction, "object" => userobject )
+ * <email protected> public
+ */
+ function setCallbackFuntiontable($functions) {
+
+ $this->callback = $functions;
+
+ } // end func setCallbackFunctiontable
+
+ /**
+ * Builds a functionlist from the template.
+ */
+ function buildFunctionlist() {
+
+ $this->functions = array();
+
+ $template = $this->template;
+ $num = 0;
+
+ while (preg_match($this->functionRegExp, $template, $regs)) {
+
+ $pos = strpos($template, $regs[0]);
+ $template = substr($template, $pos + strlen($regs[0]));
+
+ $head = $this->getValue($template, ")");
+ $args = array();
+
+ $this->template = str_replace($regs[0].$head.")", "{__function".$num."__}", $this->template);
+ $template = str_replace($regs[0].$head.")", "{__function".$num."__}", $template);
+
+ while ("" != $head && $arg = $this->getValue($head, ",")) {
+ $args[] = trim($arg);
+ if ($arg == $head)
+ break;
+ $head = substr($head, strlen($arg)+1);
+ }
+
+ $this->functions[$num++] = array(
+ "name" => $regs[1],
+ "args" => $args
+ );
+ }
+
+ } // end func buildFunctionlist
+
+
+ function getValue($code, $delimiter) {
+ if (""==$code)
+ return "";
+
+ if (!is_array($delimiter))
+ $delimiter = array( $delimiter => true );
<

