17d101cc1SGerry Weißbach<?php 27d101cc1SGerry Weißbach/** 37d101cc1SGerry Weißbach * Search with Scopes 47d101cc1SGerry Weißbach * 57d101cc1SGerry Weißbach * @license GPL 2 (http://www.gnu.org/licenses/gpl.html) 67d101cc1SGerry Weißbach * @author i-net software <tools@inetsoftware.de> 77d101cc1SGerry Weißbach * @author Gerry Weissbach <gweissbach@inetsoftware.de> 87d101cc1SGerry Weißbach */ 97d101cc1SGerry Weißbach 107d101cc1SGerry Weißbach// must be run within Dokuwiki 117d101cc1SGerry Weißbachif(!defined('DOKU_INC')) die(); 127d101cc1SGerry Weißbachif (!defined('DOKU_PLUGIN')) define('DOKU_PLUGIN',DOKU_INC.'lib/plugins/'); 137d101cc1SGerry Weißbach 147d101cc1SGerry Weißbachrequire_once(DOKU_PLUGIN.'syntax.php'); 157d101cc1SGerry Weißbach 167d101cc1SGerry Weißbachclass syntax_plugin_siteexport_toc extends DokuWiki_Syntax_Plugin { 177d101cc1SGerry Weißbach 187d101cc1SGerry Weißbach var $insideToc = false; 197d101cc1SGerry Weißbach var $savedToc = array(); 20*5321bc23SGerry Weißbach var $options = array(); 217d101cc1SGerry Weißbach 227d101cc1SGerry Weißbach var $mergedPages = array(); 237d101cc1SGerry Weißbach var $includedPages = array(); 247d101cc1SGerry Weißbach 257d101cc1SGerry Weißbach function getType() { return 'protected'; } 267d101cc1SGerry Weißbach function getPType() { return 'block'; } 277d101cc1SGerry Weißbach function getAllowedTypes() { return array('container'); } 287d101cc1SGerry Weißbach function getSort() { return 100; } 297d101cc1SGerry Weißbach 307d101cc1SGerry Weißbach /** 317d101cc1SGerry Weißbach * for backward compatability 327d101cc1SGerry Weißbach * @see inc/DokuWiki_Plugin#getInfo() 337d101cc1SGerry Weißbach */ 347d101cc1SGerry Weißbach function getInfo(){ 357d101cc1SGerry Weißbach if ( method_exists(parent, 'getInfo')) { 367d101cc1SGerry Weißbach $info = parent::getInfo(); 377d101cc1SGerry Weißbach } 387d101cc1SGerry Weißbach return is_array($info) ? $info : confToHash(dirname(__FILE__).'/../plugin.info.txt'); 397d101cc1SGerry Weißbach } 407d101cc1SGerry Weißbach 417d101cc1SGerry Weißbach /** 427d101cc1SGerry Weißbach * Connect pattern to lexer 437d101cc1SGerry Weißbach */ 447d101cc1SGerry Weißbach function connectTo($mode) { 457d101cc1SGerry Weißbach $this->Lexer->addEntryPattern('<toc>(?=.*?</toc>)',$mode,'plugin_siteexport_toc'); 467d101cc1SGerry Weißbach $this->Lexer->addEntryPattern('<toc .+?>(?=.*?</toc>)',$mode,'plugin_siteexport_toc'); 477d101cc1SGerry Weißbach $this->Lexer->addSpecialPattern("\[\[.+?\]\]",$mode,'plugin_siteexport_toc'); 487d101cc1SGerry Weißbach } 497d101cc1SGerry Weißbach 507d101cc1SGerry Weißbach function postConnect() { 517d101cc1SGerry Weißbach $this->Lexer->addExitPattern('</toc.*?>', 'plugin_siteexport_toc'); 527d101cc1SGerry Weißbach } 537d101cc1SGerry Weißbach 547d101cc1SGerry Weißbach function handle($match, $state, $pos, &$handler) { 557d101cc1SGerry Weißbach global $ID, $INFO; 567d101cc1SGerry Weißbach 577d101cc1SGerry Weißbach switch ($state) { 587d101cc1SGerry Weißbach case DOKU_LEXER_ENTER: 597d101cc1SGerry Weißbach 607d101cc1SGerry Weißbach $this->insideToc = true; 617d101cc1SGerry Weißbach 62*5321bc23SGerry Weißbach $this->options = explode(' ', substr($match, 5, -1)); 63*5321bc23SGerry Weißbach return array('start' => true, 'pos' => $pos, 'options' => $this->options); 647d101cc1SGerry Weißbach break; 657d101cc1SGerry Weißbach 667d101cc1SGerry Weißbach case DOKU_LEXER_SPECIAL: 677d101cc1SGerry Weißbach 687d101cc1SGerry Weißbach if ( $this->insideToc ) { 697d101cc1SGerry Weißbach 707d101cc1SGerry Weißbach $link = preg_replace(array('/^\[\[/','/\]\]$/u'),'',$match); 717d101cc1SGerry Weißbach // Split title from URL 727d101cc1SGerry Weißbach $link = explode('|',$link,2); 737d101cc1SGerry Weißbach if ( !isset($link[1]) ) { 747d101cc1SGerry Weißbach $link[1] = NULL; 757d101cc1SGerry Weißbach } else if ( preg_match('/^\{\{[^\}]+\}\}$/',$link[1]) ) { 767d101cc1SGerry Weißbach // If the title is an image, convert it to an array containing the image details 777d101cc1SGerry Weißbach $link[1] = Doku_Handler_Parse_Media($link[1]); 787d101cc1SGerry Weißbach } 797d101cc1SGerry Weißbach $link[0] = trim($link[0]); 807d101cc1SGerry Weißbach 817d101cc1SGerry Weißbach if ( ! (preg_match('/^[a-zA-Z0-9\.]+>{1}.*$/u',$link[0]) || 827d101cc1SGerry Weißbach preg_match('/^\\\\\\\\[\w.:?\-;,]+?\\\\/u',$link[0]) || 837d101cc1SGerry Weißbach preg_match('#^([a-z0-9\-\.+]+?)://#i',$link[0]) || 847d101cc1SGerry Weißbach preg_match('<'.PREG_PATTERN_VALID_EMAIL.'>',$link[0]) || 857d101cc1SGerry Weißbach preg_match('!^#.+!',$link[0]) ) 867d101cc1SGerry Weißbach ) { 877d101cc1SGerry Weißbach 887d101cc1SGerry Weißbach // Get current depth from call stack 897d101cc1SGerry Weißbach $depth = 1; 907d101cc1SGerry Weißbach if ( $handler->CallWriter instanceof Doku_Handler_List ) { 917d101cc1SGerry Weißbach 927d101cc1SGerry Weißbach $calls = array_reverse($handler->CallWriter->calls); 937d101cc1SGerry Weißbach $call = $calls[0]; 947d101cc1SGerry Weißbach foreach ( $calls as $item ) { 957d101cc1SGerry Weißbach if ( in_array( $item[0], array( 'list_item', 'list_open') ) ) { $call = $item; break;} 967d101cc1SGerry Weißbach } 977d101cc1SGerry Weißbach 987d101cc1SGerry Weißbach $depth = $handler->CallWriter->interpretSyntax($call[1][0], $listType); 997d101cc1SGerry Weißbach 1007d101cc1SGerry Weißbach } 1017d101cc1SGerry Weißbach 1027d101cc1SGerry Weißbach if ( empty( $link[0] ) ) { break; } // No empty elements. This would lead to problems 1037d101cc1SGerry Weißbach return array($link[0], $link[1], $depth); 1047d101cc1SGerry Weißbach break; 1057d101cc1SGerry Weißbach } else { 1067d101cc1SGerry Weißbach // use parser! - but with another p 1077d101cc1SGerry Weißbach $handler->internallink($match, $state, $pos); 1087d101cc1SGerry Weißbach } 1097d101cc1SGerry Weißbach } else { 1107d101cc1SGerry Weißbach // use parser! 1117d101cc1SGerry Weißbach $handler->internallink($match, $state, $pos); 1127d101cc1SGerry Weißbach } 1137d101cc1SGerry Weißbach 1147d101cc1SGerry Weißbach return false; 1157d101cc1SGerry Weißbach case DOKU_LEXER_UNMATCHED: 1167d101cc1SGerry Weißbach 1177d101cc1SGerry Weißbach $handler->_addCall('cdata',array($match), $pos); 118*5321bc23SGerry Weißbach 1197d101cc1SGerry Weißbach return false; 1207d101cc1SGerry Weißbach break; 1217d101cc1SGerry Weißbach case DOKU_LEXER_EXIT: 1227d101cc1SGerry Weißbach 1237d101cc1SGerry Weißbach $this->insideToc = false; 1247d101cc1SGerry Weißbach return 'save__meta'; 1257d101cc1SGerry Weißbach break; 1267d101cc1SGerry Weißbach } 1277d101cc1SGerry Weißbach return false; 1287d101cc1SGerry Weißbach } 1297d101cc1SGerry Weißbach 1307d101cc1SGerry Weißbach function render($mode, &$renderer, $data) { 1317d101cc1SGerry Weißbach global $ID, $lang, $INFO; 1327d101cc1SGerry Weißbach 1337d101cc1SGerry Weißbach list( $SID, $NAME, $DEPTH ) = $data; 1347d101cc1SGerry Weißbach 1357d101cc1SGerry Weißbach resolve_pageid(getNS($ID),$SID,$exists); 1367d101cc1SGerry Weißbach// $SID = cleanID($SID); // hier kein cleanID, da sonst m�glicherweise der anker verloren geht 1377d101cc1SGerry Weißbach 1387d101cc1SGerry Weißbach // Render XHTML and ODT 1397d101cc1SGerry Weißbach if ($mode == 'xhtml' || $mode == 'odt') { 1407d101cc1SGerry Weißbach 1417d101cc1SGerry Weißbach // TOC Title 142f3b63992SGerry Weißbach if ( isset($data['start']) ) { 1437d101cc1SGerry Weißbach 1447d101cc1SGerry Weißbach if ( is_Array($data['options']) ) { 1457d101cc1SGerry Weißbach foreach( $data['options'] as $opt ) { 1467d101cc1SGerry Weißbach switch( $opt ) { 1477d101cc1SGerry Weißbach case 'description' : $renderer->meta['sitetoc']['showDescription'] = true; break; 1487d101cc1SGerry Weißbach case 'notoc' : $renderer->meta['sitetoc']['noTOC'] = true; break; 1497d101cc1SGerry Weißbach case 'merge' : $renderer->meta['sitetoc']['mergeDoc'] = true; break; 1507d101cc1SGerry Weißbach case 'nohead' : $renderer->meta['sitetoc']['noTocHeader'] = true; break; 151*5321bc23SGerry Weißbach case 'mergeheader' : $renderer->meta['sitetoc']['mergeHeader'] = true; break; 1527d101cc1SGerry Weißbach } 1537d101cc1SGerry Weißbach } 1547d101cc1SGerry Weißbach } 1557d101cc1SGerry Weißbach 1567d101cc1SGerry Weißbach $renderer->section_open("1 sitetoc"); 1577d101cc1SGerry Weißbach if ( $renderer->meta['sitetoc']['noTocHeader'] === false ) { 1587d101cc1SGerry Weißbach $renderer->header($lang['toc'], 1, $data['pos']); 1597d101cc1SGerry Weißbach } 1607d101cc1SGerry Weißbach 1617d101cc1SGerry Weißbach return true; 1627d101cc1SGerry Weißbach } 1637d101cc1SGerry Weißbach 1647d101cc1SGerry Weißbach // All Output has been done 1657d101cc1SGerry Weißbach if ( !is_array($data) && $data == 'save__meta' ) { 1667d101cc1SGerry Weißbach 1677d101cc1SGerry Weißbach // Close TOC 1687d101cc1SGerry Weißbach $renderer->section_close(); 1697d101cc1SGerry Weißbach 1707d101cc1SGerry Weißbach if ( $renderer->meta['sitetoc']['noTOC'] === true ) { 1717d101cc1SGerry Weißbach $renderer->doc = preg_replace("/<div.*?sitetoc.*?$/si", "", $renderer->doc); 1727d101cc1SGerry Weißbach } 1737d101cc1SGerry Weißbach 1747d101cc1SGerry Weißbach // If this is not set, we may have it as Metadata 1757d101cc1SGerry Weißbach if ( !$this->mergedPages && $renderer->meta['sitetoc']['mergeDoc'] ) { 1767d101cc1SGerry Weißbach $toc = $renderer->meta['sitetoc']['siteexportTOC']; 1777d101cc1SGerry Weißbach if ( is_array($toc)) { 1787d101cc1SGerry Weißbach foreach ($toc as $tocItem ) { 1797d101cc1SGerry Weißbach $this->mergedPages[] = $tocItem['id']; 1807d101cc1SGerry Weißbach } 1817d101cc1SGerry Weißbach } 1827d101cc1SGerry Weißbach } 1837d101cc1SGerry Weißbach 1847d101cc1SGerry Weißbach // If there is some data to be merged 1857d101cc1SGerry Weißbach if ( count($this->mergedPages) > 0) { 1867d101cc1SGerry Weißbach 187*5321bc23SGerry Weißbach $renderer->doc = ''; // Start fresh! 188*5321bc23SGerry Weißbach 1897d101cc1SGerry Weißbach $renderer->section_open("1 mergedsite"); 1907d101cc1SGerry Weißbach 1917d101cc1SGerry Weißbach // Prepare lookup Array 1927d101cc1SGerry Weißbach foreach ( $this->mergedPages as $tocItem ) { 1937d101cc1SGerry Weißbach $this->includedPages[] = array_shift(explode('#', $tocItem)); 1947d101cc1SGerry Weißbach } 1957d101cc1SGerry Weißbach 196*5321bc23SGerry Weißbach // Load the instructions 197*5321bc23SGerry Weißbach $instr = array(); 1987d101cc1SGerry Weißbach foreach ( $this->mergedPages as $tocItem ) { 199*5321bc23SGerry Weißbach $file = wikiFN($tocItem); 200*5321bc23SGerry Weißbach $instructions = p_cached_instructions($file, false); 201*5321bc23SGerry Weißbach 202*5321bc23SGerry Weißbach // Convert Link instructions 203*5321bc23SGerry Weißbach $instructions = $this->_convertInstructions($instructions, $addID, $renderer); 204*5321bc23SGerry Weißbach 205*5321bc23SGerry Weißbach if ( $renderer->meta['sitetoc']['mergeHeader'] && !empty($instr) ) { 206*5321bc23SGerry Weißbach // Merge 207*5321bc23SGerry Weißbach $instr = $this->_mergeWithHeaders($instr, $instructions, 1); 208*5321bc23SGerry Weißbach // print_r($instr); 209*5321bc23SGerry Weißbach 210*5321bc23SGerry Weißbach } else { 211*5321bc23SGerry Weißbach // Concat 212*5321bc23SGerry Weißbach $instr = array_merge($instr, $instructions); 2137d101cc1SGerry Weißbach } 214*5321bc23SGerry Weißbach } 215*5321bc23SGerry Weißbach 216*5321bc23SGerry Weißbach //page was empty 217*5321bc23SGerry Weißbach if (empty($instr)) { 218*5321bc23SGerry Weißbach return; 219*5321bc23SGerry Weißbach } 220*5321bc23SGerry Weißbach 221*5321bc23SGerry Weißbach $this->_cleanInstructions($instr, '/section_(close|open)/'); 222*5321bc23SGerry Weißbach $this->_cleanInstructions($instr, '/listu_(close|open)/'); 223*5321bc23SGerry Weißbach $this->_cleanInstructions($instr, '/listo_(close|open)/'); 224*5321bc23SGerry Weißbach 225*5321bc23SGerry Weißbach $this->_render_output($renderer, $mode, $instr); 2267d101cc1SGerry Weißbach 2277d101cc1SGerry Weißbach $renderer->section_close(); 2287d101cc1SGerry Weißbach } 2297d101cc1SGerry Weißbach return true; 2307d101cc1SGerry Weißbach } 2317d101cc1SGerry Weißbach 2327d101cc1SGerry Weißbach // Save the current ID 2337d101cc1SGerry Weißbach $LNID = $SID; 2347d101cc1SGerry Weißbach 2357d101cc1SGerry Weißbach // Add ID to flags['mergeDoc'] 2367d101cc1SGerry Weißbach if ( $renderer->meta['sitetoc']['mergeDoc'] === true ) { // || (count($renderer->meta['sitetoc']['siteexportTOC']) > 0 && $renderer->meta['sitetoc']['siteexportMergeDoc'] === true) ) { 2377d101cc1SGerry Weißbach $this->mergedPages[] = $SID; 2387d101cc1SGerry Weißbach $default = $renderer->_simpleTitle($SID); $isImage = false; 2397d101cc1SGerry Weißbach resolve_pageid(getNS($ID),$SID,$exists); 2407d101cc1SGerry Weißbach 2417d101cc1SGerry Weißbach $NAME = empty($NAME) ? p_get_first_heading($SID,true) : $NAME; 2427d101cc1SGerry Weißbach $LNID = "$ID#" . sectionID($SID, $check); 243*5321bc23SGerry Weißbach } else { 244*5321bc23SGerry Weißbach // // print normal internal link (XHTML odt) 2457d101cc1SGerry Weißbach $renderer->internallink($LNID, $NAME, null); 2467d101cc1SGerry Weißbach 2477d101cc1SGerry Weißbach // Display Description underneath 2487d101cc1SGerry Weißbach if ( $renderer->meta['sitetoc']['showDescription'] === true ) { 2497d101cc1SGerry Weißbach // $renderer->p_open(); 2507d101cc1SGerry Weißbach $renderer->cdata(p_get_metadata($SID, 'description abstract', true)); 2517d101cc1SGerry Weißbach // $renderer->p_close(); 2527d101cc1SGerry Weißbach } 253*5321bc23SGerry Weißbach } 2547d101cc1SGerry Weißbach 2557d101cc1SGerry Weißbach // Render Metadata 2567d101cc1SGerry Weißbach } else if ($mode == 'metadata') { 2577d101cc1SGerry Weißbach if ( !is_array($data) && $data == 'save__meta' ) { 2587d101cc1SGerry Weißbach $renderer->meta['sitetoc']['siteexportTOC'] = $this->savedToc; 2597d101cc1SGerry Weißbach 2607d101cc1SGerry Weißbach foreach ($this->savedToc as $page) { 2617d101cc1SGerry Weißbach $renderer->meta['relation']['references'][$page['id']] = $page['exists']; 2627d101cc1SGerry Weißbach } 2637d101cc1SGerry Weißbach 2647d101cc1SGerry Weißbach $this->savedToc = array(); 2657d101cc1SGerry Weißbach } else if ( !isset($data['start']) && !isset($data['pos']) ) { 2667d101cc1SGerry Weißbach $this->savedToc[] = $this->__addTocItem($SID, $NAME, $DEPTH, $renderer); 2677d101cc1SGerry Weißbach } 2687d101cc1SGerry Weißbach } else { 2697d101cc1SGerry Weißbach return false; 2707d101cc1SGerry Weißbach } 2717d101cc1SGerry Weißbach 2727d101cc1SGerry Weißbach return true; 2737d101cc1SGerry Weißbach } 2747d101cc1SGerry Weißbach 2757d101cc1SGerry Weißbach /* 2767d101cc1SGerry Weißbach * pull apart the ID and create an Entry for the TOC 2777d101cc1SGerry Weißbach */ 2787d101cc1SGerry Weißbach function __addTocItem($id, $name, $depth, $renderer) { 2797d101cc1SGerry Weißbach global $conf; 2807d101cc1SGerry Weißbach global $ID; 2817d101cc1SGerry Weißbach 2827d101cc1SGerry Weißbach // Render Title 2837d101cc1SGerry Weißbach $default = $renderer->_simpleTitle($id); 2847d101cc1SGerry Weißbach $exists = false; $isImage = false; $linktype = null; 2857d101cc1SGerry Weißbach resolve_pageid(getNS($ID),$id,$exists); 2867d101cc1SGerry Weißbach $name = $renderer->_getLinkTitle($name, $default, $isImage, $id, $linktype); 2877d101cc1SGerry Weißbach 2887d101cc1SGerry Weißbach //keep hash anchor 2897d101cc1SGerry Weißbach list($id,$hash) = explode('#',$id,2); 2907d101cc1SGerry Weißbach if(!empty($hash)) $hash = $renderer->_headerToLink($hash); 2917d101cc1SGerry Weißbach 2927d101cc1SGerry Weißbach // Build Sitetoc Item 2937d101cc1SGerry Weißbach $item = array(); 2947d101cc1SGerry Weißbach $item['id'] = $id; 2957d101cc1SGerry Weißbach $item['name'] = $name; 2967d101cc1SGerry Weißbach $item['anchor'] = $hash; 2977d101cc1SGerry Weißbach $item['depth'] = $depth; 2987d101cc1SGerry Weißbach $item['exists'] = $exists; 2997d101cc1SGerry Weißbach if(!$conf['skipacl'] && auth_quickaclcheck($item['id']) < AUTH_READ){ 3007d101cc1SGerry Weißbach return false; 3017d101cc1SGerry Weißbach } 3027d101cc1SGerry Weißbach 3037d101cc1SGerry Weißbach return $item; 3047d101cc1SGerry Weißbach } 3057d101cc1SGerry Weißbach 3067d101cc1SGerry Weißbach /* 3077d101cc1SGerry Weißbach * Render the output of one page 3087d101cc1SGerry Weißbach */ 309*5321bc23SGerry Weißbach function _render_output($renderer, $mode, $instr) { 3107d101cc1SGerry Weißbach global $ID; 3117d101cc1SGerry Weißbach 3127d101cc1SGerry Weißbach // Section IDs 313*5321bc23SGerry Weißbach // $addID = sectionID($addID, $check); //not possible to use a:b:c for id 3147d101cc1SGerry Weißbach 3157d101cc1SGerry Weißbach if ( $mode == 'xhtml' ) { 316*5321bc23SGerry Weißbach 3177d101cc1SGerry Weißbach //--------RENDER 3187d101cc1SGerry Weißbach //renderer information(TOC build / Cache used) 3197d101cc1SGerry Weißbach $info = array(); 3207d101cc1SGerry Weißbach $content = p_render($mode, $instr, $info); 3217d101cc1SGerry Weißbach 3227d101cc1SGerry Weißbach //Remove TOC`s, section edit buttons and tags 3237d101cc1SGerry Weißbach $content = $this->_cleanXHTML($content); 3247d101cc1SGerry Weißbach 3257d101cc1SGerry Weißbach // embed the included page 3267d101cc1SGerry Weißbach $renderer->doc .= '<div class="include">'; 3277d101cc1SGerry Weißbach //add an anchor to find start of a inserted page 328*5321bc23SGerry Weißbach // $renderer->doc .= "<a name='$addID' id='$addID'>"; 3297d101cc1SGerry Weißbach $renderer->doc .= $content; 3307d101cc1SGerry Weißbach $renderer->doc .= '</div>'; 3317d101cc1SGerry Weißbach } else if ( $mode == 'odt') { 3327d101cc1SGerry Weißbach 3337d101cc1SGerry Weißbach // Loop through the instructions 3347d101cc1SGerry Weißbach foreach ( $instr as $instruction ) { 3357d101cc1SGerry Weißbach // Execute the callback against the Renderer 3367d101cc1SGerry Weißbach call_user_func_array(array($renderer, $instruction[0]),$instruction[1]); 3377d101cc1SGerry Weißbach } 3387d101cc1SGerry Weißbach } 3397d101cc1SGerry Weißbach } 3407d101cc1SGerry Weißbach 3417d101cc1SGerry Weißbach /* 3427d101cc1SGerry Weißbach * Corrects relative internal links and media and 3437d101cc1SGerry Weißbach * converts headers of included pages to subheaders of the current page 3447d101cc1SGerry Weißbach */ 3457d101cc1SGerry Weißbach function _convertInstructions($instr, $id, &$renderer) { 3467d101cc1SGerry Weißbach global $ID; 3477d101cc1SGerry Weißbach global $conf; 3487d101cc1SGerry Weißbach 3497d101cc1SGerry Weißbach $n = count($instr); 3507d101cc1SGerry Weißbach 3517d101cc1SGerry Weißbach for ($i = 0; $i < $n; $i++){ 3527d101cc1SGerry Weißbach //internal links(links inside this wiki) an relative links 3537d101cc1SGerry Weißbach if((substr($instr[$i][0], 0, 12) == 'internallink')){ 3547d101cc1SGerry Weißbach $this->_convert_link($renderer,$instr[$i],$id); 3557d101cc1SGerry Weißbach } 3567d101cc1SGerry Weißbach else if((substr($instr[$i][0], 0, 13) == 'internalmedia')){ 3577d101cc1SGerry Weißbach $this->_convert_media($renderer,$instr[$i],$id); 3587d101cc1SGerry Weißbach } 3597d101cc1SGerry Weißbach } 3607d101cc1SGerry Weißbach 3617d101cc1SGerry Weißbach //if its the document start, cut off the first element(document information) 3627d101cc1SGerry Weißbach if ($instr[0][0] == 'document_start') 3637d101cc1SGerry Weißbach return array_slice($instr, 1, -1); 3647d101cc1SGerry Weißbach else 3657d101cc1SGerry Weißbach return $instr; 3667d101cc1SGerry Weißbach } 3677d101cc1SGerry Weißbach 3687d101cc1SGerry Weißbach /* 3697d101cc1SGerry Weißbach * Convert link of given instruction 3707d101cc1SGerry Weißbach */ 3717d101cc1SGerry Weißbach function _convert_link(&$renderer,&$instr,$id) { 3727d101cc1SGerry Weißbach global $ID; 3737d101cc1SGerry Weißbach 3747d101cc1SGerry Weißbach $exists = false; 3757d101cc1SGerry Weißbach 3767d101cc1SGerry Weißbach resolve_pageid(getNS($id),$instr[1][0],$exists); 3777d101cc1SGerry Weißbach list( $pageID, $pageReference ) = explode("#", $instr[1][0], 2); 3787d101cc1SGerry Weißbach 3797d101cc1SGerry Weißbach if ( in_array($pageID, $this->includedPages) ) { 3807d101cc1SGerry Weißbach // Crate new internal Links 3817d101cc1SGerry Weißbach $check = null; 3827d101cc1SGerry Weißbach 3837d101cc1SGerry Weißbach // Either get existing reference or create from first heading. If still not there take the alternate ID 3847d101cc1SGerry Weißbach $pageNameLink = empty( $pageReference ) ? sectionID($pageID,$check) : $pageReference; 3857d101cc1SGerry Weißbach 3867d101cc1SGerry Weißbach $instr[1][0] = $ID . "#" . $pageNameLink; 3877d101cc1SGerry Weißbach 3887d101cc1SGerry Weißbach } else { 3897d101cc1SGerry Weißbach // Convert external Links to plain Text 3907d101cc1SGerry Weißbach 3917d101cc1SGerry Weißbach $instr = array( 3927d101cc1SGerry Weißbach "cdata", 3937d101cc1SGerry Weißbach array($instr[1][1]), 3947d101cc1SGerry Weißbach $instr[2] 3957d101cc1SGerry Weißbach ); 3967d101cc1SGerry Weißbach } 3977d101cc1SGerry Weißbach } 3987d101cc1SGerry Weißbach 3997d101cc1SGerry Weißbach /* 4007d101cc1SGerry Weißbach * Convert internalmedia of given instruction 4017d101cc1SGerry Weißbach */ 4027d101cc1SGerry Weißbach function _convert_media(&$renderer,&$instr,$id) { 4037d101cc1SGerry Weißbach global $ID; 4047d101cc1SGerry Weißbach 4057d101cc1SGerry Weißbach // Resolvemedia returns the absolute path to media by reference 4067d101cc1SGerry Weißbach $exists = false; 4077d101cc1SGerry Weißbach resolve_mediaid(getNS($id),$instr[1][0],$exists); 4087d101cc1SGerry Weißbach } 4097d101cc1SGerry Weißbach 410*5321bc23SGerry Weißbach function _mergeWithHeaders($existing, $newInstructions, $level = 1) { 411*5321bc23SGerry Weißbach 412*5321bc23SGerry Weißbach $returnInstructions = array(); 413*5321bc23SGerry Weißbach $preparedInstructions = array(); 414*5321bc23SGerry Weißbach $existingStart = $existingEnd = 0; 415*5321bc23SGerry Weißbach $firstRun = true; 416*5321bc23SGerry Weißbach 417*5321bc23SGerry Weißbach while ( $this->_findNextHeaderSection($existing, $level, $existingStart, $existingEnd) ) { 418*5321bc23SGerry Weißbach 419*5321bc23SGerry Weißbach if ( $firstRun ) { 420*5321bc23SGerry Weißbach $returnInstructions = array_merge($returnInstructions, array_slice($existing, 0, $existingStart)); 421*5321bc23SGerry Weißbach $firstRun = false; 422*5321bc23SGerry Weißbach } 423*5321bc23SGerry Weißbach 424*5321bc23SGerry Weißbach $currentSlice = array_slice($existing, $existingStart, $existingEnd - $existingStart); 425*5321bc23SGerry Weißbach 426*5321bc23SGerry Weißbach // Find matching part with headername 427*5321bc23SGerry Weißbach $newStart = $newEnd = 0; 428*5321bc23SGerry Weißbach if ( $this->_findNextHeaderSection($newInstructions, $level, $newStart, $newEnd, $currentSlice[0][1][0]) ) { 429*5321bc23SGerry Weißbach 430*5321bc23SGerry Weißbach $newSlice = array_slice($newInstructions, $newStart, $newEnd - $newStart); 431*5321bc23SGerry Weißbach if ( $newSlice[0][0] == 'header' ) 432*5321bc23SGerry Weißbach array_shift($newSlice); // Remove Heading 433*5321bc23SGerry Weißbach 434*5321bc23SGerry Weißbach // merge found parts on next level. 435*5321bc23SGerry Weißbach $returnedInstructions = $this->_mergeWithHeaders($currentSlice, $newSlice, $level+1); 436*5321bc23SGerry Weißbach 437*5321bc23SGerry Weißbach // Put them at the end! 438*5321bc23SGerry Weißbach $preparedInstructions = array_merge($preparedInstructions, $returnedInstructions); 439*5321bc23SGerry Weißbach 440*5321bc23SGerry Weißbach // Remove from input 441*5321bc23SGerry Weißbach array_splice($newInstructions, $newStart, $newEnd - $newStart); 442*5321bc23SGerry Weißbach } else { 443*5321bc23SGerry Weißbach $preparedInstructions = array_merge($preparedInstructions, $currentSlice); 444*5321bc23SGerry Weißbach } 445*5321bc23SGerry Weißbach 446*5321bc23SGerry Weißbach $existingStart = $existingEnd; 447*5321bc23SGerry Weißbach } 448*5321bc23SGerry Weißbach 449*5321bc23SGerry Weißbach // Append the rest 450*5321bc23SGerry Weißbach $returnInstructions = array_merge($returnInstructions, array_slice($existing, $existingStart)); 451*5321bc23SGerry Weißbach 452*5321bc23SGerry Weißbach // Check for section close inconsistencies and put one at the very end ... 453*5321bc23SGerry Weißbach $section_postpend = array(); 454*5321bc23SGerry Weißbach if ( array_slice($newInstructions, -1)[0][0] == 'section_close' && array_slice($newInstructions, -2)[0][0] == 'section_close' ) { 455*5321bc23SGerry Weißbach $section_postpend = array_splice($newInstructions, -1); 456*5321bc23SGerry Weißbach } 457*5321bc23SGerry Weißbach if ( array_slice($returnInstructions, -1)[0][0] == 'section_close' && array_slice($returnInstructions, -2)[0][0] == 'section_close' ) { 458*5321bc23SGerry Weißbach $section_postpend = array_merge($section_postpend, array_splice($returnInstructions, -1)); 459*5321bc23SGerry Weißbach } 460*5321bc23SGerry Weißbach 461*5321bc23SGerry Weißbach // What if there are headings left inside the $newInstructions????? 462*5321bc23SGerry Weißbach // Find matching part with headername 463*5321bc23SGerry Weißbach $newStart = $newEnd = 0; 464*5321bc23SGerry Weißbach $section_prepend = array(); 465*5321bc23SGerry Weißbach if ( $this->_findNextHeaderSection($newInstructions, $level, $newStart, $newEnd) ) { 466*5321bc23SGerry Weißbach // If there are header in here, build a prepend and have the rest at the end 467*5321bc23SGerry Weißbach $section_prepend = array_splice($newInstructions, 0, $newStart); 468*5321bc23SGerry Weißbach } else { 469*5321bc23SGerry Weißbach // If not, prepend all of it. 470*5321bc23SGerry Weißbach $section_prepend = $newInstructions; 471*5321bc23SGerry Weißbach $newInstructions = array(); 472*5321bc23SGerry Weißbach } 473*5321bc23SGerry Weißbach 474*5321bc23SGerry Weißbach $returnInstructions = array_merge($returnInstructions, $section_prepend, $preparedInstructions, $newInstructions, $section_postpend); 475*5321bc23SGerry Weißbach 476*5321bc23SGerry Weißbach return $returnInstructions; 477*5321bc23SGerry Weißbach } 478*5321bc23SGerry Weißbach 479*5321bc23SGerry Weißbach function _findNextHeaderSection($section, $level, &$start, &$end, $headerName = null) { 480*5321bc23SGerry Weißbach 481*5321bc23SGerry Weißbach $inCount = count($section); 482*5321bc23SGerry Weißbach $currentSlice = -1; 483*5321bc23SGerry Weißbach 484*5321bc23SGerry Weißbach // Find Level 1 Header that matches. 485*5321bc23SGerry Weißbach for( $i=$start ; $i < $inCount ; $i++ ) { 486*5321bc23SGerry Weißbach 487*5321bc23SGerry Weißbach $instruction = $section[$i]; 488*5321bc23SGerry Weißbach $end = $i; // Or it will be lost and a section close will be missing. 489*5321bc23SGerry Weißbach 490*5321bc23SGerry Weißbach // First Level Header 491*5321bc23SGerry Weißbach if ( $instruction[0] == 'header' && $instruction[1][1] == $level ) { 492*5321bc23SGerry Weißbach 493*5321bc23SGerry Weißbach if ( $currentSlice > 0 ) { 494*5321bc23SGerry Weißbach return true; 495*5321bc23SGerry Weißbach } 496*5321bc23SGerry Weißbach 497*5321bc23SGerry Weißbach if ( $headerName == null || ( $headerName == $instruction[1][0] ) ) { 498*5321bc23SGerry Weißbach // Begin of new slice ... 499*5321bc23SGerry Weißbach $start = $currentSlice = $i; 500*5321bc23SGerry Weißbach } 501*5321bc23SGerry Weißbach } 502*5321bc23SGerry Weißbach } 503*5321bc23SGerry Weißbach 504*5321bc23SGerry Weißbach // Nothing found 505*5321bc23SGerry Weißbach $end = $i; // Or it will be lost and a section close will be missing. 506*5321bc23SGerry Weißbach return $currentSlice > 0; 507*5321bc23SGerry Weißbach } 508*5321bc23SGerry Weißbach 509*5321bc23SGerry Weißbach function _cleanInstructions(&$instructions, $tag) { 510*5321bc23SGerry Weißbach 511*5321bc23SGerry Weißbach $inCount = count($instructions); 512*5321bc23SGerry Weißbach for( $i=0 ; $i < $inCount ; $i++ ) { 513*5321bc23SGerry Weißbach 514*5321bc23SGerry Weißbach // Last instruction 515*5321bc23SGerry Weißbach if ( $i == $inCount-1 ) { 516*5321bc23SGerry Weißbach break; 517*5321bc23SGerry Weißbach } 518*5321bc23SGerry Weißbach 519*5321bc23SGerry Weißbach if ( preg_match($tag, $instructions[$i][0]) && preg_match($tag, $instructions[$i+1][0]) && $instructions[$i][0] != $instructions[$i+1][0] ) { 520*5321bc23SGerry Weißbach 521*5321bc23SGerry Weißbach // found different tags, but both match the expression and follow each other - so they can be elliminated 522*5321bc23SGerry Weißbach array_splice($instructions, $i, 2); 523*5321bc23SGerry Weißbach $inCount -= 2; 524*5321bc23SGerry Weißbach $i--; 525*5321bc23SGerry Weißbach } 526*5321bc23SGerry Weißbach 527*5321bc23SGerry Weißbach } 528*5321bc23SGerry Weißbach } 529*5321bc23SGerry Weißbach 5307d101cc1SGerry Weißbach /** 5317d101cc1SGerry Weißbach * Remove TOC, section edit buttons and tags 5327d101cc1SGerry Weißbach */ 5337d101cc1SGerry Weißbach function _cleanXHTML($xhtml){ 5347d101cc1SGerry Weißbach $replace = array( 5357d101cc1SGerry Weißbach '!<div class="toc">.*?(</div>\n</div>)!s' => '', // remove TOCs 5367d101cc1SGerry Weißbach '#<!-- SECTION \[(\d*-\d*)\] -->#e' => '', // remove section edit buttons 5377d101cc1SGerry Weißbach '!<div id="tags">.*?(</div>)!s' => '' // remove category tags 5387d101cc1SGerry Weißbach ); 5397d101cc1SGerry Weißbach $xhtml = preg_replace(array_keys($replace), array_values($replace), $xhtml); 5407d101cc1SGerry Weißbach return $xhtml; 5417d101cc1SGerry Weißbach } 5427d101cc1SGerry Weißbach 5437d101cc1SGerry Weißbach 5447d101cc1SGerry Weißbach /** 5457d101cc1SGerry Weißbach * Allow the plugin to prevent DokuWiki creating a second instance of itself 5467d101cc1SGerry Weißbach * 5477d101cc1SGerry Weißbach * @return bool true if the plugin can not be instantiated more than once 5487d101cc1SGerry Weißbach */ 5497d101cc1SGerry Weißbach function isSingleton() { 5507d101cc1SGerry Weißbach return true; 5517d101cc1SGerry Weißbach } 5527d101cc1SGerry Weißbach} 5537d101cc1SGerry Weißbach// vim:ts=4:sw=4:et:enc=utf-8: 554