All pastes #743959 Raw Edit

Miscellany

public text v1 · immutable
·published 2007-10-20 23:00 UTC
rendered paste body
<?php

if(!APP) exit;

require_once('tag.php');

class TemplateParser
{
	public function parse($template_buffer)
	{		
		$tags = preg_split("~<(/?)([a-z0-9_]+)\:([a-z0-9_]+)((?: [^>]*)?)>~i", $template_buffer, -1, PREG_SPLIT_DELIM_CAPTURE);
		
		$tree = array();
		$tree[] = new RootTag();
		 
		$i = -1;
		while(isset($tags[++$i])) {
			$Tag = $tags[$i];
			$ParentTag = end($tree);
			
			$key = $i % 5;
			
			if($key == 0) {
				$ParentTag->append($Tag);
			}
			
			if(isset($tags[$i + 4])) {
				$tag_info = array(
					'closing' => $tags[$i + 1] == '/',
					'ns' => trim($tags[$i + 2]),
					'name' => trim($tags[$i + 3]),
					'attributes' => trim($tags[$i + 4]),
					'non_closing' => false
				);
				
				if(!empty($tag_info['attributes']) && $tag_info['attributes']{strlen($tag_info['attributes']) - 1} == '/') {
					$tag_info['non_closing'] = true;
					$tag_info['attibutes'] = trim(substr($tag_info['attibutes'], 0, -1));
				}
				
				if($tag_info['closing']) {
					$Tag = array_pop($tree);
					$ParentTag = end($tree);
					
					if($tag_info['name'] == $Tag->name) {
						$ParentTag->append($Tag->parse());
					} else {
						$ParentTag->append("<!-- Improper closing tag for [{$tag_info['ns']}:{$tag_info['name']} -->");
					}
				} else {
					$tag_info['file'] = LIB_DIR . DS . 'template'  . DS . 'tags' . DS . $tag_info['ns'] . DS . "{$tag_info['name']}.php";
					$tag_info['class'] = strtoupper($tag_info['name']) . 'Tag';
					
					if(!file_exists($tag_info['file'])) {
						$tag_info['file'] = PLUGIN_DIR . $tag_info['ns'] . DS . 'template' . DS . 'tags' . DS . "{$tag_info['name']}.php";
						$tag_info['class'] = strtoupper($tag_info['ns']) . strtoupper($tag_info['name']) . 'Tag';
					}
					
					if(file_exists($tag_info['file'])) {
						include_once($tag_info['file']);
					}
					
					$Tag = (class_exists($tag_info['class'], false)) ? new $tag_info['class']($tag_info['name']) : new UnknownTag($tag_info['name']);
					
					if($tag_info['attributes']) {
						preg_match_all('~(?P<key>[a-z]+)="(?P<value>[^"]*)"~i', $tag_info['attributes'], $attributes);
						$Tag->attributes = $this->parseTagAttributes($attributes);
					}
					
					if($tag_info['non_closing']) {
						$ParentTag->append($Tag->parse());
					} else {
						$tree[] = $Tag; 
					}
				}
			}
			
			$i += 4;
		}
		
		while($Tag = array_pop($tree)) {
			if($Tag instanceof TemplateTag) {
				$template_buffer = $Tag->template_buffer;
			}
		}
		
		return preg_replace_callback('~{(\$|\@|\/)([^}]*)}~', array($this, 'parseVariables'), $template_buffer);
	}

	public function parseVariables($matches)
	{
		$variable_type = $matches[1];
		$variable_block = trim($matches[2]);
		
		switch($variable_type) {
			case '$':
				if(!empty($variable_block)) {
					$callbacks = explode('|', $variable_block);
					$variable_key = array_shift($callbacks);

					$template_buffer = "\$Template['{$variable_key}']";
					
					foreach($callbacks as $callback) {
						$args = explode(':', $callback);
						$function = array_shift($args);
						
						if(function_exists($function)) {
							$args = !empty($args) ? ', ' . implode(', ', $args) : null;
							$template_buffer = "{$function}({$template_buffer}{$args})";
						}
					}
					
					$template_buffer = "<?= {$template_buffer} ?>";
				}
			break;
			case '@':
				// Gettext support goes here.
				$template_buffer = $variable_block;
			break;
			case '/':
				// Relative url support goes here.
				$template_buffer = $variable_block;
			break;
		}
		
		return $template_buffer;
	}
	
	private function parseTagAttributes(array $parts = array())
	{		
		$attributes = array();
			
		foreach($parts['key'] as $i => $attrib) {
			$attributes[strtolower($attrib)] = $parts['value'][$i];
		}
		
		return $attributes;
	}
}

?>