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.4 2005/01/22 06:32:19 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.             if ($t->token == 'Php'{
  169.                 continue;
  170.             }
  171.             $i++;
  172.             $this->tokens[$i$tokenizer->value;
  173.             $this->tokens[$i]->id = $i;
  174.             
  175.             
  176.             
  177.             //print_r($_HTML_TEMPLATE_FLEXY_TOKEN['tokens'][$i]);
  178.              
  179.         }
  180.         //echo "BUILT TOKENS";
  181.     }
  182.     
  183.     
  184.     /**
  185.     * Replace blocks of text which have {tags} in them with place holders
  186.     * for use with sprintf.
  187.     *
  188.     * This is to enable translation tools to grab the content.
  189.     *
  190.     * This is a little out of place here as it depends on the existance of token_text.
  191.     *
  192.     *
  193.     * @return   none 
  194.     * @access   public
  195.     */
  196.   
  197.     function makeSprintf()
  198.     {
  199.         $res &$this->tokens;
  200.        
  201.         // DEBUG DUMPTING : foreach($res as $k) {  $k->dump(); }
  202.         
  203.         
  204.         $stack = array();
  205.         $total count($this->tokens);
  206.         
  207.         
  208.         // merge variables into strings. so printf && gettext work.
  209.         // adds a $element->argVars[] to the Object
  210.         // ??? should this be in here!!!!
  211.         
  212.         for($i=1;$i<$total;$i++{
  213.             if (!isset($res[$i])) {
  214.                 continue;
  215.             }
  216.             if (!is_a($res[$i],'HTML_Template_Flexy_Token_Text')) {
  217.                 continue;
  218.             }
  219.             if (!$res[$i]->isWord()) {
  220.                 continue;
  221.             }
  222.             $res[$i]->backSearch($this->tokens);
  223.             $i $res[$i]->forwardSearch($this->tokens);
  224.         }
  225.          
  226.         
  227.     }
  228.     
  229.     /**
  230.     * Match the opening and closing tags eg. </B> is the closer of <B>
  231.     *
  232.     * aliases the ->close to the tokens[{closeid}] element
  233.     * 
  234.     * @return   none 
  235.     * @access   public
  236.     */
  237.   
  238.     function matchClosers(
  239.     {
  240.         $res &$this->tokens;
  241.         $total count($this->tokens);
  242.         // connect open  and close tags.
  243.         
  244.         // this is done by having a stack for each of the tag types..
  245.         // then removing it when it finds the closing one
  246.         // eg.
  247.         //  <a href=""><img src=""></a>
  248.         //  ends up with a stack for <a>'s and a stack for <img>'s
  249.         //
  250.         //
  251.         //
  252.         
  253.        
  254.         for($i=1;$i<$total;$i++{
  255.             //echo "Checking TAG $i\n";
  256.             if (!isset($res[$i]->tag)) {
  257.                 continue;
  258.             }
  259.             $tag strtoupper($res[$i]->tag);
  260.             if ($tag{0!= '/'// it's not a close tag..
  261.                   
  262.                 
  263.                 if (!isset($stack[$tag])) {
  264.                     $npos $stack[$tag]['pos'= 0;
  265.                 else {
  266.                     $npos = ++$stack[$tag]['pos'];
  267.                 }
  268.                 $stack[$tag][$npos$i;
  269.                 continue;
  270.             }
  271.         
  272.             //echo "GOT END TAG: {$res[$i]->tag}\n";
  273.             $tag substr($tag,1);
  274.             if (!isset($stack[$tag]['pos'])) {
  275.                 continue; // unmatched
  276.             }
  277.             
  278.             $npos $stack[$tag]['pos'];
  279.             if (!isset($stack[$tag][$npos])) {
  280.                 // stack is empty!!!
  281.                 continue;
  282.             }
  283.             // alias closer to opener..
  284.             $this->tokens[$stack[$tag][$npos]]->close = &$this->tokens[$i];
  285.             $stack[$tag]['pos']--;
  286.             // take it off the stack so no one else uses it!!!
  287.             unset($stack[$tag][$npos]);
  288.             if ($stack[$tag]['pos'< 0{
  289.                 // too many closes - just ignore it..
  290.                 $stack[$tag]['pos'= 0;
  291.             }
  292.             continue;
  293.  
  294.             // new entry on stack..
  295.           
  296.             
  297.            
  298.         }
  299.                 
  300.         // create a dummy close for the end
  301.         $i $total;
  302.         $this->tokens[$i= new HTML_Template_Flexy_Token;
  303.         $this->tokens[$i]->id = $total;
  304.         $this->tokens[0]->close = &$this->tokens[$i];
  305.         
  306.         // now is it possible to connect children...
  307.         // now we need to GLOBALIZE!! - 
  308.    
  309.     }
  310.     
  311.    /**
  312.     * Build the child array for each element.
  313.     * RECURSIVE FUNCTION!!!!
  314.     *
  315.     * does not move tokens, just aliases the child nodes into the token array.
  316.     *
  317.     * @param   int  id of node to add children to.
  318.     *
  319.     * @access   public
  320.     */
  321.     function buildChildren($id
  322.     {
  323.       
  324.         
  325.         $base &$this->tokens[$id];
  326.         $base->children = array();
  327.         $start $base->id +1;
  328.         $end $base->close->id;
  329.         
  330.         for ($i=$start$i<$end$i++{
  331.             //echo "{$base->id}:{$base->tag} ADDING {$i}{$_HTML_TEMPLATE_FLEXY_TOKEN['tokens'][$i]->tag}<BR>";
  332.             //if ($base->id == 1176) {
  333.             //    echo "<PRE>";print_r($_HTML_TEMPLATE_FLEXY_TOKEN['tokens'][$i]);
  334.             // }
  335.             $base->children[&$this->tokens[$i];
  336.             if (isset($this->tokens[$i]->close)) {
  337.             
  338.                 // if the close id is greater than my id - ignore it! - 
  339.                 if ($this->tokens[$i]->close->id > $end{
  340.                     continue;
  341.                 }
  342.                 $this->buildChildren($i);
  343.                 $i $this->tokens[$i]->close->id;
  344.             }
  345.         }
  346.     }
  347.             
  348.          
  349.     /**
  350.     * Locates Flexy:startchildren etc. if it is used.
  351.     * and returns the base of the tree. (eg. otherwise token[0].
  352.     *
  353.     * @return  HTML_Template_Flexy_Token (base of tree.)
  354.     * @access   public
  355.     */
  356.     
  357.     function returnStart({
  358.     
  359.         foreach(array_keys($this->tokensas $i{
  360.             switch(true{
  361.                 case isset($this->tokens[$i]->ucAttributes['FLEXYSTART']):
  362.                 case isset($this->tokens[$i]->ucAttributes['FLEXY:START']):
  363.                     $this->tokens[$i]->removeAttribute('FLEXY:START');
  364.                     $this->tokens[$i]->removeAttribute('FLEXYSTART');
  365.                     return $this->tokens[$i];
  366.                 case isset($this->tokens[$i]->ucAttributes['FLEXYSTARTCHILDREN']):
  367.                 case isset($this->tokens[$i]->ucAttributes['FLEXY:STARTCHILDREN']):
  368.                     $this->tokens[0]->children = $this->tokens[$i]->children;
  369.                     return $this->tokens[0];
  370.             }
  371.         }
  372.         return $this->tokens[0];
  373.        
  374.     
  375.     }
  376.     
  377. }

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