From 6e2df481d795946dd90cd7c2526cc18fef4e19dd Mon Sep 17 00:00:00 2001 From: Mario Fetka Date: Thu, 8 Mar 2018 14:20:46 +0100 Subject: [PATCH] Imported Upstream version 1.3.1 --- .../HTML/Template/IT.php | 2372 ++++++++--------- .../HTML/Template/ITX.php | 1778 ++++++------ .../HTML/Template/IT_Error.php | 130 +- .../LICENSE | 44 +- .../examples/sample_it.php | 54 +- .../examples/sample_itx_addblockfile.php | 120 +- .../templates/addblockfile_list.tpl.htm | 10 +- .../templates/addblockfile_main.tpl.htm | 22 +- .../examples/templates/main.tpl.htm | 26 +- .../tests/AllTests.php | 0 .../tests/ITTest.php | 832 +++--- .../tests/ITXTest.php | 342 +-- .../tests/templates/__include.html | 2 +- .../tests/templates/addblock.html | 2 +- .../tests/templates/blockiteration.html | 12 +- .../tests/templates/blocks.html | 16 +- .../tests/templates/bug_9853_01.tpl | 0 .../tests/templates/bug_9853_02.tpl | 0 .../tests/templates/globals.html | 26 +- .../tests/templates/include.html | 2 +- .../tests/templates/loadtemplatefile.html | 2 +- .../placeholderreplacementscope.html | 0 .../tests/templates/replaceblock.html | 10 +- package.sig | 6 + package.xml | 81 +- 25 files changed, 2949 insertions(+), 2940 deletions(-) rename {HTML_Template_IT-1.3.0 => HTML_Template_IT-1.3.1}/HTML/Template/IT.php (96%) mode change 100644 => 100755 rename {HTML_Template_IT-1.3.0 => HTML_Template_IT-1.3.1}/HTML/Template/ITX.php (96%) mode change 100644 => 100755 rename {HTML_Template_IT-1.3.0 => HTML_Template_IT-1.3.1}/HTML/Template/IT_Error.php (90%) rename {HTML_Template_IT-1.3.0 => HTML_Template_IT-1.3.1}/LICENSE (98%) rename {HTML_Template_IT-1.3.0 => HTML_Template_IT-1.3.1}/examples/sample_it.php (96%) rename {HTML_Template_IT-1.3.0 => HTML_Template_IT-1.3.1}/examples/sample_itx_addblockfile.php (93%) mode change 100644 => 100755 rename {HTML_Template_IT-1.3.0 => HTML_Template_IT-1.3.1}/examples/templates/addblockfile_list.tpl.htm (89%) rename {HTML_Template_IT-1.3.0 => HTML_Template_IT-1.3.1}/examples/templates/addblockfile_main.tpl.htm (88%) rename {HTML_Template_IT-1.3.0 => HTML_Template_IT-1.3.1}/examples/templates/main.tpl.htm (92%) rename {HTML_Template_IT-1.3.0 => HTML_Template_IT-1.3.1}/tests/AllTests.php (100%) rename {HTML_Template_IT-1.3.0 => HTML_Template_IT-1.3.1}/tests/ITTest.php (96%) rename {HTML_Template_IT-1.3.0 => HTML_Template_IT-1.3.1}/tests/ITXTest.php (96%) rename {HTML_Template_IT-1.3.0 => HTML_Template_IT-1.3.1}/tests/templates/__include.html (93%) rename {HTML_Template_IT-1.3.0 => HTML_Template_IT-1.3.1}/tests/templates/addblock.html (94%) rename {HTML_Template_IT-1.3.0 => HTML_Template_IT-1.3.1}/tests/templates/blockiteration.html (78%) rename {HTML_Template_IT-1.3.0 => HTML_Template_IT-1.3.1}/tests/templates/blocks.html (95%) rename {HTML_Template_IT-1.3.0 => HTML_Template_IT-1.3.1}/tests/templates/bug_9853_01.tpl (100%) rename {HTML_Template_IT-1.3.0 => HTML_Template_IT-1.3.1}/tests/templates/bug_9853_02.tpl (100%) rename {HTML_Template_IT-1.3.0 => HTML_Template_IT-1.3.1}/tests/templates/globals.html (95%) rename {HTML_Template_IT-1.3.0 => HTML_Template_IT-1.3.1}/tests/templates/include.html (97%) rename {HTML_Template_IT-1.3.0 => HTML_Template_IT-1.3.1}/tests/templates/loadtemplatefile.html (91%) rename {HTML_Template_IT-1.3.0 => HTML_Template_IT-1.3.1}/tests/templates/placeholderreplacementscope.html (100%) mode change 100644 => 100755 rename {HTML_Template_IT-1.3.0 => HTML_Template_IT-1.3.1}/tests/templates/replaceblock.html (96%) create mode 100644 package.sig diff --git a/HTML_Template_IT-1.3.0/HTML/Template/IT.php b/HTML_Template_IT-1.3.1/HTML/Template/IT.php old mode 100644 new mode 100755 similarity index 96% rename from HTML_Template_IT-1.3.0/HTML/Template/IT.php rename to HTML_Template_IT-1.3.1/HTML/Template/IT.php index c32f1b3..7f10d0c --- a/HTML_Template_IT-1.3.0/HTML/Template/IT.php +++ b/HTML_Template_IT-1.3.1/HTML/Template/IT.php @@ -1,1186 +1,1186 @@ - - * Pierre-Alain Joye - * David Soria Parra - * - * @category HTML - * @package HTML_Template_IT - * @author Ulf Wendel - * @license BSD http://www.opensource.org/licenses/bsd-license.php - * @version CVS: $Id: IT.php 295605 2010-02-28 22:48:07Z gregorycu $ - * @link http://pear.php.net/packages/HTML_Template_IT - * @access public - */ - -require_once 'PEAR.php'; - -define('IT_OK', 1); -define('IT_ERROR', -1); -define('IT_TPL_NOT_FOUND', -2); -define('IT_BLOCK_NOT_FOUND', -3); -define('IT_BLOCK_DUPLICATE', -4); -define('IT_UNKNOWN_OPTION', -6); - -/** - * 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. - * - * - * - * - * - * - * - * - * - *
- * __global__ - *

- * (hidden and automatically added) - *

block1 - * - * - * - * - * - * - * - * - *
block2
inner1inner2
- *
- * - * To add content to block1 you simply type: - * $tpl->setCurrentBlock("block1"); - * and repeat this as often as needed: - * - * $tpl->setVariable(...); - * $tpl->parseCurrentBlock(); - * - * - * To add content to block2 you would type something like: - * - * $tpl->setCurrentBlock("inner1"); - * $tpl->setVariable(...); - * $tpl->parseCurrentBlock(); - * - * $tpl->setVariable(...); - * $tpl->parseCurrentBlock(); - * - * $tpl->parse("block1"); - * - * - * 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: - * - * $tpl = new HTML_Template_IT( [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(); - * - * - * @category HTML - * @package HTML_Template_IT - * @author Ulf Wendel - * @license BSD http://www.opensource.org/licenses/bsd-license.php - * @link http://pear.php.net/packages/HTML_Template_IT - * @access public - */ -class HTML_Template_IT -{ - /** - * Contains the error objects - * @var array - * @access public - * @see halt(), $printError, $haltOnError - */ - var $err = array(); - - /** - * Clear cache on get()? - - * @var boolean - * @acces public - */ - var $clearCache = false; - - /** - * First character of a variable placeholder ( _{_VARIABLE} ). - * @var string - * @access public - * @see $closingDelimiter, $blocknameRegExp, $variablenameRegExp - */ - var $openingDelimiter = '{'; - - /** - * Last character of a variable placeholder ( {VARIABLE_}_ ). - * @var string - * @access public - * @see $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. - * @var string - * @access public - * @see $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. - * @var string - * @access public - * @see $blocknameRegExp, $openingDelimiter, $closingDelimiter - */ - var $variablenameRegExp = '[\.0-9A-Za-z_-]+'; - - /** - * RegExp used to find variable placeholder, filled by the constructor. - * @var string Looks somewhat like @(delimiter varname delimiter)@ - * @access private - * @see IntegratedTemplate() - */ - var $variablesRegExp = ''; - - /** - * RegExp used to strip unused variable placeholder. - * @access private - * @brother $variablesRegExp - */ - var $removeVariablesRegExp = ''; - - /** - * Controls the handling of unknown variables, default is remove. - * @var boolean - * @access public - */ - var $removeUnknownVariables = true; - - /** - * Controls the handling of empty blocks, default is remove. - * @var boolean - * @access public - */ - var $removeEmptyBlocks = true; - - /** - * RegExp used to find blocks an their content, filled by the constructor. - * @var string - * @see IntegratedTemplate() - * @access private - */ - var $blockRegExp = ''; - - /** - * Name of the current block. - * @var string - * @access private - */ - var $currentBlock = '__global__'; - - /** - * Content of the template. - * @var string - * @access private - */ - var $template = ''; - - /** - * Array of all blocks and their content. - * - * @var array - * @see findBlocks() - * @access private - */ - var $blocklist = array(); - - /** - * Array with the parsed content of a block. - * - * @var array - * @access private - */ - var $blockdata = array(); - - /** - * Array of variables in a block. - * @var array - * @access private - */ - var $blockvariables = array(); - - /** - * Array of inner blocks of a block. - * @var array - * @access private - */ - 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 thisyou 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. - * - * @var array $touchedBlocks - * @see touchBlock(), $removeEmptyBlocks - * @access private - */ - var $touchedBlocks = array(); - - /** - * List of blocks which should not be shown even if not "empty" - * @var array $_hiddenBlocks - * @see hideBlock(), $removeEmptyBlocks - * @access private - */ - var $_hiddenBlocks = array(); - - /** - * Variable cache. - * - * Variables get cached before any replacement is done. - * Advantage: empty blocks can be removed automatically. - * Disadvantage: might take some more memory - * - * @var array - * @see setVariable(), $clearCacheOnParse - * @access private - */ - 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. - * - * @var boolean - * @access public - */ - var $clearCacheOnParse = false; - - /** - * Root directory for all file operations. - * The string gets prefixed to all filenames given. - * @var string - * @see HTML_Template_IT(), setRoot() - * @access private - */ - var $fileRoot = ''; - - /** - * Internal flag indicating that a blockname was used multiple times. - * @var boolean - * @access private - */ - var $flagBlocktrouble = false; - - /** - * Flag indicating that the global block was parsed. - * @var boolean - * @access private - */ - var $flagGlobalParsed = false; - - /** - * EXPERIMENTAL! FIXME! - * Flag indication that a template gets cached. - * - * Complex templates require some times to be preparsed - * before the replacement can take place. Often I use - * one template file over and over again but I don't know - * before that I will use the same template file again. - * Now IT could notice this and skip the preparse. - * - * @var boolean - * @access private - */ - var $flagCacheTemplatefile = true; - - /** - * EXPERIMENTAL! FIXME! - * @access private - */ - var $lastTemplatefile = ''; - - /** - * $_options['preserve_data'] Whether to substitute variables and remove - * empty placeholders in data passed through setVariable - * (see also bugs #20199, #21951). - * $_options['use_preg'] Whether to use preg_replace instead of - * str_replace in parse() - * (this is a backwards compatibility feature, see also bugs #21951, #20392) - * - * @var array - * @access private - */ - var $_options = array( - 'preserve_data' => false, - 'use_preg' => true, - 'preserve_input'=> true - ); - - /** - * 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. - * - * @param string $root File root directory, prefix for all filenames - * given to the object. - * @param mixed $options Unknown - * - * @see setRoot() - * @access public - */ - function HTML_Template_IT($root = '', $options = null) - { - if (!is_null($options)) { - $this->setOptions($options); - } - - $this->variablesRegExp = '@' . $this->openingDelimiter . - '(' . $this->variablenameRegExp . ')' . - $this->closingDelimiter . '@sm'; - - $this->removeVariablesRegExp = '@' . $this->openingDelimiter . - "\s*(" . $this->variablenameRegExp . - ")\s*" . $this->closingDelimiter .'@sm'; - - $this->blockRegExp = '@(.*)@sm'; - - $this->setRoot($root); - } // end constructor - - - /** - * Sets the option for the template class - * - * @param string $option option name - * @param mixed $value option value - * - * @access public - * @return mixed IT_OK on success, error object on failure - */ - function setOption($option, $value) - { - switch ($option) { - case 'removeEmptyBlocks': - $this->removeEmptyBlocks = $value; - return IT_OK; - } - - if (array_key_exists($option, $this->_options)) { - $this->_options[$option] = $value; - return IT_OK; - } - - return PEAR::raiseError( - $this->errorMessage(IT_UNKNOWN_OPTION) . ": '{$option}'", - IT_UNKNOWN_OPTION - ); - } - - /** - * Sets the options for the template class - * - * @param string[] $options options array of options - * default value: - * 'preserve_data' => false, - * 'use_preg' => true - * - * @access public - * @return mixed IT_OK on success, error object on failure - * @see $options - */ - function setOptions($options) - { - if (is_array($options)) { - foreach ($options as $option => $value) { - $error = $this->setOption($option, $value); - if (PEAR::isError($error)) { - return $error; - } - } - } - - return IT_OK; - } - - /** - * Print a certain block with all replacements done. - * - * @param string $block block - * - * @brother get() - * @access public - * @return null - */ - function show($block = '__global__') - { - print $this->get($block); - } // end func show - - /** - * Returns a block with all replacements done. - * - * @param string $block name of the block - * - * @return string - * @throws PEAR_Error - * @access public - * @see show() - */ - function get($block = '__global__') - { - if ($block == '__global__' && !$this->flagGlobalParsed) { - $this->parse('__global__'); - } - - if (!isset($this->blocklist[$block])) { - $this->err[] = PEAR::raiseError( - $this->errorMessage(IT_BLOCK_NOT_FOUND) . '"' . $block . "'", - IT_BLOCK_NOT_FOUND - ); - return ''; - } - - if (isset($this->blockdata[$block])) { - $ret = $this->blockdata[$block]; - - if ($this->clearCache) { - unset($this->blockdata[$block]); - if ($block == '__global__') { - $this->flagGlobalParsed = false; - } - } - - if ($this->_options['preserve_data']) { - $ret = str_replace( - $this->openingDelimiter . - '%preserved%' . $this->closingDelimiter, - $this->openingDelimiter, - $ret - ); - } - return $ret; - } - - return ''; - } // end func get() - - /** - * Parses the given block. - * - * @param string $block name of the block to be parsed - * @param bool $flag_recursion unknown - * - * @access public - * @see parseCurrentBlock() - * @throws PEAR_Error - * @return null - */ - function parse($block = '__global__', $flag_recursion = false) - { - static $regs, $values; - - if (!isset($this->blocklist[$block])) { - return PEAR::raiseError( - $this->errorMessage(IT_BLOCK_NOT_FOUND) . '"' . $block . "'", - IT_BLOCK_NOT_FOUND - ); - } - - if ($block == '__global__') { - $this->flagGlobalParsed = true; - } - - if (!$flag_recursion) { - $regs = array(); - $values = array(); - } - $outer = $this->blocklist[$block]; - $empty = true; - - $variablelist = array(); - if ($this->clearCacheOnParse) { - foreach ($this->variableCache as $name => $value) { - $regs[] = $this->openingDelimiter . - $name . $this->closingDelimiter; - - $values[] = $value; - - $empty = false; - - $variablelist[] = $name; - } - $this->variableCache = array(); - } else { - foreach ($this->blockvariables[$block] as $allowedvar => $v) { - - if (isset($this->variableCache[$allowedvar])) { - $regs[] = $this->openingDelimiter . - $allowedvar . $this->closingDelimiter; - $values[] = $this->variableCache[$allowedvar]; - - unset($this->variableCache[$allowedvar]); - - $empty = false; - - $variablelist[] = $allowedvar; - } - } - } - - if (isset($this->blockinner[$block])) { - foreach ($this->blockinner[$block] as $k => $innerblock) { - - $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 (!$flag_recursion && 0 != count($values)) { - if ($this->_options['use_preg']) { - $regs = array_map(array(&$this, '_addPregDelimiters'), $regs); - $values = array_map(array(&$this, '_escapeBackreferences'), $values); - - $funcReplace = 'preg_replace'; - } else { - $funcReplace = 'str_replace'; - } - - if ($this->_options['preserve_data']) { - $values = array_map( - array(&$this, '_preserveOpeningDelimiter'), - $values - ); - } - - $outer = $funcReplace($regs, $values, $outer); - } - - if ($this->removeUnknownVariables) { - $outer = $this->removeUnknownVariablesFromBlock( - $block, - $outer, - $variablelist - ); - } - - if ($empty) { - if (!$this->removeEmptyBlocks) { - $this->blockdata[$block ] .= $outer; - } else { - if (isset($this->touchedBlocks[$block])) { - $this->blockdata[$block] .= $outer; - unset($this->touchedBlocks[$block]); - } - } - } else { - if (empty($this->blockdata[$block])) { - $this->blockdata[$block] = $outer; - } else { - $this->blockdata[$block] .= $outer; - } - } - - return $empty; - } // end func parse - - /** - * Removes unknown variables from block. If preserve_input is set to true - * only unknown variables that were present during setTemplate or - * loadTemplatefile are removed. Thus you can set a variable to - * "{SOMEINPUTDATA}" which is preserved. - * - * @param string $blockname block - * @param string $blockinner unknown - * @param string $variableList unknown - * - * @see parse() - * @access private - * @return null - */ - function removeUnknownVariablesFromBlock ($blockname, $blockinner, $variableList) - { - if ($this->_options['preserve_input']) { - foreach ($this->blockvariables[$blockname] as $var => $setted) { - if (!in_array($var, $variableList)) { - $blockinner = str_replace( - $this->openingDelimiter . $var . $this->closingDelimiter, - '', - $blockinner - ); - } - } - } else { - $blockinner = preg_replace( - $this->removeVariablesRegExp, - '', - $blockinner - ); - } - - return $blockinner; - } - - /** - * Parses the current block - * - * @see parse(), setCurrentBlock(), $currentBlock - * @access public - * @return null - */ - function parseCurrentBlock() - { - return $this->parse($this->currentBlock); - } // end func parseCurrentBlock - - /** - * Checks to see if a placeholder exists within a block (and its children) - * - * @access public - * @return bool - */ - function checkPlaceholderExists($blockname, $placeholder) { - if (isset($this->blockvariables[$blockname][$placeholder])) { - return true; - } - if (isset($this->blockinner[$blockname])) { - foreach ($this->blockinner[$blockname] as $block) { - if ($this->checkPlaceholderExists($block, $placeholder)) { - return true; - } - } - } - return false; - } // end func checkPlaceholderExists - - /** - * 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(). - * - * @param mixed $variable string with the variable name or an array - * %variables["varname"] = "value" - * @param string $value value of the variable or empty if $variable - * is an array. - * - * @access public - * @return null - */ - function setVariable($variable, $value = '') - { - if (is_array($variable)) { - foreach ($variable as $key => $value) { - $this->setVariable($key, $value); - } - } else { - if ($this->checkPlaceholderExists($this->currentBlock, $variable)) { - $this->variableCache[$variable] = $value; - } - } - } // end func setVariable - - /** - * Sets the name of the current block that is the block where variables - * are added. - * - * @param string $block name of the block - * - * @return boolean false on failure, otherwise true - * @throws PEAR_Error - * @access public - */ - function setCurrentBlock($block = '__global__') - { - - if (!isset($this->blocklist[$block])) { - return PEAR::raiseError( - $this->errorMessage(IT_BLOCK_NOT_FOUND) - . '"' . $block . "'", - IT_BLOCK_NOT_FOUND - ); - } - - $this->currentBlock = $block; - - return true; - } // end func setCurrentBlock - - /** - * Preserves an empty block even if removeEmptyBlocks is true. - * - * @param string $block name of the block - * - * @return boolean false on false, otherwise true - * @throws PEAR_Error - * @access public - * @see $removeEmptyBlocks - */ - function touchBlock($block) - { - if (!isset($this->blocklist[$block])) { - return PEAR::raiseError( - $this->errorMessage(IT_BLOCK_NOT_FOUND) . '"' . $block . "'", - IT_BLOCK_NOT_FOUND - ); - } - - $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. - * - * @access private - * @see free() - * @return null - */ - function init() - { - $this->free(); - $this->findBlocks($this->template); - // we don't need it any more - $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. - * - * @access private - * @see init() - * @return null - */ - function free() - { - $this->err = array(); - - $this->currentBlock = '__global__'; - - $this->variableCache = array(); - $this->blocklist = 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. - * - * @param string $template template content - * @param bool $removeUnknownVariables how to handle unknown variables. - * @param bool $removeEmptyBlocks how to handle empty blocks. - * - * @see LoadTemplatefile(), $template - * @access public - * @return boolean - */ - function setTemplate( $template, - $removeUnknownVariables = true, - $removeEmptyBlocks = true) { - $this->removeUnknownVariables = $removeUnknownVariables; - - $this->removeEmptyBlocks = $removeEmptyBlocks; - - if ($template == '' && $this->flagCacheTemplatefile) { - $this->variableCache = array(); - $this->blockdata = array(); - $this->touchedBlocks = array(); - $this->currentBlock = '__global__'; - } else { - $this->template = '' . $template . - ''; - $this->init(); - } - - if ($this->flagBlocktrouble) { - return false; - } - - return true; - } // end func setTemplate - - /** - * Reads a template file from the disk. - * - * @param string $filename name of the template file - * @param bool $removeUnknownVariables how to handle unknown variables. - * @param bool $removeEmptyBlocks how to handle empty blocks. - * - * @access public - * @return boolean false on failure, otherwise true - * @see $template, setTemplate(), $removeUnknownVariables, - * $removeEmptyBlocks - */ - function loadTemplatefile( $filename, - $removeUnknownVariables = true, - $removeEmptyBlocks = true ) {; - $template = ''; - if (!$this->flagCacheTemplatefile - || $this->lastTemplatefile != $filename - ) { - $template = $this->getFile($filename); - } - $this->lastTemplatefile = $filename; - - return $template != '' ? - $this->setTemplate( - $template, - $removeUnknownVariables, - $removeEmptyBlocks) : false; - } // 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. - * - * @param string $root File root - * - * @see HTML_Template_IT() - * @access public - * @return null - */ - function setRoot($root) - { - if ($root != '' && substr($root, -1) != '/') { - $root .= '/'; - } - - $this->fileRoot = $root; - } // end func setRoot - - /** - * Build a list of all variables within of a block - * - * @access private - * @return null - */ - function buildBlockvariablelist() - { - foreach ($this->blocklist as $name => $content) { - preg_match_all($this->variablesRegExp, $content, $regs); - - if (count($regs[1]) != 0) { - foreach ($regs[1] as $k => $var) { - $this->blockvariables[$name][$var] = true; - } - } else { - $this->blockvariables[$name] = array(); - } - } - } // end func buildBlockvariablelist - - /** - * Returns a list of all global variables - * - * @access public - * @return array - */ - function getGlobalvariables() - { - $regs = array(); - $values = array(); - - foreach ($this->blockvariables['__global__'] as $allowedvar => $v) { - 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. - * - * @param string $string string that gets scanned - * - * @access private - * @see $blocklist - * @return array - */ - function findBlocks($string) - { - $blocklist = array(); - - if (preg_match_all($this->blockRegExp, $string, $regs, PREG_SET_ORDER)) { - foreach ($regs as $k => $match) { - $blockname = $match[1]; - $blockcontent = $match[2]; - - if (isset($this->blocklist[$blockname])) { - $msg = $this->errorMessage(IT_BLOCK_DUPLICATE, $blockname); - - $this->err[] = PEAR::raiseError($msg, IT_BLOCK_DUPLICATE); - - $this->flagBlocktrouble = true; - } - - $this->blocklist[$blockname] = $blockcontent; - $this->blockdata[$blockname] = ""; - - $blocklist[] = $blockname; - - $inner = $this->findBlocks($blockcontent); - $regex = '@(.*)@sm'; - foreach ($inner as $k => $name) { - $pattern = sprintf($regex, preg_quote($name), preg_quote($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. - * - * @param string $filename Filename - * - * @return string Filecontent - * @access private - */ - function getFile($filename) - { - if ($filename{0} == '/' && substr($this->fileRoot, -1) == '/') { - $filename = substr($filename, 1); - } - - $filename = $this->fileRoot . $filename; - - if (!($fh = @fopen($filename, 'r'))) { - $this->err[] = PEAR::raiseError( - $this->errorMessage(IT_TPL_NOT_FOUND) . ': "' .$filename .'"', - IT_TPL_NOT_FOUND - ); - return ""; - } - - $fsize = filesize($filename); - if ($fsize < 1) { - fclose($fh); - return ''; - } - - $content = fread($fh, $fsize); - fclose($fh); - - return preg_replace( - "##ime", - "\$this->getFile('\\1')", - $content - ); - } // end func getFile - - /** - * Adds delimiters to a string, so it can be used as a pattern - * in preg_* functions - * - * @param string $str input - * - * @return string - * @access private - */ - function _addPregDelimiters($str) - { - return '@' . preg_quote($str) . '@'; - } - - /** - * Escapes $ and \ as preg_replace will treat - * them as a backreference and not literal. - * See bug #9501 - * - * @param string $str String to escape - * - * @since 1.2.2 - * @return string - * @access private - */ - function _escapeBackreferences($str) - { - $str = str_replace('\\', '\\\\', $str); - $str = preg_replace('@\$([0-9]{1,2})@', '\\\$${1}', $str); - return $str; - } - - /** - * Replaces an opening delimiter by a special string - * - * @param string $str special string - * - * @return string - * @access private - */ - function _preserveOpeningDelimiter($str) - { - return (false === strpos($str, $this->openingDelimiter))? - $str: - str_replace( - $this->openingDelimiter, - $this->openingDelimiter . - '%preserved%' . $this->closingDelimiter, - $str - ); - } - - /** - * Return a textual error message for a IT error code - * - * @param integer $value error code - * @param string $blockname unknown - * - * @access private - * @return string error message, or false if the error code was - * not recognized - */ - function errorMessage($value, $blockname = '') - { - static $errorMessages; - if (!isset($errorMessages)) { - $errorMessages = array( - IT_OK => '', - IT_ERROR => 'unknown error', - IT_TPL_NOT_FOUND => 'Cannot read the template file', - IT_BLOCK_NOT_FOUND => 'Cannot find this block', - IT_BLOCK_DUPLICATE => 'The name of a block must be'. - ' uniquewithin a template.'. - ' Found "' . $blockname . '" twice.'. - 'Unpredictable results '. - 'may appear.', - IT_UNKNOWN_OPTION => 'Unknown option' - ); - } - - if (PEAR::isError($value)) { - $value = $value->getCode(); - } - - return isset($errorMessages[$value]) ? - $errorMessages[$value] : $errorMessages[IT_ERROR]; - } -} // end class IntegratedTemplate -?> + + * Pierre-Alain Joye + * David Soria Parra + * + * @category HTML + * @package HTML_Template_IT + * @author Ulf Wendel + * @license BSD http://www.opensource.org/licenses/bsd-license.php + * @version CVS: $Id$ + * @link http://pear.php.net/packages/HTML_Template_IT + * @access public + */ + +require_once 'PEAR.php'; + +define('IT_OK', 1); +define('IT_ERROR', -1); +define('IT_TPL_NOT_FOUND', -2); +define('IT_BLOCK_NOT_FOUND', -3); +define('IT_BLOCK_DUPLICATE', -4); +define('IT_UNKNOWN_OPTION', -6); + +/** + * 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. + * + * + * + * + * + * + * + * + * + *
+ * __global__ + *

+ * (hidden and automatically added) + *

block1 + * + * + * + * + * + * + * + * + *
block2
inner1inner2
+ *
+ * + * To add content to block1 you simply type: + * $tpl->setCurrentBlock("block1"); + * and repeat this as often as needed: + * + * $tpl->setVariable(...); + * $tpl->parseCurrentBlock(); + * + * + * To add content to block2 you would type something like: + * + * $tpl->setCurrentBlock("inner1"); + * $tpl->setVariable(...); + * $tpl->parseCurrentBlock(); + * + * $tpl->setVariable(...); + * $tpl->parseCurrentBlock(); + * + * $tpl->parse("block1"); + * + * + * 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: + * + * $tpl = new HTML_Template_IT( [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(); + * + * + * @category HTML + * @package HTML_Template_IT + * @author Ulf Wendel + * @license BSD http://www.opensource.org/licenses/bsd-license.php + * @link http://pear.php.net/packages/HTML_Template_IT + * @access public + */ +class HTML_Template_IT +{ + /** + * Contains the error objects + * @var array + * @access public + * @see halt(), $printError, $haltOnError + */ + var $err = array(); + + /** + * Clear cache on get()? + + * @var boolean + * @acces public + */ + var $clearCache = false; + + /** + * First character of a variable placeholder ( _{_VARIABLE} ). + * @var string + * @access public + * @see $closingDelimiter, $blocknameRegExp, $variablenameRegExp + */ + var $openingDelimiter = '{'; + + /** + * Last character of a variable placeholder ( {VARIABLE_}_ ). + * @var string + * @access public + * @see $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. + * @var string + * @access public + * @see $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. + * @var string + * @access public + * @see $blocknameRegExp, $openingDelimiter, $closingDelimiter + */ + var $variablenameRegExp = '[\.0-9A-Za-z_-]+'; + + /** + * RegExp used to find variable placeholder, filled by the constructor. + * @var string Looks somewhat like @(delimiter varname delimiter)@ + * @access private + * @see IntegratedTemplate() + */ + var $variablesRegExp = ''; + + /** + * RegExp used to strip unused variable placeholder. + * @access private + * @brother $variablesRegExp + */ + var $removeVariablesRegExp = ''; + + /** + * Controls the handling of unknown variables, default is remove. + * @var boolean + * @access public + */ + var $removeUnknownVariables = true; + + /** + * Controls the handling of empty blocks, default is remove. + * @var boolean + * @access public + */ + var $removeEmptyBlocks = true; + + /** + * RegExp used to find blocks an their content, filled by the constructor. + * @var string + * @see IntegratedTemplate() + * @access private + */ + var $blockRegExp = ''; + + /** + * Name of the current block. + * @var string + * @access private + */ + var $currentBlock = '__global__'; + + /** + * Content of the template. + * @var string + * @access private + */ + var $template = ''; + + /** + * Array of all blocks and their content. + * + * @var array + * @see findBlocks() + * @access private + */ + var $blocklist = array(); + + /** + * Array with the parsed content of a block. + * + * @var array + * @access private + */ + var $blockdata = array(); + + /** + * Array of variables in a block. + * @var array + * @access private + */ + var $blockvariables = array(); + + /** + * Array of inner blocks of a block. + * @var array + * @access private + */ + 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 thisyou 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. + * + * @var array $touchedBlocks + * @see touchBlock(), $removeEmptyBlocks + * @access private + */ + var $touchedBlocks = array(); + + /** + * List of blocks which should not be shown even if not "empty" + * @var array $_hiddenBlocks + * @see hideBlock(), $removeEmptyBlocks + * @access private + */ + var $_hiddenBlocks = array(); + + /** + * Variable cache. + * + * Variables get cached before any replacement is done. + * Advantage: empty blocks can be removed automatically. + * Disadvantage: might take some more memory + * + * @var array + * @see setVariable(), $clearCacheOnParse + * @access private + */ + 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. + * + * @var boolean + * @access public + */ + var $clearCacheOnParse = false; + + /** + * Root directory for all file operations. + * The string gets prefixed to all filenames given. + * @var string + * @see HTML_Template_IT(), setRoot() + * @access private + */ + var $fileRoot = ''; + + /** + * Internal flag indicating that a blockname was used multiple times. + * @var boolean + * @access private + */ + var $flagBlocktrouble = false; + + /** + * Flag indicating that the global block was parsed. + * @var boolean + * @access private + */ + var $flagGlobalParsed = false; + + /** + * EXPERIMENTAL! FIXME! + * Flag indication that a template gets cached. + * + * Complex templates require some times to be preparsed + * before the replacement can take place. Often I use + * one template file over and over again but I don't know + * before that I will use the same template file again. + * Now IT could notice this and skip the preparse. + * + * @var boolean + * @access private + */ + var $flagCacheTemplatefile = true; + + /** + * EXPERIMENTAL! FIXME! + * @access private + */ + var $lastTemplatefile = ''; + + /** + * $_options['preserve_data'] Whether to substitute variables and remove + * empty placeholders in data passed through setVariable + * (see also bugs #20199, #21951). + * $_options['use_preg'] Whether to use preg_replace instead of + * str_replace in parse() + * (this is a backwards compatibility feature, see also bugs #21951, #20392) + * + * @var array + * @access private + */ + var $_options = array( + 'preserve_data' => false, + 'use_preg' => true, + 'preserve_input'=> true + ); + + /** + * 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. + * + * @param string $root File root directory, prefix for all filenames + * given to the object. + * @param mixed $options Unknown + * + * @see setRoot() + * @access public + */ + function __construct($root = '', $options = null) + { + if (!is_null($options)) { + $this->setOptions($options); + } + + $this->variablesRegExp = '@' . $this->openingDelimiter . + '(' . $this->variablenameRegExp . ')' . + $this->closingDelimiter . '@sm'; + + $this->removeVariablesRegExp = '@' . $this->openingDelimiter . + "\s*(" . $this->variablenameRegExp . + ")\s*" . $this->closingDelimiter .'@sm'; + + $this->blockRegExp = '@(.*)@sm'; + + $this->setRoot($root); + } // end constructor + + + /** + * Sets the option for the template class + * + * @param string $option option name + * @param mixed $value option value + * + * @access public + * @return mixed IT_OK on success, error object on failure + */ + function setOption($option, $value) + { + switch ($option) { + case 'removeEmptyBlocks': + $this->removeEmptyBlocks = $value; + return IT_OK; + } + + if (array_key_exists($option, $this->_options)) { + $this->_options[$option] = $value; + return IT_OK; + } + + return PEAR::raiseError( + $this->errorMessage(IT_UNKNOWN_OPTION) . ": '{$option}'", + IT_UNKNOWN_OPTION + ); + } + + /** + * Sets the options for the template class + * + * @param string[] $options options array of options + * default value: + * 'preserve_data' => false, + * 'use_preg' => true + * + * @access public + * @return mixed IT_OK on success, error object on failure + * @see $options + */ + function setOptions($options) + { + if (is_array($options)) { + foreach ($options as $option => $value) { + $error = $this->setOption($option, $value); + if (PEAR::isError($error)) { + return $error; + } + } + } + + return IT_OK; + } + + /** + * Print a certain block with all replacements done. + * + * @param string $block block + * + * @brother get() + * @access public + * @return null + */ + function show($block = '__global__') + { + print $this->get($block); + } // end func show + + /** + * Returns a block with all replacements done. + * + * @param string $block name of the block + * + * @return string + * @throws PEAR_Error + * @access public + * @see show() + */ + function get($block = '__global__') + { + if ($block == '__global__' && !$this->flagGlobalParsed) { + $this->parse('__global__'); + } + + if (!isset($this->blocklist[$block])) { + $this->err[] = PEAR::raiseError( + $this->errorMessage(IT_BLOCK_NOT_FOUND) . '"' . $block . "'", + IT_BLOCK_NOT_FOUND + ); + return ''; + } + + if (isset($this->blockdata[$block])) { + $ret = $this->blockdata[$block]; + + if ($this->clearCache) { + unset($this->blockdata[$block]); + if ($block == '__global__') { + $this->flagGlobalParsed = false; + } + } + + if ($this->_options['preserve_data']) { + $ret = str_replace( + $this->openingDelimiter . + '%preserved%' . $this->closingDelimiter, + $this->openingDelimiter, + $ret + ); + } + return $ret; + } + + return ''; + } // end func get() + + /** + * Parses the given block. + * + * @param string $block name of the block to be parsed + * @param bool $flag_recursion unknown + * + * @access public + * @see parseCurrentBlock() + * @throws PEAR_Error + * @return null + */ + function parse($block = '__global__', $flag_recursion = false) + { + static $regs, $values; + + if (!isset($this->blocklist[$block])) { + return PEAR::raiseError( + $this->errorMessage(IT_BLOCK_NOT_FOUND) . '"' . $block . "'", + IT_BLOCK_NOT_FOUND + ); + } + + if ($block == '__global__') { + $this->flagGlobalParsed = true; + } + + if (!$flag_recursion) { + $regs = array(); + $values = array(); + } + $outer = $this->blocklist[$block]; + $empty = true; + + $variablelist = array(); + if ($this->clearCacheOnParse) { + foreach ($this->variableCache as $name => $value) { + $regs[] = $this->openingDelimiter . + $name . $this->closingDelimiter; + + $values[] = $value; + + $empty = false; + + $variablelist[] = $name; + } + $this->variableCache = array(); + } else { + foreach ($this->blockvariables[$block] as $allowedvar => $v) { + + if (isset($this->variableCache[$allowedvar])) { + $regs[] = $this->openingDelimiter . + $allowedvar . $this->closingDelimiter; + $values[] = $this->variableCache[$allowedvar]; + + unset($this->variableCache[$allowedvar]); + + $empty = false; + + $variablelist[] = $allowedvar; + } + } + } + + if (isset($this->blockinner[$block])) { + foreach ($this->blockinner[$block] as $k => $innerblock) { + + $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 (!$flag_recursion && 0 != count($values)) { + if ($this->_options['use_preg']) { + $regs = array_map(array(&$this, '_addPregDelimiters'), $regs); + $values = array_map(array(&$this, '_escapeBackreferences'), $values); + + $funcReplace = 'preg_replace'; + } else { + $funcReplace = 'str_replace'; + } + + if ($this->_options['preserve_data']) { + $values = array_map( + array(&$this, '_preserveOpeningDelimiter'), + $values + ); + } + + $outer = $funcReplace($regs, $values, $outer); + } + + if ($this->removeUnknownVariables) { + $outer = $this->removeUnknownVariablesFromBlock( + $block, + $outer, + $variablelist + ); + } + + if ($empty) { + if (!$this->removeEmptyBlocks) { + $this->blockdata[$block ] .= $outer; + } else { + if (isset($this->touchedBlocks[$block])) { + $this->blockdata[$block] .= $outer; + unset($this->touchedBlocks[$block]); + } + } + } else { + if (empty($this->blockdata[$block])) { + $this->blockdata[$block] = $outer; + } else { + $this->blockdata[$block] .= $outer; + } + } + + return $empty; + } // end func parse + + /** + * Removes unknown variables from block. If preserve_input is set to true + * only unknown variables that were present during setTemplate or + * loadTemplatefile are removed. Thus you can set a variable to + * "{SOMEINPUTDATA}" which is preserved. + * + * @param string $blockname block + * @param string $blockinner unknown + * @param string $variableList unknown + * + * @see parse() + * @access private + * @return null + */ + function removeUnknownVariablesFromBlock ($blockname, $blockinner, $variableList) + { + if ($this->_options['preserve_input']) { + foreach ($this->blockvariables[$blockname] as $var => $setted) { + if (!in_array($var, $variableList)) { + $blockinner = str_replace( + $this->openingDelimiter . $var . $this->closingDelimiter, + '', + $blockinner + ); + } + } + } else { + $blockinner = preg_replace( + $this->removeVariablesRegExp, + '', + $blockinner + ); + } + + return $blockinner; + } + + /** + * Parses the current block + * + * @see parse(), setCurrentBlock(), $currentBlock + * @access public + * @return null + */ + function parseCurrentBlock() + { + return $this->parse($this->currentBlock); + } // end func parseCurrentBlock + + /** + * Checks to see if a placeholder exists within a block (and its children) + * + * @access public + * @return bool + */ + function checkPlaceholderExists($blockname, $placeholder) { + if (isset($this->blockvariables[$blockname][$placeholder])) { + return true; + } + if (isset($this->blockinner[$blockname])) { + foreach ($this->blockinner[$blockname] as $block) { + if ($this->checkPlaceholderExists($block, $placeholder)) { + return true; + } + } + } + return false; + } // end func checkPlaceholderExists + + /** + * 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(). + * + * @param mixed $variable string with the variable name or an array + * %variables["varname"] = "value" + * @param string $value value of the variable or empty if $variable + * is an array. + * + * @access public + * @return null + */ + function setVariable($variable, $value = '') + { + if (is_array($variable)) { + foreach ($variable as $key => $value) { + $this->setVariable($key, $value); + } + } else { + if ($this->checkPlaceholderExists($this->currentBlock, $variable)) { + $this->variableCache[$variable] = $value; + } + } + } // end func setVariable + + /** + * Sets the name of the current block that is the block where variables + * are added. + * + * @param string $block name of the block + * + * @return boolean false on failure, otherwise true + * @throws PEAR_Error + * @access public + */ + function setCurrentBlock($block = '__global__') + { + + if (!isset($this->blocklist[$block])) { + return PEAR::raiseError( + $this->errorMessage(IT_BLOCK_NOT_FOUND) + . '"' . $block . "'", + IT_BLOCK_NOT_FOUND + ); + } + + $this->currentBlock = $block; + + return true; + } // end func setCurrentBlock + + /** + * Preserves an empty block even if removeEmptyBlocks is true. + * + * @param string $block name of the block + * + * @return boolean false on false, otherwise true + * @throws PEAR_Error + * @access public + * @see $removeEmptyBlocks + */ + function touchBlock($block) + { + if (!isset($this->blocklist[$block])) { + return PEAR::raiseError( + $this->errorMessage(IT_BLOCK_NOT_FOUND) . '"' . $block . "'", + IT_BLOCK_NOT_FOUND + ); + } + + $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. + * + * @access private + * @see free() + * @return null + */ + function init() + { + $this->free(); + $this->findBlocks($this->template); + // we don't need it any more + $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. + * + * @access private + * @see init() + * @return null + */ + function free() + { + $this->err = array(); + + $this->currentBlock = '__global__'; + + $this->variableCache = array(); + $this->blocklist = 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. + * + * @param string $template template content + * @param bool $removeUnknownVariables how to handle unknown variables. + * @param bool $removeEmptyBlocks how to handle empty blocks. + * + * @see LoadTemplatefile(), $template + * @access public + * @return boolean + */ + function setTemplate( $template, + $removeUnknownVariables = true, + $removeEmptyBlocks = true) { + $this->removeUnknownVariables = $removeUnknownVariables; + + $this->removeEmptyBlocks = $removeEmptyBlocks; + + if ($template == '' && $this->flagCacheTemplatefile) { + $this->variableCache = array(); + $this->blockdata = array(); + $this->touchedBlocks = array(); + $this->currentBlock = '__global__'; + } else { + $this->template = '' . $template . + ''; + $this->init(); + } + + if ($this->flagBlocktrouble) { + return false; + } + + return true; + } // end func setTemplate + + /** + * Reads a template file from the disk. + * + * @param string $filename name of the template file + * @param bool $removeUnknownVariables how to handle unknown variables. + * @param bool $removeEmptyBlocks how to handle empty blocks. + * + * @access public + * @return boolean false on failure, otherwise true + * @see $template, setTemplate(), $removeUnknownVariables, + * $removeEmptyBlocks + */ + function loadTemplatefile( $filename, + $removeUnknownVariables = true, + $removeEmptyBlocks = true ) {; + $template = ''; + if (!$this->flagCacheTemplatefile + || $this->lastTemplatefile != $filename + ) { + $template = $this->getFile($filename); + } + $this->lastTemplatefile = $filename; + + return $template != '' ? + $this->setTemplate( + $template, + $removeUnknownVariables, + $removeEmptyBlocks) : false; + } // 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. + * + * @param string $root File root + * + * @see HTML_Template_IT() + * @access public + * @return null + */ + function setRoot($root) + { + if ($root != '' && substr($root, -1) != '/') { + $root .= '/'; + } + + $this->fileRoot = $root; + } // end func setRoot + + /** + * Build a list of all variables within of a block + * + * @access private + * @return null + */ + function buildBlockvariablelist() + { + foreach ($this->blocklist as $name => $content) { + preg_match_all($this->variablesRegExp, $content, $regs); + + if (count($regs[1]) != 0) { + foreach ($regs[1] as $k => $var) { + $this->blockvariables[$name][$var] = true; + } + } else { + $this->blockvariables[$name] = array(); + } + } + } // end func buildBlockvariablelist + + /** + * Returns a list of all global variables + * + * @access public + * @return array + */ + function getGlobalvariables() + { + $regs = array(); + $values = array(); + + foreach ($this->blockvariables['__global__'] as $allowedvar => $v) { + 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. + * + * @param string $string string that gets scanned + * + * @access private + * @see $blocklist + * @return array + */ + function findBlocks($string) + { + $blocklist = array(); + + if (preg_match_all($this->blockRegExp, $string, $regs, PREG_SET_ORDER)) { + foreach ($regs as $k => $match) { + $blockname = $match[1]; + $blockcontent = $match[2]; + + if (isset($this->blocklist[$blockname])) { + $msg = $this->errorMessage(IT_BLOCK_DUPLICATE, $blockname); + + $this->err[] = PEAR::raiseError($msg, IT_BLOCK_DUPLICATE); + + $this->flagBlocktrouble = true; + } + + $this->blocklist[$blockname] = $blockcontent; + $this->blockdata[$blockname] = ""; + + $blocklist[] = $blockname; + + $inner = $this->findBlocks($blockcontent); + $regex = '@(.*)@sm'; + foreach ($inner as $k => $name) { + $pattern = sprintf($regex, preg_quote($name), preg_quote($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. + * + * @param string $filename Filename + * + * @return string Filecontent + * @access private + */ + function getFile($filename) + { + if ($filename{0} == '/' && substr($this->fileRoot, -1) == '/') { + $filename = substr($filename, 1); + } + + $filename = $this->fileRoot . $filename; + + if (!($fh = @fopen($filename, 'r'))) { + $this->err[] = PEAR::raiseError( + $this->errorMessage(IT_TPL_NOT_FOUND) . ': "' .$filename .'"', + IT_TPL_NOT_FOUND + ); + return ""; + } + + $fsize = filesize($filename); + if ($fsize < 1) { + fclose($fh); + return ''; + } + + $content = fread($fh, $fsize); + fclose($fh); + + return preg_replace_callback( + "##im", + function ($m) { return $this->getFile($m[1]); }, + $content + ); + } // end func getFile + + /** + * Adds delimiters to a string, so it can be used as a pattern + * in preg_* functions + * + * @param string $str input + * + * @return string + * @access private + */ + function _addPregDelimiters($str) + { + return '@' . preg_quote($str) . '@'; + } + + /** + * Escapes $ and \ as preg_replace will treat + * them as a backreference and not literal. + * See bug #9501 + * + * @param string $str String to escape + * + * @since 1.2.2 + * @return string + * @access private + */ + function _escapeBackreferences($str) + { + $str = str_replace('\\', '\\\\', $str); + $str = preg_replace('@\$([0-9]{1,2})@', '\\\$${1}', $str); + return $str; + } + + /** + * Replaces an opening delimiter by a special string + * + * @param string $str special string + * + * @return string + * @access private + */ + function _preserveOpeningDelimiter($str) + { + return (false === strpos($str, $this->openingDelimiter))? + $str: + str_replace( + $this->openingDelimiter, + $this->openingDelimiter . + '%preserved%' . $this->closingDelimiter, + $str + ); + } + + /** + * Return a textual error message for a IT error code + * + * @param integer $value error code + * @param string $blockname unknown + * + * @access private + * @return string error message, or false if the error code was + * not recognized + */ + function errorMessage($value, $blockname = '') + { + static $errorMessages; + if (!isset($errorMessages)) { + $errorMessages = array( + IT_OK => '', + IT_ERROR => 'unknown error', + IT_TPL_NOT_FOUND => 'Cannot read the template file', + IT_BLOCK_NOT_FOUND => 'Cannot find this block', + IT_BLOCK_DUPLICATE => 'The name of a block must be'. + ' uniquewithin a template.'. + ' Found "' . $blockname . '" twice.'. + 'Unpredictable results '. + 'may appear.', + IT_UNKNOWN_OPTION => 'Unknown option' + ); + } + + if (PEAR::isError($value)) { + $value = $value->getCode(); + } + + return isset($errorMessages[$value]) ? + $errorMessages[$value] : $errorMessages[IT_ERROR]; + } +} // end class IntegratedTemplate +?> diff --git a/HTML_Template_IT-1.3.0/HTML/Template/ITX.php b/HTML_Template_IT-1.3.1/HTML/Template/ITX.php old mode 100644 new mode 100755 similarity index 96% rename from HTML_Template_IT-1.3.0/HTML/Template/ITX.php rename to HTML_Template_IT-1.3.1/HTML/Template/ITX.php index b8ec37c..fbf2e67 --- a/HTML_Template_IT-1.3.0/HTML/Template/ITX.php +++ b/HTML_Template_IT-1.3.1/HTML/Template/ITX.php @@ -1,889 +1,889 @@ - - * Pierre-Alain Joye - * David Soria Parra - * - * @category HTML - * @package HTML_Template_IT - * @author Ulf Wendel - * @license BSD http://www.opensource.org/licenses/bsd-license.php - * @version CVS: $Id: ITX.php 295086 2010-02-15 06:31:36Z clockwerx $ - * @link http://pear.php.net/packages/HTML_Template_IT - * @access public - */ - -require_once 'HTML/Template/IT.php'; -require_once 'HTML/Template/IT_Error.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 modify some parts of your layout easily. -* -* Note that you can replace an existing block and add new blocks at runtime. -* Adding new blocks means changing a variable placeholder to a block. -* - * @category HTML - * @package HTML_Template_IT - * @author Ulf Wendel - * @license BSD http://www.opensource.org/licenses/bsd-license.php - * @link http://pear.php.net/packages/HTML_Template_IT - * @access public -*/ -class HTML_Template_ITX extends HTML_Template_IT -{ - /** - * Array with all warnings. - * @var array - * @access public - * @see $printWarning, $haltOnWarning, warning() - */ - var $warn = array(); - - /** - * Print warnings? - * @var array - * @access public - * @see $haltOnWarning, $warn, warning() - */ - var $printWarning = false; - - /** - * Call die() on warning? - * @var boolean - * @access public - * @see $warn, $printWarning, warning() - */ - var $haltOnWarning = false; - - /** - * RegExp used to test for a valid blockname. - * @var string - * @access private - */ - var $checkblocknameRegExp = ''; - - /** - * Functionnameprefix used when searching function calls in the template. - * @var string - * @access public - */ - var $functionPrefix = 'func_'; - - /** - * Functionname RegExp. - * @var string - * @access public - */ - 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. - * - * @access private - * @var string - * @see HTML_Template_IT() - */ - var $functionRegExp = ''; - - /** - * List of functions found in the template. - * - * @access private - * @var array - */ - var $functions = array(); - - /** - * List of callback functions specified by the user. - * - * @access private - * @var 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 your own - * template class from this one. - * - * @param string $root Root node? - * - * @access public - * @see HTML_Template_IT() - */ - function HTML_Template_ITX($root = '') - { - - $this->checkblocknameRegExp = '@' . $this->blocknameRegExp . '@'; - - $this->functionRegExp = '@' . $this->functionPrefix . '(' . - $this->functionnameRegExp . ')\s*\(@sm'; - - $this->HTML_Template_IT($root); - } // end func constructor - - /** - * 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. - * - * @access private - * @return null - */ - function init() - { - $this->free(); - $this->buildFunctionlist(); - $this->findBlocks($this->template); - - // we don't need it any more - $this->template = ''; - $this->buildBlockvariablelist(); - - } // end func init - - /** - * Replaces an existing block with new content. - * - * This function will replace a block of the template and all blocks - * contained in the replaced block and add a new block insted, means - * you can dynamically change your template. - * - * Note that changing the template structure violates one of the IT[X] - * development goals. I've tried to write a simple to use template engine - * supporting blocks. In contrast to other systems IT[X] analyses the way - * you've nested blocks and knows which block belongs into another block. - * The nesting information helps to make the API short and simple. Replacing - * blocks does not only mean that IT[X] has to update the nesting - * information (relatively time consumpting task) but you have to make sure - * that you do not get confused due to the template change itself. - * - * @param string $block Blockname - * @param string $template Blockcontent - * @param boolean $keep_content true if the new block inherits the content - * of the old block - * - * @return boolean - * @throws IT_Error - * @see replaceBlockfile(), addBlock(), addBlockfile() - * @access public - */ - function replaceBlock($block, $template, $keep_content = false) - { - if (!isset($this->blocklist[$block])) { - return new IT_Error("The block "."'$block'". - " does not exist in the template and thus it can't be replaced.", - __FILE__, __LINE__); - } - - if ($template == '') { - return new IT_Error('No block content given.', __FILE__, __LINE__); - } - - if ($keep_content) { - $blockdata = $this->blockdata[$block]; - } - - // remove all kinds of links to the block / data of the block - $this->removeBlockData($block); - - $template = "" . $template . ""; - $parents = $this->blockparents[$block]; - - $this->findBlocks($template); - $this->blockparents[$block] = $parents; - - // KLUDGE: rebuild the list for all block - could be done faster - $this->buildBlockvariablelist(); - - if ($keep_content) { - $this->blockdata[$block] = $blockdata; - } - - // old TODO - I'm not sure if we need this - // update caches - - return true; - } // end func replaceBlock - - /** - * Replaces an existing block with new content from a file. - * - * @param string $block Blockname - * @param string $filename Name of the file that contains the blockcontent - * @param boolean $keep_content true if the new block inherits the content of - * the old block - * - * @brother replaceBlock() - * @access public - * @return null - */ - function replaceBlockfile($block, $filename, $keep_content = false) - { - return $this->replaceBlock($block, $this->getFile($filename), $keep_content); - } // 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 - * and end with this would cause overhead and - * produce an error. - * - * @param string $placeholder Name of the variable placeholder, the name - * must be unique within the template. - * @param string $blockname Name of the block to be added - * @param string $template Content of the block - * - * @return boolean - * @throws IT_Error - * @see addBlockfile() - * @access public - */ - function addBlock($placeholder, $blockname, $template) - { - // Don't trust any user even if it's a programmer or yourself... - if ($placeholder == '') { - return new IT_Error('No variable placeholder given.', - __FILE__, __LINE__); - } elseif ($blockname == '' || - !preg_match($this->checkblocknameRegExp, $blockname) - ) { - return new IT_Error("No or invalid blockname '$blockname' given.", - __FILE__, __LINE__); - } elseif ($template == '') { - return new IT_Error('No block content given.', __FILE__, __LINE__); - } elseif (isset($this->blocklist[$blockname])) { - return new IT_Error('The block already exists.', - __FILE__, __LINE__); - } - - // find out where to insert the new block - $parents = $this->findPlaceholderBlocks($placeholder); - if (count($parents) == 0) { - - return new IT_Error("The variable placeholder". - " '$placeholder' was not found in the template.", - __FILE__, __LINE__); - - } elseif (count($parents) > 1) { - - reset($parents); - while (list($k, $parent) = each($parents)) { - $msg .= "$parent, "; - } - $msg = substr($parent, -2); - - return new IT_Error("The variable placeholder "."'$placeholder'". - " must be unique, found in multiple blocks '$msg'.", - __FILE__, __LINE__); - } - - $template = "" - . $template - . ""; - $this->findBlocks($template); - if ($this->flagBlocktrouble) { - return false; // findBlocks() already throws an exception - } - - $this->blockinner[$parents[0]][] = $blockname; - - $escblockname = '__' . $blockname . '__'; - - $this->blocklist[$parents[0]] = preg_replace( - '@' . $this->openingDelimiter . $placeholder . - $this->closingDelimiter . '@', - $this->openingDelimiter . $escblockname . $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. - * - * @param string $placeholder Name of the variable placeholder to be converted - * @param string $blockname Name of the block to be added - * @param string $filename File that contains the block - * - * @brother addBlock() - * @access public - * @return null - */ - 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. - * - * @param string $placeholder Name of the placeholder you're searching - * @param string $block Name of the block to scan. If left out (default) - * all blocks are scanned. - * - * @return 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. - * @throws IT_Error - * @access public - */ - function placeholderExists($placeholder, $block = '') - { - if ($placeholder == '') { - new IT_Error('No placeholder name given.', __FILE__, __LINE__); - return ''; - } - - if ($block != '' && !isset($this->blocklist[$block])) { - new IT_Error("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 ($k == $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)) { - if (is_array($variables) && isset($variables[$placeholder])) { - $found = $blockname; - break; - } - } - } - - return $found; - } // end func placeholderExists - - /** - * Checks the list of function calls in the template and - * calls their callback function. - * - * @access public - * @return null - */ - function performCallback() - { - reset($this->functions); - while (list($func_id, $function) = each($this->functions)) { - if (isset($this->callback[$function['name']])) { - if ($this->callback[$function['name']]['expandParameters']) { - $callFunction = 'call_user_func_array'; - } else { - $callFunction = 'call_user_func'; - } - - if ($this->callback[$function['name']]['object'] != '') { - $call = $callFunction( - array( - &$GLOBALS[$this->callback[$function['name']]['object']], - $this->callback[$function['name']]['function']), - $function['args']); - - } else { - $call = $callFunction( - $this->callback[$function['name']]['function'], - $function['args']); - } - $this->variableCache['__function' . $func_id . '__'] = $call; - } - } - - } // end func performCallback - - /** - * Returns a list of all function calls in the current template. - * - * @return array - * @access public - */ - function getFunctioncalls() - { - return $this->functions; - } // end func getFunctioncalls - - /** - * Replaces a function call with the given replacement. - * - * @param int $functionID Function ID - * @param string $replacement Replacement - * - * @access public - * @deprecated - * @return null - */ - function setFunctioncontent($functionID, $replacement) - { - $this->variableCache['__function' . $functionID . '__'] = $replacement; - } // end func setFunctioncontent - - /** - * Sets a callback function. - * - * IT[X] templates (note the X) can contain simple function calls. - * "function call" means that the editor of the template can add - * special placeholder to the template like 'func_h1("embedded in h1")'. - * IT[X] will grab this function calls and allow you to define a callback - * function for them. - * - * This is an absolutely evil feature. If your application makes heavy - * use of such callbacks and you're even implementing if-then etc. on - * the level of a template engine you're reiventing the wheel... - that's - * actually how PHP came into life. Anyway, sometimes it's handy. - * - * Consider also using XML/XSLT or native PHP. And please do not push - * IT[X] any further into this direction of adding logics to the template - * engine. - * - * For those of you ready for the X in IT[X]: - * - * %s', $args[0]); - * } - * - * ... - * $itx = new HTML_Template_ITX(...); - * ... - * $itx->setCallbackFunction('h1', 'h_one'); - * $itx->performCallback(); - * ?> - * - * template: - * func_h1('H1 Headline'); - * - * @param string $tplfunction Function name in the template - * @param string $callbackfunction Name of the callback function - * @param string $callbackobject Name of the callback object - * @param boolean $expandCallbackParameters If the callback is called with - * a list of parameters or with an - * array holding the parameters - * - * @return boolean False on failure. - * @throws IT_Error - * @access public - * @deprecated The $callbackobject parameter is depricated since - * version 1.2 and might be dropped in further versions. - */ - function setCallbackFunction($tplfunction, $callbackfunction, - $callbackobject = '', - $expandCallbackParameters = false) { - if ($tplfunction == '' || $callbackfunction == '') { - return new IT_Error("No template function "."('$tplfunction')". - " and/or no callback function ('$callback') given.", - __FILE__, __LINE__); - } - $this->callback[$tplfunction] = array( - 'function' => $callbackfunction, - 'object' => $callbackobject, - 'expandParameters' => (boolean) - $expandCallbackParameters); - - return true; - } // end func setCallbackFunction - - /** - * Sets the Callback function lookup table - * - * @param array $functions function table - * array[templatefunction] = - * array( - * "function" => userfunction, - * "object" => userobject - * ) - * - * @access public - * @return null - */ - function setCallbackFuntiontable($functions) - { - $this->callback = $functions; - } // end func setCallbackFunctiontable - - /** - * Recursively removes all data assiciated with a block, including - * all inner blocks - * - * @param string $block block to be removed - * - * @return null - * @access private - */ - function removeBlockData($block) - { - if (isset($this->blockinner[$block])) { - foreach ($this->blockinner[$block] as $k => $inner) { - $this->removeBlockData($inner); - } - - unset($this->blockinner[$block]); - } - - unset($this->blocklist[$block]); - unset($this->blockdata[$block]); - unset($this->blockvariables[$block]); - unset($this->touchedBlocks[$block]); - - } // end func removeBlockinner - - /** - * Returns a list of blocknames in the template. - * - * @return array [blockname => blockname] - * @access public - * @see blockExists() - */ - function getBlocklist() - { - $blocklist = array(); - foreach ($this->blocklist as $block => $content) { - $blocklist[$block] = $block; - } - - return $blocklist; - } // end func getBlocklist - - /** - * Checks wheter a block exists. - * - * @param string $blockname Blockname - * - * @return boolean - * @access public - * @see getBlocklist() - */ - function blockExists($blockname) - { - return isset($this->blocklist[$blockname]); - } // end func blockExists - - /** - * Returns a list of variables of a block. - * - * @param string $block Blockname - * - * @return array [varname => varname] - * @access public - * @see BlockvariableExists() - */ - function getBlockvariables($block) - { - if (!isset($this->blockvariables[$block])) { - return array(); - } - - $variables = array(); - foreach ($this->blockvariables[$block] as $variable => $v) { - $variables[$variable] = $variable; - } - - return $variables; - } // end func getBlockvariables - - /** - * Checks wheter a block variable exists. - * - * @param string $block Blockname - * @param string $variable Variablename - * - * @return boolean - * @access public - * @see getBlockvariables() - */ - function BlockvariableExists($block, $variable) - { - return isset($this->blockvariables[$block][$variable]); - } // end func BlockvariableExists - - /** - * Builds a functionlist from the template. - * - * @access private - * @return null - */ - 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(); - - $search = $regs[0] . $head . ')'; - - $replace = $this->openingDelimiter . - '__function' . $num . '__' . - $this->closingDelimiter; - - $this->template = str_replace($search, $replace, $this->template); - $template = str_replace($search, $replace, $template); - - while ($head != '' && $args2 = $this->getValue($head, ',')) { - $arg2 = trim($args2); - - $args[] = ('"' == $arg2{0} || "'" == $arg2{0}) ? - substr($arg2, 1, -1) : $arg2; - - if ($arg2 == $head) { - break; - } - $head = substr($head, strlen($arg2) + 1); - } - - $this->functions[$num++] = array('name' => $regs[1], - 'args' => $args); - } - - } // end func buildFunctionlist - - /** - * Truncates the given code from the first occurence of - * $delimiter but ignores $delimiter enclosed by " or '. - * - * @param string $code The code which should be parsed - * @param string $delimiter The delimiter char - * - * @access private - * @return string - * @see 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. - * - * @param string $block Blockname - * @param mixed $variables Name of one variable or array of variables - * (array (name => true ) ) to be stripped. - * - * @access private - * @return null - */ - function deleteFromBlockvariablelist($block, $variables) - { - if (!is_array($variables)) { - $variables = array($variables => true); - } - - reset($this->blockvariables[$block]); - while (list($varname, $val) = each($this->blockvariables[$block])) { - if (isset($variables[$varname])) { - unset($this->blockvariables[$block][$varname]); - } - } - } // end deleteFromBlockvariablelist - - /** - * Updates the variable list of a block. - * - * @param string $block Blockname - * - * @access private - * @return null - */ - function updateBlockvariablelist($block) - { - preg_match_all( - $this->variablesRegExp, - $this->blocklist[$block], $regs - ); - - if (count($regs[1]) != 0) { - foreach ($regs[1] as $k => $var) { - $this->blockvariables[$block][$var] = true; - } - } else { - $this->blockvariables[$block] = array(); - } - - // check if any inner blocks were found - if (isset($this->blockinner[$block]) - && is_array($this->blockinner[$block]) - && count($this->blockinner[$block]) > 0 - ) { - /* - * loop through inner blocks, registering the variable - * placeholders in each - */ - foreach ($this->blockinner[$block] as $childBlock) { - $this->updateBlockvariablelist($childBlock); - } - } - } // end func updateBlockvariablelist - - /** - * Returns an array of blocknames where the given variable - * placeholder is used. - * - * @param string $variable Variable placeholder - * - * @return array $parents parents[0..n] = blockname - * @access public - */ - function findPlaceholderBlocks($variable) - { - $parents = array(); - reset($this->blocklist); - while (list($blockname, $content) = each($this->blocklist)) { - reset($this->blockvariables[$blockname]); - - while (list($varname, $val) = 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 - * - * @param string $message Warning - * @param string $file File where the warning occured - * @param int $line Linenumber where the warning occured - * - * @see $warn, $printWarning, $haltOnWarning - * @access private - * @return null - */ - function warning($message, $file = '', $line = 0) - { - $message = sprintf( - 'HTML_Template_ITX Warning: %s [File: %s, Line: %d]', - $message, - $file, - $line - ); - - $this->warn[] = $message; - - if ($this->printWarning) { - print $message; - } - - if ($this->haltOnWarning) { - die($message); - } - } // end func warning - -} // end class HTML_Template_ITX -?> + + * Pierre-Alain Joye + * David Soria Parra + * + * @category HTML + * @package HTML_Template_IT + * @author Ulf Wendel + * @license BSD http://www.opensource.org/licenses/bsd-license.php + * @version CVS: $Id$ + * @link http://pear.php.net/packages/HTML_Template_IT + * @access public + */ + +require_once 'HTML/Template/IT.php'; +require_once 'HTML/Template/IT_Error.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 modify some parts of your layout easily. +* +* Note that you can replace an existing block and add new blocks at runtime. +* Adding new blocks means changing a variable placeholder to a block. +* + * @category HTML + * @package HTML_Template_IT + * @author Ulf Wendel + * @license BSD http://www.opensource.org/licenses/bsd-license.php + * @link http://pear.php.net/packages/HTML_Template_IT + * @access public +*/ +class HTML_Template_ITX extends HTML_Template_IT +{ + /** + * Array with all warnings. + * @var array + * @access public + * @see $printWarning, $haltOnWarning, warning() + */ + var $warn = array(); + + /** + * Print warnings? + * @var array + * @access public + * @see $haltOnWarning, $warn, warning() + */ + var $printWarning = false; + + /** + * Call die() on warning? + * @var boolean + * @access public + * @see $warn, $printWarning, warning() + */ + var $haltOnWarning = false; + + /** + * RegExp used to test for a valid blockname. + * @var string + * @access private + */ + var $checkblocknameRegExp = ''; + + /** + * Functionnameprefix used when searching function calls in the template. + * @var string + * @access public + */ + var $functionPrefix = 'func_'; + + /** + * Functionname RegExp. + * @var string + * @access public + */ + 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. + * + * @access private + * @var string + * @see HTML_Template_IT() + */ + var $functionRegExp = ''; + + /** + * List of functions found in the template. + * + * @access private + * @var array + */ + var $functions = array(); + + /** + * List of callback functions specified by the user. + * + * @access private + * @var 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 your own + * template class from this one. + * + * @param string $root Root node? + * + * @access public + * @see HTML_Template_IT() + */ + function __construct($root = '') + { + + $this->checkblocknameRegExp = '@' . $this->blocknameRegExp . '@'; + + $this->functionRegExp = '@' . $this->functionPrefix . '(' . + $this->functionnameRegExp . ')\s*\(@sm'; + + parent::__construct($root); + } // end func constructor + + /** + * 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. + * + * @access private + * @return null + */ + function init() + { + $this->free(); + $this->buildFunctionlist(); + $this->findBlocks($this->template); + + // we don't need it any more + $this->template = ''; + $this->buildBlockvariablelist(); + + } // end func init + + /** + * Replaces an existing block with new content. + * + * This function will replace a block of the template and all blocks + * contained in the replaced block and add a new block insted, means + * you can dynamically change your template. + * + * Note that changing the template structure violates one of the IT[X] + * development goals. I've tried to write a simple to use template engine + * supporting blocks. In contrast to other systems IT[X] analyses the way + * you've nested blocks and knows which block belongs into another block. + * The nesting information helps to make the API short and simple. Replacing + * blocks does not only mean that IT[X] has to update the nesting + * information (relatively time consumpting task) but you have to make sure + * that you do not get confused due to the template change itself. + * + * @param string $block Blockname + * @param string $template Blockcontent + * @param boolean $keep_content true if the new block inherits the content + * of the old block + * + * @return boolean + * @throws IT_Error + * @see replaceBlockfile(), addBlock(), addBlockfile() + * @access public + */ + function replaceBlock($block, $template, $keep_content = false) + { + if (!isset($this->blocklist[$block])) { + return new IT_Error("The block "."'$block'". + " does not exist in the template and thus it can't be replaced.", + __FILE__, __LINE__); + } + + if ($template == '') { + return new IT_Error('No block content given.', __FILE__, __LINE__); + } + + if ($keep_content) { + $blockdata = $this->blockdata[$block]; + } + + // remove all kinds of links to the block / data of the block + $this->removeBlockData($block); + + $template = "" . $template . ""; + $parents = $this->blockparents[$block]; + + $this->findBlocks($template); + $this->blockparents[$block] = $parents; + + // KLUDGE: rebuild the list for all block - could be done faster + $this->buildBlockvariablelist(); + + if ($keep_content) { + $this->blockdata[$block] = $blockdata; + } + + // old TODO - I'm not sure if we need this + // update caches + + return true; + } // end func replaceBlock + + /** + * Replaces an existing block with new content from a file. + * + * @param string $block Blockname + * @param string $filename Name of the file that contains the blockcontent + * @param boolean $keep_content true if the new block inherits the content of + * the old block + * + * @brother replaceBlock() + * @access public + * @return null + */ + function replaceBlockfile($block, $filename, $keep_content = false) + { + return $this->replaceBlock($block, $this->getFile($filename), $keep_content); + } // 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 + * and end with this would cause overhead and + * produce an error. + * + * @param string $placeholder Name of the variable placeholder, the name + * must be unique within the template. + * @param string $blockname Name of the block to be added + * @param string $template Content of the block + * + * @return boolean + * @throws IT_Error + * @see addBlockfile() + * @access public + */ + function addBlock($placeholder, $blockname, $template) + { + // Don't trust any user even if it's a programmer or yourself... + if ($placeholder == '') { + return new IT_Error('No variable placeholder given.', + __FILE__, __LINE__); + } elseif ($blockname == '' || + !preg_match($this->checkblocknameRegExp, $blockname) + ) { + return new IT_Error("No or invalid blockname '$blockname' given.", + __FILE__, __LINE__); + } elseif ($template == '') { + return new IT_Error('No block content given.', __FILE__, __LINE__); + } elseif (isset($this->blocklist[$blockname])) { + return new IT_Error('The block already exists.', + __FILE__, __LINE__); + } + + // find out where to insert the new block + $parents = $this->findPlaceholderBlocks($placeholder); + if (count($parents) == 0) { + + return new IT_Error("The variable placeholder". + " '$placeholder' was not found in the template.", + __FILE__, __LINE__); + + } elseif (count($parents) > 1) { + + reset($parents); + while (list($k, $parent) = each($parents)) { + $msg .= "$parent, "; + } + $msg = substr($parent, -2); + + return new IT_Error("The variable placeholder "."'$placeholder'". + " must be unique, found in multiple blocks '$msg'.", + __FILE__, __LINE__); + } + + $template = "" + . $template + . ""; + $this->findBlocks($template); + if ($this->flagBlocktrouble) { + return false; // findBlocks() already throws an exception + } + + $this->blockinner[$parents[0]][] = $blockname; + + $escblockname = '__' . $blockname . '__'; + + $this->blocklist[$parents[0]] = preg_replace( + '@' . $this->openingDelimiter . $placeholder . + $this->closingDelimiter . '@', + $this->openingDelimiter . $escblockname . $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. + * + * @param string $placeholder Name of the variable placeholder to be converted + * @param string $blockname Name of the block to be added + * @param string $filename File that contains the block + * + * @brother addBlock() + * @access public + * @return null + */ + 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. + * + * @param string $placeholder Name of the placeholder you're searching + * @param string $block Name of the block to scan. If left out (default) + * all blocks are scanned. + * + * @return 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. + * @throws IT_Error + * @access public + */ + function placeholderExists($placeholder, $block = '') + { + if ($placeholder == '') { + new IT_Error('No placeholder name given.', __FILE__, __LINE__); + return ''; + } + + if ($block != '' && !isset($this->blocklist[$block])) { + new IT_Error("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 ($k == $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)) { + if (is_array($variables) && isset($variables[$placeholder])) { + $found = $blockname; + break; + } + } + } + + return $found; + } // end func placeholderExists + + /** + * Checks the list of function calls in the template and + * calls their callback function. + * + * @access public + * @return null + */ + function performCallback() + { + reset($this->functions); + while (list($func_id, $function) = each($this->functions)) { + if (isset($this->callback[$function['name']])) { + if ($this->callback[$function['name']]['expandParameters']) { + $callFunction = 'call_user_func_array'; + } else { + $callFunction = 'call_user_func'; + } + + if ($this->callback[$function['name']]['object'] != '') { + $call = $callFunction( + array( + &$GLOBALS[$this->callback[$function['name']]['object']], + $this->callback[$function['name']]['function']), + $function['args']); + + } else { + $call = $callFunction( + $this->callback[$function['name']]['function'], + $function['args']); + } + $this->variableCache['__function' . $func_id . '__'] = $call; + } + } + + } // end func performCallback + + /** + * Returns a list of all function calls in the current template. + * + * @return array + * @access public + */ + function getFunctioncalls() + { + return $this->functions; + } // end func getFunctioncalls + + /** + * Replaces a function call with the given replacement. + * + * @param int $functionID Function ID + * @param string $replacement Replacement + * + * @access public + * @deprecated + * @return null + */ + function setFunctioncontent($functionID, $replacement) + { + $this->variableCache['__function' . $functionID . '__'] = $replacement; + } // end func setFunctioncontent + + /** + * Sets a callback function. + * + * IT[X] templates (note the X) can contain simple function calls. + * "function call" means that the editor of the template can add + * special placeholder to the template like 'func_h1("embedded in h1")'. + * IT[X] will grab this function calls and allow you to define a callback + * function for them. + * + * This is an absolutely evil feature. If your application makes heavy + * use of such callbacks and you're even implementing if-then etc. on + * the level of a template engine you're reiventing the wheel... - that's + * actually how PHP came into life. Anyway, sometimes it's handy. + * + * Consider also using XML/XSLT or native PHP. And please do not push + * IT[X] any further into this direction of adding logics to the template + * engine. + * + * For those of you ready for the X in IT[X]: + * + * %s', $args[0]); + * } + * + * ... + * $itx = new HTML_Template_ITX(...); + * ... + * $itx->setCallbackFunction('h1', 'h_one'); + * $itx->performCallback(); + * ?> + * + * template: + * func_h1('H1 Headline'); + * + * @param string $tplfunction Function name in the template + * @param string $callbackfunction Name of the callback function + * @param string $callbackobject Name of the callback object + * @param boolean $expandCallbackParameters If the callback is called with + * a list of parameters or with an + * array holding the parameters + * + * @return boolean False on failure. + * @throws IT_Error + * @access public + * @deprecated The $callbackobject parameter is depricated since + * version 1.2 and might be dropped in further versions. + */ + function setCallbackFunction($tplfunction, $callbackfunction, + $callbackobject = '', + $expandCallbackParameters = false) { + if ($tplfunction == '' || $callbackfunction == '') { + return new IT_Error("No template function "."('$tplfunction')". + " and/or no callback function ('$callback') given.", + __FILE__, __LINE__); + } + $this->callback[$tplfunction] = array( + 'function' => $callbackfunction, + 'object' => $callbackobject, + 'expandParameters' => (boolean) + $expandCallbackParameters); + + return true; + } // end func setCallbackFunction + + /** + * Sets the Callback function lookup table + * + * @param array $functions function table + * array[templatefunction] = + * array( + * "function" => userfunction, + * "object" => userobject + * ) + * + * @access public + * @return null + */ + function setCallbackFuntiontable($functions) + { + $this->callback = $functions; + } // end func setCallbackFunctiontable + + /** + * Recursively removes all data assiciated with a block, including + * all inner blocks + * + * @param string $block block to be removed + * + * @return null + * @access private + */ + function removeBlockData($block) + { + if (isset($this->blockinner[$block])) { + foreach ($this->blockinner[$block] as $k => $inner) { + $this->removeBlockData($inner); + } + + unset($this->blockinner[$block]); + } + + unset($this->blocklist[$block]); + unset($this->blockdata[$block]); + unset($this->blockvariables[$block]); + unset($this->touchedBlocks[$block]); + + } // end func removeBlockinner + + /** + * Returns a list of blocknames in the template. + * + * @return array [blockname => blockname] + * @access public + * @see blockExists() + */ + function getBlocklist() + { + $blocklist = array(); + foreach ($this->blocklist as $block => $content) { + $blocklist[$block] = $block; + } + + return $blocklist; + } // end func getBlocklist + + /** + * Checks wheter a block exists. + * + * @param string $blockname Blockname + * + * @return boolean + * @access public + * @see getBlocklist() + */ + function blockExists($blockname) + { + return isset($this->blocklist[$blockname]); + } // end func blockExists + + /** + * Returns a list of variables of a block. + * + * @param string $block Blockname + * + * @return array [varname => varname] + * @access public + * @see BlockvariableExists() + */ + function getBlockvariables($block) + { + if (!isset($this->blockvariables[$block])) { + return array(); + } + + $variables = array(); + foreach ($this->blockvariables[$block] as $variable => $v) { + $variables[$variable] = $variable; + } + + return $variables; + } // end func getBlockvariables + + /** + * Checks wheter a block variable exists. + * + * @param string $block Blockname + * @param string $variable Variablename + * + * @return boolean + * @access public + * @see getBlockvariables() + */ + function BlockvariableExists($block, $variable) + { + return isset($this->blockvariables[$block][$variable]); + } // end func BlockvariableExists + + /** + * Builds a functionlist from the template. + * + * @access private + * @return null + */ + 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(); + + $search = $regs[0] . $head . ')'; + + $replace = $this->openingDelimiter . + '__function' . $num . '__' . + $this->closingDelimiter; + + $this->template = str_replace($search, $replace, $this->template); + $template = str_replace($search, $replace, $template); + + while ($head != '' && $args2 = $this->getValue($head, ',')) { + $arg2 = trim($args2); + + $args[] = ('"' == $arg2{0} || "'" == $arg2{0}) ? + substr($arg2, 1, -1) : $arg2; + + if ($arg2 == $head) { + break; + } + $head = substr($head, strlen($arg2) + 1); + } + + $this->functions[$num++] = array('name' => $regs[1], + 'args' => $args); + } + + } // end func buildFunctionlist + + /** + * Truncates the given code from the first occurence of + * $delimiter but ignores $delimiter enclosed by " or '. + * + * @param string $code The code which should be parsed + * @param string $delimiter The delimiter char + * + * @access private + * @return string + * @see 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. + * + * @param string $block Blockname + * @param mixed $variables Name of one variable or array of variables + * (array (name => true ) ) to be stripped. + * + * @access private + * @return null + */ + function deleteFromBlockvariablelist($block, $variables) + { + if (!is_array($variables)) { + $variables = array($variables => true); + } + + reset($this->blockvariables[$block]); + while (list($varname, $val) = each($this->blockvariables[$block])) { + if (isset($variables[$varname])) { + unset($this->blockvariables[$block][$varname]); + } + } + } // end deleteFromBlockvariablelist + + /** + * Updates the variable list of a block. + * + * @param string $block Blockname + * + * @access private + * @return null + */ + function updateBlockvariablelist($block) + { + preg_match_all( + $this->variablesRegExp, + $this->blocklist[$block], $regs + ); + + if (count($regs[1]) != 0) { + foreach ($regs[1] as $k => $var) { + $this->blockvariables[$block][$var] = true; + } + } else { + $this->blockvariables[$block] = array(); + } + + // check if any inner blocks were found + if (isset($this->blockinner[$block]) + && is_array($this->blockinner[$block]) + && count($this->blockinner[$block]) > 0 + ) { + /* + * loop through inner blocks, registering the variable + * placeholders in each + */ + foreach ($this->blockinner[$block] as $childBlock) { + $this->updateBlockvariablelist($childBlock); + } + } + } // end func updateBlockvariablelist + + /** + * Returns an array of blocknames where the given variable + * placeholder is used. + * + * @param string $variable Variable placeholder + * + * @return array $parents parents[0..n] = blockname + * @access public + */ + function findPlaceholderBlocks($variable) + { + $parents = array(); + reset($this->blocklist); + while (list($blockname, $content) = each($this->blocklist)) { + reset($this->blockvariables[$blockname]); + + while (list($varname, $val) = 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 + * + * @param string $message Warning + * @param string $file File where the warning occured + * @param int $line Linenumber where the warning occured + * + * @see $warn, $printWarning, $haltOnWarning + * @access private + * @return null + */ + function warning($message, $file = '', $line = 0) + { + $message = sprintf( + 'HTML_Template_ITX Warning: %s [File: %s, Line: %d]', + $message, + $file, + $line + ); + + $this->warn[] = $message; + + if ($this->printWarning) { + print $message; + } + + if ($this->haltOnWarning) { + die($message); + } + } // end func warning + +} // end class HTML_Template_ITX +?> diff --git a/HTML_Template_IT-1.3.0/HTML/Template/IT_Error.php b/HTML_Template_IT-1.3.1/HTML/Template/IT_Error.php similarity index 90% rename from HTML_Template_IT-1.3.0/HTML/Template/IT_Error.php rename to HTML_Template_IT-1.3.1/HTML/Template/IT_Error.php index 20e250c..b5f4134 100644 --- a/HTML_Template_IT-1.3.0/HTML/Template/IT_Error.php +++ b/HTML_Template_IT-1.3.1/HTML/Template/IT_Error.php @@ -1,65 +1,65 @@ - - * Pierre-Alain Joye - * David Soria Parra - * - * @category HTML - * @package HTML_Template_IT - * @author Ulf Wendel - * @license BSD http://www.opensource.org/licenses/bsd-license.php - * @version CVS: $Id: IT_Error.php 295117 2010-02-15 23:25:21Z clockwerx $ - * @link http://pear.php.net/packages/HTML_Template_IT - * @access public - */ - -require_once "PEAR.php"; - -/** -* IT[X] Error class -* - * @category HTML - * @package HTML_Template_IT - * @author Ulf Wendel - * @license BSD http://www.opensource.org/licenses/bsd-license.php - * @link http://pear.php.net/packages/HTML_Template_IT - * @access public -*/ -class IT_Error extends PEAR_Error -{ - /** - * Prefix of all error messages. - * - * @var string - */ - var $error_message_prefix = "IntegratedTemplate Error: "; - - /** - * Creates an cache error object. - * - * @param string $msg error message - * @param string $file file where the error occured - * @param string $line linenumber where the error occured - */ - function IT_Error($msg, $file = __FILE__, $line = __LINE__) - { - $this->PEAR_Error(sprintf("%s [%s on line %d].", $msg, $file, $line)); - } // end func IT_Error - -} // end class IT_Error -?> + + * Pierre-Alain Joye + * David Soria Parra + * + * @category HTML + * @package HTML_Template_IT + * @author Ulf Wendel + * @license BSD http://www.opensource.org/licenses/bsd-license.php + * @version CVS: $Id$ + * @link http://pear.php.net/packages/HTML_Template_IT + * @access public + */ + +require_once "PEAR.php"; + +/** +* IT[X] Error class +* + * @category HTML + * @package HTML_Template_IT + * @author Ulf Wendel + * @license BSD http://www.opensource.org/licenses/bsd-license.php + * @link http://pear.php.net/packages/HTML_Template_IT + * @access public +*/ +class IT_Error extends PEAR_Error +{ + /** + * Prefix of all error messages. + * + * @var string + */ + var $error_message_prefix = "IntegratedTemplate Error: "; + + /** + * Creates an cache error object. + * + * @param string $msg error message + * @param string $file file where the error occured + * @param string $line linenumber where the error occured + */ + function __construct($msg, $file = __FILE__, $line = __LINE__) + { + $this->PEAR_Error(sprintf("%s [%s on line %d].", $msg, $file, $line)); + } // end func IT_Error + +} // end class IT_Error +?> diff --git a/HTML_Template_IT-1.3.0/LICENSE b/HTML_Template_IT-1.3.1/LICENSE similarity index 98% rename from HTML_Template_IT-1.3.0/LICENSE rename to HTML_Template_IT-1.3.1/LICENSE index db25e88..0857cce 100644 --- a/HTML_Template_IT-1.3.0/LICENSE +++ b/HTML_Template_IT-1.3.1/LICENSE @@ -1,22 +1,22 @@ -Redistribution and use in source and binary forms, with or without modification -, are permitted provided that the following conditions are met: - -1. Redistributions of source code must retain the above copyright notice, th - is list of conditions and the following disclaimer. - -2. Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation and/ - or other materials provided with the distribution. - -3. The name of the author may not be used to endorse or promote products derived - from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED WA -RRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABIL -ITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE -AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR C -ONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE -GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOW -EVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILI -TY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE U -SE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +Redistribution and use in source and binary forms, with or without modification +, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, th + is list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/ + or other materials provided with the distribution. + +3. The name of the author may not be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED WA +RRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABIL +ITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR C +ONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE +GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOW +EVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILI +TY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE U +SE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/HTML_Template_IT-1.3.0/examples/sample_it.php b/HTML_Template_IT-1.3.1/examples/sample_it.php similarity index 96% rename from HTML_Template_IT-1.3.0/examples/sample_it.php rename to HTML_Template_IT-1.3.1/examples/sample_it.php index 1afcc61..1fe2ac2 100644 --- a/HTML_Template_IT-1.3.0/examples/sample_it.php +++ b/HTML_Template_IT-1.3.1/examples/sample_it.php @@ -1,27 +1,27 @@ - array('Stig', 'Bakken'), - '1' => array('Martin', 'Jansen'), - '2' => array('Alexander', 'Merz') -); - -$tpl = new HTML_Template_IT('./templates'); -$tpl->loadTemplatefile('main.tpl.htm', true, true); - -foreach ($data as $name) { - foreach ($name as $cell) { - // Assign data to the inner block - $tpl->setCurrentBlock('cell'); - $tpl->setVariable('DATA', $cell); - $tpl->parseCurrentBlock(); - } - // Assign data and the inner block to the - // outer block - $tpl->setCurrentBlock('row'); - $tpl->parseCurrentBlock(); -} -// print the output -$tpl->show(); -?> + array('Stig', 'Bakken'), + '1' => array('Martin', 'Jansen'), + '2' => array('Alexander', 'Merz') +); + +$tpl = new HTML_Template_IT('./templates'); +$tpl->loadTemplatefile('main.tpl.htm', true, true); + +foreach ($data as $name) { + foreach ($name as $cell) { + // Assign data to the inner block + $tpl->setCurrentBlock('cell'); + $tpl->setVariable('DATA', $cell); + $tpl->parseCurrentBlock(); + } + // Assign data and the inner block to the + // outer block + $tpl->setCurrentBlock('row'); + $tpl->parseCurrentBlock(); +} +// print the output +$tpl->show(); +?> diff --git a/HTML_Template_IT-1.3.0/examples/sample_itx_addblockfile.php b/HTML_Template_IT-1.3.1/examples/sample_itx_addblockfile.php old mode 100644 new mode 100755 similarity index 93% rename from HTML_Template_IT-1.3.0/examples/sample_itx_addblockfile.php rename to HTML_Template_IT-1.3.1/examples/sample_itx_addblockfile.php index 8bf7295..8c32d38 --- a/HTML_Template_IT-1.3.0/examples/sample_itx_addblockfile.php +++ b/HTML_Template_IT-1.3.1/examples/sample_itx_addblockfile.php @@ -1,58 +1,62 @@ -'mypackage', - 'version' =>'1.0', - 'changelog' => array ('fix bug #002', - 'add author FOO to AUTHORS') - ), - array ('packagename'=>'mypackage', - 'version' =>'1.0 RC 1', - 'changelog' => array ('fix bug #002', - 'added method foo()') - ) - ); - -$tpl = new HTML_Template_ITX('./templates'); -$tpl->loadTemplatefile('addblockfile_main.tpl.htm', true, true); - -// The complete content of "addblockfile_main.tpl.htm" will be loaded into a block -// called "list_template". The placeholder {DESCRIPTION} will be replaced -// with the added block "list_template". -$tpl->addBlockfile('DESCRIPTION', 'list_template', 'addblockfile_list.tpl.htm'); - - -// we now have the following blocks loaded: -// __global__, row, list_template and listelement -// lets assign the data. -foreach ($data as $entry) { - // assign data to the inner block (listelement) of list_template. - $tpl->setCurrentBlock('listelement'); - foreach ($entry['changelog'] as $changelogentry) { - $tpl->setVariable('ENTRY', $changelogentry); - $tpl->parseCurrentBlock(); - } - - // assign data to the added list_template block - $tpl->setCurrentBlock('list_template'); - $tpl->setVariable('LISTNAME', $entry['version']); - $tpl->parseCurrentBlock(); - - // back in the original templatefile we assign data to the row block - // notice: - // {DESCRIPTION} is not longer available, because it was replaced by the - // list_template block - $tpl->setCurrentBlock('row'); - $tpl->setVariable('NAME', $entry['packagename']); - $tpl->parseCurrentBlock(); -} - -$tpl->show(); -?> +'mypackage', + 'version' =>'1.0', + 'changelog' => array ('fix bug #002', + 'add author FOO to AUTHORS') + ), + array ('packagename'=>'mypackage', + 'version' =>'1.0 RC 1', + 'changelog' => array ('fix bug #002', + 'added method foo()') + ) + ); + +$tpl = new HTML_Template_ITX('./templates'); +$tpl->loadTemplatefile('addblockfile_main.tpl.htm', true, true); + +// The complete content of "addblockfile_main.tpl.htm" will be loaded into a block +// called "list_template". The placeholder {DESCRIPTION} will be replaced +// with the added block "list_template". +$tpl->addBlockfile('DESCRIPTION', 'list_template', 'addblockfile_list.tpl.htm'); + + +// we now have the following blocks loaded: +// __global__, row, list_template and listelement +// lets assign the data. +foreach ($data as $entry) { + // assign data to the inner block (listelement) of list_template. + $tpl->setCurrentBlock('listelement'); + foreach ($entry['changelog'] as $changelogentry) { + $tpl->setVariable('ENTRY', $changelogentry); + $tpl->parseCurrentBlock(); + } + + // assign data to the added list_template block + $tpl->setCurrentBlock('list_template'); + $tpl->setVariable('LISTNAME', $entry['version']); + $tpl->parseCurrentBlock(); + + // back in the original templatefile we assign data to the row block + // notice: + // {DESCRIPTION} is not longer available, because it was replaced by the + // list_template block + $tpl->setCurrentBlock('row'); + $tpl->setVariable('NAME', $entry['packagename']); + $tpl->parseCurrentBlock(); +} + +$tpl->show(); +?> diff --git a/HTML_Template_IT-1.3.0/examples/templates/addblockfile_list.tpl.htm b/HTML_Template_IT-1.3.1/examples/templates/addblockfile_list.tpl.htm similarity index 89% rename from HTML_Template_IT-1.3.0/examples/templates/addblockfile_list.tpl.htm rename to HTML_Template_IT-1.3.1/examples/templates/addblockfile_list.tpl.htm index 879ba7a..69e470b 100644 --- a/HTML_Template_IT-1.3.0/examples/templates/addblockfile_list.tpl.htm +++ b/HTML_Template_IT-1.3.1/examples/templates/addblockfile_list.tpl.htm @@ -1,6 +1,6 @@ -{LISTNAME} -
    - -
  • {ENTRY}
  • - +{LISTNAME} +
      + +
    • {ENTRY}
    • +
    \ No newline at end of file diff --git a/HTML_Template_IT-1.3.0/examples/templates/addblockfile_main.tpl.htm b/HTML_Template_IT-1.3.1/examples/templates/addblockfile_main.tpl.htm similarity index 88% rename from HTML_Template_IT-1.3.0/examples/templates/addblockfile_main.tpl.htm rename to HTML_Template_IT-1.3.1/examples/templates/addblockfile_main.tpl.htm index 07992d1..db9e239 100644 --- a/HTML_Template_IT-1.3.0/examples/templates/addblockfile_main.tpl.htm +++ b/HTML_Template_IT-1.3.1/examples/templates/addblockfile_main.tpl.htm @@ -1,12 +1,12 @@ - - - - - - - - - -
    {NAME}{DESCRIPTION}
    - + + + + + + + + + +
    {NAME}{DESCRIPTION}
    + \ No newline at end of file diff --git a/HTML_Template_IT-1.3.0/examples/templates/main.tpl.htm b/HTML_Template_IT-1.3.1/examples/templates/main.tpl.htm similarity index 92% rename from HTML_Template_IT-1.3.0/examples/templates/main.tpl.htm rename to HTML_Template_IT-1.3.1/examples/templates/main.tpl.htm index d2da340..271feca 100644 --- a/HTML_Template_IT-1.3.0/examples/templates/main.tpl.htm +++ b/HTML_Template_IT-1.3.1/examples/templates/main.tpl.htm @@ -1,13 +1,13 @@ - - - - - - - - - -
    - {DATA} -
    - + + + + + + + + + +
    + {DATA} +
    + diff --git a/HTML_Template_IT-1.3.0/tests/AllTests.php b/HTML_Template_IT-1.3.1/tests/AllTests.php similarity index 100% rename from HTML_Template_IT-1.3.0/tests/AllTests.php rename to HTML_Template_IT-1.3.1/tests/AllTests.php diff --git a/HTML_Template_IT-1.3.0/tests/ITTest.php b/HTML_Template_IT-1.3.1/tests/ITTest.php similarity index 96% rename from HTML_Template_IT-1.3.0/tests/ITTest.php rename to HTML_Template_IT-1.3.1/tests/ITTest.php index 808ef0e..309e116 100644 --- a/HTML_Template_IT-1.3.0/tests/ITTest.php +++ b/HTML_Template_IT-1.3.1/tests/ITTest.php @@ -1,416 +1,416 @@ -tpl = new HTML_Template_IT(dirname(__FILE__) . '/templates'); - } - - function tearDown() - { - unset($this->tpl); - } - - function _stripWhitespace($str) - { - return preg_replace('/\\s+/', '', $str); - } - - function _methodExists($name) - { - if (in_array(strtolower($name), get_class_methods($this->tpl))) { - return true; - } - $this->assertTrue(false, 'method '. $name . ' not implemented in ' . get_class($this->tpl)); - return false; - } - - /** - * Tests a setTemplate method - * - */ - function testSetTemplate() - { - $result = $this->tpl->setTemplate('A template', false, false); - if (PEAR::isError($result)) { - $this->assertTrue(false, 'Error setting template: '. $result->getMessage()); - } - $this->assertEquals('A template', $this->tpl->get()); - } - - /** - * Tests a loadTemplatefile method - * - */ - function testLoadTemplatefile() - { - $result = $this->tpl->loadTemplatefile('loadtemplatefile.html', false, false); - if (PEAR::isError($result)) { - $this->assertTrue(false, 'Error loading template file: '. $result->getMessage()); - } - $this->assertEquals('A template', trim($this->tpl->get())); - } - - /** - * Tests a setVariable method - * - */ - function testSetVariable() - { - $result = $this->tpl->setTemplate('{placeholder1} {placeholder2} {placeholder3}', true, true); - if (PEAR::isError($result)) { - $this->assertTrue(false, 'Error setting template: '. $result->getMessage()); - } - // "scalar" call - $this->tpl->setVariable('placeholder1', 'var1'); - // array call - $this->tpl->setVariable(array( - 'placeholder2' => 'var2', - 'placeholder3' => 'var3' - )); - $this->assertEquals('var1 var2 var3', $this->tpl->get()); - } - - /** - * Tests the functionality - * - */ - function testInclude() - { - $result = $this->tpl->loadTemplateFile('include.html', false, false); - if (PEAR::isError($result)) { - $this->assertTrue(false, 'Error loading template file: '. $result->getMessage()); - } - $this->assertEquals('Master file; Included file', trim($this->tpl->get())); - } - - /** - * - */ - function testCurrentBlock() - { - $result = $this->tpl->loadTemplateFile('blockiteration.html', true, true); - if (PEAR::isError($result)) { - $this->assertTrue(false, 'Error loading template file: '. $result->getMessage()); - } - $this->tpl->setVariable('outer', 'a'); - $this->tpl->setCurrentBlock('inner_block'); - for ($i = 0; $i < 5; $i++) { - $this->tpl->setVariable('inner', $i + 1); - $this->tpl->parseCurrentBlock(); - } // for - $this->assertEquals('a|1|2|3|4|5#', $this->_stripWhitespace($this->tpl->get())); - } - - /** - * - */ - function testRemovePlaceholders() - { - $result = $this->tpl->setTemplate('{placeholder1},{placeholder2},{placeholder3}', true, true); - if (PEAR::isError($result)) { - $this->assertTrue(false, 'Error setting template: '. $result->getMessage()); - } - // we do not set {placeholder3} - $this->tpl->setVariable(array( - 'placeholder1' => 'var1', - 'placeholder2' => 'var2' - )); - $this->assertEquals('var1,var2,', $this->tpl->get()); - - // Now, we should really add a switch for keeping {stuff} in - // data supplied to setVariable() safe. Until then, removing it should - // be expected behaviour - $result = $this->tpl->setTemplate('{placeholder1},{placeholder2},{placeholder3}', true, true); - $this->tpl->setOption('preserve_input', false); - if (PEAR::isError($result)) { - $this->assertTrue(false, 'Error setting template: '. $result->getMessage()); - } - $this->tpl->setVariable(array( - 'placeholder1' => 'var1', - 'placeholder2' => 'var2', - 'placeholder3' => 'var3{stuff}' - )); - $this->assertEquals('var1,var2,var3', $this->tpl->get()); - - $result = $this->tpl->setTemplate('{placeholder1},{placeholder2},{placeholder3}', true, true); - $this->tpl->setOption('preserve_input', true); - if (PEAR::isError($result)) { - $this->assertTrue(false, 'Error setting template: '. $result->getMessage()); - } - $this->tpl->setVariable(array( - 'placeholder1' => 'var1', - 'placeholder2' => 'var2', - 'placeholder3' => 'var3{stuff}' - )); - $this->assertEquals('var1,var2,var3{stuff}', $this->tpl->get()); - - } - - /** - * - */ - function testTouchBlock() - { - $result = $this->tpl->loadTemplateFile('blockiteration.html', false, true); - if (PEAR::isError($result)) { - $this->assertTrue(false, 'Error loading template file: '. $result->getMessage()); - } - $this->tpl->setVariable('outer', 'data'); - // inner_block should be preserved in output, even if empty - $this->tpl->touchBlock('inner_block'); - $this->assertEquals('data|{inner}#', $this->_stripWhitespace($this->tpl->get())); - } - - // Not available in stock class - - /** - * - */ - /* - function testHideBlock() - { - if (!$this->_methodExists('hideBlock')) { - return; - } - $result = $this->tpl->loadTemplateFile('blockiteration.html', false, true); - if (PEAR::isError($result)) { - $this->assertTrue(false, 'Error loading template file: '. $result->getMessage()); - } - $this->tpl->setVariable(array( - 'outer' => 'data', - 'inner' => 'stuff' - )); - // inner_block is not empty, but should be removed nonetheless - $this->tpl->hideBlock('inner_block'); - $this->assertEquals('data#', $this->_stripWhitespace($this->tpl->get())); - } - */ - /** - * - */ - /* - function testSetGlobalVariable() - { - if (!$this->_methodExists('setGlobalVariable')) { - return; - } - $result = $this->tpl->loadTemplateFile('globals.html', false, true); - if (PEAR::isError($result)) { - $this->assertTrue(false, 'Error loading template file: '. $result->getMessage()); - } - $this->tpl->setGlobalVariable('glob', 'glob'); - // {var2} is not, block_two should be removed - $this->tpl->setVariable(array( - 'var1' => 'one', - 'var3' => 'three' - )); - for ($i = 0; $i < 3; $i++) { - $this->tpl->setVariable('var4', $i + 1); - $this->tpl->parse('block_four'); - } // for - $this->assertEquals('glob:one#glob:three|glob:1|glob:2|glob:3#', $this->_stripWhitespace($this->tpl->get())); - } - */ - - - /** - * Test for bug #9501. preg_replace treat $ and \ as - * backreferences. IT escapes them. - * - */ - function testBug9501() - { - $this->tpl->setTemplate("Test: {VALUE}"); - $this->tpl->clearCache = true; - - $this->tpl->setVariable("VALUE", '$12.34'); - $this->assertEquals('Test: $12.34', $this->tpl->get()); - - $this->tpl->setVariable("VALUE", '$1256.34'); - $this->assertEquals('Test: $1256.34', $this->tpl->get()); - - $this->tpl->setVariable("VALUE", '^1.34'); - $this->assertEquals('Test: ^1.34', $this->tpl->get()); - - $this->tpl->setVariable("VALUE", '$1.34'); - $this->assertEquals('Test: $1.34', $this->tpl->get()); - - $this->tpl->setVariable("VALUE", '\$12.34'); - $this->assertEquals('Test: \$12.34', $this->tpl->get()); - - $this->tpl->setVariable("VALUE", "\$12.34"); - $this->assertEquals('Test: $12.34', $this->tpl->get()); - - $this->tpl->setVariable("VALUE", "\$12.34"); - $this->assertEquals('Test: $12.34', $this->tpl->get()); - - // $12 is not parsed as a variable as it starts with a number - $this->tpl->setVariable("VALUE", "$12.34"); - $this->assertEquals('Test: $12.34', $this->tpl->get()); - - $this->tpl->setVariable("VALUE", "\\$12.34"); - $this->assertEquals('Test: \$12.34', $this->tpl->get()); - - // taken from the bugreport - $word = 'Cost is $456.98'; - $this->tpl->setVariable("VALUE", $word); - $this->assertEquals('Test: Cost is $456.98', $this->tpl->get()); - - $word = "Cost is \$" . '183.22'; - $this->tpl->setVariable("VALUE", $word); - $this->assertEquals('Test: Cost is $183.22', $this->tpl->get()); - } - - function testBug9783 () - { - $this->tpl->setTemplate("{DATA} ", true, true); - $data = array ('{Bakken}', 'Soria', 'Joye'); - foreach ($data as $name) { - $this->tpl->setCurrentBlock('entry'); - $this->tpl->setVariable('DATA', $name); - $this->tpl->parseCurrentBlock(); - } - - $this->assertEquals('{Bakken} Soria Joye', trim($this->tpl->get())); - - } - - function testBug9853 () - { - $this->tpl->loadTemplatefile("bug_9853_01.tpl", true, true); - - $this->tpl->setVariable("VAR" , "Ok !"); - $this->tpl->parse("foo1"); - - $this->tpl->setVariable("VAR" , "Ok !"); - $this->tpl->parse("foo2"); - - $this->tpl->setVariable("VAR." , "Ok !"); - $this->tpl->setVariable("VAR2" , "Okay"); - $this->tpl->parse("bar"); - - $this->tpl->parse(); - $output01 = $this->tpl->get(); - - $this->tpl->loadTemplatefile("bug_9853_02.tpl", true, true); - - $this->tpl->setVariable("VAR" , "Ok !"); - $this->tpl->parse("foo."); - - $this->tpl->setVariable("VAR" , "Ok !"); - $this->tpl->parse("foo2"); - - $this->tpl->setVariable("VAR." , "Ok !"); - $this->tpl->setVariable("VAR2" , "Okay"); - $this->tpl->parse("bar"); - - $this->tpl->parse(); - $output02 = $this->tpl->get(); - - $this->assertEquals($output01, $output02); - } - - - /** - * Tests iterations over two blocks - * - */ - function testBlockIteration() - { - $data = array( - 'a', - array('b', array('1', '2', '3', '4')), - 'c', - array('d', array('5', '6', '7')) - ); - - $result = $this->tpl->loadTemplateFile('blockiteration.html', true, true); - if (PEAR::isError($result)) { - $this->assertTrue(false, 'Error loading template file: '. $result->getMessage()); - } - foreach ($data as $value) { - if (is_array($value)) { - $this->tpl->setVariable('outer', $value[0]); - foreach ($value[1] as $v) { - $this->tpl->setVariable('inner', $v); - $this->tpl->parse('inner_block'); - } - } else { - $this->tpl->setVariable('outer', $value); - } - $this->tpl->parse('outer_block'); - } - $this->assertEquals('a#b|1|2|3|4#c#d|5|6|7#', $this->_stripWhitespace($this->tpl->get())); - } - - /** - * - * - */ - function testTouchBlockIteration() - { - $data = array('a','b','c','d','e'); - $result = $this->tpl->loadTemplateFile('blockiteration.html', true, true); - if (PEAR::isError($result)) { - $this->assertTrue(false, 'Error loading template file: '. $result->getMessage()); - } - for ($i = 0; $i < count($data); $i++) { - $this->tpl->setVariable('outer', $data[$i]); - // the inner_block is empty and should be removed - if (0 == $i % 2) { - $this->tpl->touchBlock('inner_block'); - } - $this->tpl->parse('outer_block'); - } - $this->assertEquals('a|#b#c|#d#e|#', $this->_stripWhitespace($this->tpl->get())); - } - - public function testShouldSetOptionsCorrectly() { - $result = $this->tpl->setOption('removeEmptyBlocks', false); - - $this->assertFalse(PEAR::isError($result)); - - $this->assertFalse($this->tpl->removeEmptyBlocks); - - $result = $this->tpl->setOption('removeEmptyBlocks', true); - - $this->assertFalse(PEAR::isError($result)); - - $this->assertTrue($this->tpl->removeEmptyBlocks); - - } - - - public function testPlaceholderReplacementScope() { - $result = $this->tpl->loadTemplateFile('placeholderreplacementscope.html', true, true); - - if (PEAR::isError($result)) { - $this->fail('Error loading template file: ' . $result->getMessage()); - } - - - $this->tpl->setCurrentBlock('foo'); - $this->tpl->setVariable('var1','test'); - $this->tpl->parseCurrentBlock(); - $this->tpl->setCurrentBlock('bar'); - $this->tpl->setVariable('var1','not'); - $this->tpl->setVariable('var2','good'); - $this->tpl->parseCurrentBlock(); - - $actual = $this->_stripWhitespace($this->tpl->get()); - $this->assertEquals('testgood', $actual); - } - -} - -?> +tpl = new HTML_Template_IT(dirname(__FILE__) . '/templates'); + } + + function tearDown() + { + unset($this->tpl); + } + + function _stripWhitespace($str) + { + return preg_replace('/\\s+/', '', $str); + } + + function _methodExists($name) + { + if (in_array(strtolower($name), get_class_methods($this->tpl))) { + return true; + } + $this->assertTrue(false, 'method '. $name . ' not implemented in ' . get_class($this->tpl)); + return false; + } + + /** + * Tests a setTemplate method + * + */ + function testSetTemplate() + { + $result = $this->tpl->setTemplate('A template', false, false); + if (PEAR::isError($result)) { + $this->assertTrue(false, 'Error setting template: '. $result->getMessage()); + } + $this->assertEquals('A template', $this->tpl->get()); + } + + /** + * Tests a loadTemplatefile method + * + */ + function testLoadTemplatefile() + { + $result = $this->tpl->loadTemplatefile('loadtemplatefile.html', false, false); + if (PEAR::isError($result)) { + $this->assertTrue(false, 'Error loading template file: '. $result->getMessage()); + } + $this->assertEquals('A template', trim($this->tpl->get())); + } + + /** + * Tests a setVariable method + * + */ + function testSetVariable() + { + $result = $this->tpl->setTemplate('{placeholder1} {placeholder2} {placeholder3}', true, true); + if (PEAR::isError($result)) { + $this->assertTrue(false, 'Error setting template: '. $result->getMessage()); + } + // "scalar" call + $this->tpl->setVariable('placeholder1', 'var1'); + // array call + $this->tpl->setVariable(array( + 'placeholder2' => 'var2', + 'placeholder3' => 'var3' + )); + $this->assertEquals('var1 var2 var3', $this->tpl->get()); + } + + /** + * Tests the functionality + * + */ + function testInclude() + { + $result = $this->tpl->loadTemplateFile('include.html', false, false); + if (PEAR::isError($result)) { + $this->assertTrue(false, 'Error loading template file: '. $result->getMessage()); + } + $this->assertEquals('Master file; Included file', trim($this->tpl->get())); + } + + /** + * + */ + function testCurrentBlock() + { + $result = $this->tpl->loadTemplateFile('blockiteration.html', true, true); + if (PEAR::isError($result)) { + $this->assertTrue(false, 'Error loading template file: '. $result->getMessage()); + } + $this->tpl->setVariable('outer', 'a'); + $this->tpl->setCurrentBlock('inner_block'); + for ($i = 0; $i < 5; $i++) { + $this->tpl->setVariable('inner', $i + 1); + $this->tpl->parseCurrentBlock(); + } // for + $this->assertEquals('a|1|2|3|4|5#', $this->_stripWhitespace($this->tpl->get())); + } + + /** + * + */ + function testRemovePlaceholders() + { + $result = $this->tpl->setTemplate('{placeholder1},{placeholder2},{placeholder3}', true, true); + if (PEAR::isError($result)) { + $this->assertTrue(false, 'Error setting template: '. $result->getMessage()); + } + // we do not set {placeholder3} + $this->tpl->setVariable(array( + 'placeholder1' => 'var1', + 'placeholder2' => 'var2' + )); + $this->assertEquals('var1,var2,', $this->tpl->get()); + + // Now, we should really add a switch for keeping {stuff} in + // data supplied to setVariable() safe. Until then, removing it should + // be expected behaviour + $result = $this->tpl->setTemplate('{placeholder1},{placeholder2},{placeholder3}', true, true); + $this->tpl->setOption('preserve_input', false); + if (PEAR::isError($result)) { + $this->assertTrue(false, 'Error setting template: '. $result->getMessage()); + } + $this->tpl->setVariable(array( + 'placeholder1' => 'var1', + 'placeholder2' => 'var2', + 'placeholder3' => 'var3{stuff}' + )); + $this->assertEquals('var1,var2,var3', $this->tpl->get()); + + $result = $this->tpl->setTemplate('{placeholder1},{placeholder2},{placeholder3}', true, true); + $this->tpl->setOption('preserve_input', true); + if (PEAR::isError($result)) { + $this->assertTrue(false, 'Error setting template: '. $result->getMessage()); + } + $this->tpl->setVariable(array( + 'placeholder1' => 'var1', + 'placeholder2' => 'var2', + 'placeholder3' => 'var3{stuff}' + )); + $this->assertEquals('var1,var2,var3{stuff}', $this->tpl->get()); + + } + + /** + * + */ + function testTouchBlock() + { + $result = $this->tpl->loadTemplateFile('blockiteration.html', false, true); + if (PEAR::isError($result)) { + $this->assertTrue(false, 'Error loading template file: '. $result->getMessage()); + } + $this->tpl->setVariable('outer', 'data'); + // inner_block should be preserved in output, even if empty + $this->tpl->touchBlock('inner_block'); + $this->assertEquals('data|{inner}#', $this->_stripWhitespace($this->tpl->get())); + } + + // Not available in stock class + + /** + * + */ + /* + function testHideBlock() + { + if (!$this->_methodExists('hideBlock')) { + return; + } + $result = $this->tpl->loadTemplateFile('blockiteration.html', false, true); + if (PEAR::isError($result)) { + $this->assertTrue(false, 'Error loading template file: '. $result->getMessage()); + } + $this->tpl->setVariable(array( + 'outer' => 'data', + 'inner' => 'stuff' + )); + // inner_block is not empty, but should be removed nonetheless + $this->tpl->hideBlock('inner_block'); + $this->assertEquals('data#', $this->_stripWhitespace($this->tpl->get())); + } + */ + /** + * + */ + /* + function testSetGlobalVariable() + { + if (!$this->_methodExists('setGlobalVariable')) { + return; + } + $result = $this->tpl->loadTemplateFile('globals.html', false, true); + if (PEAR::isError($result)) { + $this->assertTrue(false, 'Error loading template file: '. $result->getMessage()); + } + $this->tpl->setGlobalVariable('glob', 'glob'); + // {var2} is not, block_two should be removed + $this->tpl->setVariable(array( + 'var1' => 'one', + 'var3' => 'three' + )); + for ($i = 0; $i < 3; $i++) { + $this->tpl->setVariable('var4', $i + 1); + $this->tpl->parse('block_four'); + } // for + $this->assertEquals('glob:one#glob:three|glob:1|glob:2|glob:3#', $this->_stripWhitespace($this->tpl->get())); + } + */ + + + /** + * Test for bug #9501. preg_replace treat $ and \ as + * backreferences. IT escapes them. + * + */ + function testBug9501() + { + $this->tpl->setTemplate("Test: {VALUE}"); + $this->tpl->clearCache = true; + + $this->tpl->setVariable("VALUE", '$12.34'); + $this->assertEquals('Test: $12.34', $this->tpl->get()); + + $this->tpl->setVariable("VALUE", '$1256.34'); + $this->assertEquals('Test: $1256.34', $this->tpl->get()); + + $this->tpl->setVariable("VALUE", '^1.34'); + $this->assertEquals('Test: ^1.34', $this->tpl->get()); + + $this->tpl->setVariable("VALUE", '$1.34'); + $this->assertEquals('Test: $1.34', $this->tpl->get()); + + $this->tpl->setVariable("VALUE", '\$12.34'); + $this->assertEquals('Test: \$12.34', $this->tpl->get()); + + $this->tpl->setVariable("VALUE", "\$12.34"); + $this->assertEquals('Test: $12.34', $this->tpl->get()); + + $this->tpl->setVariable("VALUE", "\$12.34"); + $this->assertEquals('Test: $12.34', $this->tpl->get()); + + // $12 is not parsed as a variable as it starts with a number + $this->tpl->setVariable("VALUE", "$12.34"); + $this->assertEquals('Test: $12.34', $this->tpl->get()); + + $this->tpl->setVariable("VALUE", "\\$12.34"); + $this->assertEquals('Test: \$12.34', $this->tpl->get()); + + // taken from the bugreport + $word = 'Cost is $456.98'; + $this->tpl->setVariable("VALUE", $word); + $this->assertEquals('Test: Cost is $456.98', $this->tpl->get()); + + $word = "Cost is \$" . '183.22'; + $this->tpl->setVariable("VALUE", $word); + $this->assertEquals('Test: Cost is $183.22', $this->tpl->get()); + } + + function testBug9783 () + { + $this->tpl->setTemplate("{DATA} ", true, true); + $data = array ('{Bakken}', 'Soria', 'Joye'); + foreach ($data as $name) { + $this->tpl->setCurrentBlock('entry'); + $this->tpl->setVariable('DATA', $name); + $this->tpl->parseCurrentBlock(); + } + + $this->assertEquals('{Bakken} Soria Joye', trim($this->tpl->get())); + + } + + function testBug9853 () + { + $this->tpl->loadTemplatefile("bug_9853_01.tpl", true, true); + + $this->tpl->setVariable("VAR" , "Ok !"); + $this->tpl->parse("foo1"); + + $this->tpl->setVariable("VAR" , "Ok !"); + $this->tpl->parse("foo2"); + + $this->tpl->setVariable("VAR." , "Ok !"); + $this->tpl->setVariable("VAR2" , "Okay"); + $this->tpl->parse("bar"); + + $this->tpl->parse(); + $output01 = $this->tpl->get(); + + $this->tpl->loadTemplatefile("bug_9853_02.tpl", true, true); + + $this->tpl->setVariable("VAR" , "Ok !"); + $this->tpl->parse("foo."); + + $this->tpl->setVariable("VAR" , "Ok !"); + $this->tpl->parse("foo2"); + + $this->tpl->setVariable("VAR." , "Ok !"); + $this->tpl->setVariable("VAR2" , "Okay"); + $this->tpl->parse("bar"); + + $this->tpl->parse(); + $output02 = $this->tpl->get(); + + $this->assertEquals($output01, $output02); + } + + + /** + * Tests iterations over two blocks + * + */ + function testBlockIteration() + { + $data = array( + 'a', + array('b', array('1', '2', '3', '4')), + 'c', + array('d', array('5', '6', '7')) + ); + + $result = $this->tpl->loadTemplateFile('blockiteration.html', true, true); + if (PEAR::isError($result)) { + $this->assertTrue(false, 'Error loading template file: '. $result->getMessage()); + } + foreach ($data as $value) { + if (is_array($value)) { + $this->tpl->setVariable('outer', $value[0]); + foreach ($value[1] as $v) { + $this->tpl->setVariable('inner', $v); + $this->tpl->parse('inner_block'); + } + } else { + $this->tpl->setVariable('outer', $value); + } + $this->tpl->parse('outer_block'); + } + $this->assertEquals('a#b|1|2|3|4#c#d|5|6|7#', $this->_stripWhitespace($this->tpl->get())); + } + + /** + * + * + */ + function testTouchBlockIteration() + { + $data = array('a','b','c','d','e'); + $result = $this->tpl->loadTemplateFile('blockiteration.html', true, true); + if (PEAR::isError($result)) { + $this->assertTrue(false, 'Error loading template file: '. $result->getMessage()); + } + for ($i = 0; $i < count($data); $i++) { + $this->tpl->setVariable('outer', $data[$i]); + // the inner_block is empty and should be removed + if (0 == $i % 2) { + $this->tpl->touchBlock('inner_block'); + } + $this->tpl->parse('outer_block'); + } + $this->assertEquals('a|#b#c|#d#e|#', $this->_stripWhitespace($this->tpl->get())); + } + + public function testShouldSetOptionsCorrectly() { + $result = $this->tpl->setOption('removeEmptyBlocks', false); + + $this->assertFalse(PEAR::isError($result)); + + $this->assertFalse($this->tpl->removeEmptyBlocks); + + $result = $this->tpl->setOption('removeEmptyBlocks', true); + + $this->assertFalse(PEAR::isError($result)); + + $this->assertTrue($this->tpl->removeEmptyBlocks); + + } + + + public function testPlaceholderReplacementScope() { + $result = $this->tpl->loadTemplateFile('placeholderreplacementscope.html', true, true); + + if (PEAR::isError($result)) { + $this->fail('Error loading template file: ' . $result->getMessage()); + } + + + $this->tpl->setCurrentBlock('foo'); + $this->tpl->setVariable('var1','test'); + $this->tpl->parseCurrentBlock(); + $this->tpl->setCurrentBlock('bar'); + $this->tpl->setVariable('var1','not'); + $this->tpl->setVariable('var2','good'); + $this->tpl->parseCurrentBlock(); + + $actual = $this->_stripWhitespace($this->tpl->get()); + $this->assertEquals('testgood', $actual); + } + +} + +?> diff --git a/HTML_Template_IT-1.3.0/tests/ITXTest.php b/HTML_Template_IT-1.3.1/tests/ITXTest.php similarity index 96% rename from HTML_Template_IT-1.3.0/tests/ITXTest.php rename to HTML_Template_IT-1.3.1/tests/ITXTest.php index f481dfc..9f3709b 100644 --- a/HTML_Template_IT-1.3.0/tests/ITXTest.php +++ b/HTML_Template_IT-1.3.1/tests/ITXTest.php @@ -1,171 +1,171 @@ -tpl = new HTML_Template_ITX(dirname(__FILE__) . '/templates'); - } - - function testPlaceholderExists() - { - $this->tpl->setTemplate('{var}'); - $this->assertSame("__global__", $this->tpl->placeholderExists('var'), 'Existing placeholder \'var\' reported as nonexistant'); - $this->assertSame("", $this->tpl->placeholderExists('foobar'), 'Nonexistant placeholder \'foobar\' reported as existing'); - $this->assertSame("__global__", $this->tpl->placeholderExists('var', '__global__'), 'Existing in block \'__global__\' placeholder \'var\' reported as nonexistant'); - $this->assertSame("", $this->tpl->placeholderExists('foobar', '__global__'), 'Nonexistant in block \'__global__\' placeholder \'foobar\' reported as existing'); - } - - function testBlockExists() - { - $this->tpl->setTemplate('{var}'); - $this->assertTrue($this->tpl->blockExists('__global__'), 'Existing block \'__global__\' reported as nonexistant'); - $this->assertTrue(!$this->tpl->blockExists('foobar'), 'Nonexistant block \'foobar\' reported as existing'); - } - - function testAddBlock() - { - $result = $this->tpl->loadTemplatefile('blocks.html', true, true); - if (PEAR::isError($result)) { - $this->assertTrue(false, 'Error loading template file: '. $result->getMessage()); - } - $this->tpl->addBlock('var', 'added', 'added:{new_var}'); - $this->assertTrue($this->tpl->blockExists('added'), 'The new block seems to be missing'); - $this->assertTrue(!$this->tpl->placeholderExists('var'), 'The old variable seems to be still present in the template'); - $this->tpl->setVariable('new_var', 'new_value'); - $this->assertEquals('added:new_value', $this->_stripWhitespace($this->tpl->get())); - } - - function testAddBlockfile() - { - $result = $this->tpl->loadTemplatefile('blocks.html', true, true); - if (PEAR::isError($result)) { - $this->assertTrue(false, 'Error loading template file: '. $result->getMessage()); - } - $result = $this->tpl->addBlockfile('var', 'added', 'addblock.html'); - if (PEAR::isError($result)) { - $this->assertTrue(false, 'Error adding block from file: '. $result->getMessage()); - } - $this->assertTrue($this->tpl->blockExists('added'), 'The new block seems to be missing'); - $this->assertTrue(!$this->tpl->placeholderExists('var'), 'The old variable seems to be still present in the template'); - $this->tpl->setVariable('new_var', 'new_value'); - $this->assertEquals('added:new_value', $this->_stripWhitespace($this->tpl->get())); - } - - function testReplaceBlock() - { - $result = $this->tpl->loadTemplatefile('blocks.html', true, true); - if (PEAR::isError($result)) { - $this->assertTrue(false, 'Error loading template file: '. $result->getMessage()); - } - $this->tpl->setVariable('old_var', 'old_value'); - $this->tpl->parse('old_block'); - // old_block's contents should be discarded - $this->tpl->replaceBlock('old_block', 'replaced:{replaced_var}#', false); - $this->assertTrue(!$this->tpl->blockExists('old_inner_block') && !$this->tpl->placeholderExists('old_var'), - 'The replaced block\'s contents seem to be still present'); - $this->tpl->setVariable('replaced_var', 'replaced_value'); - $this->tpl->parse('old_block'); - // this time old_block's contents should be preserved - $this->tpl->replaceBlock('old_block', 'replaced_again:{brand_new_var}', true); - $this->tpl->setVariable('brand_new_var', 'brand_new_value'); - $this->assertEquals('replaced:replaced_value#replaced_again:brand_new_value', $this->_stripWhitespace($this->tpl->get())); - } - - function testReplaceBlockfile() - { - $result = $this->tpl->loadTemplatefile('blocks.html', true, true); - if (PEAR::isError($result)) { - $this->assertTrue(false, 'Error loading template file: '. $result->getMessage()); - } - $this->tpl->setVariable('old_var', 'old_value'); - $this->tpl->parse('old_block'); - // old_block's contents should be discarded - $result = $this->tpl->replaceBlockfile('old_block', 'replaceblock.html', false); - if (PEAR::isError($result)) { - $this->assertTrue(false, 'Error replacing block from file: '. $result->getMessage()); - } - $this->assertTrue(!$this->tpl->blockExists('old_inner_block') && !$this->tpl->placeholderExists('old_var'), - 'The replaced block\'s contents seem to be still present'); - $this->tpl->setVariable(array( - 'replaced_var' => 'replaced_value', - 'replaced_inner_var' => 'inner_value' - )); - $this->tpl->parse('old_block'); - // this time old_block's contents should be preserved - $result = $this->tpl->replaceBlockfile('old_block', 'addblock.html', true); - if (PEAR::isError($result)) { - $this->assertTrue(false, 'Error replacing block from file: '. $result->getMessage()); - } - $this->tpl->setVariable('new_var', 'again'); - $this->assertEquals('replaced:replaced_value|inner_value#added:again', $this->_stripWhitespace($this->tpl->get())); - } - - function testCallback() - { - $this->tpl->setTemplate('callback:func_uppercase(word)'); - $this->tpl->setCallbackFunction('uppercase', '_uppercaseCallback'); - $res = $this->tpl->performCallback(); - if (PEAR::isError($res)) { - $this->assertTrue(false, 'Error performing callback: '. $res->getMessage()); - } - $this->assertEquals('callback:WORD', $this->tpl->get()); - - $this->tpl->setTemplate('callback:func_lowercase(Word)'); - $this->tpl->setCallbackFunction('lowercase', array('Callbacks','_lowercaseCallback')); - $res = $this->tpl->performCallback(); - if (PEAR::isError($res)) { - $this->assertTrue(false, 'Error performing callback: '. $res->getMessage()); - } - $this->assertEquals('callback:word', $this->tpl->get()); - - $this->tpl->setTemplate('callback:func_lowercase(Word)'); - $this->tpl->setCallbackFunction('lowercase', array(new Callbacks,'_lowercaseCallback')); - $res = $this->tpl->performCallback(); - if (PEAR::isError($res)) { - $this->assertTrue(false, 'Error performing callback: '. $res->getMessage()); - } - $this->assertEquals('callback:word', $this->tpl->get()); - - $this->tpl->setTemplate('callback:func_numberFormat(1.5, 2)'); - $this->tpl->setCallbackFunction('numberFormat', array('Callbacks', '_numberFormatCallback'), '', true); - $res = $this->tpl->performCallback(); - if (PEAR::isError($res)) { - $this->assertTrue(false, 'Error performing callback: '. $res->getMessage()); - } - $this->assertEquals('callback:1.50', $this->tpl->get()); - - $this->tpl->setTemplate('callback:func_numberFormat(1.5, 2)'); - $GLOBALS['obj'] = new Callbacks; - $this->tpl->setCallbackFunction('numberFormat', '_numberFormatCallback', 'obj', true); - $res = $this->tpl->performCallback(); - if (PEAR::isError($res)) { - $this->assertTrue(false, 'Error performing callback: '. $res->getMessage()); - } - $this->assertEquals('callback:1.50', $this->tpl->get()); - } -} - -?> +tpl = new HTML_Template_ITX(dirname(__FILE__) . '/templates'); + } + + function testPlaceholderExists() + { + $this->tpl->setTemplate('{var}'); + $this->assertSame("__global__", $this->tpl->placeholderExists('var'), 'Existing placeholder \'var\' reported as nonexistant'); + $this->assertSame("", $this->tpl->placeholderExists('foobar'), 'Nonexistant placeholder \'foobar\' reported as existing'); + $this->assertSame("__global__", $this->tpl->placeholderExists('var', '__global__'), 'Existing in block \'__global__\' placeholder \'var\' reported as nonexistant'); + $this->assertSame("", $this->tpl->placeholderExists('foobar', '__global__'), 'Nonexistant in block \'__global__\' placeholder \'foobar\' reported as existing'); + } + + function testBlockExists() + { + $this->tpl->setTemplate('{var}'); + $this->assertTrue($this->tpl->blockExists('__global__'), 'Existing block \'__global__\' reported as nonexistant'); + $this->assertTrue(!$this->tpl->blockExists('foobar'), 'Nonexistant block \'foobar\' reported as existing'); + } + + function testAddBlock() + { + $result = $this->tpl->loadTemplatefile('blocks.html', true, true); + if (PEAR::isError($result)) { + $this->assertTrue(false, 'Error loading template file: '. $result->getMessage()); + } + $this->tpl->addBlock('var', 'added', 'added:{new_var}'); + $this->assertTrue($this->tpl->blockExists('added'), 'The new block seems to be missing'); + $this->assertTrue(!$this->tpl->placeholderExists('var'), 'The old variable seems to be still present in the template'); + $this->tpl->setVariable('new_var', 'new_value'); + $this->assertEquals('added:new_value', $this->_stripWhitespace($this->tpl->get())); + } + + function testAddBlockfile() + { + $result = $this->tpl->loadTemplatefile('blocks.html', true, true); + if (PEAR::isError($result)) { + $this->assertTrue(false, 'Error loading template file: '. $result->getMessage()); + } + $result = $this->tpl->addBlockfile('var', 'added', 'addblock.html'); + if (PEAR::isError($result)) { + $this->assertTrue(false, 'Error adding block from file: '. $result->getMessage()); + } + $this->assertTrue($this->tpl->blockExists('added'), 'The new block seems to be missing'); + $this->assertTrue(!$this->tpl->placeholderExists('var'), 'The old variable seems to be still present in the template'); + $this->tpl->setVariable('new_var', 'new_value'); + $this->assertEquals('added:new_value', $this->_stripWhitespace($this->tpl->get())); + } + + function testReplaceBlock() + { + $result = $this->tpl->loadTemplatefile('blocks.html', true, true); + if (PEAR::isError($result)) { + $this->assertTrue(false, 'Error loading template file: '. $result->getMessage()); + } + $this->tpl->setVariable('old_var', 'old_value'); + $this->tpl->parse('old_block'); + // old_block's contents should be discarded + $this->tpl->replaceBlock('old_block', 'replaced:{replaced_var}#', false); + $this->assertTrue(!$this->tpl->blockExists('old_inner_block') && !$this->tpl->placeholderExists('old_var'), + 'The replaced block\'s contents seem to be still present'); + $this->tpl->setVariable('replaced_var', 'replaced_value'); + $this->tpl->parse('old_block'); + // this time old_block's contents should be preserved + $this->tpl->replaceBlock('old_block', 'replaced_again:{brand_new_var}', true); + $this->tpl->setVariable('brand_new_var', 'brand_new_value'); + $this->assertEquals('replaced:replaced_value#replaced_again:brand_new_value', $this->_stripWhitespace($this->tpl->get())); + } + + function testReplaceBlockfile() + { + $result = $this->tpl->loadTemplatefile('blocks.html', true, true); + if (PEAR::isError($result)) { + $this->assertTrue(false, 'Error loading template file: '. $result->getMessage()); + } + $this->tpl->setVariable('old_var', 'old_value'); + $this->tpl->parse('old_block'); + // old_block's contents should be discarded + $result = $this->tpl->replaceBlockfile('old_block', 'replaceblock.html', false); + if (PEAR::isError($result)) { + $this->assertTrue(false, 'Error replacing block from file: '. $result->getMessage()); + } + $this->assertTrue(!$this->tpl->blockExists('old_inner_block') && !$this->tpl->placeholderExists('old_var'), + 'The replaced block\'s contents seem to be still present'); + $this->tpl->setVariable(array( + 'replaced_var' => 'replaced_value', + 'replaced_inner_var' => 'inner_value' + )); + $this->tpl->parse('old_block'); + // this time old_block's contents should be preserved + $result = $this->tpl->replaceBlockfile('old_block', 'addblock.html', true); + if (PEAR::isError($result)) { + $this->assertTrue(false, 'Error replacing block from file: '. $result->getMessage()); + } + $this->tpl->setVariable('new_var', 'again'); + $this->assertEquals('replaced:replaced_value|inner_value#added:again', $this->_stripWhitespace($this->tpl->get())); + } + + function testCallback() + { + $this->tpl->setTemplate('callback:func_uppercase(word)'); + $this->tpl->setCallbackFunction('uppercase', '_uppercaseCallback'); + $res = $this->tpl->performCallback(); + if (PEAR::isError($res)) { + $this->assertTrue(false, 'Error performing callback: '. $res->getMessage()); + } + $this->assertEquals('callback:WORD', $this->tpl->get()); + + $this->tpl->setTemplate('callback:func_lowercase(Word)'); + $this->tpl->setCallbackFunction('lowercase', array('Callbacks','_lowercaseCallback')); + $res = $this->tpl->performCallback(); + if (PEAR::isError($res)) { + $this->assertTrue(false, 'Error performing callback: '. $res->getMessage()); + } + $this->assertEquals('callback:word', $this->tpl->get()); + + $this->tpl->setTemplate('callback:func_lowercase(Word)'); + $this->tpl->setCallbackFunction('lowercase', array(new Callbacks,'_lowercaseCallback')); + $res = $this->tpl->performCallback(); + if (PEAR::isError($res)) { + $this->assertTrue(false, 'Error performing callback: '. $res->getMessage()); + } + $this->assertEquals('callback:word', $this->tpl->get()); + + $this->tpl->setTemplate('callback:func_numberFormat(1.5, 2)'); + $this->tpl->setCallbackFunction('numberFormat', array('Callbacks', '_numberFormatCallback'), '', true); + $res = $this->tpl->performCallback(); + if (PEAR::isError($res)) { + $this->assertTrue(false, 'Error performing callback: '. $res->getMessage()); + } + $this->assertEquals('callback:1.50', $this->tpl->get()); + + $this->tpl->setTemplate('callback:func_numberFormat(1.5, 2)'); + $GLOBALS['obj'] = new Callbacks; + $this->tpl->setCallbackFunction('numberFormat', '_numberFormatCallback', 'obj', true); + $res = $this->tpl->performCallback(); + if (PEAR::isError($res)) { + $this->assertTrue(false, 'Error performing callback: '. $res->getMessage()); + } + $this->assertEquals('callback:1.50', $this->tpl->get()); + } +} + +?> diff --git a/HTML_Template_IT-1.3.0/tests/templates/__include.html b/HTML_Template_IT-1.3.1/tests/templates/__include.html similarity index 93% rename from HTML_Template_IT-1.3.0/tests/templates/__include.html rename to HTML_Template_IT-1.3.1/tests/templates/__include.html index d5dc31c..5291e99 100644 --- a/HTML_Template_IT-1.3.0/tests/templates/__include.html +++ b/HTML_Template_IT-1.3.1/tests/templates/__include.html @@ -1 +1 @@ -Included file +Included file diff --git a/HTML_Template_IT-1.3.0/tests/templates/addblock.html b/HTML_Template_IT-1.3.1/tests/templates/addblock.html similarity index 94% rename from HTML_Template_IT-1.3.0/tests/templates/addblock.html rename to HTML_Template_IT-1.3.1/tests/templates/addblock.html index 9e19c4f..bf58efa 100644 --- a/HTML_Template_IT-1.3.0/tests/templates/addblock.html +++ b/HTML_Template_IT-1.3.1/tests/templates/addblock.html @@ -1 +1 @@ -added:{new_var} +added:{new_var} diff --git a/HTML_Template_IT-1.3.0/tests/templates/blockiteration.html b/HTML_Template_IT-1.3.1/tests/templates/blockiteration.html similarity index 78% rename from HTML_Template_IT-1.3.0/tests/templates/blockiteration.html rename to HTML_Template_IT-1.3.1/tests/templates/blockiteration.html index 111e823..d64cadb 100644 --- a/HTML_Template_IT-1.3.0/tests/templates/blockiteration.html +++ b/HTML_Template_IT-1.3.1/tests/templates/blockiteration.html @@ -1,7 +1,7 @@ - -{outer} - - |{inner} - -# + +{outer} + + |{inner} + +# \ No newline at end of file diff --git a/HTML_Template_IT-1.3.0/tests/templates/blocks.html b/HTML_Template_IT-1.3.1/tests/templates/blocks.html similarity index 95% rename from HTML_Template_IT-1.3.0/tests/templates/blocks.html rename to HTML_Template_IT-1.3.1/tests/templates/blocks.html index f3110f2..e426ca0 100644 --- a/HTML_Template_IT-1.3.0/tests/templates/blocks.html +++ b/HTML_Template_IT-1.3.1/tests/templates/blocks.html @@ -1,8 +1,8 @@ -{var} - -old:{old_var} - - |{old_inner_var} - -# - +{var} + +old:{old_var} + + |{old_inner_var} + +# + diff --git a/HTML_Template_IT-1.3.0/tests/templates/bug_9853_01.tpl b/HTML_Template_IT-1.3.1/tests/templates/bug_9853_01.tpl similarity index 100% rename from HTML_Template_IT-1.3.0/tests/templates/bug_9853_01.tpl rename to HTML_Template_IT-1.3.1/tests/templates/bug_9853_01.tpl diff --git a/HTML_Template_IT-1.3.0/tests/templates/bug_9853_02.tpl b/HTML_Template_IT-1.3.1/tests/templates/bug_9853_02.tpl similarity index 100% rename from HTML_Template_IT-1.3.0/tests/templates/bug_9853_02.tpl rename to HTML_Template_IT-1.3.1/tests/templates/bug_9853_02.tpl diff --git a/HTML_Template_IT-1.3.0/tests/templates/globals.html b/HTML_Template_IT-1.3.1/tests/templates/globals.html similarity index 95% rename from HTML_Template_IT-1.3.0/tests/templates/globals.html rename to HTML_Template_IT-1.3.1/tests/templates/globals.html index dc3e3b9..7157f12 100644 --- a/HTML_Template_IT-1.3.0/tests/templates/globals.html +++ b/HTML_Template_IT-1.3.1/tests/templates/globals.html @@ -1,13 +1,13 @@ - -{glob}:{var1}# - - -{glob}:{var2}# - - -{glob}:{var3} - - |{glob}:{var4} - -# - + +{glob}:{var1}# + + +{glob}:{var2}# + + +{glob}:{var3} + + |{glob}:{var4} + +# + diff --git a/HTML_Template_IT-1.3.0/tests/templates/include.html b/HTML_Template_IT-1.3.1/tests/templates/include.html similarity index 97% rename from HTML_Template_IT-1.3.0/tests/templates/include.html rename to HTML_Template_IT-1.3.1/tests/templates/include.html index 827cbf5..2704378 100644 --- a/HTML_Template_IT-1.3.0/tests/templates/include.html +++ b/HTML_Template_IT-1.3.1/tests/templates/include.html @@ -1 +1 @@ -Master file; +Master file; diff --git a/HTML_Template_IT-1.3.0/tests/templates/loadtemplatefile.html b/HTML_Template_IT-1.3.1/tests/templates/loadtemplatefile.html similarity index 91% rename from HTML_Template_IT-1.3.0/tests/templates/loadtemplatefile.html rename to HTML_Template_IT-1.3.1/tests/templates/loadtemplatefile.html index 7093929..07bc2df 100644 --- a/HTML_Template_IT-1.3.0/tests/templates/loadtemplatefile.html +++ b/HTML_Template_IT-1.3.1/tests/templates/loadtemplatefile.html @@ -1 +1 @@ -A template +A template diff --git a/HTML_Template_IT-1.3.0/tests/templates/placeholderreplacementscope.html b/HTML_Template_IT-1.3.1/tests/templates/placeholderreplacementscope.html old mode 100644 new mode 100755 similarity index 100% rename from HTML_Template_IT-1.3.0/tests/templates/placeholderreplacementscope.html rename to HTML_Template_IT-1.3.1/tests/templates/placeholderreplacementscope.html diff --git a/HTML_Template_IT-1.3.0/tests/templates/replaceblock.html b/HTML_Template_IT-1.3.1/tests/templates/replaceblock.html similarity index 96% rename from HTML_Template_IT-1.3.0/tests/templates/replaceblock.html rename to HTML_Template_IT-1.3.1/tests/templates/replaceblock.html index 03fcf77..133485e 100644 --- a/HTML_Template_IT-1.3.0/tests/templates/replaceblock.html +++ b/HTML_Template_IT-1.3.1/tests/templates/replaceblock.html @@ -1,5 +1,5 @@ -replaced:{replaced_var} - - |{replaced_inner_var} - -# +replaced:{replaced_var} + + |{replaced_inner_var} + +# diff --git a/package.sig b/package.sig new file mode 100644 index 0000000..4423c0c --- /dev/null +++ b/package.sig @@ -0,0 +1,6 @@ +-----BEGIN PGP SIGNATURE----- + +iEYEABECAAYFAlpl7wAACgkQcqMhusJF8XUPAgCgkkhDLmcbWpQvpV5aXtWXmSME +1eAAoMuMxtygcY5OOoitupbXVn1sDGYF +=tmsd +-----END PGP SIGNATURE----- diff --git a/package.xml b/package.xml index e589163..fc384d0 100644 --- a/package.xml +++ b/package.xml @@ -1,5 +1,5 @@ - + HTML_Template_IT pear.php.net Integrated Templates @@ -10,7 +10,7 @@ There are two classes to use for templating. HTML_Template_IT is used for basic Gregory Currie gregorycu gregorycu@php.net - yes + no Pierre-Alain Joye @@ -36,10 +36,10 @@ There are two classes to use for templating. HTML_Template_IT is used for basic ulf.wendel@phpdoc.de no - 2010-03-10 - + 2018-01-22 + - 1.3.0 + 1.3.1 1.3.0 @@ -48,49 +48,33 @@ There are two classes to use for templating. HTML_Template_IT is used for basic Modified BSD license -Changes since last stable release (1.2.1): -- Add support for pear package 2.0 format -- Remove support for pear package 1.0 format -- Fix bug #9501, doller signs disapear if preg_match is used. -- Fix bug #9783, don't remove variable which values follow the variable pattern - To allow backwards compatbility an option preserve_input is added. - If it is false, the old behaviour will be used and therefore those values will be deleted. - Default is true, so new behaviour. -- Fix bug #9853, problems with dots in placeholders or blocknames -- Fix bug #13935, docblock is wrong -- Fix bug #17129 -- Add option 'preserve_input' to only remove unkown variable that were present - during setTemplate or loadTemplatefile - which is the behaviour before 1.3.0a1 -- Improved PHPCS (Request #15039) -- Added unit tests -- Fixed unit tests +- PR #2: Fixes for deprecated code - - - - - - - - + + + + + + + + - - - - - + + + + + - - - + + + - - - + + + @@ -331,5 +315,20 @@ Changes since last stable release (1.2.1): - Fixed unit tests + + + 1.3.1 + 1.3.0 + + + stable + stable + + 2018-01-22 + Modified BSD license + +- PR #2: Fixes for deprecated code + +