15153720fSfkaag71<?php 25153720fSfkaag71/** 35153720fSfkaag71 * @license GPL 2 (http://www.gnu.org/licenses/gpl.html) 45153720fSfkaag71 * @author Brend Wanders <b.wanders@utwente.nl> 55153720fSfkaag71 */ 65153720fSfkaag71// must be run within Dokuwiki 75153720fSfkaag71if(!defined('DOKU_INC')) die('Meh.'); 85153720fSfkaag71 95153720fSfkaag71use dokuwiki\Parsing\Parser; 105153720fSfkaag71use dokuwiki\Parsing\Handler\Block; 11*8147e7f0SFKaaguse dokuwiki\Extension\Event; 125153720fSfkaag71 135153720fSfkaag71/** 145153720fSfkaag71 * The 'render as wiki text' type. 155153720fSfkaag71 */ 165153720fSfkaag71class plugin_strata_type_wiki extends plugin_strata_type { 175153720fSfkaag71 function normalize($value, $hint) { 185153720fSfkaag71 $ins = $this->_instructions($value); 195153720fSfkaag71 205153720fSfkaag71 $value = "\n".str_replace("\r\n","\n",$value)."\n"; 215153720fSfkaag71 225153720fSfkaag71 for($i=count($ins)-1;$i>=0;$i--) { 235153720fSfkaag71 switch($ins[$i][0]) { 245153720fSfkaag71 case 'internallink': 255153720fSfkaag71 $replacement = $this->_normalize_internallink($ins[$i][1]); 265153720fSfkaag71 break; 275153720fSfkaag71 case 'locallink': 285153720fSfkaag71 $replacement = $this->_normalize_locallink($ins[$i][1]); 295153720fSfkaag71 break; 305153720fSfkaag71 case 'internalmedia': 315153720fSfkaag71 $replacement = $this->_normalize_media($ins[$i][1]); 325153720fSfkaag71 break; 335153720fSfkaag71 case 'externallink': 345153720fSfkaag71 $replacement = $this->_linkSyntax($ins[$i][1], $ins[$i][1][0]); 355153720fSfkaag71 break; 365153720fSfkaag71 default: 375153720fSfkaag71 continue 2; 385153720fSfkaag71 } 395153720fSfkaag71 405153720fSfkaag71 $value = substr_replace($value, $replacement, $ins[$i][2], $ins[$i+1][2] - $ins[$i][2]); 415153720fSfkaag71 } 425153720fSfkaag71 435153720fSfkaag71 // strip off only the inserted newlines 445153720fSfkaag71 return substr($value,1,-1); 455153720fSfkaag71 } 465153720fSfkaag71 475153720fSfkaag71 /** 485153720fSfkaag71 * Normalizes an internal link. 495153720fSfkaag71 */ 505153720fSfkaag71 function _normalize_internallink($instruction) { 515153720fSfkaag71 global $ID; 525153720fSfkaag71 535153720fSfkaag71 // split off query string 545153720fSfkaag71 $parts = explode('?', $instruction[0] ,2); 555153720fSfkaag71 565153720fSfkaag71 $id = $parts[0]; 575153720fSfkaag71 585153720fSfkaag71 list($id,$hash) = explode('#', $id, 2); 595153720fSfkaag71 // normalize selflink 605153720fSfkaag71 if($id === '') { 615153720fSfkaag71 $id = $ID; 625153720fSfkaag71 } 635153720fSfkaag71 645153720fSfkaag71 // actually resolve the page 655153720fSfkaag71 resolve_pageid(getNS($ID), $id, $exists); 665153720fSfkaag71 // make the resolved pageid absolute, so it does not re-resolve to something else later on 675153720fSfkaag71 $id = ':'.$id; 685153720fSfkaag71 695153720fSfkaag71 // render the link 705153720fSfkaag71 return $this->_linkSyntax($instruction, $id.'#'.$hash); 715153720fSfkaag71 } 725153720fSfkaag71 735153720fSfkaag71 /** 745153720fSfkaag71 * Normalizes a local link. 755153720fSfkaag71 */ 765153720fSfkaag71 function _normalize_locallink($instruction) { 775153720fSfkaag71 global $ID; 785153720fSfkaag71 795153720fSfkaag71 // simply prefix the current page 805153720fSfkaag71 return $this->_linkSyntax($instruction, $ID.'#'.$instruction[0]); 815153720fSfkaag71 } 825153720fSfkaag71 835153720fSfkaag71 /** 845153720fSfkaag71 * Normalizes a media array. 855153720fSfkaag71 */ 865153720fSfkaag71 function _normalize_media($instruction) { 875153720fSfkaag71 global $ID; 885153720fSfkaag71 895153720fSfkaag71 // construct media structure based on input 905153720fSfkaag71 if(isset($instruction['type'])) { 915153720fSfkaag71 $media = $instruction; 925153720fSfkaag71 } else { 935153720fSfkaag71 list($src, $title, $align, $width, $height, $cache, $linking) = $instruction; 945153720fSfkaag71 $media = compact('src','title','align','width','height'); 955153720fSfkaag71 $media['type']= 'internalmedia'; 965153720fSfkaag71 } 975153720fSfkaag71 985153720fSfkaag71 // normalize internal media links 995153720fSfkaag71 if($media['type'] == 'internalmedia') { 1005153720fSfkaag71 list($src,$hash) = explode('#',$media['src'],2); 1015153720fSfkaag71 resolve_mediaid(getNS($ID),$src, $exists); 1025153720fSfkaag71 if($hash) $src.='#'.$hash; 1035153720fSfkaag71 $media['src'] = ':'.$src; 1045153720fSfkaag71 } 1055153720fSfkaag71 1065153720fSfkaag71 // render the media structure 1075153720fSfkaag71 return $this->_mediaSyntax($media); 1085153720fSfkaag71 } 1095153720fSfkaag71 1105153720fSfkaag71 /** 1115153720fSfkaag71 * Renders the media syntax. 1125153720fSfkaag71 */ 1135153720fSfkaag71 function _mediaSyntax($media) { 1145153720fSfkaag71 // the source 1155153720fSfkaag71 $src = $media['src']; 1165153720fSfkaag71 1175153720fSfkaag71 // the resizing part 1185153720fSfkaag71 if(isset($media['width'])) { 1195153720fSfkaag71 $size = '?'.$media['width']; 1205153720fSfkaag71 if(isset($media['height'])) { 1215153720fSfkaag71 $size .= 'x'.$media['height']; 1225153720fSfkaag71 } 1235153720fSfkaag71 } else { 1245153720fSfkaag71 $size = ''; 1255153720fSfkaag71 } 1265153720fSfkaag71 1275153720fSfkaag71 // the title part 1285153720fSfkaag71 if(isset($media['title'])) { 1295153720fSfkaag71 $title = '|'.$media['title']; 1305153720fSfkaag71 } else { 1315153720fSfkaag71 $title = ''; 1325153720fSfkaag71 } 1335153720fSfkaag71 1345153720fSfkaag71 // the alignment parts 1355153720fSfkaag71 if(isset($media['align'])) { 1365153720fSfkaag71 switch($media['align']) { 1375153720fSfkaag71 case 'left': 1385153720fSfkaag71 $al = ''; $ar = ' '; break; 1395153720fSfkaag71 case 'right': 1405153720fSfkaag71 $al = ' '; $ar = ''; break; 1415153720fSfkaag71 case 'center': 1425153720fSfkaag71 $al = ' '; $ar = ' '; break; 1435153720fSfkaag71 } 1445153720fSfkaag71 } 1455153720fSfkaag71 1465153720fSfkaag71 // construct the syntax 1475153720fSfkaag71 return '{{'.$al.$src.$size.$ar.$title.'}}'; 1485153720fSfkaag71 } 1495153720fSfkaag71 1505153720fSfkaag71 /** 1515153720fSfkaag71 * Renders the link syntax, invoking media normalization 1525153720fSfkaag71 * if required. 1535153720fSfkaag71 */ 1545153720fSfkaag71 function _linkSyntax($instruction, $newLink) { 1555153720fSfkaag71 // fetch params from old link 1565153720fSfkaag71 $parts = explode('?', $instruction[0],2); 1575153720fSfkaag71 if(count($parts) === 2) { 1585153720fSfkaag71 $params = '?'.$parts[1]; 1595153720fSfkaag71 } else { 1605153720fSfkaag71 $params = ''; 1615153720fSfkaag71 } 1625153720fSfkaag71 1635153720fSfkaag71 // determine title 1645153720fSfkaag71 $title = ''; 1655153720fSfkaag71 if(isset($instruction[1])) { 1665153720fSfkaag71 if(is_array($instruction[1])) { 1675153720fSfkaag71 if($instruction[1]['type'] == 'internalmedia') { 1685153720fSfkaag71 $title='|'.$this->_normalize_media($instruction[1]); 1695153720fSfkaag71 } else { 1705153720fSfkaag71 $title='|'.$this->_mediaSyntax($instruction[1]); 1715153720fSfkaag71 } 1725153720fSfkaag71 } else { 1735153720fSfkaag71 $title = '|'.$instruction[1]; 1745153720fSfkaag71 } 1755153720fSfkaag71 } 1765153720fSfkaag71 1775153720fSfkaag71 // construct a new link string 1785153720fSfkaag71 return '[['.$newLink.$params.$title.']]'; 1795153720fSfkaag71 1805153720fSfkaag71 } 1815153720fSfkaag71 1825153720fSfkaag71 function render($mode, &$R, &$T, $value, $hint) { 1835153720fSfkaag71 // though this breaks backlink functionality, we really do not want 1845153720fSfkaag71 // metadata renders of included pieces of wiki. 1855153720fSfkaag71 if($mode == 'xhtml' || $mode == 'odt') { 1865153720fSfkaag71 $instructions = $this->_instructions($value); 1875153720fSfkaag71 $instructions = array_slice($instructions, 2, -2); 1885153720fSfkaag71 1895153720fSfkaag71 // last-minute fix of newline in front of content 1905153720fSfkaag71 if(!empty($instructions[0][0]) && $instructions[0][0]=='cdata') { 1915153720fSfkaag71 $instructions[0][1][0] = ltrim($instructions[0][1][0]); 1925153720fSfkaag71 } 1935153720fSfkaag71 1945153720fSfkaag71 // actual render of content 1955153720fSfkaag71 $R->nest($instructions); 1965153720fSfkaag71 } 1975153720fSfkaag71 } 1985153720fSfkaag71 1995153720fSfkaag71 function getInfo() { 2005153720fSfkaag71 return array( 2015153720fSfkaag71 'desc'=>'Allows the use of dokuwiki syntax; only non-block syntax is allowed (only links, formatting, etc.; no tables, headers, and other large stuff). The hint is ignored.', 2025153720fSfkaag71 'tags'=>array() 2035153720fSfkaag71 ); 2045153720fSfkaag71 } 2055153720fSfkaag71 2065153720fSfkaag71 function _instructions($text) { 2075153720fSfkaag71 // determine all parser modes that are allowable as inline modes 2085153720fSfkaag71 // (i.e., those that are allowed inside a table cell, minus those 2095153720fSfkaag71 // that have a paragraph type other than 'normal') 2105153720fSfkaag71 2115153720fSfkaag71 // determine all modes allowed inside a table cell or list item 2125153720fSfkaag71 2135153720fSfkaag71 // import parser classes and mode definitions to make the $PARSER_MODES global available to us 2145153720fSfkaag71 require_once(DOKU_INC . 'inc/parser/parser.php'); 2155153720fSfkaag71 global $PARSER_MODES; 2165153720fSfkaag71 $allowedModes = array_merge( 2175153720fSfkaag71 $PARSER_MODES['formatting'], 2185153720fSfkaag71 $PARSER_MODES['substition'], 2195153720fSfkaag71 $PARSER_MODES['disabled'], 2205153720fSfkaag71 $PARSER_MODES['protected'] 2215153720fSfkaag71 ); 2225153720fSfkaag71 2235153720fSfkaag71 // determine all modes that are not allowed either due to paragraph 2245153720fSfkaag71 // handling, or because they're blacklisted as they don't make sense. 2255153720fSfkaag71 $blockHandler = new Block(); 2265153720fSfkaag71 $disallowedModes = array_merge( 2275153720fSfkaag71 // inlined from Block::blockOpen due to being protected: 2285153720fSfkaag71 array( 2295153720fSfkaag71 'header', 2305153720fSfkaag71 'listu_open','listo_open','listitem_open','listcontent_open', 2315153720fSfkaag71 'table_open','tablerow_open','tablecell_open','tableheader_open','tablethead_open', 2325153720fSfkaag71 'quote_open', 2335153720fSfkaag71 'code','file','hr','preformatted','rss', 2345153720fSfkaag71 'htmlblock','phpblock', 2355153720fSfkaag71 'footnote_open', 2365153720fSfkaag71 ), 2375153720fSfkaag71 // inlined from Block::stackOpen due to being protected: 2385153720fSfkaag71 array( 2395153720fSfkaag71 'section_open', 2405153720fSfkaag71 ), 2415153720fSfkaag71 array('notoc', 'nocache') 2425153720fSfkaag71 ); 2435153720fSfkaag71 2445153720fSfkaag71 $allowedModes = array_diff($allowedModes, $disallowedModes); 2455153720fSfkaag71 2465153720fSfkaag71 $parser = new Parser(new Doku_Handler()); 2475153720fSfkaag71 2485153720fSfkaag71 foreach(p_get_parsermodes() as $mode) { 2495153720fSfkaag71 if(!in_array($mode['mode'], $allowedModes)) continue; 2505153720fSfkaag71 $parser->addMode($mode['mode'], $mode['obj']); 2515153720fSfkaag71 } 2525153720fSfkaag71 253*8147e7f0SFKaag Event::createAndTrigger('PARSER_WIKITEXT_PREPROCESS', $text); 2545153720fSfkaag71 $p = $parser->parse($text); 2555153720fSfkaag71 return $p; 2565153720fSfkaag71 } 2575153720fSfkaag71} 258