Lightweight HTML/PHP parser

The parser

function parse($file, $section, $vars = null) {
	
        // clear file status cache
        clearstatcache();
        
        $basename = basename($file);
        
        // if the section is stored in $GLOBALS, use section that was stored 
        // so that we do not need to find the section again from the template file 
        if (isset($GLOBALS['parser'][$basename][$section])) {
            $result = $GLOBALS['parser'][$basename][$section];
        }
        
        // read template file and find $section
        if (!isset($result)) {
            $fileLines = file($file);
            $file_i = implode('<@>', $fileLines);
            $start_i = strpos($file_i, '['.$section.']');
            $start = sizeof(explode('<@>', substr($file_i, 0, $start_i))) - 1;
            $end_i = strpos($file_i, '[/'.$section.']');
            $end = sizeof(explode('<@>', substr($file_i, 0, $end_i))) - 1;

            for ($i=$start+1; $i<=$end-1; $i++) {
                    $result .= $fileLines[$i];
            }
        }
        
        // if template does not contain the section 
        if (empty($result)) {
                return 'source: '.$file. ' is empty ('.$section.')';
        }

        // store the section
        $GLOBALS['parser'][$basename][$section] = $result;

        // remove comments
        $result = preg_replace('![comment].+[/comment]!s', '', $result);

        // place values  into section
        if (is_array($vars)) {
                foreach($vars as $key => $value) { 
                        $tag = "{VAR:" . $key . "}";
                        $result = str_replace($tag, $value, $result);
                }
        }

        // remove VAR tags that had no mathing replacement in $vars
        $result = preg_replace("/{VAR:(.*)}/U", "", $result);

        return $result;
}

What the function does

Clears the file status cache so that latest version of template file is used:

        clearstatcache();

If the section is stored in $GLOBALS, use section that was stored so that we do not need to find the section again from the template file:

        $basename = basename($file);
  
        if (isset($GLOBALS['parser'][$basename][$section])) {
            $result = $GLOBALS['parser'][$basename][$section];
        }

Read template file and find $section:


        if (!isset($result)) {
            $fileLines = file($file);
            $file_i = implode('<@>', $fileLines);
            $start_i = strpos($file_i, '['.$section.']');
            $start = sizeof(explode('<@>', substr($file_i, 0, $start_i))) - 1;
            $end_i = strpos($file_i, '[/'.$section.']');
            $end = sizeof(explode('<@>', substr($file_i, 0, $end_i))) - 1;

            for ($i=$start+1; $i<=$end-1; $i++) {
                    $result .= $fileLines[$i];
            }
        }

If template does not contain the section, return error:

        if (empty($result)) {
                return 'source: '.$file. ' is empty ('.$section.')';
        }

Store the section for possible re-use during this pageload:

        $GLOBALS['parser'][$basename][$section] = $result;

Remove comments:

        $result = preg_replace('![comment].+[/comment]!s', '', $result);

Place values into section:

        if (is_array($vars)) {
                foreach($vars as $key => $value) { 
                        $tag = "{VAR:" . $key . "}";
                        $result = str_replace($tag, $value, $result);
                }
        }

Remove VAR tags that had no matching replacement value in $vars:

        $result = preg_replace("/{VAR:(.*)}/U", "", $result);

Using the parser

HTML template:

[section1]
The number is: "{VAR:number}"
[/section1]

PHP script:

$params['number'] = '1000';

$html = parse('templates/test1.tpl', 'section1', $params);

echo $html;

Complete demo as .zip

Download usage sample .zip here.

Leave a Reply

Your email address will not be published. Required fields are marked *