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 334846 2014-09-12 04:50:56Z alan_k $
  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.         $r $t->tokenize($data);
  114.         if (is_object($r&& is_a($r,'PEAR_Error')) {
  115.             return $r;
  116.         }
  117.         
  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::staticRaiseError(
  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.     
  186.     /**
  187.     * Match the opening and closing tags eg. </B> is the closer of <B>
  188.     *
  189.     * aliases the ->close to the tokens[{closeid}] element
  190.     * 
  191.     * @return   none 
  192.     * @access   public
  193.     */
  194.   
  195.     function matchClosers(
  196.     {
  197.         $res &$this->tokens;
  198.         $total count($this->tokens);
  199.         // connect open  and close tags.
  200.         
  201.         // this is done by having a stack for each of the tag types..
  202.         // then removing it when it finds the closing one
  203.         // eg.
  204.         //  <a href=""><img src=""></a>
  205.         //  ends up with a stack for <a>'s and a stack for <img>'s
  206.         //
  207.         //
  208.         //
  209.         
  210.        
  211.         for($i=1;$i<$total;$i++{
  212.             //echo "Checking TAG $i\n";
  213.             if (!isset($res[$i]->tag)) {
  214.                 continue;
  215.             }
  216.             $tag strtoupper($res[$i]->tag);
  217.             if ($tag{0!= '/'// it's not a close tag..
  218.                   
  219.                 
  220.                 if (!isset($stack[$tag])) {
  221.                     $npos $stack[$tag]['pos'= 0;
  222.                 else {
  223.                     $npos = ++$stack[$tag]['pos'];
  224.                 }
  225.                 $stack[$tag][$npos$i;
  226.                 continue;
  227.             }
  228.         
  229.             //echo "GOT END TAG: {$res[$i]->tag}\n";
  230.             $tag substr($tag,1);
  231.             if (!isset($stack[$tag]['pos'])) {
  232.                 continue; // unmatched
  233.             }
  234.             
  235.             $npos $stack[$tag]['pos'];
  236.             if (!isset($stack[$tag][$npos])) {
  237.                 // stack is empty!!!
  238.                 continue;
  239.             }
  240.             // alias closer to opener..
  241.             $this->tokens[$stack[$tag][$npos]]->close = &$this->tokens[$i];
  242.             $stack[$tag]['pos']--;
  243.             // take it off the stack so no one else uses it!!!
  244.             unset($stack[$tag][$npos]);
  245.             if ($stack[$tag]['pos'< 0{
  246.                 // too many closes - just ignore it..
  247.                 $stack[$tag]['pos'= 0;
  248.             }
  249.             continue;
  250.  
  251.             // new entry on stack..
  252.           
  253.             
  254.            
  255.         }
  256.                 
  257.         // create a dummy close for the end
  258.         $i $total;
  259.         $this->tokens[$i= new HTML_Template_Flexy_Token;
  260.         $this->tokens[$i]->id = $total;
  261.         $this->tokens[0]->close = &$this->tokens[$i];
  262.         
  263.         // now is it possible to connect children...
  264.         // now we need to GLOBALIZE!! - 
  265.    
  266.     }
  267.     
  268.    /**
  269.     * Build the child array for each element.
  270.     * RECURSIVE FUNCTION!!!!
  271.     *
  272.     * does not move tokens, just aliases the child nodes into the token array.
  273.     *
  274.     * @param   int  id of node to add children to.
  275.     *
  276.     * @access   public
  277.     */
  278.     function buildChildren($id
  279.     {
  280.       
  281.         
  282.         $base &$this->tokens[$id];
  283.         $base->children = array();
  284.         $start $base->id +1;
  285.         $end $base->close->id;
  286.         
  287.         for ($i=$start$i<$end$i++{
  288.             //echo "{$base->id}:{$base->tag} ADDING {$i}{$_HTML_TEMPLATE_FLEXY_TOKEN['tokens'][$i]->tag}<BR>";
  289.             //if ($base->id == 1176) {
  290.             //    echo "<PRE>";print_r($_HTML_TEMPLATE_FLEXY_TOKEN['tokens'][$i]);
  291.             // }
  292.             $base->children[&$this->tokens[$i];
  293.             if (isset($this->tokens[$i]->close)) {
  294.             
  295.                 // if the close id is greater than my id - ignore it! - 
  296.                 if ($this->tokens[$i]->close->id > $end{
  297.                     continue;
  298.                 }
  299.                 $this->buildChildren($i);
  300.                 $i $this->tokens[$i]->close->id;
  301.             }
  302.         }
  303.     }
  304.             
  305.          
  306.     /**
  307.     * Locates Flexy:startchildren etc. if it is used.
  308.     * and returns the base of the tree. (eg. otherwise token[0].
  309.     *
  310.     * @return  HTML_Template_Flexy_Token (base of tree.)
  311.     * @access   public
  312.     */
  313.     
  314.     function returnStart({
  315.     
  316.         foreach(array_keys($this->tokensas $i{
  317.             switch(true{
  318.                 case isset($this->tokens[$i]->ucAttributes['FLEXYSTART']):
  319.                 case isset($this->tokens[$i]->ucAttributes['FLEXY:START']):
  320.                     $this->tokens[$i]->removeAttribute('FLEXY:START');
  321.                     $this->tokens[$i]->removeAttribute('FLEXYSTART');
  322.                     return $this->tokens[$i];
  323.                 case isset($this->tokens[$i]->ucAttributes['FLEXYSTARTCHILDREN']):
  324.                 case isset($this->tokens[$i]->ucAttributes['FLEXY:STARTCHILDREN']):
  325.                     $this->tokens[0]->children = $this->tokens[$i]->children;
  326.                     return $this->tokens[0];
  327.             }
  328.         }
  329.         return $this->tokens[0];
  330.        
  331.     
  332.     }
  333.     
  334. }

Documentation generated on Mon, 11 Mar 2019 16:00:04 -0400 by phpDocumentor 1.4.4. PEAR Logo Copyright © PHP Group 2004.