home *** CD-ROM | disk | FTP | other *** search
/ Cricao de Sites - 650 Layouts Prontos / WebMasters.iso / Servidores / xampp-win32-1.6.7-installer.exe / php / PEAR / HTML / Template / Flexy / Tree.php < prev   
Encoding:
PHP Script  |  2008-07-02  |  10.7 KB  |  333 lines

  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.5 2005/01/31 06:57:44 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->matchClosers();
  118.         $t->buildChildren(0);
  119.         //new Gtk_VarDump($_HTML_TEMPLATE_FLEXY_TOKEN['tokens'][0]);
  120.         
  121.         $GLOBALS[__CLASS__]['cache'][$md5] = $t->returnStart();
  122.         return $GLOBALS[__CLASS__]['cache'][$md5];
  123.  
  124.     }
  125.     
  126.     /**
  127.     * The core tokenizing part - runs the tokenizer on the data,
  128.     * and stores the results in $this->tokens[]
  129.     *
  130.     * @param   string               Data to tokenize
  131.     * 
  132.     * @return   none | PEAR::Error
  133.     * @access   public|private
  134.     * @see      see also methods.....
  135.     */
  136.   
  137.     
  138.     function tokenize($data) {
  139.         require_once 'HTML/Template/Flexy/Tokenizer.php';
  140.         $tokenizer =  &HTML_Template_Flexy_Tokenizer::construct($data,$this->options);
  141.         
  142.         // initialize state - this trys to make sure that
  143.         // you dont do to many elses etc.
  144.        
  145.         //echo "RUNNING TOKENIZER";
  146.         // step one just tokenize it.
  147.         $i=1;
  148.         while ($t = $tokenizer->yylex()) {  
  149.             
  150.             if ($t == HTML_TEMPLATE_FLEXY_TOKEN_ERROR) {
  151.                 return HTML_Template_Flexy::raiseError(
  152.                     array(
  153.                             "HTML_Template_Flexy_Tree::Syntax error in File: %s (Line %s)\n".
  154.                             "Tokenizer Error: %s\n".
  155.                             "Context:\n\n%s\n\n >>>>>> %s\n",
  156.                         $this->options['filename'], $tokenizer->yyline ,
  157.                         $tokenizer->error,
  158.                         htmlspecialchars(substr($tokenizer->yy_buffer,0,$tokenizer->yy_buffer_end)),
  159.                         htmlspecialchars(substr($tokenizer->yy_buffer,$tokenizer->yy_buffer_end,100))
  160.                     )
  161.                     ,HTML_TEMPLATE_FLEXY_ERROR_SYNTAX ,HTML_TEMPLATE_FLEXY_ERROR_DIE);
  162.             }
  163.                 
  164.             if ($t == HTML_TEMPLATE_FLEXY_TOKEN_NONE) {
  165.                 continue;
  166.             }
  167.             if ($t->token == 'Php') {
  168.                 continue;
  169.             }
  170.             $i++;
  171.             $this->tokens[$i] = $tokenizer->value;
  172.             $this->tokens[$i]->id = $i;
  173.             
  174.             
  175.             
  176.             //print_r($_HTML_TEMPLATE_FLEXY_TOKEN['tokens'][$i]);
  177.              
  178.         }
  179.         //echo "BUILT TOKENS";
  180.     }
  181.     
  182.     
  183.      
  184.     
  185.     /**
  186.     * Match the opening and closing tags eg. </B> is the closer of <B>
  187.     *
  188.     * aliases the ->close to the tokens[{closeid}] element
  189.     * 
  190.     * @return   none
  191.     * @access   public
  192.     */
  193.   
  194.     function matchClosers() 
  195.     {
  196.         $res = &$this->tokens;
  197.         $total = count($this->tokens);
  198.         // connect open  and close tags.
  199.         
  200.         // this is done by having a stack for each of the tag types..
  201.         // then removing it when it finds the closing one
  202.         // eg.
  203.         //  <a href=""><img src=""></a>
  204.         //  ends up with a stack for <a>'s and a stack for <img>'s
  205.         //
  206.         //
  207.         //
  208.         
  209.        
  210.         for($i=1;$i<$total;$i++) {
  211.             //echo "Checking TAG $i\n";
  212.             if (!isset($res[$i]->tag)) {
  213.                 continue;
  214.             }
  215.             $tag = strtoupper($res[$i]->tag);
  216.             if ($tag{0} != '/') { // it's not a close tag..
  217.                   
  218.                 
  219.                 if (!isset($stack[$tag])) {
  220.                     $npos = $stack[$tag]['pos'] = 0;
  221.                 } else {
  222.                     $npos = ++$stack[$tag]['pos'];
  223.                 }
  224.                 $stack[$tag][$npos] = $i;
  225.                 continue;
  226.             }
  227.         
  228.             //echo "GOT END TAG: {$res[$i]->tag}\n";
  229.             $tag = substr($tag,1);
  230.             if (!isset($stack[$tag]['pos'])) {
  231.                 continue; // unmatched
  232.             }
  233.             
  234.             $npos = $stack[$tag]['pos'];
  235.             if (!isset($stack[$tag][$npos])) {
  236.                 // stack is empty!!!
  237.                 continue;
  238.             }
  239.             // alias closer to opener..
  240.             $this->tokens[$stack[$tag][$npos]]->close = &$this->tokens[$i];
  241.             $stack[$tag]['pos']--;
  242.             // take it off the stack so no one else uses it!!!
  243.             unset($stack[$tag][$npos]);
  244.             if ($stack[$tag]['pos'] < 0) {
  245.                 // too many closes - just ignore it..
  246.                 $stack[$tag]['pos'] = 0;
  247.             }
  248.             continue;
  249.  
  250.             // new entry on stack..
  251.           
  252.             
  253.            
  254.         }
  255.                 
  256.         // create a dummy close for the end
  257.         $i = $total;
  258.         $this->tokens[$i] = new HTML_Template_Flexy_Token;
  259.         $this->tokens[$i]->id = $total;
  260.         $this->tokens[0]->close = &$this->tokens[$i];
  261.         
  262.         // now is it possible to connect children...
  263.         // now we need to GLOBALIZE!! - 
  264.    
  265.     }
  266.     
  267.    /**
  268.     * Build the child array for each element.
  269.     * RECURSIVE FUNCTION!!!!
  270.     *
  271.     * does not move tokens, just aliases the child nodes into the token array.
  272.     *
  273.     * @param   int  id of node to add children to.
  274.     *
  275.     * @access   public
  276.     */
  277.     function buildChildren($id) 
  278.     {
  279.       
  280.         
  281.         $base = &$this->tokens[$id];
  282.         $base->children = array();
  283.         $start = $base->id +1;
  284.         $end = $base->close->id;
  285.         
  286.         for ($i=$start; $i<$end; $i++) {
  287.             //echo "{$base->id}:{$base->tag} ADDING {$i}{$_HTML_TEMPLATE_FLEXY_TOKEN['tokens'][$i]->tag}<BR>";
  288.             //if ($base->id == 1176) {
  289.             //    echo "<PRE>";print_r($_HTML_TEMPLATE_FLEXY_TOKEN['tokens'][$i]);
  290.             // }
  291.             $base->children[] = &$this->tokens[$i];
  292.             if (isset($this->tokens[$i]->close)) {
  293.             
  294.                 // if the close id is greater than my id - ignore it! - 
  295.                 if ($this->tokens[$i]->close->id > $end) {
  296.                     continue;
  297.                 }
  298.                 $this->buildChildren($i);
  299.                 $i = $this->tokens[$i]->close->id;
  300.             }
  301.         }
  302.     }
  303.             
  304.          
  305.     /**
  306.     * Locates Flexy:startchildren etc. if it is used.
  307.     * and returns the base of the tree. (eg. otherwise token[0].
  308.     *
  309.     * @return  HTML_Template_Flexy_Token (base of tree.)
  310.     * @access   public
  311.     */
  312.     
  313.     function returnStart() {
  314.     
  315.         foreach(array_keys($this->tokens) as $i) {
  316.             switch(true) {
  317.                 case isset($this->tokens[$i]->ucAttributes['FLEXYSTART']):
  318.                 case isset($this->tokens[$i]->ucAttributes['FLEXY:START']):
  319.                     $this->tokens[$i]->removeAttribute('FLEXY:START');
  320.                     $this->tokens[$i]->removeAttribute('FLEXYSTART');
  321.                     return $this->tokens[$i];
  322.                 case isset($this->tokens[$i]->ucAttributes['FLEXYSTARTCHILDREN']):
  323.                 case isset($this->tokens[$i]->ucAttributes['FLEXY:STARTCHILDREN']):
  324.                     $this->tokens[0]->children = $this->tokens[$i]->children;
  325.                     return $this->tokens[0];
  326.             }
  327.         }
  328.         return $this->tokens[0];
  329.        
  330.     
  331.     }
  332.     
  333. }