<?php
/**
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* @author Kai Dorschner <the-hide@address.com>
* @copyright Copyright 2010, Kai Dorschner
* @license http://www.gnu.org/licenses/lgpl.html LGPLv3
*/
/**
* Static wiki parser class.
*
* Parses a text for wiki elements selected via regex patterns set in the
* {@see WikiElement::$pattern} subclasses of the WikiElement class.
*/
class WikiParser
{
/**
* List of parsed elements.
*
* @access protected
* @var Array
*/
protected $elements = array
(
'HeadlineWikiElement',
'UnderlineWikiElement',
'StrongWikiElement',
'StrikeWikiElement',
'AnchorWikiElement',
'ParagraphWikiElement',
'BreakWikiElement'
);
public function __construct(Array $forbiddenElements = array())
{
foreach($forbiddenElements as $element)
{
if($k = array_search($element, $this->elements))
{
unset($this->elements[$k]);
}
}
}
public function parse($text, $wrapIn = null)
{
foreach($this->elements as $element)
{
if(class_exists($element))
{
$object = new $element();
$text = preg_replace_callback($object->pattern, array(&$object, 'program'), $text);
}
}
if($wrapIn)
{
if(preg_match('/[A-z]\w*/', $wrapIn))
{
$text = '<'.$wrapIn.'>'.$text.'</'.$wrapIn.'>';
}
else
{
throw new Exception('The wrapping element "'.$wrapIn.'" is invalid. It must neither be empty nor start with a digit nor contain special chars. Please verify your second argument in '.__METHOD__);
}
}
return $text;
}
public function parseAsDomDocument($text, $wrapIn = 'wiki')
{
$x = new DomDocument();
$x->loadXML($this->parse($text, $wrapIn));
return $x;
}
}
/**
* General structure of a WikiElement.
*/
abstract class WikiElement
{
/**
* Pattern for a wiki element.
*
* @access public
* @var String
*/
public $pattern = '/^.*$/';
/**
* XML node name.
*
* @access protected
* @var String
*/
protected $name;
/**
* This method can be inherited and extended for own purposes.
*
* @access public
* @return void
* @param Array $v Array of matches.
*/
public function program(Array $v)
{
return '<'.$this->getName().'>'.$v[1].'</'.$this->getName().'>';
}
/**
* Getter of {@see $name}
*
* @access protected
* @return String XML node name.
*/
protected function getName()
{
return $this->name;
}
}
class UnderlineWikiElement extends WikiElement
{
public $pattern = '/_{2}\s*([^_{2}]+)\s*_{2}/';
protected $name = 'text';
public function program(Array $v)
{
return '<'.$this->getName().' format="underline">'.$v[1].'</'.$this->getName().'>';
}
}
class AnchorWikiElement extends WikiElement
{
public $pattern = '/\[\[([^\]\]]+)\]\]/';
protected $name = 'anchor';
public function program(Array $v)
{
$external = false;
$value = (count($array = explode('|', $v[1])) > 1 ? $array[1] : $array[0]);
if(preg_match('/http:\/\/(.+)/', $array[0]))
{
$href = $array[0];
$external = true;
}
else
{
if($GLOBALS['filesystem']->isFile($array[0]))
{
$href = sprintf($GLOBALS['pathformat'], $GLOBALS['linkprefix'], $array[0], $GLOBALS['media']);
}
else
{
return '';
}
}
return '<'.$this->getName().' href="'.$href.'" '.($external ? ' location="external"':'').'>'.$value.'</'.$this->getName().'>';
}
}
class StrikeWikiElement extends WikiElement
{
public $pattern = '/-{2}\s*([^-{2}]+)\s*-{2}/';
protected $name = 'text';
public function program(Array $v)
{
return '<'.$this->getName().' format="strike">'.$v[1].'</'.$this->getName().'>';
}
}
class StrongWikiElement extends WikiElement
{
public $pattern = '/\'{3}\s*([^\'{3}]+)\s*\'{3}/';
protected $name = 'text';
public function program(Array $v)
{
return '<'.$this->getName().' format="strong">'.$v[1].'</'.$this->getName().'>';
}
}
class BreakWikiElement extends WikiElement
{
public $pattern = '/(.+)\n/';
protected $name = 'linebreak';
public function program(Array $v)
{
return $v[1].'<'.$this->getName().'/>';
}
}
class ParagraphWikiElement extends WikiElement
{
public $pattern = '/(?:(?:[\r\n]{1,}){2,})?\s*(.+)/';
protected $name = 'paragraph';
}