wullxz
wullxz

Reputation: 19430

Recursive regex pattern in PHP

I'd like to use tag-style annotations in html text to replace sections of text/html depending on variable names using PHP. The replacement itself works perfectly if not using nested tags.
But if there are nested tags, only the outer one gets replaced.

My regex is this one:

\[\@if(not)?:([a-zA-Z0-9]+)(?:=(.*?))?\].*?\[\@endif:\2\]

You can see this regex in action with example content to parse here:
https://regex101.com/r/rE3fL1/2

I've read about (?R) but can't get it to work.
I tried replacing the .*? in the middle with (.*?|(?R)) but that doesn't even change anything.

How do I change the regex to also capture nested Tags?

Code: ($this->output accesses the Text)

public function output($dbAccess = true) {
        // only translate when dbaccess is granted
        if ($dbAccess) 
            $this->localize();

        // insert values into template
        foreach ( $this->values as $key => $value ) {
            $tagToReplace = "[@$key]";
            $this->output = str_replace ( $tagToReplace, $value, $this->output );
        }

        // gather conditional content sections from output
        $condis = array();
        $conmatches = array ();
        preg_match_all ( '/\[\@if(not)?:([a-zA-Z0-9]+)(?:=(.*?))?\].*?\[\@endif:\2\]/s', $this->output, $conmatches );
        if (count($conmatches) > 0) {
            $c = $conmatches[0];
//          if (count($c) > 0)
//              echo "found " . count($c[0]) . " conditional tpl statement matches!";
            for ($i=0; $i<count($c); $i++) {
                $text = $c[$i];
                $not = $conmatches[1][$i];
                $name = $conmatches[2][$i];
                $value = $conmatches[3][$i];
                $condis[] = new ConditionalContent($text, $not, $name, $value);
            }

            // substitute conditional content sections
            foreach ($condis as $cc) {
                // convenience and readability vars!
                $varname = $cc->name();
                $vals = &$this->values;
                $value = $cc->value();

                // if condition is bound to value of variable and not just existence
                if ($value != "") {
                    // del if name == exists(value)
                    if ($cc->not() && isset($vals[$varname])) {
                        if ($vals[$varname] == $value) {
                            $this->delContent($cc->content());
                        }
                    }
                    // del if not exists(value) or value != name
                    else {
                        if (!isset($vals[$varname]) || $vals[$varname] != $value) {
                            $this->delContent($cc->content());
                        }
                    }
                }
                else {
                    if (    isset($vals[$varname]) && $cc->not() || 
                            !isset($vals[$varname]) && !$cc->not()) {
                        $this->delContent($cc->content());
                    }
                }
            }

            // delete all left over if(not) and endif statements
            $this->output = preg_replace('/\[@(?:if(?:not){0,1}|endif):[a-zA-Z0-9]+(=.*?)?\]/', '', $this->output);
        }
        //else { echo "found no conditional tpl statements"; }

        return $this->output;
    }

Upvotes: 1

Views: 76

Answers (0)

Related Questions