Search code examples
phpregextemplate-engine

Regex, delete tags not content


Good morning

I'm working on a templateclass. I will make conditions in the tpl file like so:

@if('eee' == 'esee')
  <h2>Test</h2>
@endif

@if('aaa' == 'aaa')
  <h2>Test</h2>
@endif

When the condition are false are work that all hidden, but whan true so i will delete the @if('eee' == 'esee') and @endif but i do not know how.

here my function

private static function get_condition(){
    $control = array();
    preg_match_all('/@if\((?P<control>[^)]+)\)/', self::$viewMainContent, $control);
$matches = isset($control['control']) ? count($control['control']) : 0;
for($i = 0; $i < $matches; $i++) {
        $operators = [' == ', ' != ', ' >= ', ' <= ', ' > ', ' < '];
        foreach($operators as $operator){
            if(preg_match('/'.$operator.'/', $control['control'][$i])){
                $val = explode($operator, $control['control'][$i]);
                $param = preg_grep('/\'[^"]*\'/is', $val, PREG_SET_ORDER);
                $show = false;
                if(count($param) == 2){
                    switch(trim($operator)){
                        case "==":
                            if($param[0] == $param[1]){ $show = true; }
                            break;
                        case "!=":
                            if($param[0] != $param[1]){ $show = true; }
                            break;
                        case ">=":
                            if($param[0] >= $param[1]){ $show = true; }
                            break;
                        case "<=":
                            if($param[0] <= $param[1]){ $show = true; }
                            break;
                        case ">":
                            if($param[0] > $param[1]){ $show = true; }
                            break;
                        case "<":
                            if($param[0] < $param[1]){ $show = true; }
                            break;

                    }
                }

                self::$viewMainContent = str_replace("\n", " ", self::$viewMainContent);
                if(!$show){
                    self::$viewMainContent = preg_replace('/'.preg_quote($control[0][$i]).'(.*?)\@endif/', '', self::$viewMainContent);
                } else {
                    //self::$viewMainContent = preg_replace('/'.preg_quote($control[0][$i]).'/', '', self::$viewMainContent);
                    //self::$viewMainContent = preg_replace('/@endif/', '', self::$viewMainContent);
                }
            }
        }
}
}

How i can delete the tags without the content?

Thx


Solution

  • This is really not secure, but I used eval() here, just for the sake of simplicity. You can replace it with your switch() case logic. I think the one of the ways to do what you want is with preg_replace_callback():

    $template = <<<'EOD'
    @if('eee' == 'eee')
      <h2>Test</h2>
    @endif
    
    @if('aaa' == 'aaa')
      <h2>Test</h2>
    @endif
    EOD;
    
    $regex = '/@if\((?P<condition>.*)\)\n*\s*(?P<content>(?s:[\=\"\s\/\<\>\w\n]*))@endif/m';
    
    preg_match_all($regex, $template, $matches);
    
    $template = preg_replace_callback(
        $regex,
        function ($matches) {
            if (eval('return ' . $matches['condition'] . ';')) {
                return rtrim($matches['content']);
            }
    
            return '';
        },
        $template
    );
    
    var_dump($template);
    

    Here is demo.

    You can also experiment with '/@if\((?P<condition>.*)\)\n*\s*(?P<content>(?s:[\=\"\s\/\<\>\w\n]*))@endif/m' regex here.