summaryrefslogtreecommitdiff
path: root/inc/parser/xhtml.php
diff options
context:
space:
mode:
authorAndreas Gohr <andi@splitbrain.org>2014-09-29 20:17:39 +0200
committerAndreas Gohr <andi@splitbrain.org>2014-09-29 20:17:39 +0200
commit6c1ae996157551dcf5bb4e7e8922677bb3d3d358 (patch)
treeb3a4162367176a4e2ebadbd6ab31753c1b042be0 /inc/parser/xhtml.php
parent35f3340eb3b989194a496861abfb5b3d3c9a630d (diff)
parent57271d078b9c433bec79d75cb44dadcafeae07df (diff)
downloadrpg-6c1ae996157551dcf5bb4e7e8922677bb3d3d358.tar.gz
rpg-6c1ae996157551dcf5bb4e7e8922677bb3d3d358.tar.bz2
Merge branch 'master' into stable
* master: (214 commits) release preparations postgresql auth plugin: correct function name parse AT parameter: first strtotime then timestamp remove config option move more strings to lang.php move strings to lang.php add placeholders for create page text phpdocs parserutils improve some scrutinizer issues visibility plugin methods use config cascade for loading of localizations reformatting config cascade add lang files to cascading work around missing gzopen on certain systems #865 translation update fix scrutinizer issues fixed typos in docblock comments do not allow empty passwords clean user credentials from control chars added filter method to INPUT class translation update ...
Diffstat (limited to 'inc/parser/xhtml.php')
-rw-r--r--inc/parser/xhtml.php1098
1 files changed, 750 insertions, 348 deletions
diff --git a/inc/parser/xhtml.php b/inc/parser/xhtml.php
index cf36a8175..5627a0353 100644
--- a/inc/parser/xhtml.php
+++ b/inc/parser/xhtml.php
@@ -7,37 +7,54 @@
*/
if(!defined('DOKU_INC')) die('meh.');
-if ( !defined('DOKU_LF') ) {
+if(!defined('DOKU_LF')) {
// Some whitespace to help View > Source
- define ('DOKU_LF',"\n");
+ define ('DOKU_LF', "\n");
}
-if ( !defined('DOKU_TAB') ) {
+if(!defined('DOKU_TAB')) {
// Some whitespace to help View > Source
- define ('DOKU_TAB',"\t");
+ define ('DOKU_TAB', "\t");
}
/**
- * The Renderer
+ * The XHTML Renderer
+ *
+ * This is DokuWiki's main renderer used to display page content in the wiki
*/
class Doku_Renderer_xhtml extends Doku_Renderer {
+ /** @var array store the table of contents */
+ public $toc = array();
+
+ /** @var array A stack of section edit data */
+ protected $sectionedits = array();
+ var $date_at = ''; // link pages and media against this revision
- // @access public
- var $doc = ''; // will contain the whole document
- var $toc = array(); // will contain the Table of Contents
+ /** @var int last section edit id, used by startSectionEdit */
+ protected $lastsecid = 0;
- var $sectionedits = array(); // A stack of section edit data
- private $lastsecid = 0; // last section edit id, used by startSectionEdit
+ /** @var array the list of headers used to create unique link ids */
+ protected $headers = array();
- 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);
- var $store = '';
+ protected $footnotes = array();
+
+ /** @var int current section level */
+ protected $lastlevel = 0;
+ /** @var array section node tracker */
+ protected $node = array(0, 0, 0, 0, 0);
+
+ /** @var string temporary $doc store */
+ protected $store = '';
- var $_counter = array(); // used as global counter, introduced for table classes
- var $_codeblock = 0; // counts the code and file blocks, used to provide download links
+ /** @var array global counter, for table classes etc. */
+ protected $_counter = array(); //
+
+ /** @var int counts the code and file blocks, used to provide download links */
+ protected $_codeblock = 0;
+
+ /** @var array list of allowed URL schemes */
+ protected $schemes = null;
/**
* Register a new edit section range
@@ -50,43 +67,53 @@ class Doku_Renderer_xhtml extends Doku_Renderer {
*/
public function startSectionEdit($start, $type, $title = null) {
$this->sectionedits[] = array(++$this->lastsecid, $start, $type, $title);
- return 'sectionedit' . $this->lastsecid;
+ return 'sectionedit'.$this->lastsecid;
}
/**
* Finish an edit section range
*
- * @param $end int The byte position for the edit end; null for the rest of
+ * @param $end int The byte position for the edit end; null for the rest of
* the page
* @author Adrian Lang <lang@cosmocode.de>
*/
public function finishSectionEdit($end = null) {
list($id, $start, $type, $title) = array_pop($this->sectionedits);
- if (!is_null($end) && $end <= $start) {
+ if(!is_null($end) && $end <= $start) {
return;
}
- $this->doc .= "<!-- EDIT$id " . strtoupper($type) . ' ';
- if (!is_null($title)) {
- $this->doc .= '"' . str_replace('"', '', $title) . '" ';
+ $this->doc .= "<!-- EDIT$id ".strtoupper($type).' ';
+ if(!is_null($title)) {
+ $this->doc .= '"'.str_replace('"', '', $title).'" ';
}
- $this->doc .= "[$start-" . (is_null($end) ? '' : $end) . '] -->';
+ $this->doc .= "[$start-".(is_null($end) ? '' : $end).'] -->';
}
- function getFormat(){
+ /**
+ * Returns the format produced by this renderer.
+ *
+ * @return string always 'xhtml'
+ */
+ function getFormat() {
return 'xhtml';
}
-
+ /**
+ * Initialize the document
+ */
function document_start() {
//reset some internals
$this->toc = array();
$this->headers = array();
}
+ /**
+ * Finalize the document
+ */
function document_end() {
// Finish open section edits.
- while (count($this->sectionedits) > 0) {
- if ($this->sectionedits[count($this->sectionedits) - 1][1] <= 1) {
+ while(count($this->sectionedits) > 0) {
+ if($this->sectionedits[count($this->sectionedits) - 1][1] <= 1) {
// If there is only one section, do not write a section edit
// marker.
array_pop($this->sectionedits);
@@ -95,12 +122,12 @@ class Doku_Renderer_xhtml extends Doku_Renderer {
}
}
- if ( count ($this->footnotes) > 0 ) {
+ if(count($this->footnotes) > 0) {
$this->doc .= '<div class="footnotes">'.DOKU_LF;
- foreach ( $this->footnotes as $id => $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") {
+ if(substr($footnote, 0, 5) != "@@FNT") {
// open the footnote and set the anchor and backlink
$this->doc .= '<div class="fn">';
@@ -110,8 +137,8 @@ class Doku_Renderer_xhtml extends Doku_Renderer {
// get any other footnotes that use the same markup
$alt = array_keys($this->footnotes, "@@FNT$id");
- if (count($alt)) {
- foreach ($alt as $ref) {
+ if(count($alt)) {
+ 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;
@@ -120,7 +147,7 @@ class Doku_Renderer_xhtml extends Doku_Renderer {
// add footnote markup and close this footnote
$this->doc .= $footnote;
- $this->doc .= '</div>' . DOKU_LF;
+ $this->doc .= '</div>'.DOKU_LF;
}
}
$this->doc .= '</div>'.DOKU_LF;
@@ -128,139 +155,221 @@ class Doku_Renderer_xhtml extends Doku_Renderer {
// Prepare the TOC
global $conf;
- if($this->info['toc'] && is_array($this->toc) && $conf['tocminheads'] && count($this->toc) >= $conf['tocminheads']){
+ if($this->info['toc'] && is_array($this->toc) && $conf['tocminheads'] && count($this->toc) >= $conf['tocminheads']) {
global $TOC;
$TOC = $this->toc;
}
// make sure there are no empty paragraphs
- $this->doc = preg_replace('#<p>\s*</p>#','',$this->doc);
+ $this->doc = preg_replace('#<p>\s*</p>#', '', $this->doc);
}
+ /**
+ * Add an item to the TOC
+ *
+ * @param string $id the hash link
+ * @param string $text the text to display
+ * @param int $level the nesting level
+ */
function toc_additem($id, $text, $level) {
global $conf;
//handle TOC
- if($level >= $conf['toptoclevel'] && $level <= $conf['maxtoclevel']){
- $this->toc[] = html_mktocitem($id, $text, $level-$conf['toptoclevel']+1);
+ if($level >= $conf['toptoclevel'] && $level <= $conf['maxtoclevel']) {
+ $this->toc[] = html_mktocitem($id, $text, $level - $conf['toptoclevel'] + 1);
}
}
+ /**
+ * Render a heading
+ *
+ * @param string $text the text to display
+ * @param int $level header level
+ * @param int $pos byte position in the original source
+ */
function header($text, $level, $pos) {
global $conf;
if(!$text) return; //skip empty headlines
- $hid = $this->_headerToLink($text,true);
+ $hid = $this->_headerToLink($text, true);
//only add items within configured levels
$this->toc_additem($hid, $text, $level);
// adjust $node to reflect hierarchy of levels
- $this->node[$level-1]++;
- if ($level < $this->lastlevel) {
- for ($i = 0; $i < $this->lastlevel-$level; $i++) {
- $this->node[$this->lastlevel-$i-1] = 0;
+ $this->node[$level - 1]++;
+ if($level < $this->lastlevel) {
+ for($i = 0; $i < $this->lastlevel - $level; $i++) {
+ $this->node[$this->lastlevel - $i - 1] = 0;
}
}
$this->lastlevel = $level;
- if ($level <= $conf['maxseclevel'] &&
+ if($level <= $conf['maxseclevel'] &&
count($this->sectionedits) > 0 &&
- $this->sectionedits[count($this->sectionedits) - 1][2] === 'section') {
+ $this->sectionedits[count($this->sectionedits) - 1][2] === 'section'
+ ) {
$this->finishSectionEdit($pos - 1);
}
// write the header
$this->doc .= DOKU_LF.'<h'.$level;
- if ($level <= $conf['maxseclevel']) {
- $this->doc .= ' class="' . $this->startSectionEdit($pos, 'section', $text) . '"';
+ if($level <= $conf['maxseclevel']) {
+ $this->doc .= ' class="'.$this->startSectionEdit($pos, 'section', $text).'"';
}
$this->doc .= ' id="'.$hid.'">';
$this->doc .= $this->_xmlEntities($text);
$this->doc .= "</h$level>".DOKU_LF;
}
+ /**
+ * Open a new section
+ *
+ * @param int $level section level (as determined by the previous header)
+ */
function section_open($level) {
- $this->doc .= '<div class="level' . $level . '">' . DOKU_LF;
+ $this->doc .= '<div class="level'.$level.'">'.DOKU_LF;
}
+ /**
+ * Close the current section
+ */
function section_close() {
$this->doc .= DOKU_LF.'</div>'.DOKU_LF;
}
+ /**
+ * Render plain text data
+ *
+ * @param $text
+ */
function cdata($text) {
$this->doc .= $this->_xmlEntities($text);
}
+ /**
+ * Open a paragraph
+ */
function p_open() {
$this->doc .= DOKU_LF.'<p>'.DOKU_LF;
}
+ /**
+ * Close a paragraph
+ */
function p_close() {
$this->doc .= DOKU_LF.'</p>'.DOKU_LF;
}
+ /**
+ * Create a line break
+ */
function linebreak() {
$this->doc .= '<br/>'.DOKU_LF;
}
+ /**
+ * Create a horizontal line
+ */
function hr() {
$this->doc .= '<hr />'.DOKU_LF;
}
+ /**
+ * Start strong (bold) formatting
+ */
function strong_open() {
$this->doc .= '<strong>';
}
+ /**
+ * Stop strong (bold) formatting
+ */
function strong_close() {
$this->doc .= '</strong>';
}
+ /**
+ * Start emphasis (italics) formatting
+ */
function emphasis_open() {
$this->doc .= '<em>';
}
+ /**
+ * Stop emphasis (italics) formatting
+ */
function emphasis_close() {
$this->doc .= '</em>';
}
+ /**
+ * Start underline formatting
+ */
function underline_open() {
$this->doc .= '<em class="u">';
}
+ /**
+ * Stop underline formatting
+ */
function underline_close() {
$this->doc .= '</em>';
}
+ /**
+ * Start monospace formatting
+ */
function monospace_open() {
$this->doc .= '<code>';
}
+ /**
+ * Stop monospace formatting
+ */
function monospace_close() {
$this->doc .= '</code>';
}
+ /**
+ * Start a subscript
+ */
function subscript_open() {
$this->doc .= '<sub>';
}
+ /**
+ * Stop a subscript
+ */
function subscript_close() {
$this->doc .= '</sub>';
}
+ /**
+ * Start a superscript
+ */
function superscript_open() {
$this->doc .= '<sup>';
}
+ /**
+ * Stop a superscript
+ */
function superscript_close() {
$this->doc .= '</sup>';
}
+ /**
+ * Start deleted (strike-through) formatting
+ */
function deleted_open() {
$this->doc .= '<del>';
}
+ /**
+ * Stop deleted (strike-through) formatting
+ */
function deleted_close() {
$this->doc .= '</del>';
}
@@ -296,14 +405,14 @@ class Doku_Renderer_xhtml extends Doku_Renderer {
$fnid++;
// recover footnote into the stack and restore old content
- $footnote = $this->doc;
- $this->doc = $this->store;
+ $footnote = $this->doc;
+ $this->doc = $this->store;
$this->store = '';
// check to see if this footnote has been seen before
$i = array_search($footnote, $this->footnotes);
- if ($i === false) {
+ if($i === false) {
// its a new footnote, add it to the $footnotes array
$this->footnotes[$fnid] = $footnote;
} else {
@@ -315,38 +424,71 @@ class Doku_Renderer_xhtml extends Doku_Renderer {
$this->doc .= '<sup><a href="#fn__'.$fnid.'" id="fnt__'.$fnid.'" class="fn_top">'.$fnid.')</a></sup>';
}
+ /**
+ * Open an unordered list
+ */
function listu_open() {
$this->doc .= '<ul>'.DOKU_LF;
}
+ /**
+ * Close an unordered list
+ */
function listu_close() {
$this->doc .= '</ul>'.DOKU_LF;
}
+ /**
+ * Open an ordered list
+ */
function listo_open() {
$this->doc .= '<ol>'.DOKU_LF;
}
+ /**
+ * Close an ordered list
+ */
function listo_close() {
$this->doc .= '</ol>'.DOKU_LF;
}
+ /**
+ * Open a list item
+ *
+ * @param int $level the nesting level
+ */
function listitem_open($level) {
$this->doc .= '<li class="level'.$level.'">';
}
+ /**
+ * Close a list item
+ */
function listitem_close() {
$this->doc .= '</li>'.DOKU_LF;
}
+ /**
+ * Start the content of a list item
+ */
function listcontent_open() {
$this->doc .= '<div class="li">';
}
+ /**
+ * Stop the content of a list item
+ */
function listcontent_close() {
$this->doc .= '</div>'.DOKU_LF;
}
+ /**
+ * Output unformatted $text
+ *
+ * Defaults to $this->cdata()
+ *
+ * @param string $text
+ */
function unformatted($text) {
$this->doc .= $this->_xmlEntities($text);
}
@@ -354,15 +496,15 @@ class Doku_Renderer_xhtml extends Doku_Renderer {
/**
* Execute PHP code if allowed
*
- * @param string $text PHP code that is either executed or printed
- * @param string $wrapper html element to wrap result if $conf['phpok'] is okff
+ * @param string $text PHP code that is either executed or printed
+ * @param string $wrapper html element to wrap result if $conf['phpok'] is okff
*
* @author Andreas Gohr <andi@splitbrain.org>
*/
- function php($text, $wrapper='code') {
+ function php($text, $wrapper = 'code') {
global $conf;
- if($conf['phpok']){
+ if($conf['phpok']) {
ob_start();
eval($text);
$this->doc .= ob_get_contents();
@@ -372,6 +514,14 @@ class Doku_Renderer_xhtml extends Doku_Renderer {
}
}
+ /**
+ * Output block level PHP code
+ *
+ * If $conf['phpok'] is true this should evaluate the given code and append the result
+ * to $doc
+ *
+ * @param string $text The PHP code
+ */
function phpblock($text) {
$this->php($text, 'pre');
}
@@ -379,75 +529,110 @@ class Doku_Renderer_xhtml extends Doku_Renderer {
/**
* Insert HTML if allowed
*
- * @param string $text html text
- * @param string $wrapper html element to wrap result if $conf['htmlok'] is okff
+ * @param string $text html text
+ * @param string $wrapper html element to wrap result if $conf['htmlok'] is okff
*
* @author Andreas Gohr <andi@splitbrain.org>
*/
- function html($text, $wrapper='code') {
+ function html($text, $wrapper = 'code') {
global $conf;
- if($conf['htmlok']){
+ if($conf['htmlok']) {
$this->doc .= $text;
} else {
$this->doc .= p_xhtml_cached_geshi($text, 'html4strict', $wrapper);
}
}
+ /**
+ * Output raw block-level HTML
+ *
+ * If $conf['htmlok'] is true this should add the code as is to $doc
+ *
+ * @param string $text The HTML
+ */
function htmlblock($text) {
$this->html($text, 'pre');
}
+ /**
+ * Start a block quote
+ */
function quote_open() {
$this->doc .= '<blockquote><div class="no">'.DOKU_LF;
}
+ /**
+ * Stop a block quote
+ */
function quote_close() {
$this->doc .= '</div></blockquote>'.DOKU_LF;
}
+ /**
+ * Output preformatted text
+ *
+ * @param string $text
+ */
function preformatted($text) {
- $this->doc .= '<pre class="code">' . trim($this->_xmlEntities($text),"\n\r") . '</pre>'. DOKU_LF;
+ $this->doc .= '<pre class="code">'.trim($this->_xmlEntities($text), "\n\r").'</pre>'.DOKU_LF;
}
- function file($text, $language=null, $filename=null) {
- $this->_highlight('file',$text,$language,$filename);
+ /**
+ * Display text as file content, optionally syntax highlighted
+ *
+ * @param string $text text to show
+ * @param string $language programming language to use for syntax highlighting
+ * @param string $filename file path label
+ */
+ function file($text, $language = null, $filename = null) {
+ $this->_highlight('file', $text, $language, $filename);
}
- function code($text, $language=null, $filename=null) {
- $this->_highlight('code',$text,$language,$filename);
+ /**
+ * Display text as code content, optionally syntax highlighted
+ *
+ * @param string $text text to show
+ * @param string $language programming language to use for syntax highlighting
+ * @param string $filename file path label
+ */
+ function code($text, $language = null, $filename = null) {
+ $this->_highlight('code', $text, $language, $filename);
}
/**
* Use GeSHi to highlight language syntax in code and file blocks
*
* @author Andreas Gohr <andi@splitbrain.org>
+ * @param string $type code|file
+ * @param string $text text to show
+ * @param string $language programming language to use for syntax highlighting
+ * @param string $filename file path label
*/
- function _highlight($type, $text, $language=null, $filename=null) {
- global $conf;
+ function _highlight($type, $text, $language = null, $filename = null) {
global $ID;
global $lang;
- if($filename){
+ if($filename) {
// add icon
- list($ext) = mimetype($filename,false);
- $class = preg_replace('/[^_\-a-z0-9]+/i','_',$ext);
+ list($ext) = mimetype($filename, false);
+ $class = preg_replace('/[^_\-a-z0-9]+/i', '_', $ext);
$class = 'mediafile mf_'.$class;
$this->doc .= '<dl class="'.$type.'">'.DOKU_LF;
- $this->doc .= '<dt><a href="'.exportlink($ID,'code',array('codeblock'=>$this->_codeblock)).'" title="'.$lang['download'].'" class="'.$class.'">';
+ $this->doc .= '<dt><a href="'.exportlink($ID, 'code', array('codeblock' => $this->_codeblock)).'" title="'.$lang['download'].'" class="'.$class.'">';
$this->doc .= hsc($filename);
$this->doc .= '</a></dt>'.DOKU_LF.'<dd>';
}
- if ($text{0} == "\n") {
+ if($text{0} == "\n") {
$text = substr($text, 1);
}
- if (substr($text, -1) == "\n") {
+ if(substr($text, -1) == "\n") {
$text = substr($text, 0, -1);
}
- if ( is_null($language) ) {
+ if(is_null($language)) {
$this->doc .= '<pre class="'.$type.'">'.$this->_xmlEntities($text).'</pre>'.DOKU_LF;
} else {
$class = 'code'; //we always need the code class to make the syntax highlighting apply
@@ -456,16 +641,23 @@ class Doku_Renderer_xhtml extends Doku_Renderer {
$this->doc .= "<pre class=\"$class $language\">".p_xhtml_cached_geshi($text, $language, '').'</pre>'.DOKU_LF;
}
- if($filename){
+ if($filename) {
$this->doc .= '</dd></dl>'.DOKU_LF;
}
$this->_codeblock++;
}
+ /**
+ * Format an acronym
+ *
+ * Uses $this->acronyms
+ *
+ * @param string $acronym
+ */
function acronym($acronym) {
- if ( array_key_exists($acronym, $this->acronyms) ) {
+ if(array_key_exists($acronym, $this->acronyms)) {
$title = $this->_xmlEntities($this->acronyms[$acronym]);
@@ -477,73 +669,109 @@ class Doku_Renderer_xhtml extends Doku_Renderer {
}
}
+ /**
+ * Format a smiley
+ *
+ * Uses $this->smiley
+ *
+ * @param string $smiley
+ */
function smiley($smiley) {
- if ( array_key_exists($smiley, $this->smileys) ) {
- $title = $this->_xmlEntities($this->smileys[$smiley]);
+ if(array_key_exists($smiley, $this->smileys)) {
$this->doc .= '<img src="'.DOKU_BASE.'lib/images/smileys/'.$this->smileys[$smiley].
'" class="icon" alt="'.
- $this->_xmlEntities($smiley).'" />';
+ $this->_xmlEntities($smiley).'" />';
} else {
$this->doc .= $this->_xmlEntities($smiley);
}
}
- /*
- * not used
- function wordblock($word) {
- if ( array_key_exists($word, $this->badwords) ) {
- $this->doc .= '** BLEEP **';
- } else {
- $this->doc .= $this->_xmlEntities($word);
- }
- }
- */
-
+ /**
+ * Format an entity
+ *
+ * Entities are basically small text replacements
+ *
+ * Uses $this->entities
+ *
+ * @param string $entity
+ */
function entity($entity) {
- if ( array_key_exists($entity, $this->entities) ) {
+ if(array_key_exists($entity, $this->entities)) {
$this->doc .= $this->entities[$entity];
} else {
$this->doc .= $this->_xmlEntities($entity);
}
}
+ /**
+ * Typographically format a multiply sign
+ *
+ * Example: ($x=640, $y=480) should result in "640×480"
+ *
+ * @param string|int $x first value
+ * @param string|int $y second value
+ */
function multiplyentity($x, $y) {
$this->doc .= "$x&times;$y";
}
+ /**
+ * Render an opening single quote char (language specific)
+ */
function singlequoteopening() {
global $lang;
$this->doc .= $lang['singlequoteopening'];
}
+ /**
+ * Render a closing single quote char (language specific)
+ */
function singlequoteclosing() {
global $lang;
$this->doc .= $lang['singlequoteclosing'];
}
+ /**
+ * Render an apostrophe char (language specific)
+ */
function apostrophe() {
global $lang;
$this->doc .= $lang['apostrophe'];
}
+ /**
+ * Render an opening double quote char (language specific)
+ */
function doublequoteopening() {
global $lang;
$this->doc .= $lang['doublequoteopening'];
}
+ /**
+ * Render an closinging double quote char (language specific)
+ */
function doublequoteclosing() {
global $lang;
$this->doc .= $lang['doublequoteclosing'];
}
/**
+ * Render a CamelCase link
+ *
+ * @param string $link The link name
+ * @see http://en.wikipedia.org/wiki/CamelCase
*/
function camelcaselink($link) {
- $this->internallink($link,$link);
+ $this->internallink($link, $link);
}
-
- function locallink($hash, $name = null){
+ /**
+ * Render a page local link
+ *
+ * @param string $hash hash link identifier
+ * @param string $name name for the link
+ */
+ function locallink($hash, $name = null) {
global $ID;
$name = $this->_getLinkTitle($name, $hash, $isImage);
$hash = $this->_headerToLink($hash);
@@ -559,23 +787,23 @@ class Doku_Renderer_xhtml extends Doku_Renderer {
* $search,$returnonly & $linktype are not for the renderer but are used
* elsewhere - no need to implement them in other renderers
*
- * @param string $id pageid
- * @param string|null $name link name
- * @param string|null $search adds search url param
- * @param bool $returnonly whether to return html or write to doc attribute
- * @param string $linktype type to set use of headings
- * @return void|string writes to doc attribute or returns html depends on $returnonly
* @author Andreas Gohr <andi@splitbrain.org>
+ * @param string $id pageid
+ * @param string|null $name link name
+ * @param string|null $search adds search url param
+ * @param bool $returnonly whether to return html or write to doc attribute
+ * @param string $linktype type to set use of headings
+ * @return void|string writes to doc attribute or returns html depends on $returnonly
*/
- 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;
$params = '';
- $parts = explode('?', $id, 2);
- if (count($parts) === 2) {
- $id = $parts[0];
+ $parts = explode('?', $id, 2);
+ if(count($parts) === 2) {
+ $id = $parts[0];
$params = $parts[1];
}
@@ -583,7 +811,7 @@ class Doku_Renderer_xhtml extends Doku_Renderer {
// We need this check because _simpleTitle needs
// correct $id and resolve_pageid() use cleanID($id)
// (some things could be lost)
- if ($id === '') {
+ if($id === '') {
$id = $ID;
}
@@ -591,22 +819,22 @@ class Doku_Renderer_xhtml extends Doku_Renderer {
$default = $this->_simpleTitle($id);
// now first resolve and clean up the $id
- resolve_pageid(getNS($ID),$id,$exists);
+ resolve_pageid(getNS($ID), $id, $exists, $this->date_at, true);
$name = $this->_getLinkTitle($name, $default, $isImage, $id, $linktype);
- if ( !$isImage ) {
- if ( $exists ) {
- $class='wikilink1';
+ if(!$isImage) {
+ if($exists) {
+ $class = 'wikilink1';
} else {
- $class='wikilink2';
- $link['rel']='nofollow';
+ $class = 'wikilink2';
+ $link['rel'] = 'nofollow';
}
} else {
- $class='media';
+ $class = 'media';
}
//keep hash anchor
- @list($id,$hash) = explode('#',$id,2);
+ @list($id, $hash) = explode('#', $id, 2);
if(!empty($hash)) $hash = $this->_headerToLink($hash);
//prepare for formating
@@ -615,37 +843,46 @@ class Doku_Renderer_xhtml extends Doku_Renderer {
$link['pre'] = '';
$link['suf'] = '';
// highlight link to current page
- if ($id == $INFO['id']) {
- $link['pre'] = '<span class="curid">';
- $link['suf'] = '</span>';
+ if($id == $INFO['id']) {
+ $link['pre'] = '<span class="curid">';
+ $link['suf'] = '</span>';
}
$link['more'] = '';
$link['class'] = $class;
+ if($this->date_at) {
+ $params['at'] = $this->date_at;
+ }
$link['url'] = wl($id, $params);
$link['name'] = $name;
$link['title'] = $id;
//add search string
- if($search){
- ($conf['userewrite']) ? $link['url'].='?' : $link['url'].='&amp;';
- if(is_array($search)){
- $search = array_map('rawurlencode',$search);
- $link['url'] .= 's[]='.join('&amp;s[]=',$search);
- }else{
+ if($search) {
+ ($conf['userewrite']) ? $link['url'] .= '?' : $link['url'] .= '&amp;';
+ if(is_array($search)) {
+ $search = array_map('rawurlencode', $search);
+ $link['url'] .= 's[]='.join('&amp;s[]=', $search);
+ } else {
$link['url'] .= 's='.rawurlencode($search);
}
}
//keep hash
- if($hash) $link['url'].='#'.$hash;
+ if($hash) $link['url'] .= '#'.$hash;
//output formatted
- if($returnonly){
+ if($returnonly) {
return $this->_formatLink($link);
- }else{
+ } else {
$this->doc .= $this->_formatLink($link);
}
}
+ /**
+ * Render an external link
+ *
+ * @param string $url full URL with scheme
+ * @param string|array $name name for the link, array for media file
+ */
function externallink($url, $name = null) {
global $conf;
@@ -653,21 +890,21 @@ class Doku_Renderer_xhtml extends Doku_Renderer {
// url might be an attack vector, only allow registered protocols
if(is_null($this->schemes)) $this->schemes = getSchemes();
- list($scheme) = explode('://',$url);
+ list($scheme) = explode('://', $url);
$scheme = strtolower($scheme);
- if(!in_array($scheme,$this->schemes)) $url = '';
+ if(!in_array($scheme, $this->schemes)) $url = '';
// is there still an URL?
- if(!$url){
+ if(!$url) {
$this->doc .= $name;
return;
}
// set class
- if ( !$isImage ) {
- $class='urlextern';
+ if(!$isImage) {
+ $class = 'urlextern';
} else {
- $class='media';
+ $class = 'media';
}
//prepare for formating
@@ -679,8 +916,8 @@ class Doku_Renderer_xhtml extends Doku_Renderer {
$link['class'] = $class;
$link['url'] = $url;
- $link['name'] = $name;
- $link['title'] = $this->_xmlEntities($url);
+ $link['name'] = $name;
+ $link['title'] = $this->_xmlEntities($url);
if($conf['relnofollow']) $link['more'] .= ' rel="nofollow"';
//output formatted
@@ -688,11 +925,19 @@ class Doku_Renderer_xhtml extends Doku_Renderer {
}
/**
+ * Render an interwiki link
+ *
+ * You may want to use $this->_resolveInterWiki() here
+ *
+ * @param string $match original link - probably not much use
+ * @param string|array $name name for the link, array for media file
+ * @param string $wikiName indentifier (shortcut) for the remote wiki
+ * @param string $wikiUri the fragment parsed from the original link
*/
function interwikilink($match, $name = null, $wikiName, $wikiUri) {
global $conf;
- $link = array();
+ $link = array();
$link['target'] = $conf['target']['interwiki'];
$link['pre'] = '';
$link['suf'] = '';
@@ -701,10 +946,10 @@ class Doku_Renderer_xhtml extends Doku_Renderer {
//get interwiki URL
$exists = null;
- $url = $this->_resolveInterWiki($wikiName, $wikiUri, $exists);
+ $url = $this->_resolveInterWiki($wikiName, $wikiUri, $exists);
if(!$isImage) {
- $class = preg_replace('/[^_\-a-z0-9]+/i', '_', $wikiName);
+ $class = preg_replace('/[^_\-a-z0-9]+/i', '_', $wikiName);
$link['class'] = "interwiki iw_$class";
} else {
$link['class'] = 'media';
@@ -723,7 +968,7 @@ class Doku_Renderer_xhtml extends Doku_Renderer {
}
}
- $link['url'] = $url;
+ $link['url'] = $url;
$link['title'] = htmlspecialchars($link['url']);
//output formatted
@@ -731,54 +976,66 @@ class Doku_Renderer_xhtml extends Doku_Renderer {
}
/**
+ * Link to windows share
+ *
+ * @param string $url the link
+ * @param string|array $name name for the link, array for media file
*/
function windowssharelink($url, $name = null) {
global $conf;
- global $lang;
+
//simple setup
$link['target'] = $conf['target']['windows'];
$link['pre'] = '';
- $link['suf'] = '';
+ $link['suf'] = '';
$link['style'] = '';
$link['name'] = $this->_getLinkTitle($name, $url, $isImage);
- if ( !$isImage ) {
+ if(!$isImage) {
$link['class'] = 'windows';
} else {
$link['class'] = 'media';
}
$link['title'] = $this->_xmlEntities($url);
- $url = str_replace('\\','/',$url);
- $url = 'file:///'.$url;
- $link['url'] = $url;
+ $url = str_replace('\\', '/', $url);
+ $url = 'file:///'.$url;
+ $link['url'] = $url;
//output formatted
$this->doc .= $this->_formatLink($link);
}
+ /**
+ * Render a linked E-Mail Address
+ *
+ * Honors $conf['mailguard'] setting
+ *
+ * @param string $address Email-Address
+ * @param string|array $name name for the link, array for media file
+ */
function emaillink($address, $name = null) {
global $conf;
//simple setup
- $link = array();
+ $link = array();
$link['target'] = '';
$link['pre'] = '';
- $link['suf'] = '';
+ $link['suf'] = '';
$link['style'] = '';
$link['more'] = '';
$name = $this->_getLinkTitle($name, '', $isImage);
- if ( !$isImage ) {
- $link['class']='mail';
+ if(!$isImage) {
+ $link['class'] = 'mail';
} else {
- $link['class']='media';
+ $link['class'] = 'media';
}
$address = $this->_xmlEntities($address);
$address = obfuscate($address);
$title = $address;
- if(empty($name)){
+ if(empty($name)) {
$name = $address;
}
@@ -792,74 +1049,104 @@ 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, $return=NULL) {
+ /**
+ * Render an internal media file
+ *
+ * @param string $src media ID
+ * @param string $title descriptive text
+ * @param string $align left|center|right
+ * @param int $width width of media in pixel
+ * @param int $height height of media in pixel
+ * @param string $cache cache|recache|nocache
+ * @param string $linking linkonly|detail|nolink
+ * @param bool $return return HTML instead of adding to $doc
+ * @return void|string
+ */
+ function internalmedia($src, $title = null, $align = null, $width = null,
+ $height = null, $cache = null, $linking = null, $return = false) {
global $ID;
- list($src,$hash) = explode('#',$src,2);
- resolve_mediaid(getNS($ID),$src, $exists);
+ list($src, $hash) = explode('#', $src, 2);
+ resolve_mediaid(getNS($ID), $src, $exists, $this->date_at, true);
$noLink = false;
$render = ($linking == 'linkonly') ? false : true;
- $link = $this->_getMediaLinkConf($src, $title, $align, $width, $height, $cache, $render);
+ $link = $this->_getMediaLinkConf($src, $title, $align, $width, $height, $cache, $render);
- list($ext,$mime,$dl) = mimetype($src,false);
- if(substr($mime,0,5) == 'image' && $render){
- $link['url'] = ml($src,array('id'=>$ID,'cache'=>$cache),($linking=='direct'));
- }elseif(($mime == 'application/x-shockwave-flash' || media_supportedav($mime)) && $render){
+ list($ext, $mime) = mimetype($src, false);
+ if(substr($mime, 0, 5) == 'image' && $render) {
+ $link['url'] = ml($src, array('id' => $ID, 'cache' => $cache, 'rev'=>$this->_getLastMediaRevisionAt($src)), ($linking == 'direct'));
+ } elseif(($mime == 'application/x-shockwave-flash' || media_supportedav($mime)) && $render) {
// don't link movies
$noLink = true;
- }else{
+ } else {
// add file icons
- $class = preg_replace('/[^_\-a-z0-9]+/i','_',$ext);
+ $class = preg_replace('/[^_\-a-z0-9]+/i', '_', $ext);
$link['class'] .= ' mediafile mf_'.$class;
- $link['url'] = ml($src,array('id'=>$ID,'cache'=>$cache),true);
- if ($exists) $link['title'] .= ' (' . filesize_h(filesize(mediaFN($src))).')';
+ $link['url'] = ml($src, array('id' => $ID, 'cache' => $cache , 'rev'=>$this->_getLastMediaRevisionAt($src)), true);
+ if($exists) $link['title'] .= ' ('.filesize_h(filesize(mediaFN($src))).')';
}
if($hash) $link['url'] .= '#'.$hash;
//markup non existing files
- if (!$exists) {
+ if(!$exists) {
$link['class'] .= ' wikilink2';
}
//output formatted
- if ($return) {
- if ($linking == 'nolink' || $noLink) return $link['name'];
+ if($return) {
+ if($linking == 'nolink' || $noLink) return $link['name'];
else return $this->_formatLink($link);
} else {
- if ($linking == 'nolink' || $noLink) $this->doc .= $link['name'];
+ if($linking == 'nolink' || $noLink) $this->doc .= $link['name'];
else $this->doc .= $this->_formatLink($link);
}
}
- function externalmedia ($src, $title=null, $align=null, $width=null,
- $height=null, $cache=null, $linking=null) {
- list($src,$hash) = explode('#',$src,2);
+ /**
+ * Render an external media file
+ *
+ * @param string $src full media URL
+ * @param string $title descriptive text
+ * @param string $align left|center|right
+ * @param int $width width of media in pixel
+ * @param int $height height of media in pixel
+ * @param string $cache cache|recache|nocache
+ * @param string $linking linkonly|detail|nolink
+ * @param bool $return return HTML instead of adding to $doc
+ */
+ function externalmedia($src, $title = null, $align = null, $width = null,
+ $height = null, $cache = null, $linking = null, $return = false) {
+ list($src, $hash) = explode('#', $src, 2);
$noLink = false;
$render = ($linking == 'linkonly') ? false : true;
- $link = $this->_getMediaLinkConf($src, $title, $align, $width, $height, $cache, $render);
+ $link = $this->_getMediaLinkConf($src, $title, $align, $width, $height, $cache, $render);
- $link['url'] = ml($src,array('cache'=>$cache));
+ $link['url'] = ml($src, array('cache' => $cache));
- list($ext,$mime,$dl) = mimetype($src,false);
- if(substr($mime,0,5) == 'image' && $render){
+ list($ext, $mime) = mimetype($src, false);
+ if(substr($mime, 0, 5) == 'image' && $render) {
// link only jpeg images
// if ($ext != 'jpg' && $ext != 'jpeg') $noLink = true;
- }elseif(($mime == 'application/x-shockwave-flash' || media_supportedav($mime)) && $render){
+ } elseif(($mime == 'application/x-shockwave-flash' || media_supportedav($mime)) && $render) {
// don't link movies
$noLink = true;
- }else{
+ } else {
// add file icons
- $class = preg_replace('/[^_\-a-z0-9]+/i','_',$ext);
+ $class = preg_replace('/[^_\-a-z0-9]+/i', '_', $ext);
$link['class'] .= ' mediafile mf_'.$class;
}
if($hash) $link['url'] .= '#'.$hash;
//output formatted
- if ($linking == 'nolink' || $noLink) $this->doc .= $link['name'];
- else $this->doc .= $this->_formatLink($link);
+ if($return) {
+ if($linking == 'nolink' || $noLink) return $link['name'];
+ else return $this->_formatLink($link);
+ } else {
+ if($linking == 'nolink' || $noLink) $this->doc .= $link['name'];
+ else $this->doc .= $this->_formatLink($link);
+ }
}
/**
@@ -867,7 +1154,7 @@ class Doku_Renderer_xhtml extends Doku_Renderer {
*
* @author Andreas Gohr <andi@splitbrain.org>
*/
- function rss ($url,$params){
+ function rss($url, $params) {
global $lang;
global $conf;
@@ -876,17 +1163,21 @@ class Doku_Renderer_xhtml extends Doku_Renderer {
$feed->set_feed_url($url);
//disable warning while fetching
- if (!defined('DOKU_E_LEVEL')) { $elvl = error_reporting(E_ERROR); }
+ if(!defined('DOKU_E_LEVEL')) {
+ $elvl = error_reporting(E_ERROR);
+ }
$rc = $feed->init();
- if (!defined('DOKU_E_LEVEL')) { error_reporting($elvl); }
+ if(isset($elvl)) {
+ error_reporting($elvl);
+ }
//decide on start and end
- if($params['reverse']){
- $mod = -1;
- $start = $feed->get_item_quantity()-1;
+ if($params['reverse']) {
+ $mod = -1;
+ $start = $feed->get_item_quantity() - 1;
$end = $start - ($params['max']);
$end = ($end < -1) ? -1 : $end;
- }else{
+ } else {
$mod = 1;
$start = 0;
$end = $feed->get_item_quantity();
@@ -894,36 +1185,38 @@ class Doku_Renderer_xhtml extends Doku_Renderer {
}
$this->doc .= '<ul class="rss">';
- if($rc){
- for ($x = $start; $x != $end; $x += $mod) {
+ if($rc) {
+ for($x = $start; $x != $end; $x += $mod) {
$item = $feed->get_item($x);
$this->doc .= '<li><div class="li">';
// support feeds without links
$lnkurl = $item->get_permalink();
- if($lnkurl){
+ if($lnkurl) {
// title is escaped by SimplePie, we unescape here because it
// is escaped again in externallink() FS#1705
- $this->externallink($item->get_permalink(),
- html_entity_decode($item->get_title(), ENT_QUOTES, 'UTF-8'));
- }else{
+ $this->externallink(
+ $item->get_permalink(),
+ html_entity_decode($item->get_title(), ENT_QUOTES, 'UTF-8')
+ );
+ } else {
$this->doc .= ' '.$item->get_title();
}
- if($params['author']){
+ if($params['author']) {
$author = $item->get_author(0);
- if($author){
+ if($author) {
$name = $author->get_name();
if(!$name) $name = $author->get_email();
if($name) $this->doc .= ' '.$lang['by'].' '.$name;
}
}
- if($params['date']){
+ if($params['date']) {
$this->doc .= ' ('.$item->get_local_date($conf['dformat']).')';
}
- if($params['details']){
+ if($params['details']) {
$this->doc .= '<div class="detail">';
- if($conf['htmlok']){
+ if($conf['htmlok']) {
$this->doc .= $item->get_description();
- }else{
+ } else {
$this->doc .= strip_tags($item->get_description());
}
$this->doc .= '</div>';
@@ -931,11 +1224,11 @@ class Doku_Renderer_xhtml extends Doku_Renderer {
$this->doc .= '</div></li>';
}
- }else{
+ } else {
$this->doc .= '<li><div class="li">';
$this->doc .= '<em>'.$lang['rssfailed'].'</em>';
$this->externallink($url);
- if($conf['allowdebug']){
+ if($conf['allowdebug']) {
$this->doc .= '<!--'.hsc($feed->error).'-->';
}
$this->doc .= '</div></li>';
@@ -943,89 +1236,130 @@ class Doku_Renderer_xhtml extends Doku_Renderer {
$this->doc .= '</ul>';
}
- // $numrows not yet implemented
- function table_open($maxcols = null, $numrows = null, $pos = null){
- global $lang;
+ /**
+ * Start a table
+ *
+ * @param int $maxcols maximum number of columns
+ * @param int $numrows NOT IMPLEMENTED
+ * @param int $pos byte position in the original source
+ */
+ function table_open($maxcols = null, $numrows = null, $pos = null) {
// initialize the row counter used for classes
$this->_counter['row_counter'] = 0;
- $class = 'table';
- if ($pos !== null) {
- $class .= ' ' . $this->startSectionEdit($pos, 'table');
+ $class = 'table';
+ if($pos !== null) {
+ $class .= ' '.$this->startSectionEdit($pos, 'table');
}
- $this->doc .= '<div class="' . $class . '"><table class="inline">' .
- DOKU_LF;
+ $this->doc .= '<div class="'.$class.'"><table class="inline">'.
+ DOKU_LF;
}
- function table_close($pos = null){
+ /**
+ * Close a table
+ *
+ * @param int $pos byte position in the original source
+ */
+ function table_close($pos = null) {
$this->doc .= '</table></div>'.DOKU_LF;
- if ($pos !== null) {
+ if($pos !== null) {
$this->finishSectionEdit($pos);
}
}
- function tablethead_open(){
- $this->doc .= DOKU_TAB . '<thead>' . DOKU_LF;
+ /**
+ * Open a table header
+ */
+ function tablethead_open() {
+ $this->doc .= DOKU_TAB.'<thead>'.DOKU_LF;
}
- function tablethead_close(){
- $this->doc .= DOKU_TAB . '</thead>' . DOKU_LF;
+ /**
+ * Close a table header
+ */
+ function tablethead_close() {
+ $this->doc .= DOKU_TAB.'</thead>'.DOKU_LF;
}
- function tablerow_open(){
+ /**
+ * Open a table row
+ */
+ function tablerow_open() {
// initialize the cell counter used for classes
$this->_counter['cell_counter'] = 0;
- $class = 'row' . $this->_counter['row_counter']++;
- $this->doc .= DOKU_TAB . '<tr class="'.$class.'">' . DOKU_LF . DOKU_TAB . DOKU_TAB;
+ $class = 'row'.$this->_counter['row_counter']++;
+ $this->doc .= DOKU_TAB.'<tr class="'.$class.'">'.DOKU_LF.DOKU_TAB.DOKU_TAB;
}
- function tablerow_close(){
- $this->doc .= DOKU_LF . DOKU_TAB . '</tr>' . DOKU_LF;
+ /**
+ * Close a table row
+ */
+ function tablerow_close() {
+ $this->doc .= DOKU_LF.DOKU_TAB.'</tr>'.DOKU_LF;
}
- function tableheader_open($colspan = 1, $align = null, $rowspan = 1){
- $class = 'class="col' . $this->_counter['cell_counter']++;
- if ( !is_null($align) ) {
+ /**
+ * Open a table header cell
+ *
+ * @param int $colspan
+ * @param string $align left|center|right
+ * @param int $rowspan
+ */
+ function tableheader_open($colspan = 1, $align = null, $rowspan = 1) {
+ $class = 'class="col'.$this->_counter['cell_counter']++;
+ if(!is_null($align)) {
$class .= ' '.$align.'align';
}
$class .= '"';
- $this->doc .= '<th ' . $class;
- if ( $colspan > 1 ) {
- $this->_counter['cell_counter'] += $colspan-1;
+ $this->doc .= '<th '.$class;
+ if($colspan > 1) {
+ $this->_counter['cell_counter'] += $colspan - 1;
$this->doc .= ' colspan="'.$colspan.'"';
}
- if ( $rowspan > 1 ) {
+ if($rowspan > 1) {
$this->doc .= ' rowspan="'.$rowspan.'"';
}
$this->doc .= '>';
}
- function tableheader_close(){
+ /**
+ * Close a table header cell
+ */
+ function tableheader_close() {
$this->doc .= '</th>';
}
- function tablecell_open($colspan = 1, $align = null, $rowspan = 1){
- $class = 'class="col' . $this->_counter['cell_counter']++;
- if ( !is_null($align) ) {
+ /**
+ * Open a table cell
+ *
+ * @param int $colspan
+ * @param string $align left|center|right
+ * @param int $rowspan
+ */
+ function tablecell_open($colspan = 1, $align = null, $rowspan = 1) {
+ $class = 'class="col'.$this->_counter['cell_counter']++;
+ if(!is_null($align)) {
$class .= ' '.$align.'align';
}
$class .= '"';
$this->doc .= '<td '.$class;
- if ( $colspan > 1 ) {
- $this->_counter['cell_counter'] += $colspan-1;
+ if($colspan > 1) {
+ $this->_counter['cell_counter'] += $colspan - 1;
$this->doc .= ' colspan="'.$colspan.'"';
}
- if ( $rowspan > 1 ) {
+ if($rowspan > 1) {
$this->doc .= ' rowspan="'.$rowspan.'"';
}
$this->doc .= '>';
}
- function tablecell_close(){
+ /**
+ * Close a table cell
+ */
+ function tablecell_close() {
$this->doc .= '</td>';
}
- //----------------------------------------------------------
- // Utils
+ #region Utility functions
/**
* Build a link
@@ -1034,29 +1368,29 @@ class Doku_Renderer_xhtml extends Doku_Renderer {
*
* @author Andreas Gohr <andi@splitbrain.org>
*/
- function _formatLink($link){
+ function _formatLink($link) {
//make sure the url is XHTML compliant (skip mailto)
- if(substr($link['url'],0,7) != 'mailto:'){
- $link['url'] = str_replace('&','&amp;',$link['url']);
- $link['url'] = str_replace('&amp;amp;','&amp;',$link['url']);
+ if(substr($link['url'], 0, 7) != 'mailto:') {
+ $link['url'] = str_replace('&', '&amp;', $link['url']);
+ $link['url'] = str_replace('&amp;amp;', '&amp;', $link['url']);
}
//remove double encodings in titles
- $link['title'] = str_replace('&amp;amp;','&amp;',$link['title']);
+ $link['title'] = str_replace('&amp;amp;', '&amp;', $link['title']);
// be sure there are no bad chars in url or title
// (we can't do this for name because it can contain an img tag)
- $link['url'] = strtr($link['url'],array('>'=>'%3E','<'=>'%3C','"'=>'%22'));
- $link['title'] = strtr($link['title'],array('>'=>'&gt;','<'=>'&lt;','"'=>'&quot;'));
+ $link['url'] = strtr($link['url'], array('>' => '%3E', '<' => '%3C', '"' => '%22'));
+ $link['title'] = strtr($link['title'], array('>' => '&gt;', '<' => '&lt;', '"' => '&quot;'));
- $ret = '';
+ $ret = '';
$ret .= $link['pre'];
$ret .= '<a href="'.$link['url'].'"';
- if(!empty($link['class'])) $ret .= ' class="'.$link['class'].'"';
+ if(!empty($link['class'])) $ret .= ' class="'.$link['class'].'"';
if(!empty($link['target'])) $ret .= ' target="'.$link['target'].'"';
- if(!empty($link['title'])) $ret .= ' title="'.$link['title'].'"';
- if(!empty($link['style'])) $ret .= ' style="'.$link['style'].'"';
- if(!empty($link['rel'])) $ret .= ' rel="'.$link['rel'].'"';
- if(!empty($link['more'])) $ret .= ' '.$link['more'];
+ if(!empty($link['title'])) $ret .= ' title="'.$link['title'].'"';
+ if(!empty($link['style'])) $ret .= ' style="'.$link['style'].'"';
+ if(!empty($link['rel'])) $ret .= ' rel="'.$link['rel'].'"';
+ if(!empty($link['more'])) $ret .= ' '.$link['more'];
$ret .= '>';
$ret .= $link['name'];
$ret .= '</a>';
@@ -1068,102 +1402,112 @@ class Doku_Renderer_xhtml extends Doku_Renderer {
* Renders internal and external media
*
* @author Andreas Gohr <andi@splitbrain.org>
+ * @param string $src media ID
+ * @param string $title descriptive text
+ * @param string $align left|center|right
+ * @param int $width width of media in pixel
+ * @param int $height height of media in pixel
+ * @param string $cache cache|recache|nocache
+ * @param bool $render should the media be embedded inline or just linked
+ * @return string
*/
- 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 = '';
- list($ext,$mime,$dl) = mimetype($src);
- if(substr($mime,0,5) == 'image'){
+ list($ext, $mime) = mimetype($src);
+ if(substr($mime, 0, 5) == 'image') {
// first get the $title
- if (!is_null($title)) {
- $title = $this->_xmlEntities($title);
- }elseif($ext == 'jpg' || $ext == 'jpeg'){
+ if(!is_null($title)) {
+ $title = $this->_xmlEntities($title);
+ } elseif($ext == 'jpg' || $ext == 'jpeg') {
//try to use the caption from IPTC/EXIF
require_once(DOKU_INC.'inc/JpegMeta.php');
- $jpeg =new JpegMeta(mediaFN($src));
+ $jpeg = new JpegMeta(mediaFN($src));
if($jpeg !== false) $cap = $jpeg->getTitle();
- if($cap){
+ if(!empty($cap)) {
$title = $this->_xmlEntities($cap);
}
}
- if (!$render) {
+ if(!$render) {
// if the picture is not supposed to be rendered
// return the title of the picture
- if (!$title) {
+ if(!$title) {
// just show the sourcename
$title = $this->_xmlEntities(utf8_basename(noNS($src)));
}
return $title;
}
//add image tag
- $ret .= '<img src="'.ml($src,array('w'=>$width,'h'=>$height,'cache'=>$cache)).'"';
+ $ret .= '<img src="'.ml($src, array('w' => $width, 'h' => $height, 'cache' => $cache, 'rev'=>$this->_getLastMediaRevisionAt($src))).'"';
$ret .= ' class="media'.$align.'"';
- if ($title) {
- $ret .= ' title="' . $title . '"';
- $ret .= ' alt="' . $title .'"';
- }else{
+ if($title) {
+ $ret .= ' title="'.$title.'"';
+ $ret .= ' alt="'.$title.'"';
+ } else {
$ret .= ' alt=""';
}
- if ( !is_null($width) )
+ if(!is_null($width))
$ret .= ' width="'.$this->_xmlEntities($width).'"';
- if ( !is_null($height) )
+ if(!is_null($height))
$ret .= ' height="'.$this->_xmlEntities($height).'"';
$ret .= ' />';
- }elseif(media_supportedav($mime, 'video') || media_supportedav($mime, 'audio')){
+ } elseif(media_supportedav($mime, 'video') || media_supportedav($mime, 'audio')) {
// first get the $title
$title = !is_null($title) ? $this->_xmlEntities($title) : false;
- if (!$render) {
+ if(!$render) {
// if the file is not supposed to be rendered
// return the title of the file (just the sourcename if there is no title)
return $title ? $title : $this->_xmlEntities(utf8_basename(noNS($src)));
}
- $att = array();
+ $att = array();
$att['class'] = "media$align";
- if ($title) {
+ if($title) {
$att['title'] = $title;
}
- if (media_supportedav($mime, 'video')) {
+ if(media_supportedav($mime, 'video')) {
//add video
$ret .= $this->_video($src, $width, $height, $att);
}
- if (media_supportedav($mime, 'audio')) {
+ if(media_supportedav($mime, 'audio')) {
//add audio
$ret .= $this->_audio($src, $att);
}
- }elseif($mime == 'application/x-shockwave-flash'){
- if (!$render) {
+ } elseif($mime == 'application/x-shockwave-flash') {
+ if(!$render) {
// if the flash is not supposed to be rendered
// return the title of the flash
- if (!$title) {
+ if(!$title) {
// just show the sourcename
$title = utf8_basename(noNS($src));
}
return $this->_xmlEntities($title);
}
- $att = array();
+ $att = array();
$att['class'] = "media$align";
if($align == 'right') $att['align'] = 'right';
- if($align == 'left') $att['align'] = 'left';
- $ret .= html_flashobject(ml($src,array('cache'=>$cache),true,'&'),$width,$height,
- array('quality' => 'high'),
- null,
- $att,
- $this->_xmlEntities($title));
- }elseif($title){
+ if($align == 'left') $att['align'] = 'left';
+ $ret .= html_flashobject(
+ ml($src, array('cache' => $cache), true, '&'), $width, $height,
+ array('quality' => 'high'),
+ null,
+ $att,
+ $this->_xmlEntities($title)
+ );
+ } elseif($title) {
// well at least we have a title to display
$ret .= $this->_xmlEntities($title);
- }else{
+ } else {
// just show the sourcename
$ret .= $this->_xmlEntities(utf8_basename(noNS($src)));
}
@@ -1171,23 +1515,30 @@ class Doku_Renderer_xhtml extends Doku_Renderer {
return $ret;
}
+ /**
+ * Escape string for output
+ *
+ * @param $string
+ * @return string
+ */
function _xmlEntities($string) {
- return htmlspecialchars($string,ENT_QUOTES,'UTF-8');
+ return htmlspecialchars($string, ENT_QUOTES, 'UTF-8');
}
/**
* Creates a linkid from a headline
*
+ * @author Andreas Gohr <andi@splitbrain.org>
* @param string $title The headline title
* @param boolean $create Create a new unique ID?
- * @author Andreas Gohr <andi@splitbrain.org>
+ * @return string
*/
- function _headerToLink($title,$create=false) {
- if($create){
- return sectionID($title,$this->headers);
- }else{
+ function _headerToLink($title, $create = false) {
+ if($create) {
+ return sectionID($title, $this->headers);
+ } else {
$check = false;
- return sectionID($title,$check);
+ return sectionID($title, $check);
}
}
@@ -1195,18 +1546,22 @@ class Doku_Renderer_xhtml extends Doku_Renderer {
* Construct a title and handle images in titles
*
* @author Harry Fuecks <hfuecks@gmail.com>
+ * @param string|array $title either string title or media array
+ * @param string $default default title if nothing else is found
+ * @param bool $isImage will be set to true if it's a media file
+ * @param null|string $id linked page id (used to extract title from first heading)
+ * @param string $linktype content|navigation
+ * @return string HTML of the title, might be full image tag or just escaped text
*/
- function _getLinkTitle($title, $default, & $isImage, $id=null, $linktype='content') {
- global $conf;
-
+ function _getLinkTitle($title, $default, &$isImage, $id = null, $linktype = 'content') {
$isImage = false;
- if ( is_array($title) ) {
+ if(is_array($title)) {
$isImage = true;
return $this->_imageTitle($title);
- } elseif ( is_null($title) || trim($title)=='') {
- if (useHeading($linktype) && $id) {
+ } elseif(is_null($title) || trim($title) == '') {
+ if(useHeading($linktype) && $id) {
$heading = p_get_first_heading($id);
- if ($heading) {
+ if($heading) {
return $this->_xmlEntities($heading);
}
}
@@ -1217,48 +1572,51 @@ class Doku_Renderer_xhtml extends Doku_Renderer {
}
/**
- * Returns an HTML code for images used in link titles
+ * Returns HTML code for images used in link titles
*
- * @todo Resolve namespace on internal images
* @author Andreas Gohr <andi@splitbrain.org>
+ * @param string $img
+ * @return string HTML img tag or similar
*/
function _imageTitle($img) {
global $ID;
// some fixes on $img['src']
// see internalmedia() and externalmedia()
- list($img['src'],$hash) = explode('#',$img['src'],2);
- if ($img['type'] == 'internalmedia') {
- resolve_mediaid(getNS($ID),$img['src'],$exists);
+ list($img['src']) = explode('#', $img['src'], 2);
+ if($img['type'] == 'internalmedia') {
+ resolve_mediaid(getNS($ID), $img['src'], $exists ,$this->date_at, true);
}
- return $this->_media($img['src'],
- $img['title'],
- $img['align'],
- $img['width'],
- $img['height'],
- $img['cache']);
+ return $this->_media(
+ $img['src'],
+ $img['title'],
+ $img['align'],
+ $img['width'],
+ $img['height'],
+ $img['cache']
+ );
}
/**
- * _getMediaLinkConf is a helperfunction to internalmedia() and externalmedia()
- * which returns a basic link to a media.
+ * helperfunction to return a basic link to a media
*
- * @author Pierre Spring <pierre.spring@liip.ch>
- * @param string $src
- * @param string $title
- * @param string $align
- * @param string $width
- * @param string $height
- * @param string $cache
- * @param string $render
- * @access protected
- * @return array
+ * used in internalmedia() and externalmedia()
+ *
+ * @author Pierre Spring <pierre.spring@liip.ch>
+ * @param string $src media ID
+ * @param string $title descriptive text
+ * @param string $align left|center|right
+ * @param int $width width of media in pixel
+ * @param int $height height of media in pixel
+ * @param string $cache cache|recache|nocache
+ * @param bool $render should the media be embedded inline or just linked
+ * @return array associative array with link config
*/
function _getMediaLinkConf($src, $title, $align, $width, $height, $cache, $render) {
global $conf;
- $link = array();
+ $link = array();
$link['class'] = 'media';
$link['style'] = '';
$link['pre'] = '';
@@ -1271,50 +1629,64 @@ class Doku_Renderer_xhtml extends Doku_Renderer {
return $link;
}
-
/**
* Embed video(s) in HTML
*
* @author Anika Henke <anika@selfthinker.org>
*
- * @param string $src - ID of video to embed
- * @param int $width - width of the video in pixels
- * @param int $height - height of the video in pixels
- * @param array $atts - additional attributes for the <video> tag
+ * @param string $src - ID of video to embed
+ * @param int $width - width of the video in pixels
+ * @param int $height - height of the video in pixels
+ * @param array $atts - additional attributes for the <video> tag
* @return string
*/
- function _video($src,$width,$height,$atts=null){
+ function _video($src, $width, $height, $atts = null) {
// prepare width and height
if(is_null($atts)) $atts = array();
$atts['width'] = (int) $width;
$atts['height'] = (int) $height;
- if(!$atts['width']) $atts['width'] = 320;
+ if(!$atts['width']) $atts['width'] = 320;
if(!$atts['height']) $atts['height'] = 240;
- // prepare alternative formats
- $extensions = array('webm', 'ogv', 'mp4');
- $alternatives = media_alternativefiles($src, $extensions);
- $poster = media_alternativefiles($src, array('jpg', 'png'), true);
$posterUrl = '';
- if (!empty($poster)) {
- $posterUrl = ml(reset($poster),array('cache'=>$cache),true,'&');
+ $files = array();
+ $isExternal = media_isexternal($src);
+
+ if ($isExternal) {
+ // take direct source for external files
+ list(/*ext*/, $srcMime) = mimetype($src);
+ $files[$srcMime] = $src;
+ } else {
+ // prepare alternative formats
+ $extensions = array('webm', 'ogv', 'mp4');
+ $files = media_alternativefiles($src, $extensions);
+ $poster = media_alternativefiles($src, array('jpg', 'png'), true);
+ if(!empty($poster)) {
+ $posterUrl = ml(reset($poster), '', true, '&');
+ }
}
$out = '';
// open video tag
$out .= '<video '.buildAttributes($atts).' controls="controls"';
- if ($posterUrl) $out .= ' poster="'.hsc($posterUrl).'"';
+ if($posterUrl) $out .= ' poster="'.hsc($posterUrl).'"';
$out .= '>'.NL;
$fallback = '';
// output source for each alternative video format
- foreach($alternatives as $mime => $file) {
- $url = ml($file,array('cache'=>$cache),true,'&');
+ foreach($files as $mime => $file) {
+ if ($isExternal) {
+ $url = $file;
+ $linkType = 'externalmedia';
+ } else {
+ $url = ml($file, '', true, '&');
+ $linkType = 'internalmedia';
+ }
$title = $atts['title'] ? $atts['title'] : $this->_xmlEntities(utf8_basename(noNS($file)));
$out .= '<source src="'.hsc($url).'" type="'.$mime.'" />'.NL;
// alternative content (just a link to the file)
- $fallback .= $this->internalmedia($file, $title, NULL, NULL, NULL, $cache=NULL, $linking='linkonly', $return=true);
+ $fallback .= $this->$linkType($file, $title, null, null, null, $cache = null, $linking = 'linkonly', $return = true);
}
// finish
@@ -1328,15 +1700,23 @@ class Doku_Renderer_xhtml extends Doku_Renderer {
*
* @author Anika Henke <anika@selfthinker.org>
*
- * @param string $src - ID of audio to embed
- * @param array $atts - additional attributes for the <audio> tag
+ * @param string $src - ID of audio to embed
+ * @param array $atts - additional attributes for the <audio> tag
* @return string
*/
- function _audio($src,$atts=null){
-
- // prepare alternative formats
- $extensions = array('ogg', 'mp3', 'wav');
- $alternatives = media_alternativefiles($src, $extensions);
+ function _audio($src, $atts = null) {
+ $files = array();
+ $isExternal = media_isexternal($src);
+
+ if ($isExternal) {
+ // take direct source for external files
+ list(/*ext*/, $srcMime) = mimetype($src);
+ $files[$srcMime] = $src;
+ } else {
+ // prepare alternative formats
+ $extensions = array('ogg', 'mp3', 'wav');
+ $files = media_alternativefiles($src, $extensions);
+ }
$out = '';
// open audio tag
@@ -1344,13 +1724,19 @@ class Doku_Renderer_xhtml extends Doku_Renderer {
$fallback = '';
// output source for each alternative audio format
- foreach($alternatives as $mime => $file) {
- $url = ml($file,array('cache'=>$cache),true,'&');
+ foreach($files as $mime => $file) {
+ if ($isExternal) {
+ $url = $file;
+ $linkType = 'externalmedia';
+ } else {
+ $url = ml($file, '', true, '&');
+ $linkType = 'internalmedia';
+ }
$title = $atts['title'] ? $atts['title'] : $this->_xmlEntities(utf8_basename(noNS($file)));
$out .= '<source src="'.hsc($url).'" type="'.$mime.'" />'.NL;
// alternative content (just a link to the file)
- $fallback .= $this->internalmedia($file, $title, NULL, NULL, NULL, $cache=NULL, $linking='linkonly', $return=true);
+ $fallback .= $this->$linkType($file, $title, null, null, null, $cache = null, $linking = 'linkonly', $return = true);
}
// finish
@@ -1358,7 +1744,23 @@ class Doku_Renderer_xhtml extends Doku_Renderer {
$out .= '</audio>'.NL;
return $out;
}
+
+ /**
+ * _getLastMediaRevisionAt is a helperfunction to internalmedia() and _media()
+ * which returns an existing media revision less or equal to rev or date_at
+ *
+ * @author lisps
+ * @param string $media_id
+ * @access protected
+ * @return string revision ('' for current)
+ */
+ function _getLastMediaRevisionAt($media_id){
+ if(!$this->date_at || media_isexternal($media_id)) return '';
+ $pagelog = new MediaChangeLog($media_id);
+ return $pagelog->getLastRevisionAt($this->date_at);
+ }
+ #endregion
}
//Setup VIM: ex: et ts=4 :