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

Source for file Tree.php

Documentation is available at Tree.php

  1. <?php
  2. /* vim: set expandtab tabstop=4 shiftwidth=4: */
  3. // +----------------------------------------------------------------------+
  4. // | PHP Version 4                                                        |
  5. // +----------------------------------------------------------------------+
  6. // | Copyright (c) 1997-2002 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:  Alan Knowles <alan@akbkhome.com>                           |
  17. // +----------------------------------------------------------------------+
  18. //
  19. // $Id: Tree.php,v 1.3 2004/07/29 04:26:23 alan_k Exp $
  20. //
  21. // The Html Tree Component of Flexy
  22. // Designed to be used on it's own
  23. // 
  24. //
  25. //
  26. // The concept:
  27. // - it builds a big tokens[] array : 
  28. // - filters "Text with {placeholders}" into sprintf formated strings.
  29. // - matches closers to openers eg. token[4]->close = &token[5];
  30. // - it aliases the tokens into token[0] as children as a tree
  31. // - locates the base of the file. (flexy:startchildren.
  32. // returns a nice tree..
  33.  
  34.  
  35. class HTML_Template_Flexy_Tree {
  36.  
  37.     /**
  38.     * Options for Tree:
  39.     * 'ignore'          =>   dont change {xxxX} into placeholders?
  40.     * 'filename'        =>   filename of file being parsed. (for error messages.)
  41.     * 'ignore_html'     =>   return <html> elements as strings.
  42.     * 'ignore_php'      =>   DELETE/DESTROY any php code in the original template.
  43.     */
  44.   
  45.     var $options = array(
  46.         'ignore'        => false// was flexyIgnore
  47.         'filename'      => false,
  48.         'ignore_html'   => false,
  49.         'ignore_php'    => true,
  50.     );
  51.     
  52.         
  53.     /**
  54.     * Array of all tokens (eg. nodes / text / tags etc. )
  55.     * All nodes have ID's
  56.     *
  57.     * eg.
  58.     *   <b>some text</b>
  59.     *  [0] => Token_Tag::
  60.     *         tagname = '<b>'
  61.     *         children = array( &tag[1] );
  62.               close  = &tag[2];
  63.     *  [1] => Token_Text::'some test'
  64.     *  [2] => Token_Tag::
  65.     *         tagname = '</b>';
  66.     *
  67.     *
  68.     *  under normal situations, the tree is built into node[0], the remaining nodes are referenced by alias.
  69.     *  if caching is used (the nodes > 0 will not exist, and everything will just be a child of node 0.
  70.     *
  71.     *
  72.     *
  73.     * @var array 
  74.     * @access public
  75.     */
  76.     
  77.     var $tokens     = array();
  78.     var $strings    = array();
  79.         
  80.     
  81.     
  82.     
  83.     
  84.    
  85.     /**
  86.     * Run a Tokenizer and Store its results and return the tree.
  87.     * It should build a DOM Tree of the HTML
  88.     * 
  89.     * @param   string $data         data to parse.
  90.     * @param    array $options      see options array.
  91.     *
  92.     * @access   public
  93.     * @return   base token (really a dummy token, which contains the tree)
  94.     * @static
  95.     */
  96.   
  97.     function construct($data,$options=array()) 
  98.     {
  99.     
  100.         // local caching!
  101.         $md5 md5($data);
  102.         if (isset($GLOBALS[__CLASS__]['cache'][$md5])) {
  103.             return $GLOBALS[__CLASS__]['cache'][$md5];
  104.         
  105.         
  106.         $t = new HTML_Template_Flexy_Tree;
  107.         $t->options = $t->options + $options;
  108.         require_once 'HTML/Template/Flexy/Token.php';
  109.         $t->tokens = array(new HTML_Template_Flexy_Token);
  110.         $t->tokens[0]->id =0;
  111.         
  112.         // process
  113.         if (is_a($r $t->tokenize($data),'PEAR_Error')) {
  114.             return $r;
  115.         }
  116.         
  117.         $t->makeSprintf();
  118.         $t->matchClosers();
  119.         $t->buildChildren(0);
  120.         //new Gtk_VarDump($_HTML_TEMPLATE_FLEXY_TOKEN['tokens'][0]);
  121.         
  122.         $GLOBALS[__CLASS__]['cache'][$md5$t->returnStart();
  123.         return $GLOBALS[__CLASS__]['cache'][$md5];
  124.  
  125.     }
  126.     
  127.     /**
  128.     * The core tokenizing part - runs the tokenizer on the data,
  129.     * and stores the results in $this->tokens[]
  130.     *
  131.     * @param   string               Data to tokenize
  132.     * 
  133.     * @return   none | PEAR::Error
  134.     * @access   public|private
  135.     * @see      see also methods.....
  136.     */
  137.   
  138.     
  139.     function tokenize($data{
  140.         require_once 'HTML/Template/Flexy/Tokenizer.php';
  141.         $tokenizer =  &HTML_Template_Flexy_Tokenizer::construct($data,$this->options);
  142.         
  143.         // initialize state - this trys to make sure that
  144.         // you dont do to many elses etc.
  145.        
  146.         //echo "RUNNING TOKENIZER";
  147.         // step one just tokenize it.
  148.         $i=1;
  149.         while ($t $tokenizer->yylex()) {  
  150.             
  151.             if ($t == HTML_TEMPLATE_FLEXY_TOKEN_ERROR{
  152.                 return HTML_Template_Flexy::raiseError(
  153.                     array(
  154.                             "HTML_Template_Flexy_Tree::Syntax error in File: %s (Line %s)\n".
  155.                             "Tokenizer Error: %s\n".
  156.                             "Context:\n\n%s\n\n >>>>>> %s\n",
  157.                         $this->options['filename']$tokenizer->yyline ,
  158.                         $tokenizer->error,
  159.                         htmlspecialchars(substr($tokenizer->yy_buffer,0,$tokenizer->yy_buffer_end)),
  160.                         htmlspecialchars(substr($tokenizer->yy_buffer,$tokenizer->yy_buffer_end,100))
  161.                     )
  162.                     ,HTML_TEMPLATE_FLEXY_ERROR_SYNTAX ,HTML_TEMPLATE_FLEXY_ERROR_DIE);
  163.             }
  164.                 
  165.             if ($t == HTML_TEMPLATE_FLEXY_TOKEN_NONE{
  166.                 continue;
  167.             }
  168.            
  169.             $i++;
  170.             $this->tokens[$i$tokenizer->value;
  171.             $this->tokens[$i]->id = $i;
  172.             
  173.             
  174.             
  175.             //print_r($_HTML_TEMPLATE_FLEXY_TOKEN['tokens'][$i]);
  176.              
  177.         }
  178.         //echo "BUILT TOKENS";
  179.     }
  180.     
  181.     
  182.     /**
  183.     * Replace blocks of text which have {tags} in them with place holders
  184.     * for use with sprintf.
  185.     *
  186.     * This is to enable translation tools to grab the content.
  187.     *
  188.     * This is a little out of place here as it depends on the existance of token_text.
  189.     *
  190.     *
  191.     * @return   none 
  192.     * @access   public
  193.     */
  194.   
  195.     function makeSprintf()
  196.     {
  197.         $res &$this->tokens;
  198.        
  199.         // DEBUG DUMPTING : foreach($res as $k) {  $k->dump(); }
  200.         
  201.         
  202.         $stack = array();
  203.         $total count($this->tokens);
  204.         
  205.         
  206.         // merge variables into strings. so printf && gettext work.
  207.         // adds a $element->argVars[] to the Object
  208.         // ??? should this be in here!!!!
  209.         
  210.         for($i=1;$i<$total;$i++{
  211.             if (!isset($res[$i])) {
  212.                 continue;
  213.             }
  214.             if (!is_a($res[$i],'HTML_Template_Flexy_Token_Text')) {
  215.                 continue;
  216.             }
  217.             if (!$res[$i]->isWord()) {
  218.                 continue;
  219.             }
  220.             $res[$i]->backSearch($this->tokens);
  221.             $i $res[$i]->forwardSearch($this->tokens);
  222.         }
  223.          
  224.         
  225.     }
  226.     
  227.     /**
  228.     * Match the opening and closing tags eg. </B> is the closer of <B>
  229.     *
  230.     * aliases the ->close to the tokens[{closeid}] element
  231.     * 
  232.     * @return   none 
  233.     * @access   public
  234.     */
  235.   
  236.     function matchClosers(
  237.     {
  238.         $res &$this->tokens;
  239.         $total count($this->tokens);
  240.         // connect open  and close tags.
  241.         
  242.         // this is done by having a stack for each of the tag types..
  243.         // then removing it when it finds the closing one
  244.         // eg.
  245.         //  <a href=""><img src=""></a>
  246.         //  ends up with a stack for <a>'s and a stack for <img>'s
  247.         //
  248.         //
  249.         //
  250.         
  251.        
  252.         for($i=1;$i<$total;$i++{
  253.             //echo "Checking TAG $i\n";
  254.             if (!isset($res[$i]->tag)) {
  255.                 continue;
  256.             }
  257.             $tag strtoupper($res[$i]->tag);
  258.             if ($tag{0!= '/'// it's not a close tag..
  259.                   
  260.                 
  261.                 if (!isset($stack[$tag])) {
  262.                     $npos $stack[$tag]['pos'= 0;
  263.                 else {
  264.                     $npos = ++$stack[$tag]['pos'];
  265.                 }
  266.                 $stack[$tag][$npos$i;
  267.                 continue;
  268.             }
  269.         
  270.             //echo "GOT END TAG: {$res[$i]->tag}\n";
  271.             $tag substr($tag,1);
  272.             if (!isset($stack[$tag]['pos'])) {
  273.                 continue; // unmatched
  274.             }
  275.             
  276.             $npos $stack[$tag]['pos'];
  277.             if (!isset($stack[$tag][$npos])) {
  278.                 // stack is empty!!!
  279.                 continue;
  280.             }
  281.             // alias closer to opener..
  282.             $this->tokens[$stack[$tag][$npos]]->close = &$this->tokens[$i];
  283.             $stack[$tag]['pos']--;
  284.             // take it off the stack so no one else uses it!!!
  285.             unset($stack[$tag][$npos]);
  286.             if ($stack[$tag]['pos'< 0{
  287.                 // too many closes - just ignore it..
  288.                 $stack[$tag]['pos'= 0;
  289.             }
  290.             continue;
  291.  
  292.             // new entry on stack..
  293.           
  294.             
  295.            
  296.         }
  297.                 
  298.         // create a dummy close for the end
  299.         $i $total;
  300.         $this->tokens[$i= new HTML_Template_Flexy_Token;
  301.         $this->tokens[$i]->id = $total;
  302.         $this->tokens[0]->close = &$this->tokens[$i];
  303.         
  304.         // now is it possible to connect children...
  305.         // now we need to GLOBALIZE!! - 
  306.    
  307.     }
  308.     
  309.    /**
  310.     * Build the child array for each element.
  311.     * RECURSIVE FUNCTION!!!!
  312.     *
  313.     * does not move tokens, just aliases the child nodes into the token array.
  314.     *
  315.     * @param   int  id of node to add children to.
  316.     *
  317.     * @access   public
  318.     */
  319.     function buildChildren($id
  320.     {
  321.       
  322.         
  323.         $base &$this->tokens[$id];
  324.         $base->children = array();
  325.         $start $base->id +1;
  326.         $end $base->close->id;
  327.         
  328.         for ($i=$start$i<$end$i++{
  329.             //echo "{$base->id}:{$base->tag} ADDING {$i}{$_HTML_TEMPLATE_FLEXY_TOKEN['tokens'][$i]->tag}<BR>";
  330.             //if ($base->id == 1176) {
  331.             //    echo "<PRE>";print_r($_HTML_TEMPLATE_FLEXY_TOKEN['tokens'][$i]);
  332.             // }
  333.             $base->children[&$this->tokens[$i];
  334.             if (isset($this->tokens[$i]->close)) {
  335.             
  336.                 // if the close id is greater than my id - ignore it! - 
  337.                 if ($this->tokens[$i]->close->id > $end{
  338.                     continue;
  339.                 }
  340.                 $this->buildChildren($i);
  341.                 $i $this->tokens[$i]->close->id;
  342.             }
  343.         }
  344.     }
  345.             
  346.          
  347.     /**
  348.     * Locates Flexy:startchildren etc. if it is used.
  349.     * and returns the base of the tree. (eg. otherwise token[0].
  350.     *
  351.     * @return  HTML_Template_Flexy_Token (base of tree.)
  352.     * @access   public
  353.     */
  354.     
  355.     function returnStart({
  356.     
  357.         foreach(array_keys($this->tokensas $i{
  358.             switch(true{
  359.                 case isset($this->tokens[$i]->ucAttributes['FLEXYSTART']):
  360.                 case isset($this->tokens[$i]->ucAttributes['FLEXY:START']):
  361.                     $this->tokens[$i]->removeAttribute('FLEXY:START');
  362.                     $this->tokens[$i]->removeAttribute('FLEXYSTART');
  363.                     return $this->tokens[$i];
  364.                 case isset($this->tokens[$i]->ucAttributes['FLEXYSTARTCHILDREN']):
  365.                 case isset($this->tokens[$i]->ucAttributes['FLEXY:STARTCHILDREN']):
  366.                     $this->tokens[0]->children = $this->tokens[$i]->children;
  367.                     return $this->tokens[0];
  368.             }
  369.         }
  370.         return $this->tokens[0];
  371.        
  372.     
  373.     }
  374.     
  375. }

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