<?php
/**
* This is the main Package responsable for Parsing BBCode and UnParsing
* Parsed Html supporing 4 types of parsing/unparsing tags (Direct Tags ,
* Direct Words , Indirect Non Recursive , Indirect Recursive)
* @package Parser
* @author Mohammed Yousef Bassyouni <hide@address.com>
* @license http://opensource.org/licenses/gpl-license.php GNU Public License
*/
/**
* include the configuration file
*/
require_once "Config.php";
/**
* include DB Operations Interfacing class
*/
require_once "BBE_DB_Op.php";
/**
* The Common Parsing Operations class
*/
require_once "Gen_Parsing.php";
$DBOp=new BBE_DB_Operations();
/**
* This is the BBCode Parsing class which is responsable for parsing
* 4 types of tags :-
* 1) Direct
* a) Direct Words : Directly replace words with others like
* :) =>Smile photo (html <img>)
* b) Direct Tags : Replace Html Tags with BBCode directly (text replace) like
* [b]ASD[/b] => <strong>ASD</strong>
* 2) Indirect
* a) Indirect Non Recursively : Mainpulate content in BBCode with user defined function
* Content and Arguments of BB tag is supplied to the function
* here BBCode tags can't be Nested like
* [url=http://google.com]Google[/url] => <a href="http://google.com">Google</a>
*
* b) Indirect Recursive : The Same Indirect manner with the added ability of Parsing Nested tags like
* [size=20]Big [size=40]Bigger[/size]Word[/size] => <span style="font-size: 20px;">Big<span style="font-size: 40px;">Big Label</span>Word</span>
* also lists (it's quite lenghty to be written here)
*
* also it respects thier priority of parsing allowing for dynamic tags depending on each other
* @package Parser
*/
class Parser
{
/**
* Current tag being parsed in the string
*/
public $CTag;
/**
* Instaance of General_Parsing for using it's common operations
*/
public $GParse;
/**
* Class Constructor, it just creates instance of General_Parsing and assigns it to GParse
*/
public function __construct()
{
$this->GParse=new General_Parsing();
}
/**
* An Optimization step , this function detects tags in text to be parsed
* so that it grabs them only from DB
* @param String $str String to be Parsed
*/
public function Get_used_Tags($str)
{
global $DBOp;
$Tags=array();
preg_match_all("#\[([^/][^\s\]\=]*).*?\]#s",$str,$Tags);
$Tags=array_unique($Tags[1]);
$DB_Tags=$DBOp->Get_Tags_From_Array($Tags,'Parse');
return $DB_Tags;
}
/**
* Method respnsable for Parsing indrect tags depends on calling a
* middle method with preg_replace_callback and than that method calls user
* function from DB on Content enclosed in BBCode passing it's argument's also
*
* @param Reference $str Reference to string to be parsed
* @param Array $Tag Array Representing DB row containing Tag
*/
public function Replace_Indirect_BB(&$str,$Tag)
{
$tag=preg_quote($Tag["Tag"],'#');
$this->CTag=$Tag;
if ($Tag['Recursive']==1)
$str=preg_replace_callback($this->GParse->Recursive_RE_Generator($tag,"\[","\]"),array($this,"Indirect_Replacer_Recursive"),$str);
else if($Tag['Recursive']==0)
$str=preg_replace_callback($this->GParse->Non_Recursive_RE_Generator($tag,"\[","\]"),array($this,"Indirect_Replacer_Non_Recursive"),$str);
}
/**
* a small method to generate separators for encloseing indirectly parsed tags
* @param String $Sep Separator assigned to that tag
*/
public function Generate_Separator($Sep)
{
$RSep[0]="<!-- Block_{$Sep} -->";
$RSep[1]="</!-- Block_{$Sep} -->";
return $RSep;
}
/**
* the Callback method called for parsing tags recursively
* it calls the user defined method for tag giving it two params $Args => BBcode arguments
* $Data => data enclosed by BBCode
*
* @param Array $match Matched substrings from main tobe-parsed string
*/
public function Indirect_Replacer_Recursive($match)
{
$tag=preg_quote($this->CTag["Tag"],'#');
$match[2]=preg_replace_callback($this->GParse->Recursive_RE_Generator($tag,"\[","\]"),array($this,"Indirect_Replacer_Recursive"),$match[2]);
$Args=$this->GetArgs($match[1]);
$Func=create_function('$Args,$Data',$this->CTag["Func"]);
$match[2]=$Func($Args,$match[2]);
return $this->Add_Separator($match[2]);
}
/**
* the Callback method called for parsing tags non-recursively
* it calls the user defined method for tag giving it two params $Args => BBcode arguments
* $Data => data enclosed by BBCode
*
* @param Array $match Matched substrings from main tobe-parsed string
*/
public function Indirect_Replacer_Non_Recursive($match)
{
$Args=$this->GetArgs($match[1]);
$Func=create_function('$Args,$Data',$this->CTag["Func"]);
$match[2]=$Func($Args,$match[2]);
return $this->Add_Separator($match[2]);
}
/**
* small method to extract arguments from a BBCode Tag
*
* @param String $TagOpen BBCode opening part (i.e [url=http://google.com open"New_Window"])
*/
function GetArgs($TagOpen)
{
$TagOpen=split(" ",trim($TagOpen));
$Args=array();
foreach ($TagOpen as $e)
{
$a=split("=",$e);
$Args[$a[0]]=$a[1];
}
return $Args;
}
/**
* a small method to enclose indirectly parsed tags in separators (so as to be recognized in UnParsing)
* @param String $Match String to be enclosed with Separator
*/
function Add_Separator($Match)
{
$Sep_arr=$this->Generate_Separator($this->CTag['Sep']);
$Match=$Sep_arr[0].$Match.$Sep_arr[1];
return $Match;
}
/**
* method to compare to tags in order of thier Parsing Priority
* it's used with usrot() for sorting Tags
*
* @param Array $a Tag1
* @param Array $b Tag2
*/
function Cmp_Tag_Priority($a, $b)
{
return ($a['Priority'] > $b['Priority']) ? +1 : -1;
}
/**
* The Main parsing function ,
* it loops over all tags in documents (identified by Get_used_Tags) after ordering
* them ASC in according to thier Priorities
*
* @param Reference $str reference to the string to be parsed
*/
public function Parse($str)
{
$Arr_Tags=$this->Get_used_Tags($str);
$Arr_Tags=array_merge($Arr_Tags[0],$Arr_Tags[1],$Arr_Tags[2]);
usort($Arr_Tags,array($this,"Cmp_Tag_Priority"));
//var_dump($Arr_Tags);
for ($i=0;$i<count($Arr_Tags);$i++)
{
if(isset($Arr_Tags[$i]['Word']))
{
$this->GParse->Replace_Direct_Word_BB($str,$Arr_Tags[$i]);
}
else if(isset($Arr_Tags[$i]['Func']))
{
$this->Replace_Indirect_BB($str,$Arr_Tags[$i]);
}
else
{
$this->GParse->Replace_Direct_Tag_BB($str,$Arr_Tags[$i],"Parse",array('[',']'),array('<','>'));
}
}
return $str;
}
}
?>