Location: PHPKode > scripts > BBEngine > bbengine/Parse.php
<?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;
    }
}
?>
Return current item: BBEngine