home *** CD-ROM | disk | FTP | other *** search
/ PC World 2001 August / PCWorld_2001-08_cd.bin / Komunikace / phptriad / phptriadsetup2-11.exe / php / pear / HTML / IT.php < prev    next >
PHP Script  |  2001-02-08  |  27KB  |  829 lines

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