summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--inc/html.php2
-rw-r--r--inc/init.php5
-rw-r--r--inc/parser/handler.php19
-rw-r--r--inc/parser/lexer.php7
-rw-r--r--inc/parser/parser.php134
-rw-r--r--inc/parser/xhtml.php10
-rw-r--r--inc/parserutils.php28
-rw-r--r--inc/plugins/info/syntax.php63
-rw-r--r--inc/plugins/syntax.php66
-rw-r--r--inc/pluginutils.php62
-rw-r--r--inc/template.php2
11 files changed, 350 insertions, 48 deletions
diff --git a/inc/html.php b/inc/html.php
index c49a2b220..370754c52 100644
--- a/inc/html.php
+++ b/inc/html.php
@@ -364,7 +364,7 @@ function html_search(){
*
* @author Andreas Gohr <andi@splitbrain.org>
*/
-function html_locked($ip){
+function html_locked(){
global $ID;
global $conf;
global $lang;
diff --git a/inc/init.php b/inc/init.php
index 150e07d83..af1d1eb9c 100644
--- a/inc/init.php
+++ b/inc/init.php
@@ -10,6 +10,7 @@
error_reporting(E_ALL ^ E_NOTICE);
//prepare config array()
+ global $conf;
$conf = array();
// load the config file(s)
@@ -17,12 +18,16 @@
@include_once(DOKU_INC.'conf/local.php');
//prepare language array
+ global $lang;
$lang = array();
// define baseURL
if(!defined('DOKU_BASE')) define('DOKU_BASE',getBaseURL());
if(!defined('DOKU_URL')) define('DOKU_URL',getBaseURL(true));
+ // define Plugin dir
+ if(!defined('DOKU_PLUGIN')) define('DOKU_PLUGIN',DOKU_INC.'inc/plugins/');
+
// define main script
if(!defined('DOKU_SCRIPT')) define('DOKU_SCRIPT','doku.php');
diff --git a/inc/parser/handler.php b/inc/parser/handler.php
index e1ded183a..2379d60ff 100644
--- a/inc/parser/handler.php
+++ b/inc/parser/handler.php
@@ -54,6 +54,25 @@ class Doku_Handler {
}
return FALSE;
}
+
+
+ /**
+ * Special plugin handler
+ *
+ * This handler is called for all modes starting with 'plugin_'.
+ * An additional parameter with the plugin name is passed
+ *
+ * @author Andreas Gohr <andi@splitbrain.org>
+ */
+ function plugin($match, $state, $pos, $pluginname){
+ $data = array($match);
+ $plugin = null;
+ if(plugin_load('syntax',$pluginname,$plugin)){
+ $data = $plugin->handle($match, $state, $pos, $handler);
+ }
+ $this->_addCall('plugin',array($pluginname,$data,$pos),$pos);
+ return TRUE;
+ }
function base($match, $state, $pos) {
switch ( $state ) {
diff --git a/inc/parser/lexer.php b/inc/parser/lexer.php
index e7961932d..1cacaeed5 100644
--- a/inc/parser/lexer.php
+++ b/inc/parser/lexer.php
@@ -471,6 +471,13 @@ class Doku_Lexer {
if (isset($this->_mode_handlers[$handler])) {
$handler = $this->_mode_handlers[$handler];
}
+ // modes starting with plugin_ are all handled by the same
+ // handler but with an additional parameter
+ if(substr($handler,0,7)=='plugin_'){
+ list($handler,$plugin) = split('_',$handler,2);
+ return $this->_parser->$handler($content, $is_match, $pos, $plugin);
+ }
+
return $this->_parser->$handler($content, $is_match, $pos);
}
diff --git a/inc/parser/parser.php b/inc/parser/parser.php
index dd2b72aa0..87a29328c 100644
--- a/inc/parser/parser.php
+++ b/inc/parser/parser.php
@@ -5,6 +5,45 @@ if(!defined('DOKU_INC')) define('DOKU_INC',realpath(dirname(__FILE__).'/../../')
require_once DOKU_INC . 'inc/parser/lexer.php';
require_once DOKU_INC . 'inc/parser/handler.php';
+
+/**
+ * Define various types of modes used by the parser - they are used to
+ * populate the list of modes another mode accepts
+ */
+global $PARSER_MODES;
+$PARSER_MODES = array(
+ // containers are complex modes that can contain many other modes
+ // hr breaks the principle but they shouldn't be used in tables / lists
+ // so they are put here
+ 'container' => array('listblock','table','quote','hr'),
+
+ // some mode are allowed inside the base mode only
+ 'baseonly' => array('header'),
+
+ // modes for styling text -- footnote behaves similar to styling
+ 'formatting' => array('strong', 'emphasis', 'underline', 'monospace',
+ 'subscript', 'superscript', 'deleted', 'footnote'),
+
+ // modes where the token is simply replaced - they can not contain any
+ // other modes
+ 'substition' => array('acronym','smiley','wordblock','entity',
+ 'camelcaselink', 'internallink','media',
+ 'externallink','linebreak','emaillink',
+ 'windowssharelink','filelink','notoc',
+ 'nocache','multiplyentity','quotes','rss'),
+
+ // modes which have a start and end token but inside which
+ // no other modes should be applied
+ 'protected' => array('preformatted','code','file','php','html'),
+
+ // inside this mode no wiki markup should be applied but lineendings
+ // and whitespace isn't preserved
+ 'disabled' => array('unformatted'),
+
+ // used to mark paragraph boundaries
+ 'paragraphs' => array('eol')
+);
+
//-------------------------------------------------------------------
/**
@@ -101,7 +140,7 @@ class Doku_Parser_Mode {
var $Lexer;
var $allowedModes = array();
-
+
// Called before any calls to connectTo
function preConnect() {}
@@ -120,15 +159,16 @@ class Doku_Parser_Mode {
class Doku_Parser_Mode_Base extends Doku_Parser_Mode {
function Doku_Parser_Mode_Base() {
+ global $PARSER_MODES;
$this->allowedModes = array_merge (
- Doku_Parser_BlockContainers(),
- Doku_Parser_BaseOnly(),
- Doku_Parser_Paragraphs(),
- Doku_Parser_Formatting(),
- Doku_Parser_Substition(),
- Doku_Parser_Protected(),
- Doku_Parser_Disabled()
+ $PARSER_MODES['container'],
+ $PARSER_MODES['baseonly'],
+ $PARSER_MODES['paragraphs'],
+ $PARSER_MODES['formatting'],
+ $PARSER_MODES['substition'],
+ $PARSER_MODES['protected'],
+ $PARSER_MODES['disabled']
);
}
}
@@ -137,13 +177,14 @@ class Doku_Parser_Mode_Base extends Doku_Parser_Mode {
class Doku_Parser_Mode_Footnote extends Doku_Parser_Mode {
function Doku_Parser_Mode_Footnote() {
+ global $PARSER_MODES;
$this->allowedModes = array_merge (
- Doku_Parser_BlockContainers(),
- Doku_Parser_Formatting(),
- Doku_Parser_Substition(),
- Doku_Parser_Protected(),
- Doku_Parser_Disabled()
+ $PARSER_MODES['container'],
+ $PARSER_MODES['formatting'],
+ $PARSER_MODES['substition'],
+ $PARSER_MODES['protected'],
+ $PARSER_MODES['disabled']
);
}
@@ -237,7 +278,6 @@ class Doku_Parser_Mode_HR extends Doku_Parser_Mode {
//-------------------------------------------------------------------
class Doku_Parser_Mode_Formatting extends Doku_Parser_Mode {
-
var $type;
var $formatting = array (
@@ -278,6 +318,7 @@ class Doku_Parser_Mode_Formatting extends Doku_Parser_Mode {
);
function Doku_Parser_Mode_Formatting($type) {
+ global $PARSER_MODES;
if ( !array_key_exists($type, $this->formatting) ) {
trigger_error('Invalid formatting type '.$type, E_USER_WARNING);
@@ -285,12 +326,18 @@ class Doku_Parser_Mode_Formatting extends Doku_Parser_Mode {
$this->type = $type;
+ // formatting may contain other formatting but not it self
+ $modes = $PARSER_MODES['formatting'];
+ $key = array_search($type, $modes);
+ if ( is_int($key) ) {
+ unset($modes[$key]);
+ }
+
$this->allowedModes = array_merge (
- Doku_Parser_Formatting($type),
- Doku_Parser_Substition(),
- Doku_Parser_Disabled()
+ $modes,
+ $PARSER_MODES['substition'],
+ $PARSER_MODES['disabled']
);
-
}
function connectTo($mode) {
@@ -321,20 +368,16 @@ class Doku_Parser_Mode_Formatting extends Doku_Parser_Mode {
class Doku_Parser_Mode_ListBlock extends Doku_Parser_Mode {
function Doku_Parser_Mode_ListBlock() {
+ global $PARSER_MODES;
$this->allowedModes = array_merge (
- Doku_Parser_Formatting(),
- Doku_Parser_Substition(),
- Doku_Parser_Disabled()
+ $PARSER_MODES['formatting'],
+ $PARSER_MODES['substition'],
+ $PARSER_MODES['disabled'],
+ $PARSER_MODES['protected'] #XXX new
);
- $this->allowedModes[] = 'footnote';
- $this->allowedModes[] = 'preformatted';
- $this->allowedModes[] = 'unformatted';
- $this->allowedModes[] = 'html';
- $this->allowedModes[] = 'php';
- $this->allowedModes[] = 'code';
- $this->allowedModes[] = 'file';
+ // $this->allowedModes[] = 'footnote';
}
function connectTo($mode) {
@@ -355,15 +398,17 @@ class Doku_Parser_Mode_ListBlock extends Doku_Parser_Mode {
class Doku_Parser_Mode_Table extends Doku_Parser_Mode {
function Doku_Parser_Mode_Table() {
+ global $PARSER_MODES;
$this->allowedModes = array_merge (
- Doku_Parser_Formatting(),
- Doku_Parser_Substition(),
- Doku_Parser_Disabled()
+ $PARSER_MODES['formatting'],
+ $PARSER_MODES['substition'],
+ $PARSER_MODES['disabled'],
+ $PARSER_MODES['protected'] #XXX new
);
- $this->allowedModes[] = 'footnote';
- $this->allowedModes[] = 'preformatted';
- $this->allowedModes[] = 'unformatted';
+ #$this->allowedModes[] = 'footnote';
+ #$this->allowedModes[] = 'preformatted';
+ #$this->allowedModes[] = 'unformatted';
}
function connectTo($mode) {
@@ -473,15 +518,17 @@ class Doku_Parser_Mode_File extends Doku_Parser_Mode {
class Doku_Parser_Mode_Quote extends Doku_Parser_Mode {
function Doku_Parser_Mode_Quote() {
+ global $PARSER_MODES;
$this->allowedModes = array_merge (
- Doku_Parser_Formatting(),
- Doku_Parser_Substition(),
- Doku_Parser_Disabled()
+ $PARSER_MODES['formatting'],
+ $PARSER_MODES['substition'],
+ $PARSER_MODES['disabled'],
+ $PARSER_MODES['protected'] #XXX new
);
- $this->allowedModes[] = 'footnote';
- $this->allowedModes[] = 'preformatted';
- $this->allowedModes[] = 'unformatted';
+ #$this->allowedModes[] = 'footnote';
+ #$this->allowedModes[] = 'preformatted';
+ #$this->allowedModes[] = 'unformatted';
}
function connectTo($mode) {
@@ -774,9 +821,14 @@ class Doku_Parser_Mode_EmailLink extends Doku_Parser_Mode {
}
//-------------------------------------------------------------------
+//
+// XXX deprecated - replace by $PARSER_MODES
+//
// Help fns to keep mode lists - used to make it easier to populate
// the list of modes another mode accepts
+/*
+
// Can contain many other modes
// E.g. a footnote can containing formatting etc.
function Doku_Parser_BlockContainers() {
@@ -848,6 +900,8 @@ function Doku_Parser_Disabled() {
);
return $modes;
}
+*/
+// --------------------------------------------------------------------------
//Setup VIM: ex: et ts=4 enc=utf-8 :
diff --git a/inc/parser/xhtml.php b/inc/parser/xhtml.php
index f9f6be1e6..b58c24435 100644
--- a/inc/parser/xhtml.php
+++ b/inc/parser/xhtml.php
@@ -19,6 +19,7 @@ if ( !defined('DOKU_TAB') ) {
}
require_once DOKU_INC . 'inc/parser/renderer.php';
+require_once DOKU_INC . 'inc/pluginutils.php';
/**
* The Renderer
@@ -41,7 +42,6 @@ class Doku_Renderer_xhtml extends Doku_Renderer {
var $store = '';
-
function document_start() {
}
@@ -57,6 +57,14 @@ class Doku_Renderer_xhtml extends Doku_Renderer {
$this->doc .= '</div>'.DOKU_LF;
}
}
+
+ //handles plugin rendering
+ function plugin($name,$data){
+ $plugin = null;
+ if(plugin_load('syntax',$name,$plugin)){
+ $plugin->render('xhtml',$this,$data);
+ }
+ }
function toc_open() {
global $lang;
diff --git a/inc/parserutils.php b/inc/parserutils.php
index 802ae8a0d..9c0e4fd9c 100644
--- a/inc/parserutils.php
+++ b/inc/parserutils.php
@@ -11,6 +11,7 @@
require_once(DOKU_INC.'inc/confutils.php');
require_once(DOKU_INC.'inc/pageutils.php');
+ require_once(DOKU_INC.'inc/pluginutils.php');
/**
* Returns the parsed Wikitext in XHTML for the given id and revision.
@@ -155,14 +156,26 @@ function p_cached_instructions($file,$cacheonly=false){
function p_get_instructions($text){
global $conf;
+ //import parser classes and mode definitions
require_once DOKU_INC . 'inc/parser/parser.php';
-
+
+ // load syntax plugins
+ $pluginlist = plugin_list('syntax');
+ if(count($pluginlist)){
+ global $PARSER_MODES;
+ $plugins = array();
+ foreach($pluginlist as $p){
+ plugin_load('syntax',$p,$plugin[$p]); //load plugin into $plugin array
+ $PARSER_MODES[$plugin[$p]->getType()][] = "plugin_$p"; //register mode type
+ }
+ }
+
// Create the parser
$Parser = & new Doku_Parser();
// Add the Handler
$Parser->Handler = & new Doku_Handler();
-
+
// Load all the modes
$Parser->addMode('listblock',new Doku_Parser_Mode_ListBlock());
$Parser->addMode('preformatted',new Doku_Parser_Mode_Preformatted());
@@ -192,7 +205,7 @@ function p_get_instructions($text){
$Parser->addMode('smiley',new Doku_Parser_Mode_Smiley(array_keys(getSmileys())));
$Parser->addMode('acronym',new Doku_Parser_Mode_Acronym(array_keys(getAcronyms())));
- #$Parser->addMode('wordblock',new Doku_Parser_Mode_Wordblock(getBadWords()));
+ #$Parser->addMode('wordblock',new Doku_Parser_Mode_Wordblock($Modes,getBadWords()));
$Parser->addMode('entity',new Doku_Parser_Mode_Entity(array_keys(getEntities())));
$Parser->addMode('multiplyentity',new Doku_Parser_Mode_MultiplyEntity());
@@ -202,6 +215,11 @@ function p_get_instructions($text){
$Parser->addMode('camelcaselink',new Doku_Parser_Mode_CamelCaseLink());
}
+ //add plugins FIXME since order is important we, need to find a better way!
+ foreach ( array_keys($plugin) as $p ) {
+ $Parser->addMode("plugin_$p",$plugin[$p]);
+ }
+
$Parser->addMode('internallink',new Doku_Parser_Mode_InternalLink());
$Parser->addMode('rss',new Doku_Parser_Mode_RSS());
$Parser->addMode('media',new Doku_Parser_Mode_Media());
@@ -210,10 +228,10 @@ function p_get_instructions($text){
$Parser->addMode('windowssharelink',new Doku_Parser_Mode_WindowsShareLink());
//$Parser->addMode('filelink',new Doku_Parser_Mode_FileLink()); //FIXME ???
$Parser->addMode('eol',new Doku_Parser_Mode_Eol());
-
+
// Do the parsing
$p = $Parser->parse($text);
-# dbg($p);
+// dbg($p);
return $p;
}
diff --git a/inc/plugins/info/syntax.php b/inc/plugins/info/syntax.php
new file mode 100644
index 000000000..4567de685
--- /dev/null
+++ b/inc/plugins/info/syntax.php
@@ -0,0 +1,63 @@
+<?php
+/**
+ * Info Plugin: Displays information about various DokuWiki internals
+ *
+ * @license GPL 2 (http://www.gnu.org/licenses/gpl.html)
+ * @author Andreas Gohr <andi@splitbrain.org>
+ */
+
+if(!defined('DOKU_INC')) define('DOKU_INC',realpath(dirname(__FILE__).'/../../').'/');
+if(!defined('DOKU_PLUGIN')) define('DOKU_PLUGIN',DOKU_INC.'inc/plugins/');
+require_once(DOKU_PLUGIN.'syntax.php');
+
+/**
+ * All DokuWiki plugins to extend the parser/rendering mechanism
+ * need to inherit from this class
+ */
+class syntax_plugin_info extends DokuWiki_Syntax_Plugin {
+
+ /**
+ * What kind of syntax are we?
+ */
+ function getType(){
+ return 'substition';
+ }
+
+
+ /**
+ * Connect pattern to lexer
+ */
+ function connectTo($mode) {
+ $this->Lexer->addSpecialPattern('~~INFO:\w+~~',$mode,'plugin_info');
+ }
+
+
+ /**
+ * Handle the match
+ */
+ function handle($match, $state, $pos, &$handler){
+ $match = substr($match,7,-2); //strip ~~INFO: from start and ~~ from end
+ return array(strtolower($match));
+ }
+
+ /**
+ * Create output
+ */
+ function render($mode, &$renderer, $data) {
+ if($mode == 'xhtml'){
+ //handle various info stuff
+ switch ($data[0]){
+ case 'foo':
+ $renderer->doc .= "foo is foo";
+ break;
+ default:
+ $renderer->doc .= "no info about ".htmlspecialchars($data[0]);
+ }
+ return true;
+ }
+ return false;
+ }
+
+}
+
+//Setup VIM: ex: et ts=4 enc=utf-8 :
diff --git a/inc/plugins/syntax.php b/inc/plugins/syntax.php
new file mode 100644
index 000000000..bb5680cd3
--- /dev/null
+++ b/inc/plugins/syntax.php
@@ -0,0 +1,66 @@
+<?php
+/**
+ * Syntax Plugin Prototype
+ *
+ * @license GPL 2 (http://www.gnu.org/licenses/gpl.html)
+ * @author Andreas Gohr <andi@splitbrain.org>
+ */
+
+if(!defined('DOKU_INC')) define('DOKU_INC',realpath(dirname(__FILE__).'/../').'/');
+if(!defined('DOKU_PLUGIN')) define('DOKU_PLUGIN',DOKU_INC.'inc/plugins/');
+require_once(DOKU_INC.'inc/parser/parser.php');
+
+/**
+ * All DokuWiki plugins to extend the parser/rendering mechanism
+ * need to inherit from this class
+ */
+class DokuWiki_Syntax_Plugin extends Doku_Parser_Mode {
+
+ /**
+ * Needs to return one of the mode types defined in $PARSER_MODES in parser.php
+ */
+ function getType(){
+ trigger_error('getType() not implemented in '.get_class($this), E_USER_WARNING);
+ }
+
+ /**
+ * Handler to prepare matched data for the rendering process
+ *
+ * Usually you should only need the $match param.
+ *
+ * @param $match string The text matched by the patterns
+ * @param $state int The lexer state for the match
+ * @param $pos int The character position of the matched text
+ * @param $handler ref Reference to the Doku_Handler object
+ * @return array Return an array with all data you want to use in render
+ */
+ function handle($match, $state, $pos, &$handler){
+ trigger_error('handle() not implemented in '.get_class($this), E_USER_WARNING);
+ }
+
+ /**
+ * Handles the actual output creation.
+ *
+ * The function should always check for the given mode and return false
+ * when a mode isn't supported.
+ *
+ * $renderer contains a reference to the renderer object which is
+ * currently handling the rendering. You need to use it for writing
+ * the output. How this is done depends on the renderer used (specified
+ * by $mode
+ *
+ * The contents of the $data array depends on what the handler() function above
+ * created
+ *
+ * @param $mode string current Rendermode
+ * @param $renderer ref reference to the current renderer object
+ * @param $data array data created by handler()
+ * @return boolean rendered correctly?
+ */
+ function render($mode, &$renderer, $data) {
+ trigger_error('render() not implemented in '.get_class($this), E_USER_WARNING);
+ }
+
+}
+
+//Setup VIM: ex: et ts=4 enc=utf-8 :
diff --git a/inc/pluginutils.php b/inc/pluginutils.php
new file mode 100644
index 000000000..3be57f2d7
--- /dev/null
+++ b/inc/pluginutils.php
@@ -0,0 +1,62 @@
+<?php
+/**
+ * Utilities for handling plugins
+ *
+ * @license GPL 2 (http://www.gnu.org/licenses/gpl.html)
+ * @author Andreas Gohr <andi@splitbrain.org>
+ */
+
+/**
+ * Returns a list of available plugins of given type
+ *
+ * @author Andreas Gohr <andi@splitbrain.org>
+ */
+function plugin_list($type){
+ $plugins = array();
+ if ($dh = opendir(DOKU_PLUGIN)) {
+ while (false !== ($file = readdir($dh))) {
+ if ($file == '.' || $file == '..') continue;
+ if (is_file(DOKU_PLUGIN.$file)) continue;
+
+ if (@file_exists(DOKU_PLUGIN.$file.'/'.$type.'.php')){
+ $plugins[] = $file;
+ }
+ }
+ closedir($dh);
+ }
+ return $plugins;
+}
+
+/**
+ * Loads the given plugin and creates an object of it
+ *
+ * @author Andreas Gohr <andi@splitbrain.org>
+ *
+ * @param $type string type of plugin to load
+ * @param $name string name of the plugin to load
+ * @param $ref ref will contain the plugin object
+ * @return boolean plugin loading successful?
+ */
+function plugin_load($type,$name,&$ref){
+ //we keep all loaded plugins available in global scope for reuse
+ global $DOKU_PLUGINS;
+
+ //plugin already loaded?
+ if($DOKU_PLUGINS[$type][$name] != null){
+ $ref = $DOKU_PLUGINS[$type][$name];
+ return true;
+ }
+
+ //try to load the wanted plugin file
+ if(!@include_once(DOKU_PLUGIN.$name.'/'.$type.'.php')){
+ return false;
+ }
+
+ //construct class and instanciate
+ $class = $type.'_plugin_'.$name;
+ $DOKU_PLUGINS[$type][$name] = new $class;
+ $ref = $DOKU_PLUGINS[$type][$name];
+ return true;
+}
+
+
diff --git a/inc/template.php b/inc/template.php
index 2baa6f77e..0826ba6f8 100644
--- a/inc/template.php
+++ b/inc/template.php
@@ -88,7 +88,7 @@ function tpl_content(){
html_diff(con($PRE,$TEXT,$SUF),false);
break;
case 'locked':
- html_locked($lockedby);
+ html_locked();
break;
case 'login':
html_login();