All pastes #489499 Raw Edit

Untitled

public text v1 · immutable
·published 2007-05-15 15:49 UTC
rendered paste body
<?php

// ----------------------------------- \\
// @Zula Framework WikiParser
// @License: http://www.gnu.org/copyleft/gpl.html GNU/GPL 2
// @Author: Copyright 2005, Steve Blinch (http://code.blitzaffe.com)
// @Version 1.0
// @Modified by: Alex Cartwright for Zula Framework
// @Created: 18th April 2007
// ----------------------------------- \\
 
	class Wiki {
	
		private $reference_wiki = '';
		private $image_uri = '';
		private $ignore_images = true;
		private $preformat = '';
		
		private $emphasis = '';
		//---
		// Constructor function
		//---
		public function __construct() {
			$this->reference_wiki = '';
			$this->image_uri = '';
			$this->ignore_images = true;
		}
	
		public function handle_sections($matches) {
			$level = strlen($matches[1]);
			$content = $matches[2];
			
			$this->stop = true;
			// avoid accidental run-on emphasis
			return $this->emphasize_off() . "\n\n<h{$level}>{$content}</h{$level}>\n\n";
		}
		
		public function handle_newline($matches) {
			if ($this->suppress_linebreaks) return $this->emphasize_off();
			
			$this->stop = true;
			// avoid accidental run-on emphasis
			return $this->emphasize_off() . "<br /><br />";
		}
		
		public function handle_list($matches,$close=false) {
	 
			$listtypes = array(
				'*'=>'ul',
				'#'=>'ol',
			);
			
			$output = "";
			
			$newlevel = ($close) ? 0 : strlen($matches[1]);
			
			while ($this->list_level!=$newlevel) {
				if ( !isset( $matches[1] ) ) {
					$matches[1] = '';
				}
				$listchar = substr($matches[1],-1);
				if ( !isset( $listtypes[$listchar] ) ) {
					$listtypes[$listchar] = '';
				}
				$listtype = $listtypes[$listchar];
				
				//$output .= "[".$this->list_level."->".$newlevel."]";
				
				if ($this->list_level>$newlevel) {
					$listtype = '/'.array_pop($this->list_level_types);
					$this->list_level--;
				} else {
					$this->list_level++;
					array_push($this->list_level_types,$listtype);
				}
				$output .= "\n<{$listtype}>\n";
			}
			
			if ($close) return $output;
			
			$output .= "<li>".$matches[2]."</li>\n";
			
			return $output;
		}
		
		public function handle_definitionlist($matches,$close=false) {
			
			if ($close) {
				$this->deflist = false;
				return "</dl>\n";
			}
			
			
			$output = "";
			if (!$this->deflist) $output .= "<dl>\n";
			$this->deflist = true;
	 
			switch($matches[1]) {
				case ';':
					$term = $matches[2];
					$p = strpos($term,' :');
					if ($p!==false) {
						list($term,$definition) = explode(':',$term);
						$output .= "<dt>{$term}</dt><dd>{$definition}</dd>";
					} else {
						$output .= "<dt>{$term}</dt>";
					}
					break;
				case ':':
					$definition = $matches[2];
					$output .= "<dd>{$definition}</dd>\n";
					break;
			}
			
			return $output;
		}
		
		public function handle_preformat($matches,$close=false) {
			if ($close) {
				$this->preformat = false;
				return "</pre>\n";
			}
			
			$this->stop_all = true;
	 
			$output = "";
			if (!$this->preformat) $output .= "<pre>";
			$this->preformat = true;
			
			$output .= $matches[1];
			
			return $output."\n";
		}
		
		public function handle_horizontalrule($matches) {
			return "<hr />";
		}
		
		public function wiki_link($topic) {
			return ucfirst(str_replace(' ','_',$topic));
		}
		
		public function handle_image($href,$title,$options) {
			if ($this->ignore_images) return "";
			if (!$this->image_uri) return $title;
			
			$href = $this->image_uri . $href;
			
			$imagetag = sprintf(
				'<img src="%s" alt="%s" />',
				$href,
				$title
			);
			foreach ($options as $k=>$option) {
				switch($option) {
					case 'frame':
						$imagetag = sprintf(
							'<div style="float: right; background-color: #F5F5F5; border: 1px solid #D0D0D0; padding: 2px">'.
							'%s'.
							'<div>%s</div>'.
							'</div>',
							$imagetag,
							$title
						);
						break;
					case 'right':
						$imagetag = sprintf(
							'<div style="float: right">%s</div>',
							$imagetag
						);
						break;
				}
			}
			
			return $imagetag;
		}
		
		public function handle_internallink($matches) {
			//var_dump($matches);
			$nolink = false;
			
			if ( !isset( $matches[6] ) ) {
				$matches[6] = '';
			}
			if ( !isset( $matches[7] ) ) {
				$matches[7] = '';
			}
			$href = $matches[4];
			$title = $matches[6] ? $matches[6] : $href.$matches[7];
			$namespace = $matches[3];
	 
			if ($namespace=='Image') {
				$options = explode('|',$title);
				$title = array_pop($options);
				
				return $this->handle_image($href,$title,$options);
			}		
			
			$title = preg_replace('/\(.*?\)/','',$title);
			$title = preg_replace('/^.*?\:/','',$title);
			
			if ($this->reference_wiki) {
				$href = $this->reference_wiki.($namespace?$namespace.':':'').$this->wiki_link($href);
			} else {
				$nolink = true;
			}
	 
			if ($nolink) return $title;
			
			return sprintf(
				'<a href="%s"%s>%s</a>',
				$href,
				($newwindow?' target="_blank"':''),
				$title
			);
		}
		
		public function handle_externallink($matches) {
			if ( !isset( $matches[3] ) )  {
				$matches[3] = '';
			}
			$href = $matches[2];
			$title = $matches[3];
			if (!$title) {
				$this->linknumber++;
				$title = "[{$this->linknumber}]";
			}
			$newwindow = true;
			
			return sprintf(
				'<a href="%s"%s>%s</a>',
				$href,
				($newwindow?' target="_blank"':''),
				$title
			);		
		}
		
		public function emphasize($amount) {
			$amounts = array(
				2=>array('<em>','</em>'),
				3=>array('<strong>','</strong>'),
				4=>array('<strong>','</strong>'),
				5=>array('<em><strong>','</strong></em>'),
			);
	 
			$output = "";
	 
		if ( !isset( $this->emphasis[$amount] ) ) {
			$this->emphasis[$amount] = '';
		}
		if ( !isset( $this->emphasis[$amount-1] ) ) {
			$this->emphasis[$amount-1] = '';
		}
			// handle cases where emphasized phrases end in an apostrophe, eg: ''somethin'''
			// should read <em>somethin'</em> rather than <em>somethin<strong>
			if ( (!$this->emphasis[$amount]) && ($this->emphasis[$amount-1]) ) {
				$amount--;
				$output = "'";
			}
	 
			$output .= $amounts[$amount][(int) $this->emphasis[$amount]];
	 
			$this->emphasis[$amount] = !$this->emphasis[$amount];
			
			return $output;
		}
		
		public function handle_emphasize($matches) {
			$amount = strlen($matches[1]);
			return $this->emphasize($amount);
	 
		}
		
		public function emphasize_off() {
			$output = "";
			if ( is_array( $this->emphasis ) ) {
				foreach ($this->emphasis as $amount=>$state) {
					if ($state) $output .= $this->emphasize($amount);
				}
			}
			
			return $output;
		}
		
		public function handle_eliminate($matches) {
			return "";
		}
		
		public function handle_variable($matches) {
			switch($matches[2]) {
				case 'CURRENTMONTH': return date('m');
				case 'CURRENTMONTHNAMEGEN':
				case 'CURRENTMONTHNAME': return date('F');
				case 'CURRENTDAY': return date('d');
				case 'CURRENTDAYNAME': return date('l');
				case 'CURRENTYEAR': return date('Y');
				case 'CURRENTTIME': return date('H:i');
				case 'NUMBEROFARTICLES': return 0;
				case 'PAGENAME': return $this->page_title;
				case 'NAMESPACE': return 'None';
				case 'SITENAME': return $_SERVER['HTTP_HOST'];
				default: return '';	
			}
		}
		
		public function parse_line($line) {
			$line_regexes = array(
				'preformat'=>'^\s(.*?)$',
				'definitionlist'=>'^([\;\:])\s*(.*?)$',
				'newline'=>'^$',
				'list'=>'^([\*\#]+)(.*?)$',
				'sections'=>'^(={1,6})(.*?)(={1,6})$',
				'horizontalrule'=>'^----$',
			);
			$char_regexes = array(
	//			'link'=>'(\[\[((.*?)\:)?(.*?)(\|(.*?))?\]\]([a-z]+)?)',
				'internallink'=>'('.
					'\[\['. // opening brackets
						'(([^\]]*?)\:)?'. // namespace (if any)
						'([^\]]*?)'. // target
						'(\|([^\]]*?))?'. // title (if any)
					'\]\]'. // closing brackets
					'([a-z]+)?'. // any suffixes
					')',
				'externallink'=>'('.
					'\['.
						'([^\]]*?)'.
						'(\s+[^\]]*?)?'.
					'\]'.
					')',
				'emphasize'=>'(\'{2,5})',
				'eliminate'=>'(__TOC__|__NOTOC__|__NOEDITSECTION__)',
				'variable'=>'('. '\{\{' . '([^\}]*?)' . '\}\}' . ')',
			);
					
			$this->stop = false;
			$this->stop_all = false;
	 
			$called = array();
			
			$line = rtrim($line);
					
			foreach ($line_regexes as $func=>$regex) {
				if (preg_match("/$regex/i",$line,$matches)) {
					$called[$func] = true;
					$func = "handle_".$func;
					$line = $this->$func($matches);
					if ($this->stop || $this->stop_all) break;
				}
			}
			if (!$this->stop_all) {
				$this->stop = false;
				foreach ($char_regexes as $func=>$regex) {
					$line = preg_replace_callback("/$regex/i",array(&$this,"handle_".$func),$line);
					if ($this->stop) break;
				}
			}
			
			$isline = strlen(trim($line))>0;			
			
			if ( !isset( $called['list'] ) ) {
				$called['list'] = '';
			}
			if ( !isset( $called['definitionlist'] ) ) {
				$called['definitionlist'] = '';
			}
			// if this wasn't a list item, and we are in a list, close the list tag(s)
			if (($this->list_level>0) && !$called['list']) $line = $this->handle_list(false,true) . $line;
			if ($this->deflist && !$called['definitionlist']) $line = $this->handle_definitionlist(false,true) . $line;
			if ( !isset( $called['preformat'] ) ) {
				$called['preformat'] = '';
			}
			if ($this->preformat && !$called['preformat']) $line = $this->handle_preformat(false,true) . $line;
			
			if ( !isset( $called['newline'] ) ) {
				$called['newline'] = '';
			}
			if ( !isset( $called['sections'] ) ) {
				$called['sections'] = '';
			}
			// suppress linebreaks for the next line if we just displayed one; otherwise re-enable them
			if ($isline) $this->suppress_linebreaks = ($called['newline'] || $called['sections']);
			
			return $line;
		}
		
		public function parse($text,$title="") {
			$this->redirect = false;
			
			$this->nowikis = array();
			$this->list_level_types = array();
			$this->list_level = 0;
			
			$this->deflist = false;
			$this->linknumber = 0;
			$this->suppress_linebreaks = false;
			
			$this->page_title = $title;
	 
			$output = "";
			
			$text = preg_replace_callback('/<nowiki>([\s\S]*)<\/nowiki>/i',array(&$this,"handle_save_nowiki"),$text);
	 
			$lines = explode("\n",$text);
			
			if (preg_match('/^\#REDIRECT\s+\[\[(.*?)\]\]$/',trim($lines[0]),$matches)) {
				$this->redirect = $matches[1];
			}
			
			foreach ($lines as $k=>$line) {
				$line = $this->parse_line($line);
				$output .= $line;
			}
	 
			$output = preg_replace_callback('/<nowiki><\/nowiki>/i',array(&$this,"handle_restore_nowiki"),$output);
	 
	 
			return $output;
		}
		
		public function handle_save_nowiki($matches) {
			array_push($this->nowikis,$matches[1]);
			return "<nowiki></nowiki>";
		}
		
		public function handle_restore_nowiki($matches) {
			return array_pop($this->nowikis);
		}
	}
	
?>