为什么在我尝试扩展页面中的用户扩展时重复我的页面内容

时间:2016-08-09 15:08:31

标签: php regex template-engine

我正在编写一个模板引擎,我试图在我的模板引擎中添加一个@extends函数来处理一个文件并在运行时在我的页面中运行它:

<?php BakerApp::extends('filename.php',get_defined_vars()); ?>

上面的代码将替换为@extends('filename')和以下代码:

public function extends($BAKER_FILE_NAME,$vars){
        $BAKER_FILE_NAME.=baker::$extension;
        extract($vars);

        eval('?> '.baker::compile(file_get_contents($BAKER_FILE_NAME),0));
}

到目前为止,我的代码工作正常,但是当我在扩展文件中使用@extends时,我的代码输出如下:

Root Page RootPage>subPage RootPage>subPage RootPage>subPage RootPage>subPage RootPage>subPage RootPage>subPage RootPage>subPage RootPage>subPage RootPage>subPage RootPage>...............

虽然这应该如下:

Root Page
RootPage>subPage
rootPage>Subpage>thispage

我的页面是以下代码:

file:page.php

Root Page
@extends('app')

file:app.php

RootPage>subPage
@extends('ext')

file:ext.php

rootPage>Subpage>thispage

我的模板引擎如下:

file:baker2.class.php

<?php

function e($e){
    return htmlentities($e);
}
function mprint($array){
    echo "<br><pre>";
    print_r($array);
    echo "<br></pre>";
}
function teletype($char){
    mprint(preg_replace('~([\S\s])~', ' $1', $char));exit;
}
function write_in_file($address,$content){
    $FileHandle=fopen($address, 'w');
    fwrite($FileHandle, $content);
    fclose($FileHandle);
}

class baker
{
    public static $data;
    public static $tmp;
    public static $Current=[];
    public static $ta;
    public static $edit=true;
    public static $extension='.baker.php';
    public static $baked_extension='.baked.php';
    public static $root_of_theme=__DIR__.'/';
    public static $root_of_baked_theme=__DIR__.'/';
    public static $minify=false;
    public static $b='<?php ';
    public static $e=' ?>';
    public static $patterns=[];
    public static $func;
    public static $shortcuts;
    public static $Functions;
    public static $PshortCuts;
    public static $blocks;
    public static $shorttags;
    public static $baked_file_address='';
    function addPart($pattern,$replace){
        self::$patterns[$pattern]=$replace;
    }
    function addFunc(){
        $args=func_get_args();
        foreach ($args as $value) {
            self::$func[]=$value;
        }
    }
    function addFunction($FunctionName,$FunctionRe){
        if(is_array($FunctionName)){
            foreach ($FunctionName as $name) {
                self::$Functions[$name]=$FunctionRe;
            }
        }else{
            self::$Functions[$FunctionName]=$FunctionRe;
        }
    }
    function addShortCut($shortCutName,$ShortCutRe){
        if(is_array($shortCutName)){
            foreach ($shortCutName as $name) {
                self::$shortcuts[$name]=$ShortCutRe;
            }
        }else{
            self::$shortcuts[$shortCutName]=$ShortCutRe;
        }
    }
    function addShortTag($shortTagName,$ShortTagRe){
        if(is_array($shortTagName)){
            foreach ($shortTagName as $name) {
                self::$shorttags[$name]=$ShortTagRe;
            }
        }else{
            self::$shorttags[$shortTagName]=$ShortTagRe;
        }
    }
    function addBlock($blockName,$blockFunc){
    if(is_array($blockName)){
            foreach ($blockName as $name) {
                self::$blocks[$name]=$blockFunc;
            }
        }else{
            self::$blocks[$blockName]=$blockFunc;
        }
    }
    function ReplaceKeyToValue($string,$array){
        foreach ($array as $key => $value) {
            $string=str_replace($key, $value, $string);
        }
        return $string;
    }
    function baker($vals=[])
    {
        baker::addFunc(
            // function(){
            //  $extend='~(@extends\((?:\'|")(.+)(?:\'|")\))~';
            //  for(;;){
            //      if(preg_match($extend, baker::$tmp, $matches)){
            //          baker::$tmp = str_replace($matches[0],file_get_contents(baker::$root_of_theme.$matches[2]),baker::$tmp);
            //      }else{
            //          break;
            //      }
            //  }
            // }
            //,function(){
            //      $getsection='~@(?:GetSection|yield)\((?:\'|")(.+)(?:\'|")\)~';
            //      for(;;){
            //          if(preg_match($getsection, baker::$tmp, $matches)){
            //              baker::$tmp = str_replace($matches[0],baker::$data[$matches[1]],baker::$tmp);
            //          }else{
            //              break;
            //          }
            //      }
            // }
        );
        self::$data=$vals;
    }
    function assign($assign,$val=false)
    {
        if($val){
            self::$data[$assign]=$val;
        }else{

        }
    }

    function minify($file){
        // echo  "<pre>".preg_replace('~([a-zA-Z0-9_\<\>\[\]\?])~', ' $1', $file)."</pre>";exit;
        $minifyPattern=[
            '~[ ]+~'=>'',
            '~[ ]+~'=>' ',
            '~[
            ]~'=>'',
            '~\?\>[ ]+~'=>'?>&-SPACE_$#',
            '~[ ]+<\?php~'=>'&-SPACE_$#<?php',
            '~[ ]*\:[ ]*~'=>':',
            '~[ ]*\=[ ]*~'=>'=',
            '~[ ]*\{[ ]*~'=>'{',
            '~[ ]*\}[ ]*~'=>'}',
            '~[ ]*\[[ ]*~'=>'[',
            '~[ ]*\][ ]*~'=>']',
            '~[ ]*\'[ ]*~'=>'\'',
            '~[ ]*\"[ ]*~'=>'"',
            '~[ ]*<[ ]*~' =>'<',
            '~[ ]*>[ ]*~' =>'>',
            '~<\!\-\-([a-zA-Z0-9_ \-\<\>\\\(\)/"\'\.=&#ضصثقفغعهخحجچپشسیبلاتنمکگظطزرذدئوءأإؤژيةَُِّۀآـ«»:,؛،ريالًٌٍ\+])\-\->~'=>'',
            '~<\?php\}\?>~'=>'<?php } ?>',
            '~<\?php\}~'   =>'<?php }',
            '~&-SPACE_\$#~'=>' ',
        ];
        $ptr=[];
        $ptrRe=[];
        foreach ($minifyPattern as $key => $value) {
            $ptr[]=$key;
            $ptrRe[]=$value;
        }
        $file=preg_replace($ptr, $ptrRe, $file);
        return $file;
    }
    function loop($template_source)
    {
        $b='<?php ';
        $e=' ?>';


        // preg_match($replace_before_exe, $tmp,$matches);
        if(self::$func){
            foreach (self::$func as $key => $value) {
                $value();
            }
        }



        /**
        *
        *   @functions e.g @funcName
        *
        */
        $pt='~@(\w+)\s*(?:\((.*?)\)(?:\{(.*?)})?\s*(?=$|\n|;))?~';

        preg_match_all($pt,$template_source,$matchFunction);
        $i=0;
        foreach ($matchFunction[1] as $FuncName) {
            $FuncCode       = $matchFunction[0][$i];
            $FuncArgs       = $matchFunction[2][$i];
            $FuncOutSideArg = $matchFunction[3][$i];
            $ArgsArray=[];

            for (;;) {
                /*
                    past match
                    '~\s*((?:\w+\s*\([\s\S]*?\))|(?:"[\s\S]*?")|\'[\s\S]*?\'|[^,]*\[[\s\S]*?]|(?:true|false|null))\s*(?=(?:,|\)|$))~s'

                    new
                    '~\s*((?:\w+\s*\([\s\S]*?\))|(?:"[\s\S]*?")|\'[\s\S]*?\'|[^,]*\[[\s\S]*?]|(?:true|false|null)|(?:.+?))\s*(?=(?:,|$))~'

                    new 
                    '~\s*,?\s*((?:(?:\'.*?\')|(?:\".*?\")|array\(.*?\))|(?:\[.*?\])|(?:.+?))\s*(?=(?:,|$))~s'
                */
                if(preg_match('~\s*,?\s*((?:(?:\'.*?\')|(?:\".*?\")|array\(.*?\))|(?:\[.*?\])|(?:.+?))\s*(?=(?:,|$))~s',$FuncArgs,$args)){
                    $FuncArgs=str_replace($args[0],'',$FuncArgs);
                    $ArgsArray[]=$args[1];
                }else{
                    break;
                }
            }
            if(isset(self::$Functions[$FuncName])){
                $template_source=str_replace($FuncCode,self::$Functions[$FuncName]($ArgsArray,$FuncOutSideArg),$template_source);
            }
            $i++;
        }
        // if(isset(self::$Functions[])){
        //
        // }
        // $template_source=str_replace($matchFunction[0],'',$template_source);
        // mprint($matchFunction);
        // break;
        #Blocks#
    $pt='~{\s*(\w+)(?:\((.*?)\))?(?:\s|\~)(.*?)end\1}~s';
    preg_match_all($pt, $template_source,$match);
    $i=0;
    foreach ($match[1] as $blockName) {
        //mprint($match[2][$i]);
        $args=[];
        if(preg_match_all('~\s*,?\s*((?:(?:\'.*?\')|(?:\".*?\")|array\(.*?\))|(?:\[.*?\])|(?:.+?))\s*(?=(?:,|$))~s', $match[2][$i],$argsMatch)){
            $args=$argsMatch[1];
        }
      $blockContent=$match[3][$i];
      $block=$match[0][$i];
      $i++;

      if(isset(self::$blocks[$blockName])){
        $blockRe=self::$blocks[$blockName]($blockContent,$args);
        $template_source=str_replace($block,$blockRe,$template_source);
      }


    }
        #short cuts#
        for (;;) {
            if(preg_match('`^\s*\[\s*(\w+)(?:\s+(\w+=.*?|\~.*?))?\s*(=?~]|])\s*$`sm', $template_source,$ShortCutVal)){
                $shortCutKeyValArray=[];
                if(preg_match('~\s*(?:\~(")|\w+=)?(.*)\1\s*~s', $ShortCutVal[2],$oneArg)){
                    $shortCutKeyValArray['_']=$oneArg[2];
                }
                if($ShortCutVal[3]=='~]'){
                    $pt= '`^\s*\[\s*'.$ShortCutVal[1].'(?:\s+(?:\w+=.*?|\~.*?))?(?:\s*'.$ShortCutVal[3].')\s*(.*?)\[/\s*'.$ShortCutVal[1].'\s*]\s*$`sm';
                    preg_match($pt, $template_source,$x);
                    $ShortCutVal[0]=$x[0];
                    $shortCutKeyValArray['block_contents']=$x[1];
                }


                $shortCutName=strtolower($ShortCutVal[1]);
                $shortCutKeyValString=$ShortCutVal[2];
                $arg2=$shortCutKeyValString;

                for (;;) {
                    if(!preg_match('~(\w+)\s*=\s*"(.*?)"\s*(?=$|\w+\s*=)~s', $shortCutKeyValString,$ValOfaAttr)){
                        break;
                    }

                    $shortCutKeyValString=str_replace($ValOfaAttr[0], '', $shortCutKeyValString);
                    //mprint($ValOfaAttr);
                    $shortCutKeyValArray[$ValOfaAttr[1]]=$ValOfaAttr[2];
                }

                $template_source= str_replace($ShortCutVal[0], self::$shortcuts[$shortCutName]($shortCutKeyValArray,$arg2), $template_source);
            }else{
                break;
            }
        }
        # #@shorttag #
        $pattern='~#@(\w+)(?:\{(\*|\+)([\w ]+)})?~';

        preg_match_all($pattern, $template_source, $match);
        $i=0;
        foreach ($match[1] as $shortTagName) {
            $shortTagBody=$match[0][$i];
            if(isset(self::$shorttags[$shortTagName])){
                $replace=self::$shorttags[$shortTagName]();
                switch ($match[2][$i]) {
                    case '+':
                        $replace.=$match[3][$i];
                        break;
                    case '*':
                        $replace=str_repeat($replace, $match[3][$i]);
                        break;
                }
                $template_source=str_replace($shortTagBody, $replace, $template_source);
            }
            $i++;
        }

        /* patterns */
        self::$tmp=$template_source;
        $ptr=[];$ptrRe=[];
        foreach (self::$patterns as $key => $value) {
            if(preg_match_all($key,$template_source,$ptrMatch)){
                $value($ptrMatch);
            }
        }
        $template_source=self::$tmp;


        //$template_source= preg_replace($ptr,$ptrRe, $template_source);


        if(self::$minify){
            $template_source=self::minify($template_source);
        }
        return $template_source;

    }
    function run($template_source){
        extract(self::$data);
        eval(' ?> '.$template_source);
    }

    function compile($template_source,$cache=1){
        self::$data+=$GLOBALS;
        // $file_address=self::$root_of_theme.$name.self::$extension;
        $baked_file_address= self::$baked_file_address;

        //$template_source=file_get_contents($file_address);


        $template_source=self::loop($template_source);
        if($cache){
            $FileName = $baked_file_address;

            $FileHandle = fopen($FileName, 'w') or die("can't open file");
            fclose($FileHandle);
            file_put_contents($FileName, $template_source);
        }
        return $template_source;

    }
    function view($name){
        if(!is_dir(self::$root_of_baked_theme)){
            mkdir(self::$root_of_baked_theme);
        }
        $file_address=self::$root_of_theme.$name.self::$extension;
        $baked_file_address= self::$root_of_baked_theme.$name.self::$baked_extension;
        self::$baked_file_address=$baked_file_address;
        if(self::$edit || !file_exists($baked_file_address)){
            $template_source=self::compile(file_get_contents($file_address));
        }else{
            $template_source=file_get_contents($baked_file_address);
        }
        self::run($template_source);
    }
    function getsourse(){

    }
}
/**
* baker Compiler
*/
class BakerCompiler
{   
    public static $template_source='';
    public function BakerCompiler($resource='')
    {
        self::$template_source=$resource;
        return $this;
    }
    public function getSource($resource){
        self::$template_source=$resource;
        return $this;
    }
    public function compile($resource){

    }
}
class BakerApp
{
    public static $current_section=[];
    public static $last_section='';
    public static $sections=[];
    public function startSection($name){
        self::$current_section=array_reverse(self::$current_section);
        self::$current_section[]=$name;
        self::$current_section=array_reverse(self::$current_section);
        ob_start();
    }
    public function stopSection(){
        $section_content=ob_get_clean();
        self::$last_section=self::$current_section[0];
        self::$sections[self::$current_section[0]]=$section_content;
        array_shift(self::$current_section);
        //mprint(self::$current_section);
    }

    public function yield($name){
        return self::$sections[$name];
    }
    public function extends($BAKER_FILE_NAME,$vars){
        $BAKER_FILE_NAME.=baker::$extension;
        extract($vars);

        eval('?> '.baker::compile(file_get_contents($BAKER_FILE_NAME),0));
    }

}
?>

,用法是:

include 'baker2.class.php';

new baker();
baker::addFunction(['extends','extend'],function($args){
        return '<?php BakerApp::extends('.$args[0].',get_defined_vars()); ?>';
});
baker::$extension='.php';
baker::view('page');

我当前的代码中出现了什么问题?我该如何解决?

0 个答案:

没有答案