diff options
author | Gerrit Uitslag <klapinklapin@gmail.com> | 2013-11-19 21:26:50 +0100 |
---|---|---|
committer | Gerrit Uitslag <klapinklapin@gmail.com> | 2013-11-19 21:26:50 +0100 |
commit | 703aeaef1a43b07dc5497dba72c98151466396cc (patch) | |
tree | 1e18a6b3fc3c28156c2e56f8a3d515b8dd6a9cf9 /inc/parser | |
parent | 33c3b3817b00aa9384760813643fac0e33daaaff (diff) | |
parent | 14b3007921f7b66fc9e3621b861a3c83e7e9093c (diff) | |
download | rpg-703aeaef1a43b07dc5497dba72c98151466396cc.tar.gz rpg-703aeaef1a43b07dc5497dba72c98151466396cc.tar.bz2 |
Merge remote-tracking branch 'origin/master' into diff_navigation
Diffstat (limited to 'inc/parser')
-rw-r--r-- | inc/parser/code.php | 4 | ||||
-rw-r--r-- | inc/parser/handler.php | 224 | ||||
-rw-r--r-- | inc/parser/lexer.php | 414 | ||||
-rw-r--r-- | inc/parser/metadata.php | 764 | ||||
-rw-r--r-- | inc/parser/parser.php | 31 | ||||
-rw-r--r-- | inc/parser/renderer.php | 42 | ||||
-rw-r--r-- | inc/parser/xhtml.php | 87 |
7 files changed, 797 insertions, 769 deletions
diff --git a/inc/parser/code.php b/inc/parser/code.php index 6e159b041..0b8e3ee02 100644 --- a/inc/parser/code.php +++ b/inc/parser/code.php @@ -15,7 +15,7 @@ class Doku_Renderer_code extends Doku_Renderer { * * When the correct block was found it exits the script. */ - function code($text, $language = NULL, $filename='' ) { + function code($text, $language = null, $filename='' ) { global $INPUT; if(!$language) $language = 'txt'; if(!$filename) $filename = 'snippet.'.$language; @@ -36,7 +36,7 @@ class Doku_Renderer_code extends Doku_Renderer { /** * Wraps around code() */ - function file($text, $language = NULL, $filename='') { + function file($text, $language = null, $filename='') { $this->code($text, $language, $filename); } diff --git a/inc/parser/handler.php b/inc/parser/handler.php index 1cf32aaed..8ae991209 100644 --- a/inc/parser/handler.php +++ b/inc/parser/handler.php @@ -4,9 +4,9 @@ if (!defined('DOKU_PARSER_EOL')) define('DOKU_PARSER_EOL',"\n"); // add this t class Doku_Handler { - var $Renderer = NULL; + var $Renderer = null; - var $CallWriter = NULL; + var $CallWriter = null; var $calls = array(); @@ -35,8 +35,8 @@ class Doku_Handler { $this->CallWriter->finalise(); if ( $this->status['section'] ) { - $last_call = end($this->calls); - array_push($this->calls,array('section_close',array(), $last_call[2])); + $last_call = end($this->calls); + array_push($this->calls,array('section_close',array(), $last_call[2])); } if ( $this->rewriteBlocks ) { @@ -70,12 +70,12 @@ class Doku_Handler { */ function plugin($match, $state, $pos, $pluginname){ $data = array($match); - $plugin =& plugin_load('syntax',$pluginname); + $plugin = plugin_load('syntax',$pluginname); if($plugin != null){ $data = $plugin->handle($match, $state, $pos, $this); } if ($data !== false) { - $this->addPluginCall($pluginname,$data,$state,$pos,$match); + $this->addPluginCall($pluginname,$data,$state,$pos,$match); } return true; } @@ -190,8 +190,8 @@ class Doku_Handler { // footnotes can not be nested - however due to limitations in lexer it can't be prevented // we will still enter a new footnote mode, we just do nothing if ($this->_footnote) { - $this->_addCall('cdata',array($match), $pos); - break; + $this->_addCall('cdata',array($match), $pos); + break; } $this->_footnote = true; @@ -203,8 +203,8 @@ class Doku_Handler { case DOKU_LEXER_EXIT: // check whether we have already exitted the footnote mode, can happen if the modes were nested if (!$this->_footnote) { - $this->_addCall('cdata',array($match), $pos); - break; + $this->_addCall('cdata',array($match), $pos); + break; } $this->_footnote = false; @@ -423,7 +423,7 @@ class Doku_Handler { // Split title from URL $link = explode('|',$link,2); if ( !isset($link[1]) ) { - $link[1] = NULL; + $link[1] = null; } else if ( preg_match('/^\{\{[^\}]+\}\}$/',$link[1]) ) { // If the title is an image, convert it to an array containing the image details $link[1] = Doku_Handler_Parse_Media($link[1]); @@ -433,7 +433,7 @@ class Doku_Handler { //decide which kind of link it is if ( preg_match('/^[a-zA-Z0-9\.]+>{1}.*$/u',$link[0]) ) { - // Interwiki + // Interwiki $interwiki = explode('>',$link[0],2); $this->_addCall( 'interwikilink', @@ -441,35 +441,35 @@ class Doku_Handler { $pos ); }elseif ( preg_match('/^\\\\\\\\[^\\\\]+?\\\\/u',$link[0]) ) { - // Windows Share + // Windows Share $this->_addCall( 'windowssharelink', array($link[0],$link[1]), $pos ); }elseif ( preg_match('#^([a-z0-9\-\.+]+?)://#i',$link[0]) ) { - // external link (accepts all protocols) + // external link (accepts all protocols) $this->_addCall( 'externallink', array($link[0],$link[1]), $pos ); }elseif ( preg_match('<'.PREG_PATTERN_VALID_EMAIL.'>',$link[0]) ) { - // E-Mail (pattern above is defined in inc/mail.php) + // E-Mail (pattern above is defined in inc/mail.php) $this->_addCall( 'emaillink', array($link[0],$link[1]), $pos ); }elseif ( preg_match('!^#.+!',$link[0]) ){ - // local link + // local link $this->_addCall( 'locallink', array(substr($link[0],1),$link[1]), $pos ); }else{ - // internal link + // internal link $this->_addCall( 'internallink', array($link[0],$link[1]), @@ -481,12 +481,12 @@ class Doku_Handler { } function filelink($match, $state, $pos) { - $this->_addCall('filelink',array($match, NULL), $pos); + $this->_addCall('filelink',array($match, null), $pos); return true; } function windowssharelink($match, $state, $pos) { - $this->_addCall('windowssharelink',array($match, NULL), $pos); + $this->_addCall('windowssharelink',array($match, null), $pos); return true; } @@ -520,10 +520,10 @@ class Doku_Handler { $p['details'] = (preg_match('/\b(desc|detail)/',$params)); if (preg_match('/\b(\d+)([dhm])\b/',$params,$match)) { - $period = array('d' => 86400, 'h' => 3600, 'm' => 60); - $p['refresh'] = max(600,$match[1]*$period[$match[2]]); // n * period in seconds, minimum 10 minutes + $period = array('d' => 86400, 'h' => 3600, 'm' => 60); + $p['refresh'] = max(600,$match[1]*$period[$match[2]]); // n * period in seconds, minimum 10 minutes } else { - $p['refresh'] = 14400; // default to 4 hours + $p['refresh'] = 14400; // default to 4 hours } $this->_addCall('rss',array($link,$p),$pos); @@ -550,7 +550,7 @@ class Doku_Handler { function emaillink($match, $state, $pos) { $email = preg_replace(array('/^</','/>$/'),'',$match); - $this->_addCall('emaillink',array($email, NULL), $pos); + $this->_addCall('emaillink',array($email, null), $pos); return true; } @@ -618,7 +618,6 @@ function Doku_Handler_Parse_Media($match) { // Split title from URL $link = explode('|',$link,2); - // Check alignment $ralign = (bool)preg_match('/^ /',$link[0]); $lalign = (bool)preg_match('/ $/',$link[0]); @@ -631,12 +630,12 @@ function Doku_Handler_Parse_Media($match) { } else if ( $lalign ) { $align = 'left'; } else { - $align = NULL; + $align = null; } // The title... if ( !isset($link[1]) ) { - $link[1] = NULL; + $link[1] = null; } //remove aligning spaces @@ -654,11 +653,11 @@ function Doku_Handler_Parse_Media($match) { //parse width and height if(preg_match('#(\d+)(x(\d+))?#i',$param,$size)){ - ($size[1]) ? $w = $size[1] : $w = NULL; - ($size[3]) ? $h = $size[3] : $h = NULL; + !empty($size[1]) ? $w = $size[1] : $w = null; + !empty($size[3]) ? $h = $size[3] : $h = null; } else { - $w = NULL; - $h = NULL; + $w = null; + $h = null; } //get linking command @@ -1034,7 +1033,7 @@ class Doku_Handler_Preformatted { break; case 'preformatted_end': if (trim($this->text)) { - $this->CallWriter->writeCall(array('preformatted',array($this->text),$this->pos)); + $this->CallWriter->writeCall(array('preformatted',array($this->text),$this->pos)); } // see FS#1699 & FS#1652, add 'eol' instructions to ensure proper triggering of following p_open $this->CallWriter->writeCall(array('eol',array(),$this->pos)); @@ -1247,12 +1246,12 @@ class Doku_Handler_Table { } $this->tableCalls[] = array($this->lastCellType.'_close',array(),$call[2]); - $this->tableCalls[] = array($call[0].'_open',array(1,NULL,1),$call[2]); + $this->tableCalls[] = array($call[0].'_open',array(1,null,1),$call[2]); $this->lastCellType = $call[0]; } else { - $this->tableCalls[] = array($call[0].'_open',array(1,NULL,1),$call[2]); + $this->tableCalls[] = array($call[0].'_open',array(1,null,1),$call[2]); $this->lastCellType = $call[0]; $this->firstCell = false; @@ -1289,121 +1288,119 @@ class Doku_Handler_Table { $call = $this->tableCalls[$key]; switch ($call[0]) { - case 'tablerow_open': + case 'tablerow_open': - $lastRow++; - $lastCell = 0; - break; + $lastRow++; + $lastCell = 0; + break; - case 'tablecell_open': - case 'tableheader_open': + case 'tablecell_open': + case 'tableheader_open': - $lastCell++; - $cellKey[$lastRow][$lastCell] = $key; - break; + $lastCell++; + $cellKey[$lastRow][$lastCell] = $key; + break; - case 'table_align': + case 'table_align': - $prev = in_array($this->tableCalls[$key-1][0], array('tablecell_open', 'tableheader_open')); - $next = in_array($this->tableCalls[$key+1][0], array('tablecell_close', 'tableheader_close')); - // If the cell is empty, align left - if ($prev && $next) { - $this->tableCalls[$key-1][1][1] = 'left'; + $prev = in_array($this->tableCalls[$key-1][0], array('tablecell_open', 'tableheader_open')); + $next = in_array($this->tableCalls[$key+1][0], array('tablecell_close', 'tableheader_close')); + // If the cell is empty, align left + if ($prev && $next) { + $this->tableCalls[$key-1][1][1] = 'left'; - // If the previous element was a cell open, align right - } elseif ($prev) { - $this->tableCalls[$key-1][1][1] = 'right'; + // If the previous element was a cell open, align right + } elseif ($prev) { + $this->tableCalls[$key-1][1][1] = 'right'; + + // If the next element is the close of an element, align either center or left + } elseif ( $next) { + if ( $this->tableCalls[$cellKey[$lastRow][$lastCell]][1][1] == 'right' ) { + $this->tableCalls[$cellKey[$lastRow][$lastCell]][1][1] = 'center'; + } else { + $this->tableCalls[$cellKey[$lastRow][$lastCell]][1][1] = 'left'; + } - // If the next element is the close of an element, align either center or left - } elseif ( $next) { - if ( $this->tableCalls[$cellKey[$lastRow][$lastCell]][1][1] == 'right' ) { - $this->tableCalls[$cellKey[$lastRow][$lastCell]][1][1] = 'center'; - } else { - $this->tableCalls[$cellKey[$lastRow][$lastCell]][1][1] = 'left'; } - } + // Now convert the whitespace back to cdata + $this->tableCalls[$key][0] = 'cdata'; + break; - // Now convert the whitespace back to cdata - $this->tableCalls[$key][0] = 'cdata'; - break; + case 'colspan': - case 'colspan': + $this->tableCalls[$key-1][1][0] = false; - $this->tableCalls[$key-1][1][0] = false; + for($i = $key-2; $i >= $cellKey[$lastRow][1]; $i--) { - for($i = $key-2; $i >= $cellKey[$lastRow][1]; $i--) { + if ( $this->tableCalls[$i][0] == 'tablecell_open' || $this->tableCalls[$i][0] == 'tableheader_open' ) { - if ( $this->tableCalls[$i][0] == 'tablecell_open' || $this->tableCalls[$i][0] == 'tableheader_open' ) { + if ( false !== $this->tableCalls[$i][1][0] ) { + $this->tableCalls[$i][1][0]++; + break; + } - if ( false !== $this->tableCalls[$i][1][0] ) { - $this->tableCalls[$i][1][0]++; - break; } - - } - } - $toDelete[] = $key-1; - $toDelete[] = $key; - $toDelete[] = $key+1; - break; - - case 'rowspan': + $toDelete[] = $key-1; + $toDelete[] = $key; + $toDelete[] = $key+1; + break; - if ( $this->tableCalls[$key-1][0] == 'cdata' ) { - // ignore rowspan if previous call was cdata (text mixed with :::) we don't have to check next call as that wont match regex - $this->tableCalls[$key][0] = 'cdata'; + case 'rowspan': - } else { + if ( $this->tableCalls[$key-1][0] == 'cdata' ) { + // ignore rowspan if previous call was cdata (text mixed with :::) we don't have to check next call as that wont match regex + $this->tableCalls[$key][0] = 'cdata'; - $spanning_cell = null; - for($i = $lastRow-1; $i > 0; $i--) { + } else { - if ( $this->tableCalls[$cellKey[$i][$lastCell]][0] == 'tablecell_open' || $this->tableCalls[$cellKey[$i][$lastCell]][0] == 'tableheader_open' ) { + $spanning_cell = null; + for($i = $lastRow-1; $i > 0; $i--) { - if ($this->tableCalls[$cellKey[$i][$lastCell]][1][2] >= $lastRow - $i) { - $spanning_cell = $i; - break; - } + if ( $this->tableCalls[$cellKey[$i][$lastCell]][0] == 'tablecell_open' || $this->tableCalls[$cellKey[$i][$lastCell]][0] == 'tableheader_open' ) { + if ($this->tableCalls[$cellKey[$i][$lastCell]][1][2] >= $lastRow - $i) { + $spanning_cell = $i; + break; + } + } } - } - if (is_null($spanning_cell)) { - // No spanning cell found, so convert this cell to - // an empty one to avoid broken tables - $this->tableCells[$key][1][1] = ''; - continue; - } - $this->tableCalls[$cellKey[$spanning_cell][$lastCell]][1][2]++; + if (is_null($spanning_cell)) { + // No spanning cell found, so convert this cell to + // an empty one to avoid broken tables + $this->tableCalls[$key][0] = 'cdata'; + $this->tableCalls[$key][1][0] = ''; + continue; + } + $this->tableCalls[$cellKey[$spanning_cell][$lastCell]][1][2]++; - $this->tableCalls[$key-1][1][2] = false; + $this->tableCalls[$key-1][1][2] = false; - $toDelete[] = $key-1; - $toDelete[] = $key; - $toDelete[] = $key+1; - } - break; + $toDelete[] = $key-1; + $toDelete[] = $key; + $toDelete[] = $key+1; + } + break; - case 'tablerow_close': + case 'tablerow_close': - // Fix broken tables by adding missing cells - while (++$lastCell < $this->maxCols) { - array_splice($this->tableCalls, $key, 0, array( - array('tablecell_open', array(1, null, 1), $call[2]), - array('cdata', array(''), $call[2]), - array('tablecell_close', array(), $call[2]))); - $key += 3; - } + // Fix broken tables by adding missing cells + while (++$lastCell < $this->maxCols) { + array_splice($this->tableCalls, $key, 0, array( + array('tablecell_open', array(1, null, 1), $call[2]), + array('cdata', array(''), $call[2]), + array('tablecell_close', array(), $call[2]))); + $key += 3; + } - break; + break; } } - // condense cdata $cnt = count($this->tableCalls); for( $key = 0; $key < $cnt; $key++){ @@ -1435,6 +1432,7 @@ class Doku_Handler_Table { class Doku_Handler_Block { var $calls = array(); var $skipEol = false; + var $inParagraph = false; // Blocks these should not be inside paragraphs var $blockOpen = array( diff --git a/inc/parser/lexer.php b/inc/parser/lexer.php index b5bcb9612..2e84eca7c 100644 --- a/inc/parser/lexer.php +++ b/inc/parser/lexer.php @@ -1,18 +1,18 @@ <?php /** -* Author Markus Baker: http://www.lastcraft.com -* Version adapted from Simple Test: http://sourceforge.net/projects/simpletest/ -* For an intro to the Lexer see: -* http://www.phppatterns.com/index.php/article/articleview/106/1/2/ -* @author Marcus Baker -* @package Doku -* @subpackage Lexer -* @version $Id: lexer.php,v 1.1 2005/03/23 23:14:09 harryf Exp $ -*/ + * Author Markus Baker: http://www.lastcraft.com + * Version adapted from Simple Test: http://sourceforge.net/projects/simpletest/ + * For an intro to the Lexer see: + * http://www.phppatterns.com/index.php/article/articleview/106/1/2/ + * @author Marcus Baker + * @package Doku + * @subpackage Lexer + * @version $Id: lexer.php,v 1.1 2005/03/23 23:14:09 harryf Exp $ + */ /** -* Init path constant -*/ + * Init path constant + */ if(!defined('DOKU_INC')) die('meh.'); /**#@+ @@ -26,11 +26,12 @@ define("DOKU_LEXER_SPECIAL", 5); /**#@-*/ /** - * Compounded regular expression. Any of - * the contained patterns could match and - * when one does it's label is returned. - * @package Doku - * @subpackage Lexer + * Compounded regular expression. Any of + * the contained patterns could match and + * when one does it's label is returned. + * + * @package Doku + * @subpackage Lexer */ class Doku_LexerParallelRegex { var $_patterns; @@ -39,10 +40,11 @@ class Doku_LexerParallelRegex { var $_case; /** - * Constructor. Starts with no patterns. - * @param boolean $case True for case sensitive, false - * for insensitive. - * @access public + * Constructor. Starts with no patterns. + * + * @param boolean $case True for case sensitive, false + * for insensitive. + * @access public */ function Doku_LexerParallelRegex($case) { $this->_case = $case; @@ -52,15 +54,16 @@ class Doku_LexerParallelRegex { } /** - * Adds a pattern with an optional label. - * @param mixed $pattern Perl style regex. Must be UTF-8 - * encoded. If its a string, the (, ) - * lose their meaning unless they - * form part of a lookahead or - * lookbehind assertation. - * @param string $label Label of regex to be returned - * on a match. Label must be ASCII - * @access public + * Adds a pattern with an optional label. + * + * @param mixed $pattern Perl style regex. Must be UTF-8 + * encoded. If its a string, the (, ) + * lose their meaning unless they + * form part of a lookahead or + * lookbehind assertation. + * @param string $label Label of regex to be returned + * on a match. Label must be ASCII + * @access public */ function addPattern($pattern, $label = true) { $count = count($this->_patterns); @@ -70,13 +73,13 @@ class Doku_LexerParallelRegex { } /** - * Attempts to match all patterns at once against - * a string. - * @param string $subject String to match against. - * @param string $match First matched portion of - * subject. - * @return boolean True on success. - * @access public + * Attempts to match all patterns at once against a string. + * + * @param string $subject String to match against. + * @param string $match First matched portion of + * subject. + * @return boolean True on success. + * @access public */ function match($subject, &$match) { if (count($this->_patterns) == 0) { @@ -98,14 +101,14 @@ class Doku_LexerParallelRegex { } /** - * Attempts to split the string against all patterns at once + * Attempts to split the string against all patterns at once * - * @param string $subject String to match against. - * @param array $split The split result: array containing, pre-match, match & post-match strings - * @return boolean True on success. - * @access public + * @param string $subject String to match against. + * @param array $split The split result: array containing, pre-match, match & post-match strings + * @return boolean True on success. + * @access public * - * @author Christopher Smith <chris@jalakai.co.uk> + * @author Christopher Smith <chris@jalakai.co.uk> */ function split($subject, &$split) { if (count($this->_patterns) == 0) { @@ -143,12 +146,13 @@ class Doku_LexerParallelRegex { } /** - * Compounds the patterns into a single - * regular expression separated with the - * "or" operator. Caches the regex. - * Will automatically escape (, ) and / tokens. - * @param array $patterns List of patterns in order. - * @access private + * Compounds the patterns into a single + * regular expression separated with the + * "or" operator. Caches the regex. + * Will automatically escape (, ) and / tokens. + * + * @param array $patterns List of patterns in order. + * @access private */ function _getCompoundedRegex() { if ($this->_regex == null) { @@ -176,25 +180,25 @@ class Doku_LexerParallelRegex { */ switch($elt) { - case '(': - $pattern .= '\('; - break; - case ')': - if ($level > 0) - $level--; /* closing (? */ - else - $pattern .= '\\'; - $pattern .= ')'; - break; - case '(?': - $level++; - $pattern .= '(?'; - break; - default: - if (substr($elt, 0, 1) == '\\') - $pattern .= $elt; - else - $pattern .= str_replace('/', '\/', $elt); + case '(': + $pattern .= '\('; + break; + case ')': + if ($level > 0) + $level--; /* closing (? */ + else + $pattern .= '\\'; + $pattern .= ')'; + break; + case '(?': + $level++; + $pattern .= '(?'; + break; + default: + if (substr($elt, 0, 1) == '\\') + $pattern .= $elt; + else + $pattern .= str_replace('/', '\/', $elt); } } $this->_patterns[$i] = "($pattern)"; @@ -205,9 +209,9 @@ class Doku_LexerParallelRegex { } /** - * Accessor for perl regex mode flags to use. - * @return string Perl regex flags. - * @access private + * Accessor for perl regex mode flags to use. + * @return string Perl regex flags. + * @access private */ function _getPerlMatchingFlags() { return ($this->_case ? "msS" : "msSi"); @@ -215,47 +219,47 @@ class Doku_LexerParallelRegex { } /** - * States for a stack machine. - * @package Lexer - * @subpackage Lexer + * States for a stack machine. + * @package Lexer + * @subpackage Lexer */ class Doku_LexerStateStack { var $_stack; /** - * Constructor. Starts in named state. - * @param string $start Starting state name. - * @access public + * Constructor. Starts in named state. + * @param string $start Starting state name. + * @access public */ function Doku_LexerStateStack($start) { $this->_stack = array($start); } /** - * Accessor for current state. - * @return string State. - * @access public + * Accessor for current state. + * @return string State. + * @access public */ function getCurrent() { return $this->_stack[count($this->_stack) - 1]; } /** - * Adds a state to the stack and sets it - * to be the current state. - * @param string $state New state. - * @access public + * Adds a state to the stack and sets it + * to be the current state. + * @param string $state New state. + * @access public */ function enter($state) { array_push($this->_stack, $state); } /** - * Leaves the current state and reverts - * to the previous one. - * @return boolean False if we drop off - * the bottom of the list. - * @access public + * Leaves the current state and reverts + * to the previous one. + * @return boolean False if we drop off + * the bottom of the list. + * @access public */ function leave() { if (count($this->_stack) == 1) { @@ -267,13 +271,13 @@ class Doku_LexerStateStack { } /** - * Accepts text and breaks it into tokens. - * Some optimisation to make the sure the - * content is only scanned by the PHP regex - * parser once. Lexer modes must not start - * with leading underscores. - * @package Doku - * @subpackage Lexer + * Accepts text and breaks it into tokens. + * Some optimisation to make the sure the + * content is only scanned by the PHP regex + * parser once. Lexer modes must not start + * with leading underscores. + * @package Doku + * @subpackage Lexer */ class Doku_Lexer { var $_regexes; @@ -283,13 +287,13 @@ class Doku_Lexer { var $_case; /** - * Sets up the lexer in case insensitive matching - * by default. - * @param Doku_Parser $parser Handling strategy by - * reference. - * @param string $start Starting handler. - * @param boolean $case True for case sensitive. - * @access public + * Sets up the lexer in case insensitive matching + * by default. + * @param Doku_Parser $parser Handling strategy by + * reference. + * @param string $start Starting handler. + * @param boolean $case True for case sensitive. + * @access public */ function Doku_Lexer(&$parser, $start = "accept", $case = false) { $this->_case = $case; @@ -300,15 +304,15 @@ class Doku_Lexer { } /** - * Adds a token search pattern for a particular - * parsing mode. The pattern does not change the - * current mode. - * @param string $pattern Perl style regex, but ( and ) - * lose the usual meaning. - * @param string $mode Should only apply this - * pattern when dealing with - * this type of input. - * @access public + * Adds a token search pattern for a particular + * parsing mode. The pattern does not change the + * current mode. + * @param string $pattern Perl style regex, but ( and ) + * lose the usual meaning. + * @param string $mode Should only apply this + * pattern when dealing with + * this type of input. + * @access public */ function addPattern($pattern, $mode = "accept") { if (! isset($this->_regexes[$mode])) { @@ -318,17 +322,17 @@ class Doku_Lexer { } /** - * Adds a pattern that will enter a new parsing - * mode. Useful for entering parenthesis, strings, - * tags, etc. - * @param string $pattern Perl style regex, but ( and ) - * lose the usual meaning. - * @param string $mode Should only apply this - * pattern when dealing with - * this type of input. - * @param string $new_mode Change parsing to this new - * nested mode. - * @access public + * Adds a pattern that will enter a new parsing + * mode. Useful for entering parenthesis, strings, + * tags, etc. + * @param string $pattern Perl style regex, but ( and ) + * lose the usual meaning. + * @param string $mode Should only apply this + * pattern when dealing with + * this type of input. + * @param string $new_mode Change parsing to this new + * nested mode. + * @access public */ function addEntryPattern($pattern, $mode, $new_mode) { if (! isset($this->_regexes[$mode])) { @@ -338,12 +342,12 @@ class Doku_Lexer { } /** - * Adds a pattern that will exit the current mode - * and re-enter the previous one. - * @param string $pattern Perl style regex, but ( and ) - * lose the usual meaning. - * @param string $mode Mode to leave. - * @access public + * Adds a pattern that will exit the current mode + * and re-enter the previous one. + * @param string $pattern Perl style regex, but ( and ) + * lose the usual meaning. + * @param string $mode Mode to leave. + * @access public */ function addExitPattern($pattern, $mode) { if (! isset($this->_regexes[$mode])) { @@ -353,16 +357,16 @@ class Doku_Lexer { } /** - * Adds a pattern that has a special mode. Acts as an entry - * and exit pattern in one go, effectively calling a special - * parser handler for this token only. - * @param string $pattern Perl style regex, but ( and ) - * lose the usual meaning. - * @param string $mode Should only apply this - * pattern when dealing with - * this type of input. - * @param string $special Use this mode for this one token. - * @access public + * Adds a pattern that has a special mode. Acts as an entry + * and exit pattern in one go, effectively calling a special + * parser handler for this token only. + * @param string $pattern Perl style regex, but ( and ) + * lose the usual meaning. + * @param string $mode Should only apply this + * pattern when dealing with + * this type of input. + * @param string $special Use this mode for this one token. + * @access public */ function addSpecialPattern($pattern, $mode, $special) { if (! isset($this->_regexes[$mode])) { @@ -372,24 +376,24 @@ class Doku_Lexer { } /** - * Adds a mapping from a mode to another handler. - * @param string $mode Mode to be remapped. - * @param string $handler New target handler. - * @access public + * Adds a mapping from a mode to another handler. + * @param string $mode Mode to be remapped. + * @param string $handler New target handler. + * @access public */ function mapHandler($mode, $handler) { $this->_mode_handlers[$mode] = $handler; } /** - * Splits the page text into tokens. Will fail - * if the handlers report an error or if no - * content is consumed. If successful then each - * unparsed and parsed token invokes a call to the - * held listener. - * @param string $raw Raw HTML text. - * @return boolean True on success, else false. - * @access public + * Splits the page text into tokens. Will fail + * if the handlers report an error or if no + * content is consumed. If successful then each + * unparsed and parsed token invokes a call to the + * held listener. + * @param string $raw Raw HTML text. + * @return boolean True on success, else false. + * @access public */ function parse($raw) { if (! isset($this->_parser)) { @@ -418,18 +422,18 @@ class Doku_Lexer { } /** - * Sends the matched token and any leading unmatched - * text to the parser changing the lexer to a new - * mode if one is listed. - * @param string $unmatched Unmatched leading portion. - * @param string $matched Actual token match. - * @param string $mode Mode after match. A boolean - * false mode causes no change. - * @param int $pos Current byte index location in raw doc - * thats being parsed - * @return boolean False if there was any error - * from the parser. - * @access private + * Sends the matched token and any leading unmatched + * text to the parser changing the lexer to a new + * mode if one is listed. + * @param string $unmatched Unmatched leading portion. + * @param string $matched Actual token match. + * @param string $mode Mode after match. A boolean + * false mode causes no change. + * @param int $pos Current byte index location in raw doc + * thats being parsed + * @return boolean False if there was any error + * from the parser. + * @access private */ function _dispatchTokens($unmatched, $matched, $mode = false, $initialPos, $matchPos) { if (! $this->_invokeParser($unmatched, DOKU_LEXER_UNMATCHED, $initialPos) ){ @@ -456,50 +460,50 @@ class Doku_Lexer { } /** - * Tests to see if the new mode is actually to leave - * the current mode and pop an item from the matching - * mode stack. - * @param string $mode Mode to test. - * @return boolean True if this is the exit mode. - * @access private + * Tests to see if the new mode is actually to leave + * the current mode and pop an item from the matching + * mode stack. + * @param string $mode Mode to test. + * @return boolean True if this is the exit mode. + * @access private */ function _isModeEnd($mode) { return ($mode === "__exit"); } /** - * Test to see if the mode is one where this mode - * is entered for this token only and automatically - * leaves immediately afterwoods. - * @param string $mode Mode to test. - * @return boolean True if this is the exit mode. - * @access private + * Test to see if the mode is one where this mode + * is entered for this token only and automatically + * leaves immediately afterwoods. + * @param string $mode Mode to test. + * @return boolean True if this is the exit mode. + * @access private */ function _isSpecialMode($mode) { return (strncmp($mode, "_", 1) == 0); } /** - * Strips the magic underscore marking single token - * modes. - * @param string $mode Mode to decode. - * @return string Underlying mode name. - * @access private + * Strips the magic underscore marking single token + * modes. + * @param string $mode Mode to decode. + * @return string Underlying mode name. + * @access private */ function _decodeSpecial($mode) { return substr($mode, 1); } /** - * Calls the parser method named after the current - * mode. Empty content will be ignored. The lexer - * has a parser handler for each mode in the lexer. - * @param string $content Text parsed. - * @param boolean $is_match Token is recognised rather - * than unparsed data. - * @param int $pos Current byte index location in raw doc - * thats being parsed - * @access private + * Calls the parser method named after the current + * mode. Empty content will be ignored. The lexer + * has a parser handler for each mode in the lexer. + * @param string $content Text parsed. + * @param boolean $is_match Token is recognised rather + * than unparsed data. + * @param int $pos Current byte index location in raw doc + * thats being parsed + * @access private */ function _invokeParser($content, $is_match, $pos) { if (($content === "") || ($content === false)) { @@ -513,26 +517,26 @@ class Doku_Lexer { // 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) = explode('_',$handler,2); - return $this->_parser->$handler($content, $is_match, $pos, $plugin); + list($handler,$plugin) = explode('_',$handler,2); + return $this->_parser->$handler($content, $is_match, $pos, $plugin); } return $this->_parser->$handler($content, $is_match, $pos); } /** - * Tries to match a chunk of text and if successful - * removes the recognised chunk and any leading - * unparsed data. Empty strings will not be matched. - * @param string $raw The subject to parse. This is the - * content that will be eaten. - * @return array Three item list of unparsed - * content followed by the - * recognised token and finally the - * action the parser is to take. - * True if no match, false if there - * is a parsing error. - * @access private + * Tries to match a chunk of text and if successful + * removes the recognised chunk and any leading + * unparsed data. Empty strings will not be matched. + * @param string $raw The subject to parse. This is the + * content that will be eaten. + * @return array Three item list of unparsed + * content followed by the + * recognised token and finally the + * action the parser is to take. + * True if no match, false if there + * is a parsing error. + * @access private */ function _reduce(&$raw) { if (! isset($this->_regexes[$this->_mode->getCurrent()])) { @@ -550,9 +554,9 @@ class Doku_Lexer { } /** -* Escapes regex characters other than (, ) and / -* @TODO -*/ + * Escapes regex characters other than (, ) and / + * @TODO + */ function Doku_Lexer_Escape($str) { //$str = addslashes($str); $chars = array( diff --git a/inc/parser/metadata.php b/inc/parser/metadata.php index e17b82f8b..8ba159d62 100644 --- a/inc/parser/metadata.php +++ b/inc/parser/metadata.php @@ -23,422 +23,452 @@ require_once DOKU_INC . 'inc/parser/renderer.php'; */ class Doku_Renderer_metadata extends Doku_Renderer { - var $doc = ''; - var $meta = array(); - var $persistent = array(); + var $doc = ''; + var $meta = array(); + var $persistent = array(); - var $headers = array(); - var $capture = true; - var $store = ''; - var $firstimage = ''; + var $headers = array(); + var $capture = true; + var $store = ''; + var $firstimage = ''; - function getFormat(){ - return 'metadata'; - } + function getFormat(){ + return 'metadata'; + } + + function document_start(){ + global $ID; + + $this->headers = array(); + + // external pages are missing create date + if(!$this->persistent['date']['created']){ + $this->persistent['date']['created'] = filectime(wikiFN($ID)); + } + if(!isset($this->persistent['user'])){ + $this->persistent['user'] = ''; + } + if(!isset($this->persistent['creator'])){ + $this->persistent['creator'] = ''; + } + // reset metadata to persistent values + $this->meta = $this->persistent; + } + + function document_end(){ + global $ID; + + // store internal info in metadata (notoc,nocache) + $this->meta['internal'] = $this->info; - function document_start(){ - global $ID; + if (!isset($this->meta['description']['abstract'])){ + // cut off too long abstracts + $this->doc = trim($this->doc); + if (strlen($this->doc) > 500) + $this->doc = utf8_substr($this->doc, 0, 500).'…'; + $this->meta['description']['abstract'] = $this->doc; + } - $this->headers = array(); + $this->meta['relation']['firstimage'] = $this->firstimage; + + if(!isset($this->meta['date']['modified'])){ + $this->meta['date']['modified'] = filemtime(wikiFN($ID)); + } - // external pages are missing create date - if(!$this->persistent['date']['created']){ - $this->persistent['date']['created'] = filectime(wikiFN($ID)); } - if(!isset($this->persistent['user'])){ - $this->persistent['user'] = ''; + + function toc_additem($id, $text, $level) { + global $conf; + + //only add items within configured levels + if($level >= $conf['toptoclevel'] && $level <= $conf['maxtoclevel']){ + // the TOC is one of our standard ul list arrays ;-) + $this->meta['description']['tableofcontents'][] = array( + 'hid' => $id, + 'title' => $text, + 'type' => 'ul', + 'level' => $level-$conf['toptoclevel']+1 + ); + } + } - if(!isset($this->persistent['creator'])){ - $this->persistent['creator'] = ''; + + function header($text, $level, $pos) { + if (!isset($this->meta['title'])) $this->meta['title'] = $text; + + // add the header to the TOC + $hid = $this->_headerToLink($text,'true'); + $this->toc_additem($hid, $text, $level); + + // add to summary + if ($this->capture && ($level > 1)) $this->doc .= DOKU_LF.$text.DOKU_LF; } - // reset metadata to persistent values - $this->meta = $this->persistent; - } - function document_end(){ - global $ID; + function section_open($level){} + function section_close(){} - // store internal info in metadata (notoc,nocache) - $this->meta['internal'] = $this->info; + function cdata($text){ + if ($this->capture) $this->doc .= $text; + } - if (!isset($this->meta['description']['abstract'])){ - // cut off too long abstracts - $this->doc = trim($this->doc); - if (strlen($this->doc) > 500) - $this->doc = utf8_substr($this->doc, 0, 500).'…'; - $this->meta['description']['abstract'] = $this->doc; + function p_open(){ + if ($this->capture) $this->doc .= DOKU_LF; } - $this->meta['relation']['firstimage'] = $this->firstimage; + function p_close(){ + if ($this->capture){ + if (strlen($this->doc) > 250) $this->capture = false; + else $this->doc .= DOKU_LF; + } + } - if(!isset($this->meta['date']['modified'])){ - $this->meta['date']['modified'] = filemtime(wikiFN($ID)); + function linebreak(){ + if ($this->capture) $this->doc .= DOKU_LF; } - } + function hr(){ + if ($this->capture){ + if (strlen($this->doc) > 250) $this->capture = false; + else $this->doc .= DOKU_LF.'----------'.DOKU_LF; + } + } - function toc_additem($id, $text, $level) { - global $conf; + /** + * Callback for footnote start syntax + * + * All following content will go to the footnote instead of + * the document. To achieve this the previous rendered content + * is moved to $store and $doc is cleared + * + * @author Andreas Gohr <andi@splitbrain.org> + */ + function footnote_open() { + if ($this->capture){ + // move current content to store and record footnote + $this->store = $this->doc; + $this->doc = ''; + } + } - //only add items within configured levels - if($level >= $conf['toptoclevel'] && $level <= $conf['maxtoclevel']){ - // the TOC is one of our standard ul list arrays ;-) - $this->meta['description']['tableofcontents'][] = array( - 'hid' => $id, - 'title' => $text, - 'type' => 'ul', - 'level' => $level-$conf['toptoclevel']+1 - ); + /** + * Callback for footnote end syntax + * + * All rendered content is moved to the $footnotes array and the old + * content is restored from $store again + * + * @author Andreas Gohr + */ + function footnote_close() { + if ($this->capture){ + // restore old content + $this->doc = $this->store; + $this->store = ''; + } } - } + function listu_open(){ + if ($this->capture) $this->doc .= DOKU_LF; + } - function header($text, $level, $pos) { - if (!isset($this->meta['title'])) $this->meta['title'] = $text; + function listu_close(){ + if ($this->capture && (strlen($this->doc) > 250)) $this->capture = false; + } - // add the header to the TOC - $hid = $this->_headerToLink($text,'true'); - $this->toc_additem($hid, $text, $level); + function listo_open(){ + if ($this->capture) $this->doc .= DOKU_LF; + } - // add to summary - if ($this->capture && ($level > 1)) $this->doc .= DOKU_LF.$text.DOKU_LF; - } + function listo_close(){ + if ($this->capture && (strlen($this->doc) > 250)) $this->capture = false; + } - function section_open($level){} - function section_close(){} + function listitem_open($level){ + if ($this->capture) $this->doc .= str_repeat(DOKU_TAB, $level).'* '; + } - function cdata($text){ - if ($this->capture) $this->doc .= $text; - } + function listitem_close(){ + if ($this->capture) $this->doc .= DOKU_LF; + } - function p_open(){ - if ($this->capture) $this->doc .= DOKU_LF; - } + function listcontent_open(){} + function listcontent_close(){} - function p_close(){ - if ($this->capture){ - if (strlen($this->doc) > 250) $this->capture = false; - else $this->doc .= DOKU_LF; + function unformatted($text){ + if ($this->capture) $this->doc .= $text; } - } - function linebreak(){ - if ($this->capture) $this->doc .= DOKU_LF; - } + function preformatted($text){ + if ($this->capture) $this->doc .= $text; + } - function hr(){ - if ($this->capture){ - if (strlen($this->doc) > 250) $this->capture = false; - else $this->doc .= DOKU_LF.'----------'.DOKU_LF; + function file($text, $lang = null, $file = null){ + if ($this->capture){ + $this->doc .= DOKU_LF.$text; + if (strlen($this->doc) > 250) $this->capture = false; + else $this->doc .= DOKU_LF; + } } - } - /** - * Callback for footnote start syntax - * - * All following content will go to the footnote instead of - * the document. To achieve this the previous rendered content - * is moved to $store and $doc is cleared - * - * @author Andreas Gohr <andi@splitbrain.org> - */ - function footnote_open() { - if ($this->capture){ - // move current content to store and record footnote - $this->store = $this->doc; - $this->doc = ''; + function quote_open(){ + if ($this->capture) $this->doc .= DOKU_LF.DOKU_TAB.'"'; } - } - /** - * Callback for footnote end syntax - * - * All rendered content is moved to the $footnotes array and the old - * content is restored from $store again - * - * @author Andreas Gohr - */ - function footnote_close() { - if ($this->capture){ - // restore old content - $this->doc = $this->store; - $this->store = ''; - } - } - - function listu_open(){ - if ($this->capture) $this->doc .= DOKU_LF; - } - - function listu_close(){ - if ($this->capture && (strlen($this->doc) > 250)) $this->capture = false; - } - - function listo_open(){ - if ($this->capture) $this->doc .= DOKU_LF; - } - - function listo_close(){ - if ($this->capture && (strlen($this->doc) > 250)) $this->capture = false; - } - - function listitem_open($level){ - if ($this->capture) $this->doc .= str_repeat(DOKU_TAB, $level).'* '; - } - - function listitem_close(){ - if ($this->capture) $this->doc .= DOKU_LF; - } - - function listcontent_open(){} - function listcontent_close(){} - - function unformatted($text){ - if ($this->capture) $this->doc .= $text; - } - - function preformatted($text){ - if ($this->capture) $this->doc .= $text; - } - - function file($text, $lang = null, $file = null){ - if ($this->capture){ - $this->doc .= DOKU_LF.$text; - if (strlen($this->doc) > 250) $this->capture = false; - else $this->doc .= DOKU_LF; - } - } - - function quote_open(){ - if ($this->capture) $this->doc .= DOKU_LF.DOKU_TAB.'"'; - } - - function quote_close(){ - if ($this->capture){ - $this->doc .= '"'; - if (strlen($this->doc) > 250) $this->capture = false; - else $this->doc .= DOKU_LF; - } - } - - function code($text, $language = NULL, $file = null){ - if ($this->capture){ - $this->doc .= DOKU_LF.$text; - if (strlen($this->doc) > 250) $this->capture = false; - else $this->doc .= DOKU_LF; - } - } - - function acronym($acronym){ - if ($this->capture) $this->doc .= $acronym; - } - - function smiley($smiley){ - if ($this->capture) $this->doc .= $smiley; - } - - function entity($entity){ - if ($this->capture) $this->doc .= $entity; - } - - function multiplyentity($x, $y){ - if ($this->capture) $this->doc .= $x.'×'.$y; - } + function quote_close(){ + if ($this->capture){ + $this->doc .= '"'; + if (strlen($this->doc) > 250) $this->capture = false; + else $this->doc .= DOKU_LF; + } + } - function singlequoteopening(){ - global $lang; - if ($this->capture) $this->doc .= $lang['singlequoteopening']; - } + function code($text, $language = null, $file = null){ + if ($this->capture){ + $this->doc .= DOKU_LF.$text; + if (strlen($this->doc) > 250) $this->capture = false; + else $this->doc .= DOKU_LF; + } + } - function singlequoteclosing(){ - global $lang; - if ($this->capture) $this->doc .= $lang['singlequoteclosing']; - } + function acronym($acronym){ + if ($this->capture) $this->doc .= $acronym; + } - function apostrophe() { - global $lang; - if ($this->capture) $this->doc .= $lang['apostrophe']; - } + function smiley($smiley){ + if ($this->capture) $this->doc .= $smiley; + } - function doublequoteopening(){ - global $lang; - if ($this->capture) $this->doc .= $lang['doublequoteopening']; - } + function entity($entity){ + if ($this->capture) $this->doc .= $entity; + } - function doublequoteclosing(){ - global $lang; - if ($this->capture) $this->doc .= $lang['doublequoteclosing']; - } + function multiplyentity($x, $y){ + if ($this->capture) $this->doc .= $x.'×'.$y; + } - function camelcaselink($link) { - $this->internallink($link, $link); - } + function singlequoteopening(){ + global $lang; + if ($this->capture) $this->doc .= $lang['singlequoteopening']; + } - function locallink($hash, $name = NULL){} + function singlequoteclosing(){ + global $lang; + if ($this->capture) $this->doc .= $lang['singlequoteclosing']; + } - /** - * keep track of internal links in $this->meta['relation']['references'] - */ - function internallink($id, $name = NULL){ - global $ID; + function apostrophe() { + global $lang; + if ($this->capture) $this->doc .= $lang['apostrophe']; + } - if(is_array($name)) - $this->_firstimage($name['src']); + function doublequoteopening(){ + global $lang; + if ($this->capture) $this->doc .= $lang['doublequoteopening']; + } - $default = $this->_simpleTitle($id); - - // first resolve and clean up the $id - resolve_pageid(getNS($ID), $id, $exists); - list($page, $hash) = explode('#', $id, 2); - - // set metadata - $this->meta['relation']['references'][$page] = $exists; - // $data = array('relation' => array('isreferencedby' => array($ID => true))); - // p_set_metadata($id, $data); - - // add link title to summary - if ($this->capture){ - $name = $this->_getLinkTitle($name, $default, $id); - $this->doc .= $name; - } - } - - function externallink($url, $name = NULL){ - if(is_array($name)) - $this->_firstimage($name['src']); - - if ($this->capture){ - $this->doc .= $this->_getLinkTitle($name, '<' . $url . '>'); - } - } - - function interwikilink($match, $name = NULL, $wikiName, $wikiUri){ - if(is_array($name)) - $this->_firstimage($name['src']); - - if ($this->capture){ - list($wikiUri, $hash) = explode('#', $wikiUri, 2); - $name = $this->_getLinkTitle($name, $wikiUri); - $this->doc .= $name; - } - } - - function windowssharelink($url, $name = NULL){ - if(is_array($name)) - $this->_firstimage($name['src']); - - if ($this->capture){ - if ($name) $this->doc .= $name; - else $this->doc .= '<'.$url.'>'; - } - } - - function emaillink($address, $name = NULL){ - if(is_array($name)) - $this->_firstimage($name['src']); - - if ($this->capture){ - if ($name) $this->doc .= $name; - else $this->doc .= '<'.$address.'>'; - } - } - - function internalmedia($src, $title=NULL, $align=NULL, $width=NULL, - $height=NULL, $cache=NULL, $linking=NULL){ - if ($this->capture && $title) $this->doc .= '['.$title.']'; - $this->_firstimage($src); - } - - function externalmedia($src, $title=NULL, $align=NULL, $width=NULL, - $height=NULL, $cache=NULL, $linking=NULL){ - if ($this->capture && $title) $this->doc .= '['.$title.']'; - $this->_firstimage($src); - } - - function rss($url,$params) { - $this->meta['relation']['haspart'][$url] = true; - - $this->meta['date']['valid']['age'] = - isset($this->meta['date']['valid']['age']) ? - min($this->meta['date']['valid']['age'],$params['refresh']) : - $params['refresh']; - } - - //---------------------------------------------------------- - // Utils - - /** - * Removes any Namespace from the given name but keeps - * casing and special chars - * - * @author Andreas Gohr <andi@splitbrain.org> - */ - function _simpleTitle($name){ - global $conf; - - if(is_array($name)) return ''; - - if($conf['useslash']){ - $nssep = '[:;/]'; - }else{ - $nssep = '[:;]'; - } - $name = preg_replace('!.*'.$nssep.'!','',$name); - //if there is a hash we use the anchor name only - $name = preg_replace('!.*#!','',$name); - return $name; - } - - /** - * Creates a linkid from a headline - * - * @param string $title The headline title - * @param boolean $create Create a new unique ID? - * @author Andreas Gohr <andi@splitbrain.org> - */ - function _headerToLink($title, $create=false) { - if($create){ - return sectionID($title,$this->headers); - }else{ - $check = false; - return sectionID($title,$check); - } - } - - /** - * Construct a title and handle images in titles - * - * @author Harry Fuecks <hfuecks@gmail.com> - */ - function _getLinkTitle($title, $default, $id=NULL) { - global $conf; - - $isImage = false; - if (is_array($title)){ - if($title['title']) return '['.$title['title'].']'; - } else if (is_null($title) || trim($title)==''){ - if (useHeading('content') && $id){ - $heading = p_get_first_heading($id,METADATA_DONT_RENDER); - if ($heading) return $heading; - } - return $default; - } else { - return $title; + function doublequoteclosing(){ + global $lang; + if ($this->capture) $this->doc .= $lang['doublequoteclosing']; } - } - function _firstimage($src){ - if($this->firstimage) return; - global $ID; + function camelcaselink($link) { + $this->internallink($link, $link); + } + + function locallink($hash, $name = null){ + if(is_array($name)) { + $this->_firstimage($name['src']); + if ($name['type'] == 'internalmedia') $this->_recordMediaUsage($name['src']); + } + } - list($src,$hash) = explode('#',$src,2); - if(!media_isexternal($src)){ - resolve_mediaid(getNS($ID),$src, $exists); + /** + * keep track of internal links in $this->meta['relation']['references'] + */ + function internallink($id, $name = null){ + global $ID; + + if(is_array($name)) { + $this->_firstimage($name['src']); + if ($name['type'] == 'internalmedia') $this->_recordMediaUsage($name['src']); + } + + $parts = explode('?', $id, 2); + if (count($parts) === 2) { + $id = $parts[0]; + } + + $default = $this->_simpleTitle($id); + + // first resolve and clean up the $id + resolve_pageid(getNS($ID), $id, $exists); + list($page, $hash) = explode('#', $id, 2); + + // set metadata + $this->meta['relation']['references'][$page] = $exists; + // $data = array('relation' => array('isreferencedby' => array($ID => true))); + // p_set_metadata($id, $data); + + // add link title to summary + if ($this->capture){ + $name = $this->_getLinkTitle($name, $default, $id); + $this->doc .= $name; + } } - if(preg_match('/.(jpe?g|gif|png)$/i',$src)){ - $this->firstimage = $src; + + function externallink($url, $name = null){ + if(is_array($name)) { + $this->_firstimage($name['src']); + if ($name['type'] == 'internalmedia') $this->_recordMediaUsage($name['src']); + } + + if ($this->capture){ + $this->doc .= $this->_getLinkTitle($name, '<' . $url . '>'); + } + } + + function interwikilink($match, $name = null, $wikiName, $wikiUri){ + if(is_array($name)) { + $this->_firstimage($name['src']); + if ($name['type'] == 'internalmedia') $this->_recordMediaUsage($name['src']); + } + + if ($this->capture){ + list($wikiUri, $hash) = explode('#', $wikiUri, 2); + $name = $this->_getLinkTitle($name, $wikiUri); + $this->doc .= $name; + } + } + + function windowssharelink($url, $name = null){ + if(is_array($name)) { + $this->_firstimage($name['src']); + if ($name['type'] == 'internalmedia') $this->_recordMediaUsage($name['src']); + } + + if ($this->capture){ + if ($name) $this->doc .= $name; + else $this->doc .= '<'.$url.'>'; + } + } + + function emaillink($address, $name = null){ + if(is_array($name)) { + $this->_firstimage($name['src']); + if ($name['type'] == 'internalmedia') $this->_recordMediaUsage($name['src']); + } + + if ($this->capture){ + if ($name) $this->doc .= $name; + else $this->doc .= '<'.$address.'>'; + } + } + + function internalmedia($src, $title=null, $align=null, $width=null, + $height=null, $cache=null, $linking=null){ + if ($this->capture && $title) $this->doc .= '['.$title.']'; + $this->_firstimage($src); + $this->_recordMediaUsage($src); + } + + function externalmedia($src, $title=null, $align=null, $width=null, + $height=null, $cache=null, $linking=null){ + if ($this->capture && $title) $this->doc .= '['.$title.']'; + $this->_firstimage($src); + } + + function rss($url,$params) { + $this->meta['relation']['haspart'][$url] = true; + + $this->meta['date']['valid']['age'] = + isset($this->meta['date']['valid']['age']) ? + min($this->meta['date']['valid']['age'],$params['refresh']) : + $params['refresh']; + } + + //---------------------------------------------------------- + // Utils + + /** + * Removes any Namespace from the given name but keeps + * casing and special chars + * + * @author Andreas Gohr <andi@splitbrain.org> + */ + function _simpleTitle($name){ + global $conf; + + if(is_array($name)) return ''; + + if($conf['useslash']){ + $nssep = '[:;/]'; + }else{ + $nssep = '[:;]'; + } + $name = preg_replace('!.*'.$nssep.'!','',$name); + //if there is a hash we use the anchor name only + $name = preg_replace('!.*#!','',$name); + return $name; + } + + /** + * Creates a linkid from a headline + * + * @param string $title The headline title + * @param boolean $create Create a new unique ID? + * @author Andreas Gohr <andi@splitbrain.org> + */ + function _headerToLink($title, $create=false) { + if($create){ + return sectionID($title,$this->headers); + }else{ + $check = false; + return sectionID($title,$check); + } + } + + /** + * Construct a title and handle images in titles + * + * @author Harry Fuecks <hfuecks@gmail.com> + */ + function _getLinkTitle($title, $default, $id=null) { + global $conf; + + $isImage = false; + if (is_array($title)){ + if($title['title']) return '['.$title['title'].']'; + } else if (is_null($title) || trim($title)==''){ + if (useHeading('content') && $id){ + $heading = p_get_first_heading($id,METADATA_DONT_RENDER); + if ($heading) return $heading; + } + return $default; + } else { + return $title; + } + } + + function _firstimage($src){ + if($this->firstimage) return; + global $ID; + + list($src,$hash) = explode('#',$src,2); + if(!media_isexternal($src)){ + resolve_mediaid(getNS($ID),$src, $exists); + } + if(preg_match('/.(jpe?g|gif|png)$/i',$src)){ + $this->firstimage = $src; + } + } + + function _recordMediaUsage($src) { + global $ID; + + list ($src, $hash) = explode('#', $src, 2); + if (media_isexternal($src)) return; + resolve_mediaid(getNS($ID), $src, $exists); + $this->meta['relation']['media'][$src] = $exists; } - } } //Setup VIM: ex: et ts=4 : diff --git a/inc/parser/parser.php b/inc/parser/parser.php index 915899f53..e39a4daf5 100644 --- a/inc/parser/parser.php +++ b/inc/parser/parser.php @@ -45,9 +45,9 @@ $PARSER_MODES = array( //------------------------------------------------------------------- /** -* Sets up the Lexer with modes and points it to the Handler -* For an intro to the Lexer see: wiki:parser -*/ + * Sets up the Lexer with modes and points it to the Handler + * For an intro to the Lexer see: wiki:parser + */ class Doku_Parser { var $Handler; @@ -70,9 +70,9 @@ class Doku_Parser { } /** - * PHP preserves order of associative elements - * Mode sequence is important - */ + * PHP preserves order of associative elements + * Mode sequence is important + */ function addMode($name, & $Mode) { if ( !isset($this->modes['base']) ) { $this->addBaseMode(new Doku_Parser_Mode_base()); @@ -134,7 +134,7 @@ class Doku_Parser { * all modes are registered * * @author Harry Fuecks <hfuecks@gmail.com> -*/ + */ class Doku_Parser_Mode { /** @@ -454,8 +454,8 @@ class Doku_Parser_Mode_table extends Doku_Parser_Mode { } function connectTo($mode) { - $this->Lexer->addEntryPattern('\n\^',$mode,'table'); - $this->Lexer->addEntryPattern('\n\|',$mode,'table'); + $this->Lexer->addEntryPattern('\s*\n\^',$mode,'table'); + $this->Lexer->addEntryPattern('\s*\n\|',$mode,'table'); } function postConnect() { @@ -555,7 +555,7 @@ class Doku_Parser_Mode_preformatted extends Doku_Parser_Mode { class Doku_Parser_Mode_code extends Doku_Parser_Mode { function connectTo($mode) { - $this->Lexer->addEntryPattern('<code(?=.*</code>)',$mode,'code'); + $this->Lexer->addEntryPattern('<code\b(?=.*</code>)',$mode,'code'); } function postConnect() { @@ -571,7 +571,7 @@ class Doku_Parser_Mode_code extends Doku_Parser_Mode { class Doku_Parser_Mode_file extends Doku_Parser_Mode { function connectTo($mode) { - $this->Lexer->addEntryPattern('<file(?=.*</file>)',$mode,'file'); + $this->Lexer->addEntryPattern('<file\b(?=.*</file>)',$mode,'file'); } function postConnect() { @@ -621,7 +621,7 @@ class Doku_Parser_Mode_acronym extends Doku_Parser_Mode { var $pattern = ''; function Doku_Parser_Mode_acronym($acronyms) { - usort($acronyms,array($this,'_compare')); + usort($acronyms,array($this,'_compare')); $this->acronyms = $acronyms; } @@ -652,12 +652,12 @@ class Doku_Parser_Mode_acronym extends Doku_Parser_Mode { $a_len = strlen($a); $b_len = strlen($b); if ($a_len > $b_len) { - return -1; + return -1; } else if ($a_len < $b_len) { - return 1; + return 1; } - return 0; + return 0; } } @@ -807,7 +807,6 @@ class Doku_Parser_Mode_quotes extends Doku_Parser_Mode { "\"",$mode,'doublequoteclosing' ); - } function getSort() { diff --git a/inc/parser/renderer.php b/inc/parser/renderer.php index 7df369478..c697e990c 100644 --- a/inc/parser/renderer.php +++ b/inc/parser/renderer.php @@ -74,12 +74,12 @@ class Doku_Renderer extends DokuWiki_Plugin { */ function nest($instructions) { - foreach ( $instructions as $instruction ) { - // execute the callback against ourself - if (method_exists($this,$instruction[0])) { - call_user_func_array(array($this, $instruction[0]), $instruction[1] ? $instruction[1] : array()); + foreach ( $instructions as $instruction ) { + // execute the callback against ourself + if (method_exists($this,$instruction[0])) { + call_user_func_array(array($this, $instruction[0]), $instruction[1] ? $instruction[1] : array()); + } } - } } // dummy closing instruction issued by Doku_Handler_Nest, normally the syntax mode should @@ -203,42 +203,42 @@ class Doku_Renderer extends DokuWiki_Plugin { // $link like 'SomePage' function camelcaselink($link) {} - function locallink($hash, $name = NULL) {} + function locallink($hash, $name = null) {} // $link like 'wiki:syntax', $title could be an array (media) - function internallink($link, $title = NULL) {} + function internallink($link, $title = null) {} // $link is full URL with scheme, $title could be an array (media) - function externallink($link, $title = NULL) {} + function externallink($link, $title = null) {} function rss ($url,$params) {} // $link is the original link - probably not much use // $wikiName is an indentifier for the wiki // $wikiUri is the URL fragment to append to some known URL - function interwikilink($link, $title = NULL, $wikiName, $wikiUri) {} + function interwikilink($link, $title = null, $wikiName, $wikiUri) {} // Link to file on users OS, $title could be an array (media) - function filelink($link, $title = NULL) {} + function filelink($link, $title = null) {} // Link to a Windows share, , $title could be an array (media) - function windowssharelink($link, $title = NULL) {} + function windowssharelink($link, $title = null) {} -// function email($address, $title = NULL) {} - function emaillink($address, $name = NULL) {} +// function email($address, $title = null) {} + function emaillink($address, $name = null) {} - function internalmedia ($src, $title=NULL, $align=NULL, $width=NULL, - $height=NULL, $cache=NULL, $linking=NULL) {} + function internalmedia ($src, $title=null, $align=null, $width=null, + $height=null, $cache=null, $linking=null) {} - function externalmedia ($src, $title=NULL, $align=NULL, $width=NULL, - $height=NULL, $cache=NULL, $linking=NULL) {} + function externalmedia ($src, $title=null, $align=null, $width=null, + $height=null, $cache=null, $linking=null) {} function internalmedialink ( - $src,$title=NULL,$align=NULL,$width=NULL,$height=NULL,$cache=NULL + $src,$title=null,$align=null,$width=null,$height=null,$cache=null ) {} function externalmedialink( - $src,$title=NULL,$align=NULL,$width=NULL,$height=NULL,$cache=NULL + $src,$title=null,$align=null,$width=null,$height=null,$cache=null ) {} function table_open($maxcols = null, $numrows = null, $pos = null){} @@ -249,11 +249,11 @@ class Doku_Renderer extends DokuWiki_Plugin { function tablerow_close(){} - function tableheader_open($colspan = 1, $align = NULL, $rowspan = 1){} + function tableheader_open($colspan = 1, $align = null, $rowspan = 1){} function tableheader_close(){} - function tablecell_open($colspan = 1, $align = NULL, $rowspan = 1){} + function tablecell_open($colspan = 1, $align = null, $rowspan = 1){} function tablecell_close(){} diff --git a/inc/parser/xhtml.php b/inc/parser/xhtml.php index 84a999e56..fd02c0ce0 100644 --- a/inc/parser/xhtml.php +++ b/inc/parser/xhtml.php @@ -33,6 +33,7 @@ class Doku_Renderer_xhtml extends Doku_Renderer { private $lastsecid = 0; // last section edit id, used by startSectionEdit var $headers = array(); + /** @var array a list of footnotes, list starts at 1! */ var $footnotes = array(); var $lastlevel = 0; var $node = array(0,0,0,0,0); @@ -59,7 +60,7 @@ class Doku_Renderer_xhtml extends Doku_Renderer { * Finish an edit section range * * @param $end int The byte position for the edit end; null for the rest of - the page + * the page * @author Adrian Lang <lang@cosmocode.de> */ public function finishSectionEdit($end = null) { @@ -100,10 +101,7 @@ class Doku_Renderer_xhtml extends Doku_Renderer { if ( count ($this->footnotes) > 0 ) { $this->doc .= '<div class="footnotes">'.DOKU_LF; - $id = 0; - foreach ( $this->footnotes as $footnote ) { - $id++; // the number of the current footnote - + foreach ( $this->footnotes as $id => $footnote ) { // check its not a placeholder that indicates actual footnote text is elsewhere if (substr($footnote, 0, 5) != "@@FNT") { @@ -116,11 +114,11 @@ class Doku_Renderer_xhtml extends Doku_Renderer { $alt = array_keys($this->footnotes, "@@FNT$id"); if (count($alt)) { - foreach ($alt as $ref) { - // set anchor and backlink for the other footnotes - $this->doc .= ', <sup><a href="#fnt__'.($ref+1).'" id="fn__'.($ref+1).'" class="fn_bot">'; - $this->doc .= ($ref+1).')</a></sup> '.DOKU_LF; - } + foreach ($alt as $ref) { + // set anchor and backlink for the other footnotes + $this->doc .= ', <sup><a href="#fnt__'.($ref).'" id="fn__'.($ref).'" class="fn_bot">'; + $this->doc .= ($ref).')</a></sup> '.DOKU_LF; + } } // add footnote markup and close this footnote @@ -295,6 +293,10 @@ class Doku_Renderer_xhtml extends Doku_Renderer { * @author Andreas Gohr */ function footnote_close() { + /** @var $fnid int takes track of seen footnotes, assures they are unique even across multiple docs FS#2841 */ + static $fnid = 0; + // assign new footnote id (we start at 1) + $fnid++; // recover footnote into the stack and restore old content $footnote = $this->doc; @@ -306,17 +308,14 @@ class Doku_Renderer_xhtml extends Doku_Renderer { if ($i === false) { // its a new footnote, add it to the $footnotes array - $id = count($this->footnotes)+1; - $this->footnotes[count($this->footnotes)] = $footnote; + $this->footnotes[$fnid] = $footnote; } else { - // seen this one before, translate the index to an id and save a placeholder - $i++; - $id = count($this->footnotes)+1; - $this->footnotes[count($this->footnotes)] = "@@FNT".($i); + // seen this one before, save a placeholder + $this->footnotes[$fnid] = "@@FNT".($i); } // output the footnote reference and link - $this->doc .= '<sup><a href="#fn__'.$id.'" id="fnt__'.$id.'" class="fn_top">'.$id.')</a></sup>'; + $this->doc .= '<sup><a href="#fn__'.$fnid.'" id="fnt__'.$fnid.'" class="fn_top">'.$fnid.')</a></sup>'; } function listu_open() { @@ -367,12 +366,12 @@ class Doku_Renderer_xhtml extends Doku_Renderer { global $conf; if($conf['phpok']){ - ob_start(); - eval($text); - $this->doc .= ob_get_contents(); - ob_end_clean(); + ob_start(); + eval($text); + $this->doc .= ob_get_contents(); + ob_end_clean(); } else { - $this->doc .= p_xhtml_cached_geshi($text, 'php', $wrapper); + $this->doc .= p_xhtml_cached_geshi($text, 'php', $wrapper); } } @@ -392,9 +391,9 @@ class Doku_Renderer_xhtml extends Doku_Renderer { global $conf; if($conf['htmlok']){ - $this->doc .= $text; + $this->doc .= $text; } else { - $this->doc .= p_xhtml_cached_geshi($text, 'html4strict', $wrapper); + $this->doc .= p_xhtml_cached_geshi($text, 'html4strict', $wrapper); } } @@ -541,13 +540,13 @@ class Doku_Renderer_xhtml extends Doku_Renderer { } /** - */ + */ function camelcaselink($link) { - $this->internallink($link,$link); + $this->internallink($link,$link); } - function locallink($hash, $name = NULL){ + function locallink($hash, $name = null){ global $ID; $name = $this->_getLinkTitle($name, $hash, $isImage); $hash = $this->_headerToLink($hash); @@ -565,7 +564,7 @@ class Doku_Renderer_xhtml extends Doku_Renderer { * * @author Andreas Gohr <andi@splitbrain.org> */ - function internallink($id, $name = NULL, $search=NULL,$returnonly=false,$linktype='content') { + function internallink($id, $name = null, $search=null,$returnonly=false,$linktype='content') { global $conf; global $ID; global $INFO; @@ -644,7 +643,7 @@ class Doku_Renderer_xhtml extends Doku_Renderer { } } - function externallink($url, $name = NULL) { + function externallink($url, $name = null) { global $conf; $name = $this->_getLinkTitle($name, $url, $isImage); @@ -687,7 +686,7 @@ class Doku_Renderer_xhtml extends Doku_Renderer { /** */ - function interwikilink($match, $name = NULL, $wikiName, $wikiUri) { + function interwikilink($match, $name = null, $wikiName, $wikiUri) { global $conf; $link = array(); @@ -721,7 +720,7 @@ class Doku_Renderer_xhtml extends Doku_Renderer { /** */ - function windowssharelink($url, $name = NULL) { + function windowssharelink($url, $name = null) { global $conf; global $lang; //simple setup @@ -737,7 +736,6 @@ class Doku_Renderer_xhtml extends Doku_Renderer { $link['class'] = 'media'; } - $link['title'] = $this->_xmlEntities($url); $url = str_replace('\\','/',$url); $url = 'file:///'.$url; @@ -747,7 +745,7 @@ class Doku_Renderer_xhtml extends Doku_Renderer { $this->doc .= $this->_formatLink($link); } - function emaillink($address, $name = NULL) { + function emaillink($address, $name = null) { global $conf; //simple setup $link = array(); @@ -782,8 +780,8 @@ class Doku_Renderer_xhtml extends Doku_Renderer { $this->doc .= $this->_formatLink($link); } - function internalmedia ($src, $title=NULL, $align=NULL, $width=NULL, - $height=NULL, $cache=NULL, $linking=NULL) { + function internalmedia ($src, $title=null, $align=null, $width=null, + $height=null, $cache=null, $linking=null) { global $ID; list($src,$hash) = explode('#',$src,2); resolve_mediaid(getNS($ID),$src, $exists); @@ -818,8 +816,8 @@ class Doku_Renderer_xhtml extends Doku_Renderer { else $this->doc .= $this->_formatLink($link); } - function externalmedia ($src, $title=NULL, $align=NULL, $width=NULL, - $height=NULL, $cache=NULL, $linking=NULL) { + function externalmedia ($src, $title=null, $align=null, $width=null, + $height=null, $cache=null, $linking=null) { list($src,$hash) = explode('#',$src,2); $noLink = false; $render = ($linking == 'linkonly') ? false : true; @@ -875,7 +873,7 @@ class Doku_Renderer_xhtml extends Doku_Renderer { $mod = 1; $start = 0; $end = $feed->get_item_quantity(); - $end = ($end > $params['max']) ? $params['max'] : $end;; + $end = ($end > $params['max']) ? $params['max'] : $end; } $this->doc .= '<ul class="rss">'; @@ -959,7 +957,7 @@ class Doku_Renderer_xhtml extends Doku_Renderer { $this->doc .= DOKU_LF . DOKU_TAB . '</tr>' . DOKU_LF; } - function tableheader_open($colspan = 1, $align = NULL, $rowspan = 1){ + function tableheader_open($colspan = 1, $align = null, $rowspan = 1){ $class = 'class="col' . $this->_counter['cell_counter']++; if ( !is_null($align) ) { $class .= ' '.$align.'align'; @@ -980,7 +978,7 @@ class Doku_Renderer_xhtml extends Doku_Renderer { $this->doc .= '</th>'; } - function tablecell_open($colspan = 1, $align = NULL, $rowspan = 1){ + function tablecell_open($colspan = 1, $align = null, $rowspan = 1){ $class = 'class="col' . $this->_counter['cell_counter']++; if ( !is_null($align) ) { $class .= ' '.$align.'align'; @@ -1046,8 +1044,8 @@ class Doku_Renderer_xhtml extends Doku_Renderer { * * @author Andreas Gohr <andi@splitbrain.org> */ - function _media ($src, $title=NULL, $align=NULL, $width=NULL, - $height=NULL, $cache=NULL, $render = true) { + function _media ($src, $title=null, $align=null, $width=null, + $height=null, $cache=null, $render = true) { $ret = ''; @@ -1149,7 +1147,7 @@ class Doku_Renderer_xhtml extends Doku_Renderer { * * @author Harry Fuecks <hfuecks@gmail.com> */ - function _getLinkTitle($title, $default, & $isImage, $id=NULL, $linktype='content') { + function _getLinkTitle($title, $default, & $isImage, $id=null, $linktype='content') { global $conf; $isImage = false; @@ -1208,8 +1206,7 @@ class Doku_Renderer_xhtml extends Doku_Renderer { * @access protected * @return array */ - function _getMediaLinkConf($src, $title, $align, $width, $height, $cache, $render) - { + function _getMediaLinkConf($src, $title, $align, $width, $height, $cache, $render) { global $conf; $link = array(); |