Location: PHPKode > projects > Simple Way to Usenet > swun/libs/core/parser/tpl_parser.class.php
<?php
/**
 *  
 * @author  Benjamin Gillissen <hide@address.com>
 * 
 *	**************************************************************

	Copyright (C) 2009  Benjamin Gillissen
	
	This program is free software; you can redistribute it and/or
	modify it under the terms of the GNU General Public License
	as published by the Free Software Foundation; either version 2
	of the License, or (at your option) any later version.
	
	This program is distributed in the hope that it will be useful,
	but WITHOUT ANY WARRANTY; without even the implied warranty of
	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
	GNU General Public License for more details at:
	http://www.gnu.org/copyleft/gpl.html

 *	**************************************************************
 */
class tpl_parser {
	
	private static $detected;
	
	protected $HDL, $spos, $epos, $depth, $of;
	
	protected $blocks=Array();
	private $last_block_offset;
	
	
	protected $otag;		//open_tag
	protected $ltag;		//logic_tag
	protected $ctag;		//close_tag
	
	public function __construct($hdl, $spos, $epos, $depth, $of){
		//echo "$depth] New tpl_parser @ $spos:$epos<br/>\n";
		$this->HDL = $hdl;
		$this->spos = $spos;
		$this->epos = $epos;
		$this->depth = $depth;
		$this->of = $of;
		$this->last_block_offset=Array(0, $spos);
	}
	
	
	private function cleanup_window($buf, $size){
		if ( strlen($buf) >  $size ){ $buf = substr($buf, 1);	}
		return $buf;
	}
	
	public function plugin(){ return $this->otag->plugin(); }
	
	public function detect_block($type=NULL){
		//echo "$this->depth] Recursive Blocks Detection between $this->spos:$this->epos<br/>\n";
		fseek($this->HDL, $this->spos);
		$buf='';
		if ( $type !== NULL ){ $ctag = block_tag::open().$type.'-END'.block_tag::close(); }
		while( TRUE !== feof($this->HDL) ){
			$char = fread($this->HDL, 1);
			$pos = ftell($this->HDL);
			$buf .= $char;
			$buf = $this->cleanup_window($buf, block_tag::openlen());
			if ( $buf === block_tag::open() ){
				$buf='';
				$spos = ($pos - block_tag::openlen());
				$tag = new block_tag($this->HDL, $spos);
				if ( FALSE === $tag->detect() ){
					//echo $this->depth."] Syntax Error, malformed tag has been found @ ".$spos."<br/>\n";
					errors::raise("Syntax Error, malformed tag has been found @ ".$spos, CORE_LOG_ERROR, 'TPL');
					return FALSE;
				}
				if ( $tag->type() ==  'open' ){
					//new blocks recursive...
					//echo $this->depth."] OPEN tag has been found @ ".$spos."<br/>\n";
					if ( $spos !== $this->last_block_offset[1] ){ 
						//echo $this->depth."] ha, some content between last block end and this open_tag, we append a block_content ($this->depth)<br/>\n";
						$this->blocks[] = new tpl_content($this->HDL, $this->last_block_offset[1], $spos, $this->depth, $this->of);
						//echo $this->depth."] Updating, last detected block offset to (".$this->last_block_offset[1].":$spos)<br/>\n";
						$this->last_block_offset = Array($this->last_block_offset[1], $spos);
					}
					$blk = new tpl_block($tag);
					if ( FALSE === $blk->load_plugin($this->HDL, $this->epos, ($this->depth+1), $this->of) ){
						errors::raise("Block Plugin could not be loaded at $spos", CORE_LOG_ERROR, 'TPL');
						return FALSE;
					}
					if ( FALSE === $blk->detect_recur() ){ return FALSE; }
					$this->blocks[] = $blk;
					//echo $this->depth."] Updating, last detected block offset to ($spos:".$blk->end().")<br/>\n";
					$this->last_block_offset = Array($spos, $blk->end() );
					
				} elseif ( $tag->type() ==  'close' AND isset($ctag) ){
					
					if ( $tag->read() === $ctag ){
						$this->epos = $tag->start(); 
						$this->ctag = $tag;
						//echo $this->depth."] CLOSE tag has been found @ ".$tag->start().", updating epos: $this->epos<br/>\n";
						break;	
					}
					
				}
			}
		}
		if ( isset($ctag) AND !isset($this->ctag) ){
			echo "opened but not closed !...<br/>\n";
			return FALSE;
		} elseif ( count($this->blocks) == 0 ){
			//echo "$this->depth] No Blocks Detected between $this->spos:$this->epos <br/>\n";
			$this->blocks[] = new tpl_content($this->HDL, $this->spos, $this->epos, $this->depth, $this->of);
		} else {
			$k = count($this->blocks) - 1;
			$e = $this->blocks[$k]->end();
			if ( $e !== $this->epos ){
				//echo "$this->depth] Last detected block do not ends at end ;), new block_content<br/>\n";
				$this->blocks[] = new tpl_content($this->HDL, $this->blocks[$k]->end(), $this->epos, $this->depth, $this->of);
			}
		}
		return TRUE;
	}
	
	public function parse($l, $g=null, $return=FALSE){
		//echo "Start Parsing loaded blocks between $this->spos:$this->epos<br/>\n";
		$buf='';
		foreach($this->blocks as $blk ){ 
			$buf .= $blk->parse($l, $g, $return);
			if ( !$return ){ $buf=''; }
		}
		if ( $return ){ return $buf; }
		return TRUE;
	}
	
	public function parse_before($l, $g, $return, $bref){
		//echo "$this->depth] Start Parsing loaded blocks before $bref<br/>\n";
		$buf='';
		foreach($this->blocks as $k => $blk ){
			if ( $blk->ref() == $bref OR tpl_parser::isdetected($bref) ){
				//echo "$this->depth] Block $bref has been detected stoping here.<br/>\n";
				self::setdetected($bref);
				break; 
			} elseif ( ! self::isdetected($bref) ){
				//echo "$this->depth] Parsing block $k, before block $bref<br/>\n";
				$buf .= $blk->parse_before($l, $g, $return, $bref);
				if ( !$return ){ $buf=''; }
			} else {
				//echo "$this->depth] Skipping Parse of block $k, block $bref has been detected<br/>\n";
			}
		}
		if ( $return ){ return $buf; }
		return TRUE;
	}
	
	public function parse_once($l, $g, $return, $bref, $data, $key){
		//echo "$this->depth] Start Parsing block Array $bref Once<br/>\n";
		$buf='';
		foreach($this->blocks as $k => $blk ){
			if ( $blk->ref() == $bref ){
				//echo "$this->depth] Parsing Once Block $bref<br/>\n";
				$buf = $blk->parse_once($l, $g, $return, $bref, $data, $key);
				break; 
			} elseif ( $blk->plugin() == 'logic' OR $blk->plugin() == 'array' ){
				//echo "$this->depth] Sub Parse_once call<br/>\n";
				$buf .= $blk->parse_once($l, $g, $return, $bref, $data, $key);
				if ( !$return ){ $buf=''; }
			} else {
				//echo "$this->depth] Skipping Parse of block $k, not array or not logic<br/>\n";
			}
		}
		if ( $return ){ return $buf; }
		return TRUE;
	}
	
	public function parse_after($l, $g, $return, $bref){
		//echo "$this->depth] Start Parsing loaded blocks after $bref<br/>\n";
		$buf='';
		foreach($this->blocks as $blk ){
			if ($blk->ref() == $bref ){
				self::setdetected($bref);
			} elseif ( self::isdetected($bref) ){
				$buf .= $blk->parse($l, $g, $return);
				if ( !$return ){ $buf=''; }
			} elseif ( $blk->plugin() == 'array' OR $blk->plugin() == 'logic' ){
				$buf .= $blk->parse_after($l, $g, $return, $bref);
				if ( !$return ){ $buf=''; }
			}
		}
		if ( $return ){ return $buf; }
		return TRUE;
	}
	
	public function parse_between($l, $g, $return, $sbref, $ebref){
		echo "$this->depth] Start Parsing loaded blocks after $sbref and before $ebref<br/>\n";
		$buf='';
		foreach($this->blocks as $blk ){
			if ($blk->ref() == $sbref ){
				self::setdetected($sbref);
			} elseif($blk->ref() == $ebref ){
				self::setdetected($ebref);
			} elseif ( $blk->plugin() == 'array' OR $blk->plugin() == 'logic' ){
				$buf .= $blk->parse_between($l, $g, $return, $sbref, $ebref);
				if ( !$return ){ $buf=''; }
			} elseif ( self::isdetected($sbref) AND ! self::isdetected($ebref) ){
				$buf .= $blk->parse($l, $g, $return);
				if ( !$return ){ $buf=''; }
			}
		}
		if ( $return ){ return $buf; }
		return TRUE;
	}
	
	public static function isdetected($bref){
		return isset(self::$detected[$bref]);
	}
	
	public static function setdetected($bref){
		self::$detected[$bref] = TRUE;
	}
	
	public static function resetdetect($bref){
		unset(self::$detected[$bref]);
	}
}
Return current item: Simple Way to Usenet