HTML_Template_IT
[ class tree: HTML_Template_IT ] [ index: HTML_Template_IT ] [ all elements ]

Source for file IT.php

Documentation is available at IT.php

  1. <?php
  2. //
  3. // +----------------------------------------------------------------------+
  4. // | Copyright (c) 1997-2005 Ulf Wendel, Pierre-Alain Joye                |
  5. // +----------------------------------------------------------------------+
  6. // | This source file is subject to the New BSD license, That is bundled  |
  7. // | with this package in the file LICENSE, and is available through      |
  8. // | the world-wide-web at                                                |
  9. // | http://www.opensource.org/licenses/bsd-license.php                   |
  10. // | If you did not receive a copy of the new BSDlicense and are unable   |
  11. // | to obtain it through the world-wide-web, please send a note to       |
  12. // | pajoye@php.net so we can mail you a copy immediately.                |
  13. // +----------------------------------------------------------------------+
  14. // | Author: Ulf Wendel <ulf.wendel@phpdoc.de>                            |
  15. // |         Pierre-Alain Joye <pajoye@php.net>                           |
  16. // +----------------------------------------------------------------------+
  17. //
  18. // $Id: IT.php,v 1.20 2006/08/17 15:47:22 dsp Exp $
  19. //
  20.  
  21. require_once 'PEAR.php';
  22.  
  23. define('IT_OK',                         1);
  24. define('IT_ERROR',                     -1);
  25. define('IT_TPL_NOT_FOUND',             -2);
  26. define('IT_BLOCK_NOT_FOUND',           -3);
  27. define('IT_BLOCK_DUPLICATE',           -4);
  28. define('IT_UNKNOWN_OPTION',            -6);
  29. /**
  30.  * Integrated Template - IT
  31.  *
  32.  * Well there's not much to say about it. I needed a template class that
  33.  * supports a single template file with multiple (nested) blocks inside and
  34.  * a simple block API.
  35.  *
  36.  * The Isotemplate API is somewhat tricky for a beginner although it is the best
  37.  * one you can build. template::parse() [phplib template = Isotemplate] requests
  38.  * you to name a source and a target where the current block gets parsed into.
  39.  * Source and target can be block names or even handler names. This API gives you
  40.  * a maximum of fexibility but you always have to know what you do which is
  41.  * quite unusual for php skripter like me.
  42.  *
  43.  * I noticed that I do not any control on which block gets parsed into which one.
  44.  * If all blocks are within one file, the script knows how they are nested and in
  45.  * which way you have to parse them. IT knows that inner1 is a child of block2, there's
  46.  * no need to tell him about this.
  47.  *
  48.  * <table border>
  49.  *   <tr>
  50.  *     <td colspan=2>
  51.  *       __global__
  52.  *       <p>
  53.  *       (hidden and automatically added)
  54.  *     </td>
  55.  *   </tr>
  56.  *   <tr>
  57.  *     <td>block1</td>
  58.  *     <td>
  59.  *       <table border>
  60.  *         <tr>
  61.  *           <td colspan=2>block2</td>
  62.  *         </tr>
  63.  *         <tr>
  64.  *           <td>inner1</td>
  65.  *           <td>inner2</td>
  66.  *         </tr>
  67.  *       </table>
  68.  *     </td>
  69.  *   </tr>
  70.  * </table>
  71.  *
  72.  * To add content to block1 you simply type:
  73.  * <code>$tpl->setCurrentBlock("block1");</code>
  74.  * and repeat this as often as needed:
  75.  * <code>
  76.  *   $tpl->setVariable(...);
  77.  *   $tpl->parseCurrentBlock();
  78.  * </code>
  79.  *
  80.  * To add content to block2 you would type something like:
  81.  * <code>
  82.  * $tpl->setCurrentBlock("inner1");
  83.  * $tpl->setVariable(...);
  84.  * $tpl->parseCurrentBlock();
  85.  *
  86.  * $tpl->setVariable(...);
  87.  * $tpl->parseCurrentBlock();
  88.  *
  89.  * $tpl->parse("block1");
  90.  * </code>
  91.  *
  92.  * This will result in one repition of block1 which contains two repitions
  93.  * of inner1. inner2 will be removed if $removeEmptyBlock is set to true which is the default.
  94.  *
  95.  * Usage:
  96.  * <code>
  97.  * $tpl = new HTML_Template_IT( [string filerootdir] );
  98.  *
  99.  * // load a template or set it with setTemplate()
  100.  * $tpl->loadTemplatefile( string filename [, boolean removeUnknownVariables, boolean removeEmptyBlocks] )
  101.  *
  102.  * // set "global" Variables meaning variables not beeing within a (inner) block
  103.  * $tpl->setVariable( string variablename, mixed value );
  104.  *
  105.  * // like with the Isotemplates there's a second way to use setVariable()
  106.  * $tpl->setVariable( array ( string varname => mixed value ) );
  107.  *
  108.  * // Let's use any block, even a deeply nested one
  109.  * $tpl->setCurrentBlock( string blockname );
  110.  *
  111.  * // repeat this as often as you need it.
  112.  * $tpl->setVariable( array ( string varname => mixed value ) );
  113.  * $tpl->parseCurrentBlock();
  114.  *
  115.  * // get the parsed template or print it: $tpl->show()
  116.  * $tpl->get();
  117.  * </code>
  118.  *
  119.  * @author   Ulf Wendel <uw@netuse.de>
  120.  * @version  $Id: IT.php,v 1.20 2006/08/17 15:47:22 dsp Exp $
  121.  * @access   public
  122.  * @package  HTML_Template_IT
  123.  */
  124. {
  125.     /**
  126.      * Contains the error objects
  127.      * @var      array 
  128.      * @access   public
  129.      * @see      halt(), $printError, $haltOnError
  130.      */
  131.     var $err = array();
  132.  
  133.     /**
  134.      * Clear cache on get()?
  135.      * @var      boolean 
  136.      */
  137.     var $clearCache = false;
  138.  
  139.     /**
  140.      * First character of a variable placeholder ( _{_VARIABLE} ).
  141.      * @var      string 
  142.      * @access   public
  143.      * @see      $closingDelimiter, $blocknameRegExp, $variablenameRegExp
  144.      */
  145.     var $openingDelimiter = '{';
  146.  
  147.     /**
  148.      * Last character of a variable placeholder ( {VARIABLE_}_ ).
  149.      * @var      string 
  150.      * @access   public
  151.      * @see      $openingDelimiter, $blocknameRegExp, $variablenameRegExp
  152.      */
  153.     var $closingDelimiter     = '}';
  154.  
  155.     /**
  156.      * RegExp matching a block in the template.
  157.      * Per default "sm" is used as the regexp modifier, "i" is missing.
  158.      * That means a case sensitive search is done.
  159.      * @var      string 
  160.      * @access   public
  161.      * @see      $variablenameRegExp, $openingDelimiter, $closingDelimiter
  162.      */
  163.     var $blocknameRegExp    = '[\.0-9A-Za-z_-]+';
  164.  
  165.     /**
  166.      * RegExp matching a variable placeholder in the template.
  167.      * Per default "sm" is used as the regexp modifier, "i" is missing.
  168.      * That means a case sensitive search is done.
  169.      * @var      string 
  170.      * @access   public
  171.      * @see      $blocknameRegExp, $openingDelimiter, $closingDelimiter
  172.      */
  173.     var $variablenameRegExp    = '[\.0-9A-Za-z_-]+';
  174.  
  175.     /**
  176.      * RegExp used to find variable placeholder, filled by the constructor.
  177.      * @var      string    Looks somewhat like @(delimiter varname delimiter)@
  178.      * @access   public
  179.      * @see      IntegratedTemplate()
  180.      */
  181.     var $variablesRegExp = '';
  182.  
  183.     /**
  184.      * RegExp used to strip unused variable placeholder.
  185.      * @brother  $variablesRegExp
  186.      */
  187.     var $removeVariablesRegExp = '';
  188.  
  189.     /**
  190.      * Controls the handling of unknown variables, default is remove.
  191.      * @var      boolean 
  192.      * @access   public
  193.      */
  194.     var $removeUnknownVariables = true;
  195.  
  196.     /**
  197.      * Controls the handling of empty blocks, default is remove.
  198.      * @var      boolean 
  199.      * @access   public
  200.      */
  201.     var $removeEmptyBlocks = true;
  202.  
  203.     /**
  204.      * RegExp used to find blocks an their content, filled by the constructor.
  205.      * @var      string 
  206.      * @see      IntegratedTemplate()
  207.      */
  208.     var $blockRegExp = '';
  209.  
  210.     /**
  211.      * Name of the current block.
  212.      * @var      string 
  213.      */
  214.     var $currentBlock = '__global__';
  215.  
  216.     /**
  217.      * Content of the template.
  218.      * @var      string 
  219.      */
  220.     var $template = '';
  221.  
  222.     /**
  223.      * Array of all blocks and their content.
  224.      *
  225.      * @var      array 
  226.      * @see      findBlocks()
  227.      */
  228.     var $blocklist = array();
  229.  
  230.     /**
  231.      * Array with the parsed content of a block.
  232.      *
  233.      * @var      array 
  234.      */
  235.     var $blockdata = array();
  236.  
  237.     /**
  238.      * Array of variables in a block.
  239.      * @var      array 
  240.      */
  241.     var $blockvariables = array();
  242.  
  243.     /**
  244.      * Array of inner blocks of a block.
  245.      * @var      array 
  246.      */
  247.     var $blockinner = array();
  248.  
  249.     /**
  250.      * List of blocks to preverse even if they are "empty".
  251.      *
  252.      * This is something special. Sometimes you have blocks that
  253.      * should be preserved although they are empty (no placeholder replaced).
  254.      * Think of a shopping basket. If it's empty you have to drop a message to
  255.      * the user. If it's filled you have to show the contents of
  256.      * the shopping baseket. Now where do you place the message that the basket
  257.      * is empty? It's no good idea to place it in you applications as customers
  258.      * tend to like unecessary minor text changes. Having another template file
  259.      * for an empty basket means that it's very likely that one fine day
  260.      * the filled and empty basket templates have different layout. I decided
  261.      * to introduce blocks that to not contain any placeholder but only
  262.      * text such as the message "Your shopping basked is empty".
  263.      *
  264.      * Now if there is no replacement done in such a block the block will
  265.      * be recognized as "empty" and by default ($removeEmptyBlocks = true) be
  266.      * stripped off. To avoid thisyou can now call touchBlock() to avoid this.
  267.      *
  268.      * The array $touchedBlocks stores a list of touched block which must not
  269.      * be removed even if they are empty.
  270.      *
  271.      * @var  array    $touchedBlocks 
  272.      * @see  touchBlock(), $removeEmptyBlocks
  273.      */
  274.      var $touchedBlocks = array();
  275.  
  276.     /**
  277.      * List of blocks which should not be shown even if not "empty"
  278.      * @var  array    $_hiddenBlocks 
  279.      * @see  hideBlock(), $removeEmptyBlocks
  280.      */
  281.     var $_hiddenBlocks = array();
  282.  
  283.     /**
  284.      * Variable cache.
  285.      *
  286.      * Variables get cached before any replacement is done.
  287.      * Advantage: empty blocks can be removed automatically.
  288.      * Disadvantage: might take some more memory
  289.      *
  290.      * @var    array 
  291.      * @see    setVariable(), $clearCacheOnParse
  292.      */
  293.     var $variableCache = array();
  294.  
  295.     /**
  296.      * Clear the variable cache on parse?
  297.      *
  298.      * If you're not an expert just leave the default false.
  299.      * True reduces memory consumption somewhat if you tend to
  300.      * add lots of values for unknown placeholder.
  301.      *
  302.      * @var    boolean 
  303.      */
  304.     var $clearCacheOnParse = false;
  305.  
  306.     /**
  307.      * Root directory for all file operations.
  308.      * The string gets prefixed to all filenames given.
  309.      * @var    string 
  310.      * @see    HTML_Template_IT(), setRoot()
  311.      */
  312.     var $fileRoot = '';
  313.  
  314.     /**
  315.      * Internal flag indicating that a blockname was used multiple times.
  316.      * @var    boolean 
  317.      */
  318.     var $flagBlocktrouble = false;
  319.  
  320.     /**
  321.      * Flag indicating that the global block was parsed.
  322.      * @var    boolean 
  323.      */
  324.     var $flagGlobalParsed = false;
  325.  
  326.     /**
  327.      * EXPERIMENTAL! FIXME!
  328.      * Flag indication that a template gets cached.
  329.      *
  330.      * Complex templates require some times to be preparsed
  331.      * before the replacement can take place. Often I use
  332.      * one template file over and over again but I don't know
  333.      * before that I will use the same template file again.
  334.      * Now IT could notice this and skip the preparse.
  335.      *
  336.      * @var    boolean 
  337.      */
  338.     var $flagCacheTemplatefile = true;
  339.  
  340.     /**
  341.      * EXPERIMENTAL! FIXME!
  342.      */
  343.     var $lastTemplatefile = '';
  344.  
  345.     /**
  346.      * $_options['preserve_data'] Whether to substitute variables and remove
  347.      * empty placeholders in data passed through setVariable
  348.      * (see also bugs #20199, #21951).
  349.      * $_options['use_preg'] Whether to use preg_replace instead of
  350.      * str_replace in parse()
  351.      * (this is a backwards compatibility feature, see also bugs #21951, #20392)
  352.      */
  353.     var $_options = array(
  354.         'preserve_data' => false,
  355.         'use_preg'      => true
  356.     );
  357.  
  358.     /**
  359.      * Builds some complex regular expressions and optinally sets the
  360.      * file root directory.
  361.      *
  362.      * Make sure that you call this constructor if you derive your template
  363.      * class from this one.
  364.      *
  365.      * @param    string    File root directory, prefix for all filenames
  366.      *                      given to the object.
  367.      * @see      setRoot()
  368.      */
  369.     function HTML_Template_IT($root ''$options = null)
  370.     {
  371.         if (!is_null($options)) {
  372.             $this->setOptions($options);
  373.         }
  374.         $this->variablesRegExp = '@' $this->openingDelimiter .
  375.                                  '(' $this->variablenameRegExp . ')' .
  376.                                  $this->closingDelimiter . '@sm';
  377.         $this->removeVariablesRegExp = '@' $this->openingDelimiter .
  378.                                        "\s*(" $this->variablenameRegExp .
  379.                                        ")\s*" $this->closingDelimiter .'@sm';
  380.  
  381.         $this->blockRegExp = '@<!--\s+BEGIN\s+(' $this->blocknameRegExp .
  382.                              ')\s+-->(.*)<!--\s+END\s+\1\s+-->@sm';
  383.  
  384.         $this->setRoot($root);
  385.     // end constructor
  386.  
  387.  
  388.     /**
  389.      * Sets the option for the template class
  390.      *
  391.      * @access public
  392.      * @param  string  option name
  393.      * @param  mixed   option value
  394.      * @return mixed   IT_OK on success, error object on failure
  395.      */
  396.     function setOption($option$value)
  397.     {
  398.         if (array_key_exists($option$this->_options)) {
  399.             $this->_options[$option$value;
  400.             return IT_OK;
  401.         }
  402.  
  403.         return PEAR::raiseError(
  404.                 $this->errorMessage(IT_UNKNOWN_OPTION. ": '{$option}'",
  405.                 IT_UNKNOWN_OPTION
  406.             );
  407.     }
  408.  
  409.     /**
  410.      * Sets the options for the template class
  411.      *
  412.      * @access public
  413.      * @param  string  options array of options
  414.      *                  default value:
  415.      *                    'preserve_data' => false,
  416.      *                    'use_preg'      => true
  417.      * @param  mixed   option value
  418.      * @return mixed   IT_OK on success, error object on failure
  419.      * @see $options
  420.      */
  421.     function setOptions($options)
  422.     {
  423.         if (is_array($options)) {
  424.             foreach ($options as $option => $value{
  425.                 $error $this->setOption($option$value);
  426.                 if (PEAR::isError($error)) {
  427.                     return $error;
  428.                 }
  429.             }
  430.         }
  431.  
  432.         return IT_OK;
  433.     }
  434.  
  435.     /**
  436.      * Print a certain block with all replacements done.
  437.      * @brother get()
  438.      */
  439.     function show($block '__global__')
  440.     {
  441.         print $this->get($block);
  442.     // end func show
  443.  
  444.     /**
  445.      * Returns a block with all replacements done.
  446.      *
  447.      * @param    string     name of the block
  448.      * @return   string 
  449.      * @throws   PEAR_Error
  450.      * @access   public
  451.      * @see      show()
  452.      */
  453.     function get($block '__global__')
  454.     {
  455.         if ($block == '__global__'  && !$this->flagGlobalParsed{
  456.             $this->parse('__global__');
  457.         }
  458.  
  459.         if (!isset($this->blocklist[$block])) {
  460.             $this->err[= PEAR::raiseError(
  461.                             $this->errorMessage(IT_BLOCK_NOT_FOUND.
  462.                             '"' $block "'",
  463.                             IT_BLOCK_NOT_FOUND
  464.                         );
  465.             return '';
  466.         }
  467.  
  468.         if (isset($this->blockdata[$block])) {
  469.             $ret $this->blockdata[$block];
  470.             if ($this->clearCache{
  471.                 unset($this->blockdata[$block]);
  472.             }
  473.             if ($this->_options['preserve_data']{
  474.                 $ret str_replace(
  475.                         $this->openingDelimiter .
  476.                         '%preserved%' $this->closingDelimiter,
  477.                         $this->openingDelimiter,
  478.                         $ret
  479.                     );
  480.             }
  481.             return $ret;
  482.         }
  483.  
  484.         return '';
  485.     // end func get()
  486.  
  487.     /**
  488.      * Parses the given block.
  489.      *
  490.      * @param    string    name of the block to be parsed
  491.      * @access   public
  492.      * @see      parseCurrentBlock()
  493.      * @throws   PEAR_Error
  494.      */
  495.     function parse($block '__global__'$flag_recursion = false)
  496.     {
  497.         static $regs$values;
  498.  
  499.         if (!isset($this->blocklist[$block])) {
  500.             return PEAR::raiseError(
  501.                 $this->errorMessageIT_BLOCK_NOT_FOUND '"' $block "'",
  502.                         IT_BLOCK_NOT_FOUND
  503.                 );
  504.         }
  505.  
  506.         if ($block == '__global__'{
  507.             $this->flagGlobalParsed = true;
  508.         }
  509.  
  510.         if (!$flag_recursion{
  511.             $regs   = array();
  512.             $values = array();
  513.         }
  514.         $outer $this->blocklist[$block];
  515.         $empty = true;
  516.  
  517.         if ($this->clearCacheOnParse{
  518.             foreach ($this->variableCache as $name => $value{
  519.                 $regs[$this->openingDelimiter .
  520.                           $name $this->closingDelimiter;
  521.                 $values[$value;
  522.                 $empty = false;
  523.             }
  524.             $this->variableCache = array();
  525.         else {
  526.             foreach ($this->blockvariables[$blockas $allowedvar => $v{
  527.  
  528.                 if (isset($this->variableCache[$allowedvar])) {
  529.                    $regs[]   $this->openingDelimiter .
  530.                                $allowedvar $this->closingDelimiter;
  531.                    $values[$this->variableCache[$allowedvar];
  532.                    unset($this->variableCache[$allowedvar]);
  533.                    $empty = false;
  534.                 }
  535.             }
  536.         }
  537.  
  538.         if (isset($this->blockinner[$block])) {
  539.             foreach ($this->blockinner[$blockas $k => $innerblock{
  540.  
  541.                 $this->parse($innerblocktrue);
  542.                 if ($this->blockdata[$innerblock!= ''{
  543.                     $empty = false;
  544.                 }
  545.  
  546.                 $placeholder $this->openingDelimiter . "__" .
  547.                                 $innerblock "__" $this->closingDelimiter;
  548.                 $outer str_replace(
  549.                                     $placeholder,
  550.                                     $this->blockdata[$innerblock]$outer
  551.                         );
  552.                 $this->blockdata[$innerblock"";
  553.             }
  554.  
  555.         }
  556.  
  557.         if (!$flag_recursion && 0 != count($values)) {
  558.             if ($this->_options['use_preg']{
  559.                 $regs        array_map(array(
  560.                                     &$this'_addPregDelimiters'),
  561.                                     $regs
  562.                                 );
  563.                 $funcReplace 'preg_replace';
  564.             else {
  565.                 $funcReplace 'str_replace';
  566.             }
  567.  
  568.             if ($this->_options['preserve_data']{
  569.                 $values array_map(
  570.                             array(&$this'_preserveOpeningDelimiter')$values
  571.                         );
  572.             }
  573.  
  574.             $outer $funcReplace($regs$values$outer);
  575.  
  576.             if ($this->removeUnknownVariables{
  577.                 $outer preg_replace($this->removeVariablesRegExp""$outer);
  578.             }
  579.         }
  580.  
  581.         if ($empty{
  582.             if (!$this->removeEmptyBlocks{
  583.                 $this->blockdata[$block ].= $outer;
  584.             else {
  585.                 if (isset($this->touchedBlocks[$block])) {
  586.                     $this->blockdata[$block.= $outer;
  587.                     unset($this->touchedBlocks[$block]);
  588.                 }
  589.             }
  590.         else {
  591.             if (empty($this->blockdata[$block])) {
  592.                 $this->blockdata[$block$outer;
  593.             else {
  594.                 $this->blockdata[$block.= $outer;
  595.             }
  596.         }
  597.  
  598.         return $empty;
  599.     // end func parse
  600.  
  601.     /**
  602.      * Parses the current block
  603.      * @see      parse(), setCurrentBlock(), $currentBlock
  604.      * @access   public
  605.      */
  606.     function parseCurrentBlock()
  607.     {
  608.         return $this->parse($this->currentBlock);
  609.     // end func parseCurrentBlock
  610.  
  611.     /**
  612.      * Sets a variable value.
  613.      *
  614.      * The function can be used eighter like setVariable( "varname", "value")
  615.      * or with one array $variables["varname"] = "value"
  616.      * given setVariable($variables) quite like phplib templates set_var().
  617.      *
  618.      * @param    mixed     string with the variable name or an array
  619.      *                      %variables["varname"] = "value"
  620.      * @param    string    value of the variable or empty if $variable
  621.      *                      is an array.
  622.      * @param    string    prefix for variable names
  623.      * @access   public
  624.      */
  625.     function setVariable($variable$value '')
  626.     {
  627.         if (is_array($variable)) {
  628.             $this->variableCache = array_merge(
  629.                                             $this->variableCache$variable
  630.                                     );
  631.         else {
  632.             $this->variableCache[$variable$value;
  633.         }
  634.     // end func setVariable
  635.  
  636.     /**
  637.      * Sets the name of the current block that is the block where variables
  638.      * are added.
  639.      *
  640.      * @param    string      name of the block
  641.      * @return   boolean     false on failure, otherwise true
  642.      * @throws   PEAR_Error
  643.      * @access   public
  644.      */
  645.     function setCurrentBlock($block '__global__')
  646.     {
  647.  
  648.         if (!isset($this->blocklist[$block])) {
  649.             return PEAR::raiseError(
  650.                 $this->errorMessageIT_BLOCK_NOT_FOUND .
  651.                 '"' $block "'"IT_BLOCK_NOT_FOUND
  652.             );
  653.         }
  654.  
  655.         $this->currentBlock = $block;
  656.  
  657.         return true;
  658.     // end func setCurrentBlock
  659.  
  660.     /**
  661.      * Preserves an empty block even if removeEmptyBlocks is true.
  662.      *
  663.      * @param    string      name of the block
  664.      * @return   boolean     false on false, otherwise true
  665.      * @throws   PEAR_Error
  666.      * @access   public
  667.      * @see      $removeEmptyBlocks
  668.      */
  669.     function touchBlock($block)
  670.     {
  671.         if (!isset($this->blocklist[$block])) {
  672.             return PEAR::raiseError(
  673.                 $this->errorMessage(IT_BLOCK_NOT_FOUND.
  674.                 '"' $block "'"IT_BLOCK_NOT_FOUND);
  675.         }
  676.  
  677.         $this->touchedBlocks[$block= true;
  678.  
  679.         return true;
  680.     // end func touchBlock
  681.  
  682.     /**
  683.      * Clears all datafields of the object and rebuild the internal blocklist
  684.      *
  685.      * LoadTemplatefile() and setTemplate() automatically call this function
  686.      * when a new template is given. Don't use this function
  687.      * unless you know what you're doing.
  688.      *
  689.      * @access   public
  690.      * @see      free()
  691.      */
  692.     function init()
  693.     {
  694.         $this->free();
  695.         $this->findBlocks($this->template);
  696.         // we don't need it any more
  697.         $this->template = '';
  698.         $this->buildBlockvariablelist();
  699.     // end func init
  700.  
  701.     /**
  702.      * Clears all datafields of the object.
  703.      *
  704.      * Don't use this function unless you know what you're doing.
  705.      *
  706.      * @access   public
  707.      * @see      init()
  708.      */
  709.     function free()
  710.     {
  711.         $this->err = array();
  712.  
  713.         $this->currentBlock = '__global__';
  714.  
  715.         $this->variableCache    = array();
  716.         $this->blocklist        = array();
  717.         $this->touchedBlocks    = array();
  718.  
  719.         $this->flagBlocktrouble = false;
  720.         $this->flagGlobalParsed = false;
  721.     // end func free
  722.  
  723.     /**
  724.      * Sets the template.
  725.      *
  726.      * You can eighter load a template file from disk with
  727.      * LoadTemplatefile() or set the template manually using this function.
  728.      *
  729.      * @param        string      template content
  730.      * @param        boolean     remove unknown/unused variables?
  731.      * @param        boolean     remove empty blocks?
  732.      * @see          LoadTemplatefile(), $template
  733.      * @access       public
  734.      * @return       boolean 
  735.      */
  736.     function setTemplate$template$removeUnknownVariables = true,
  737.                           $removeEmptyBlocks = true)
  738.     {
  739.         $this->removeUnknownVariables = $removeUnknownVariables;
  740.         $this->removeEmptyBlocks = $removeEmptyBlocks;
  741.  
  742.         if ($template == '' && $this->flagCacheTemplatefile{
  743.             $this->variableCache = array();
  744.             $this->blockdata = array();
  745.             $this->touchedBlocks = array();
  746.             $this->currentBlock = '__global__';
  747.         else {
  748.             $this->template = '<!-- BEGIN __global__ -->' $template .
  749.                               '<!-- END __global__ -->';
  750.             $this->init();
  751.         }
  752.  
  753.         if ($this->flagBlocktrouble{
  754.             return false;
  755.         }
  756.  
  757.         return true;
  758.     // end func setTemplate
  759.  
  760.     /**
  761.      * Reads a template file from the disk.
  762.      *
  763.      * @param    string      name of the template file
  764.      * @param    bool        how to handle unknown variables.
  765.      * @param    bool        how to handle empty blocks.
  766.      * @access   public
  767.      * @return   boolean    false on failure, otherwise true
  768.      * @see      $template, setTemplate(), $removeUnknownVariables,
  769.      *            $removeEmptyBlocks
  770.      */
  771.     function loadTemplatefile$filename,
  772.                                $removeUnknownVariables = true,
  773.                                $removeEmptyBlocks = true )
  774.     {
  775.         $template '';
  776.         if (!$this->flagCacheTemplatefile ||
  777.             $this->lastTemplatefile != $filename
  778.         {
  779.             $template $this->getFile($filename);
  780.         }
  781.         $this->lastTemplatefile = $filename;
  782.  
  783.         return $template != '' ?
  784.                 $this->setTemplate(
  785.                         $template,$removeUnknownVariables$removeEmptyBlocks
  786.                     : false;
  787.     // end func LoadTemplatefile
  788.  
  789.     /**
  790.      * Sets the file root. The file root gets prefixed to all filenames passed
  791.      * to the object.
  792.      *
  793.      * Make sure that you override this function when using the class
  794.      * on windows.
  795.      *
  796.      * @param    string 
  797.      * @see      HTML_Template_IT()
  798.      * @access   public
  799.      */
  800.     function setRoot($root)
  801.     {
  802.         if ($root != '' && substr($root-1!= '/'{
  803.             $root .= '/';
  804.         }
  805.  
  806.         $this->fileRoot = $root;
  807.     // end func setRoot
  808.  
  809.     /**
  810.      * Build a list of all variables within of a block
  811.      */
  812.     function buildBlockvariablelist()
  813.     {
  814.         foreach ($this->blocklist as $name => $content{
  815.             preg_match_all($this->variablesRegExp$content$regs);
  816.  
  817.             if (count($regs[1]!= 0{
  818.                 foreach ($regs[1as $k => $var{
  819.                     $this->blockvariables[$name][$var= true;
  820.                 }
  821.             else {
  822.                 $this->blockvariables[$name= array();
  823.             }
  824.         }
  825.     // end func buildBlockvariablelist
  826.  
  827.     /**
  828.      * Returns a list of all global variables
  829.      */
  830.     function getGlobalvariables()
  831.     {
  832.         $regs   = array();
  833.         $values = array();
  834.  
  835.         foreach ($this->blockvariables['__global__'as $allowedvar => $v{
  836.             if (isset($this->variableCache[$allowedvar])) {
  837.                 $regs[]   '@' $this->openingDelimiter .
  838.                             $allowedvar $this->closingDelimiter . '@';
  839.                 $values[$this->variableCache[$allowedvar];
  840.                 unset($this->variableCache[$allowedvar]);
  841.             }
  842.         }
  843.  
  844.         return array($regs$values);
  845.     // end func getGlobalvariables
  846.  
  847.     /**
  848.      * Recusively builds a list of all blocks within the template.
  849.      *
  850.      * @param    string    string that gets scanned
  851.      * @see      $blocklist
  852.      */
  853.     function findBlocks($string)
  854.     {
  855.         $blocklist = array();
  856.  
  857.         if (preg_match_all($this->blockRegExp$string$regsPREG_SET_ORDER)) {
  858.             foreach ($regs as $k => $match{
  859.                 $blockname         $match[1];
  860.                 $blockcontent $match[2];
  861.  
  862.                 if (isset($this->blocklist[$blockname])) {
  863.                     $this->err[= PEAR::raiseError(
  864.                                             $this->errorMessage(
  865.                                             IT_BLOCK_DUPLICATE$blockname),
  866.                                             IT_BLOCK_DUPLICATE
  867.                                     );
  868.                     $this->flagBlocktrouble = true;
  869.                 }
  870.  
  871.                 $this->blocklist[$blockname$blockcontent;
  872.                 $this->blockdata[$blockname"";
  873.  
  874.                 $blocklist[$blockname;
  875.  
  876.                 $inner $this->findBlocks($blockcontent);
  877.                 foreach ($inner as $k => $name{
  878.                     $pattern sprintf(
  879.                         '@<!--\s+BEGIN\s+%s\s+-->(.*)<!--\s+END\s+%s\s+-->@sm',
  880.                         $name,
  881.                         $name
  882.                     );
  883.  
  884.                     $this->blocklist[$blocknamepreg_replace(
  885.                                         $pattern,
  886.                                         $this->openingDelimiter .
  887.                                         '__' $name '__' .
  888.                                         $this->closingDelimiter,
  889.                                         $this->blocklist[$blockname]
  890.                                );
  891.                     $this->blockinner[$blockname][$name;
  892.                     $this->blockparents[$name$blockname;
  893.                 }
  894.             }
  895.         }
  896.  
  897.         return $blocklist;
  898.     // end func findBlocks
  899.  
  900.     /**
  901.      * Reads a file from disk and returns its content.
  902.      * @param    string    Filename
  903.      * @return   string    Filecontent
  904.      */
  905.     function getFile($filename)
  906.     {
  907.         if ($filename{0== '/' && substr($this->fileRoot-1== '/'{
  908.             $filename substr($filename1);
  909.         }
  910.  
  911.         $filename $this->fileRoot . $filename;
  912.  
  913.         if (!($fh @fopen($filename'r'))) {
  914.             $this->err[= PEAR::raiseError(
  915.                         $this->errorMessage(IT_TPL_NOT_FOUND.
  916.                         ': "' .$filename .'"',
  917.                         IT_TPL_NOT_FOUND
  918.                     );
  919.             return "";
  920.         }
  921.  
  922.         $fsize filesize($filename);
  923.         if ($fsize < 1{
  924.             fclose($fh);
  925.             return '';
  926.         }
  927.  
  928.         $content fread($fh$fsize);
  929.         fclose($fh);
  930.  
  931.         return preg_replace(
  932.             "#<!-- INCLUDE (.*) -->#ime""\$this->getFile('\\1')"$content
  933.         );
  934.     // end func getFile
  935.  
  936.     /**
  937.      * Adds delimiters to a string, so it can be used as a pattern
  938.      * in preg_* functions
  939.      *
  940.      * @param string 
  941.      * @return string 
  942.      */
  943.     function _addPregDelimiters($str)
  944.     {
  945.         return '@' $str '@';
  946.     }
  947.  
  948.    /**
  949.     * Replaces an opening delimiter by a special string
  950.     *
  951.     * @param  string 
  952.     * @return string 
  953.     */
  954.     function _preserveOpeningDelimiter($str)
  955.     {
  956.         return (false === strpos($str$this->openingDelimiter))?
  957.                 $str:
  958.                 str_replace(
  959.                     $this->openingDelimiter,
  960.                     $this->openingDelimiter .
  961.                     '%preserved%' $this->closingDelimiter,
  962.                     $str
  963.                 );
  964.     }
  965.  
  966.     /**
  967.      * Return a textual error message for a IT error code
  968.      *
  969.      * @param integer $value error code
  970.      *
  971.      * @return string error message, or false if the error code was
  972.      *  not recognized
  973.      */
  974.     function errorMessage($value$blockname '')
  975.     {
  976.         static $errorMessages;
  977.         if (!isset($errorMessages)) {
  978.             $errorMessages = array(
  979.                 IT_OK                       => '',
  980.                 IT_ERROR                    => 'unknown error',
  981.                 IT_TPL_NOT_FOUND            => 'Cannot read the template file',
  982.                 IT_BLOCK_NOT_FOUND          => 'Cannot find this block',
  983.                 IT_BLOCK_DUPLICATE          => 'The name of a block must be'.
  984.                                                ' uniquewithin a template.'.
  985.                                                ' Found "' $blockname '" twice.'.
  986.                                                'Unpredictable results '.
  987.                                                'may appear.',
  988.                 IT_UNKNOWN_OPTION           => 'Unknown option'
  989.             );
  990.         }
  991.  
  992.         if (PEAR::isError($value)) {
  993.             $value $value->getCode();
  994.         }
  995.  
  996.         return isset($errorMessages[$value]?
  997.                 $errorMessages[$value$errorMessages[IT_ERROR];
  998.     }
  999. // end class IntegratedTemplate
  1000. ?>

Documentation generated on Mon, 11 Mar 2019 14:43:07 -0400 by phpDocumentor 1.4.4. PEAR Logo Copyright © PHP Group 2004.