[phplib-dev] cvs commit From: uw (phplib-dev <email protected>)
Date: 12/01/00

From: uw
Date: Fri Dec 1 10:32:10 2000
Modified files:
      php-lib/php/ext/integratedtemplate.inc
      php-lib/php/ext/integratedtemplateextension.inc

Log message:
- removed a debugging function
- minor apidoc change

Index: php-lib/php/ext/integratedtemplate.inc
diff -u php-lib/php/ext/integratedtemplate.inc:1.6 php-lib/php/ext/integratedtemplate.inc:1.7
--- php-lib/php/ext/integratedtemplate.inc:1.6 Fri Dec 1 10:16:41 2000
+++ php-lib/php/ext/integratedtemplate.inc Fri Dec 1 10:31:37 2000
@@ -1,862 +1,792 @@
-<?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("<", "&lt;", $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("<", "&lt;", $v)
- );
- }
- }
- print '</table>'.$this->CR_HTML;
- } // end func introspection
- var $CR_HTML = "\n";
-
-} // 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
+
+} // end class IntegratedTemplate
 ?>
Index: php-lib/php/ext/integratedtemplateextension.inc
diff -u php-lib/php/ext/integratedtemplateextension.inc:1.2 php-lib/php/ext/integratedtemplateextension.inc:1.3
--- php-lib/php/ext/integratedtemplateextension.inc:1.2 Fri Dec 1 10:16:42 2000
+++ php-lib/php/ext/integratedtemplateextension.inc Fri Dec 1 10:31:38 2000
@@ -1,569 +1,574 @@
-<?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 );
-
- $len = strlen($code);
- $enclosed = false;
- $enclosed_by = "";
-
- if (isset($delimiter[$code[0]])) {
-
- $i = 1;
-
- } else {
-
- for ($i = 0; $ i< $len; ++$i) {
-
- $char = $code[$i];
-
- if (('"' == $char || "'" == $char) && ($char == $enclosed_by || "" == $enclosed_by) && (0 == $i || ($i > 0 && "\\" != $code[$i-1]))) {
-
- if (!$enclosed)
- $enclosed_by = $char;
- else
- $enclosed_by = "";
-
- $enclosed = !$enclosed;
-
- }
- if (!$enclosed && isset($delimiter[$char]))
- break;
-
- }
-
- }
-
- return substr($code, 0, $i);
- } // end func getValue
-
-
- /**
- * 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
+<?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])) {