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 18d98cce67SGerry Weißbach private $insideToc = false; 19d98cce67SGerry Weißbach private $savedToc = array(); 20d98cce67SGerry Weißbach private $options = array(); 217d101cc1SGerry Weißbach 22d98cce67SGerry Weißbach private $mergedPages = array(); 23d98cce67SGerry Weißbach private $includedPages = array(); 24*300ce4a2SGerry Weißbach private $merghintIds = array(); 257d101cc1SGerry Weißbach 267d101cc1SGerry Weißbach function getType() { return 'protected'; } 277d101cc1SGerry Weißbach function getPType() { return 'block'; } 287d101cc1SGerry Weißbach function getAllowedTypes() { return array('container'); } 297d101cc1SGerry Weißbach function getSort() { return 100; } 307d101cc1SGerry Weißbach 317d101cc1SGerry Weißbach /** 327d101cc1SGerry Weißbach * Connect pattern to lexer 337d101cc1SGerry Weißbach */ 347d101cc1SGerry Weißbach function connectTo($mode) { 357d101cc1SGerry Weißbach $this->Lexer->addEntryPattern('<toc>(?=.*?</toc>)', $mode, 'plugin_siteexport_toc'); 367d101cc1SGerry Weißbach $this->Lexer->addEntryPattern('<toc .+?>(?=.*?</toc>)', $mode, 'plugin_siteexport_toc'); 377d101cc1SGerry Weißbach $this->Lexer->addSpecialPattern("\[\[.+?\]\]", $mode, 'plugin_siteexport_toc'); 387d101cc1SGerry Weißbach } 397d101cc1SGerry Weißbach 407d101cc1SGerry Weißbach function postConnect() { 417d101cc1SGerry Weißbach $this->Lexer->addExitPattern('</toc.*?>', 'plugin_siteexport_toc'); 427d101cc1SGerry Weißbach } 437d101cc1SGerry Weißbach 441a51ced3SGerry Weißbach function handle($match, $state, $pos, Doku_Handler $handler) { 457d101cc1SGerry Weißbach global $ID, $INFO; 467d101cc1SGerry Weißbach 477d101cc1SGerry Weißbach switch ($state) { 487d101cc1SGerry Weißbach case DOKU_LEXER_ENTER: 497d101cc1SGerry Weißbach 507d101cc1SGerry Weißbach $this->insideToc = true; 517d101cc1SGerry Weißbach 525321bc23SGerry Weißbach $this->options = explode(' ', substr($match, 5, -1)); 53d04831eaSGerry Weißbach 545321bc23SGerry Weißbach return array('start' => true, 'pos' => $pos, 'options' => $this->options); 557d101cc1SGerry Weißbach break; 567d101cc1SGerry Weißbach 577d101cc1SGerry Weißbach case DOKU_LEXER_SPECIAL: 587d101cc1SGerry Weißbach 597d101cc1SGerry Weißbach if ($this->insideToc) { 607d101cc1SGerry Weißbach 617d101cc1SGerry Weißbach $link = preg_replace(array('/^\[\[/', '/\]\]$/u'), '', $match); 627d101cc1SGerry Weißbach // Split title from URL 637d101cc1SGerry Weißbach $link = explode('|', $link, 2); 647d101cc1SGerry Weißbach if (!isset($link[1])) { 657d101cc1SGerry Weißbach $link[1] = NULL; 667d101cc1SGerry Weißbach } else if (preg_match('/^\{\{[^\}]+\}\}$/', $link[1])) { 677d101cc1SGerry Weißbach // If the title is an image, convert it to an array containing the image details 687d101cc1SGerry Weißbach $link[1] = Doku_Handler_Parse_Media($link[1]); 697d101cc1SGerry Weißbach } 707d101cc1SGerry Weißbach $link[0] = trim($link[0]); 717d101cc1SGerry Weißbach 727d101cc1SGerry Weißbach if (!(preg_match('/^[a-zA-Z0-9\.]+>{1}.*$/u', $link[0]) || 737d101cc1SGerry Weißbach preg_match('/^\\\\\\\\[\w.:?\-;,]+?\\\\/u', $link[0]) || 747d101cc1SGerry Weißbach preg_match('#^([a-z0-9\-\.+]+?)://#i', $link[0]) || 757d101cc1SGerry Weißbach preg_match('<' . PREG_PATTERN_VALID_EMAIL . '>', $link[0]) || 767d101cc1SGerry Weißbach preg_match('!^#.+!', $link[0])) 777d101cc1SGerry Weißbach ) { 787d101cc1SGerry Weißbach 797d101cc1SGerry Weißbach // Get current depth from call stack 807d101cc1SGerry Weißbach $depth = 1; 817d101cc1SGerry Weißbach if ($handler->CallWriter instanceof Doku_Handler_List) { 827d101cc1SGerry Weißbach 837d101cc1SGerry Weißbach $calls = array_reverse($handler->CallWriter->calls); 847d101cc1SGerry Weißbach $call = $calls[0]; 857d101cc1SGerry Weißbach foreach ($calls as $item) { 867d101cc1SGerry Weißbach if (in_array($item[0], array('list_item', 'list_open'))) { $call = $item; break; } 877d101cc1SGerry Weißbach } 887d101cc1SGerry Weißbach 89a99d6deeSGerry Weißbach $depth = $handler->CallWriter->interpretSyntax($call[1][0], $listType)-1; // Minus one because of plus one inside the interpret function 907d101cc1SGerry Weißbach } 917d101cc1SGerry Weißbach 927d101cc1SGerry Weißbach if (empty($link[0])) { break; } // No empty elements. This would lead to problems 937d101cc1SGerry Weißbach return array($link[0], $link[1], $depth); 947d101cc1SGerry Weißbach break; 957d101cc1SGerry Weißbach } else { 967d101cc1SGerry Weißbach // use parser! - but with another p 977d101cc1SGerry Weißbach $handler->internallink($match, $state, $pos); 987d101cc1SGerry Weißbach } 997d101cc1SGerry Weißbach } else { 1007d101cc1SGerry Weißbach // use parser! 1017d101cc1SGerry Weißbach $handler->internallink($match, $state, $pos); 1027d101cc1SGerry Weißbach } 1037d101cc1SGerry Weißbach 1047d101cc1SGerry Weißbach return false; 1057d101cc1SGerry Weißbach case DOKU_LEXER_UNMATCHED: 1067d101cc1SGerry Weißbach 1077d101cc1SGerry Weißbach $handler->_addCall('cdata', array($match), $pos); 1085321bc23SGerry Weißbach 1097d101cc1SGerry Weißbach return false; 1107d101cc1SGerry Weißbach break; 1117d101cc1SGerry Weißbach case DOKU_LEXER_EXIT: 1127d101cc1SGerry Weißbach 1137d101cc1SGerry Weißbach $this->insideToc = false; 1147d101cc1SGerry Weißbach return 'save__meta'; 1157d101cc1SGerry Weißbach break; 1167d101cc1SGerry Weißbach } 1177d101cc1SGerry Weißbach return false; 1187d101cc1SGerry Weißbach } 1197d101cc1SGerry Weißbach 120e983d60aSGerry Weißbach function render($mode, Doku_Renderer $renderer, $data) { 1217d101cc1SGerry Weißbach global $ID, $lang, $INFO; 1227d101cc1SGerry Weißbach 1237d101cc1SGerry Weißbach list($SID, $NAME, $DEPTH) = $data; 1247d101cc1SGerry Weißbach 1257d101cc1SGerry Weißbach resolve_pageid(getNS($ID), $SID, $exists); 1264d9989ecSGerry Weißbach// $SID = cleanID($SID); // hier kein cleanID, da sonst moeglicherweise der anker verloren geht 1277d101cc1SGerry Weißbach 1287d101cc1SGerry Weißbach // Render XHTML and ODT 1297d101cc1SGerry Weißbach if ($mode == 'xhtml' || $mode == 'odt') { 1307d101cc1SGerry Weißbach 1317d101cc1SGerry Weißbach // TOC Title 132d04831eaSGerry Weißbach if (is_array($data) && $data['start'] == true) { 1337d101cc1SGerry Weißbach 1347d101cc1SGerry Weißbach if (is_Array($data['options'])) { 1357d101cc1SGerry Weißbach foreach ($data['options'] as $opt) { 1367d101cc1SGerry Weißbach switch ($opt) { 1377d101cc1SGerry Weißbach case 'description' : $renderer->meta['sitetoc']['showDescription'] = true; break; 1387d101cc1SGerry Weißbach case 'notoc' : $renderer->meta['sitetoc']['noTOC'] = true; break; 1397d101cc1SGerry Weißbach case 'merge' : $renderer->meta['sitetoc']['mergeDoc'] = true; break; 1407d101cc1SGerry Weißbach case 'nohead' : $renderer->meta['sitetoc']['noTocHeader'] = true; break; 1415321bc23SGerry Weißbach case 'mergeheader' : $renderer->meta['sitetoc']['mergeHeader'] = true; break; 14222a479aeSGerry Weißbach case 'pagebreak' : $renderer->meta['sitetoc']['pagebreak'] = true; break; 1437d101cc1SGerry Weißbach } 1447d101cc1SGerry Weißbach } 1457d101cc1SGerry Weißbach } 1467d101cc1SGerry Weißbach 1477d101cc1SGerry Weißbach $renderer->section_open("1 sitetoc"); 1487d101cc1SGerry Weißbach if ($renderer->meta['sitetoc']['noTocHeader'] === false) { 1497d101cc1SGerry Weißbach $renderer->header($lang['toc'], 1, $data['pos']); 1507d101cc1SGerry Weißbach } 1517d101cc1SGerry Weißbach 1527d101cc1SGerry Weißbach return true; 153d04831eaSGerry Weißbach } else 1547d101cc1SGerry Weißbach 1557d101cc1SGerry Weißbach // All Output has been done 1567d101cc1SGerry Weißbach if (!is_array($data) && $data == 'save__meta') { 1577d101cc1SGerry Weißbach 1587d101cc1SGerry Weißbach // Close TOC 1597d101cc1SGerry Weißbach $renderer->section_close(); 1607d101cc1SGerry Weißbach 1617d101cc1SGerry Weißbach if ($renderer->meta['sitetoc']['noTOC'] === true) { 1627d101cc1SGerry Weißbach $renderer->doc = preg_replace("/<div.*?sitetoc.*?$/si", "", $renderer->doc); 1637d101cc1SGerry Weißbach } 1647d101cc1SGerry Weißbach 1657d101cc1SGerry Weißbach // If this is not set, we may have it as Metadata 1667d101cc1SGerry Weißbach if (!$this->mergedPages && $renderer->meta['sitetoc']['mergeDoc']) { 1677d101cc1SGerry Weißbach $toc = $renderer->meta['sitetoc']['siteexportTOC']; 168a99d6deeSGerry Weißbach 1697d101cc1SGerry Weißbach if (is_array($toc)) { 1707d101cc1SGerry Weißbach foreach ($toc as $tocItem) { 171a99d6deeSGerry Weißbach $this->mergedPages[] = array($tocItem['id'], $tocItem['depth']); 1727d101cc1SGerry Weißbach } 1737d101cc1SGerry Weißbach } 174a99d6deeSGerry Weißbach 1757d101cc1SGerry Weißbach } 1767d101cc1SGerry Weißbach 1777d101cc1SGerry Weißbach // If there is some data to be merged 1787d101cc1SGerry Weißbach if (count($this->mergedPages) > 0) { 1797d101cc1SGerry Weißbach 1805321bc23SGerry Weißbach $renderer->doc = ''; // Start fresh! 1815321bc23SGerry Weißbach 1827d101cc1SGerry Weißbach $renderer->section_open("1 mergedsite"); 1837d101cc1SGerry Weißbach 1847d101cc1SGerry Weißbach // Prepare lookup Array 1857d101cc1SGerry Weißbach foreach ($this->mergedPages as $tocItem) { 186a99d6deeSGerry Weißbach $this->includedPages[] = array_shift(explode('#', $tocItem[0])); 1877d101cc1SGerry Weißbach } 1887d101cc1SGerry Weißbach 1895321bc23SGerry Weißbach // Load the instructions 1905321bc23SGerry Weißbach $instr = array(); 191*300ce4a2SGerry Weißbach $mergeHint = null; 192a99d6deeSGerry Weißbach foreach ($this->mergedPages as $tocElement) { 193a99d6deeSGerry Weißbach 194a99d6deeSGerry Weißbach list($tocItem, $depth) = $tocElement; 1955321bc23SGerry Weißbach $file = wikiFN($tocItem); 1966792d0cfSGerry Weißbach 1976792d0cfSGerry Weißbach if (@file_exists($file)) { 1986792d0cfSGerry Weißbach $instructions = p_cached_instructions($file, false, $tocItem); 1996792d0cfSGerry Weißbach } else { 2006792d0cfSGerry Weißbach $instructions = p_get_instructions(io_readWikiPage($file, $tocItem)); 2016792d0cfSGerry Weißbach } 2025321bc23SGerry Weißbach 203a99d6deeSGerry Weißbach // Convert Link and header instructions 204a99d6deeSGerry Weißbach $instructions = $this->_convertInstructions($instructions, $addID, $renderer, $depth); 2055321bc23SGerry Weißbach 2065321bc23SGerry Weißbach if ($renderer->meta['sitetoc']['mergeHeader'] && !empty($instr)) { 207*300ce4a2SGerry Weißbach // get a hint for merged pages 208*300ce4a2SGerry Weißbach if ( !empty( $instr ) ) { 209*300ce4a2SGerry Weißbach // only if the first section is already there 210*300ce4a2SGerry Weißbach $mergeHint = p_get_metadata( $tocItem, 'mergehint', METADATA_RENDER_USING_SIMPLE_CACHE ); 211*300ce4a2SGerry Weißbach if ( empty( $mergeHint) ) { $mergeHint = p_get_metadata( $tocItem, 'thema', METADATA_RENDER_USING_SIMPLE_CACHE ); } 212*300ce4a2SGerry Weißbach if ( empty( $mergeHint) ) { $mergeHint = tpl_pagetitle( $tocItem, true ); } 213*300ce4a2SGerry Weißbach } 214*300ce4a2SGerry Weißbach 2155321bc23SGerry Weißbach // Merge 216*300ce4a2SGerry Weißbach $instr = $this->_mergeWithHeaders($instr, $instructions, 1, $mergeHint); 21722a479aeSGerry Weißbach } else 21822a479aeSGerry Weißbach if ($renderer->meta['sitetoc']['pagebreak']) { 219*300ce4a2SGerry Weißbach $sitepagebreak = array( array( 220*300ce4a2SGerry Weißbach 'plugin', 221*300ce4a2SGerry Weißbach array( 222*300ce4a2SGerry Weißbach 'siteexport_toctools', 223*300ce4a2SGerry Weißbach array( 224*300ce4a2SGerry Weißbach 'pagebreak', 225*300ce4a2SGerry Weißbach null, 226*300ce4a2SGerry Weißbach null 227*300ce4a2SGerry Weißbach ) 228*300ce4a2SGerry Weißbach ) 229*300ce4a2SGerry Weißbach )); 230*300ce4a2SGerry Weißbach $instr = array_merge($instr, $instructions, $sitepagebreak); 2315321bc23SGerry Weißbach } else { 2325321bc23SGerry Weißbach // Concat 2335321bc23SGerry Weißbach $instr = array_merge($instr, $instructions); 2347d101cc1SGerry Weißbach } 2355321bc23SGerry Weißbach } 2365321bc23SGerry Weißbach 237d04831eaSGerry Weißbach if (!empty($instr)) { 2385321bc23SGerry Weißbach $this->_cleanInstructions($instr, '/section_(close|open)/'); 2395321bc23SGerry Weißbach $this->_cleanInstructions($instr, '/listu_(close|open)/'); 2405321bc23SGerry Weißbach $this->_cleanInstructions($instr, '/listo_(close|open)/'); 2415321bc23SGerry Weißbach 24222a479aeSGerry Weißbach //if its the document start, cut off the first element(document information) 243*300ce4a2SGerry Weißbach if ($instr[count($instr)-1][1][0] == 'siteexport_toctools') { 24422a479aeSGerry Weißbach $instr = array_slice($instr, 0, -1); 24522a479aeSGerry Weißbach } 24622a479aeSGerry Weißbach 247*300ce4a2SGerry Weißbach 248*300ce4a2SGerry Weißbach // print "<pre>"; print_r($instr); print "</pre>"; 2495321bc23SGerry Weißbach $this->_render_output($renderer, $mode, $instr); 250d04831eaSGerry Weißbach } 251d04831eaSGerry Weißbach 2527d101cc1SGerry Weißbach $renderer->section_close(); 2537d101cc1SGerry Weißbach } 2547d101cc1SGerry Weißbach return true; 2557d101cc1SGerry Weißbach } 2567d101cc1SGerry Weißbach 2577d101cc1SGerry Weißbach // Save the current ID 2587d101cc1SGerry Weißbach $LNID = $SID; 2597d101cc1SGerry Weißbach 2607d101cc1SGerry Weißbach // Add ID to flags['mergeDoc'] 2617d101cc1SGerry Weißbach if ($renderer->meta['sitetoc']['mergeDoc'] === true) { // || (count($renderer->meta['sitetoc']['siteexportTOC']) > 0 && $renderer->meta['sitetoc']['siteexportMergeDoc'] === true) ) { 262a99d6deeSGerry Weißbach $this->mergedPages[] = array($SID, $DEPTH); 2637d101cc1SGerry Weißbach $default = $renderer->_simpleTitle($SID); $isImage = false; 2647d101cc1SGerry Weißbach resolve_pageid(getNS($ID), $SID, $exists); 2657d101cc1SGerry Weißbach 2667d101cc1SGerry Weißbach $NAME = empty($NAME) ? p_get_first_heading($SID, true) : $NAME; 2677d101cc1SGerry Weißbach $LNID = "$ID#" . sectionID($SID, $check); 268a99d6deeSGerry Weißbach 2695321bc23SGerry Weißbach } else { 2705321bc23SGerry Weißbach // // print normal internal link (XHTML odt) 2717d101cc1SGerry Weißbach $renderer->internallink($LNID, $NAME, null); 2727d101cc1SGerry Weißbach 2737d101cc1SGerry Weißbach // Display Description underneath 2747d101cc1SGerry Weißbach if ($renderer->meta['sitetoc']['showDescription'] === true) { 2757d101cc1SGerry Weißbach // $renderer->p_open(); 2767d101cc1SGerry Weißbach $renderer->cdata(p_get_metadata($SID, 'description abstract', true)); 2777d101cc1SGerry Weißbach // $renderer->p_close(); 2787d101cc1SGerry Weißbach } 2795321bc23SGerry Weißbach } 2807d101cc1SGerry Weißbach 2817d101cc1SGerry Weißbach // Render Metadata 2827d101cc1SGerry Weißbach } else if ($mode == 'metadata') { 2837d101cc1SGerry Weißbach if (!is_array($data) && $data == 'save__meta') { 2847d101cc1SGerry Weißbach $renderer->meta['sitetoc']['siteexportTOC'] = $this->savedToc; 2857d101cc1SGerry Weißbach 2867d101cc1SGerry Weißbach foreach ($this->savedToc as $page) { 2877d101cc1SGerry Weißbach $renderer->meta['relation']['references'][$page['id']] = $page['exists']; 2887d101cc1SGerry Weißbach } 2897d101cc1SGerry Weißbach 2907d101cc1SGerry Weißbach $this->savedToc = array(); 2917d101cc1SGerry Weißbach } else if (!isset($data['start']) && !isset($data['pos'])) { 2927d101cc1SGerry Weißbach $this->savedToc[] = $this->__addTocItem($SID, $NAME, $DEPTH, $renderer); 2937d101cc1SGerry Weißbach } 2947d101cc1SGerry Weißbach } else { 2957d101cc1SGerry Weißbach return false; 2967d101cc1SGerry Weißbach } 2977d101cc1SGerry Weißbach 2987d101cc1SGerry Weißbach return true; 2997d101cc1SGerry Weißbach } 3007d101cc1SGerry Weißbach 3017d101cc1SGerry Weißbach /* 3027d101cc1SGerry Weißbach * pull apart the ID and create an Entry for the TOC 3037d101cc1SGerry Weißbach */ 3047d101cc1SGerry Weißbach function __addTocItem($id, $name, $depth, $renderer) { 3057d101cc1SGerry Weißbach global $conf; 3067d101cc1SGerry Weißbach global $ID; 3077d101cc1SGerry Weißbach 3087d101cc1SGerry Weißbach // Render Title 3097d101cc1SGerry Weißbach $default = $renderer->_simpleTitle($id); 3107d101cc1SGerry Weißbach $exists = false; $isImage = false; $linktype = null; 3117d101cc1SGerry Weißbach resolve_pageid(getNS($ID), $id, $exists); 3127d101cc1SGerry Weißbach $name = $renderer->_getLinkTitle($name, $default, $isImage, $id, $linktype); 3137d101cc1SGerry Weißbach 3147d101cc1SGerry Weißbach //keep hash anchor 3157d101cc1SGerry Weißbach list($id, $hash) = explode('#', $id, 2); 3167d101cc1SGerry Weißbach if (!empty($hash)) $hash = $renderer->_headerToLink($hash); 3177d101cc1SGerry Weißbach 3187d101cc1SGerry Weißbach // Build Sitetoc Item 3197d101cc1SGerry Weißbach $item = array(); 3207d101cc1SGerry Weißbach $item['id'] = $id; 3217d101cc1SGerry Weißbach $item['name'] = $name; 3227d101cc1SGerry Weißbach $item['anchor'] = $hash; 3237d101cc1SGerry Weißbach $item['depth'] = $depth; 3247d101cc1SGerry Weißbach $item['exists'] = $exists; 3257d101cc1SGerry Weißbach if (!$conf['skipacl'] && auth_quickaclcheck($item['id']) < AUTH_READ) { 3267d101cc1SGerry Weißbach return false; 3277d101cc1SGerry Weißbach } 3287d101cc1SGerry Weißbach 3297d101cc1SGerry Weißbach return $item; 3307d101cc1SGerry Weißbach } 3317d101cc1SGerry Weißbach 3327d101cc1SGerry Weißbach /* 3337d101cc1SGerry Weißbach * Render the output of one page 3347d101cc1SGerry Weißbach */ 3355321bc23SGerry Weißbach function _render_output($renderer, $mode, $instr) { 3367d101cc1SGerry Weißbach global $ID; 3377d101cc1SGerry Weißbach 3387d101cc1SGerry Weißbach // Section IDs 3395321bc23SGerry Weißbach // $addID = sectionID($addID, $check); //not possible to use a:b:c for id 3407d101cc1SGerry Weißbach 3417d101cc1SGerry Weißbach if ($mode == 'xhtml') { 3425321bc23SGerry Weißbach 3437d101cc1SGerry Weißbach //--------RENDER 3447d101cc1SGerry Weißbach //renderer information(TOC build / Cache used) 3457d101cc1SGerry Weißbach $info = array(); 3467d101cc1SGerry Weißbach $content = p_render($mode, $instr, $info); 3477d101cc1SGerry Weißbach 3487d101cc1SGerry Weißbach //Remove TOC`s, section edit buttons and tags 3497d101cc1SGerry Weißbach $content = $this->_cleanXHTML($content); 3507d101cc1SGerry Weißbach 3517d101cc1SGerry Weißbach // embed the included page 3526792d0cfSGerry Weißbach // $renderer->doc .= '<div class="include">'; 3537d101cc1SGerry Weißbach //add an anchor to find start of a inserted page 3545321bc23SGerry Weißbach // $renderer->doc .= "<a name='$addID' id='$addID'>"; 3557d101cc1SGerry Weißbach $renderer->doc .= $content; 3566792d0cfSGerry Weißbach // $renderer->doc .= '</div>'; 3577d101cc1SGerry Weißbach } else if ($mode == 'odt') { 3587d101cc1SGerry Weißbach 3597d101cc1SGerry Weißbach // Loop through the instructions 3607d101cc1SGerry Weißbach foreach ($instr as $instruction) { 3617d101cc1SGerry Weißbach // Execute the callback against the Renderer 3627d101cc1SGerry Weißbach call_user_func_array(array($renderer, $instruction[0]), $instruction[1]); 3637d101cc1SGerry Weißbach } 3647d101cc1SGerry Weißbach } 3657d101cc1SGerry Weißbach } 3667d101cc1SGerry Weißbach 3677d101cc1SGerry Weißbach /* 3687d101cc1SGerry Weißbach * Corrects relative internal links and media and 3697d101cc1SGerry Weißbach * converts headers of included pages to subheaders of the current page 3707d101cc1SGerry Weißbach */ 371a99d6deeSGerry Weißbach function _convertInstructions($instr, $id, &$renderer, $depth = 1) { 3727d101cc1SGerry Weißbach global $ID; 3737d101cc1SGerry Weißbach global $conf; 3747d101cc1SGerry Weißbach 3757d101cc1SGerry Weißbach $n = count($instr); 3767d101cc1SGerry Weißbach 3777d101cc1SGerry Weißbach for ($i = 0; $i < $n; $i++) { 3787d101cc1SGerry Weißbach //internal links(links inside this wiki) an relative links 3797d101cc1SGerry Weißbach if ((substr($instr[$i][0], 0, 12) == 'internallink')) { 3807d101cc1SGerry Weißbach $this->_convert_link($renderer, $instr[$i], $id); 3817d101cc1SGerry Weißbach } 3827d101cc1SGerry Weißbach else if ((substr($instr[$i][0], 0, 13) == 'internalmedia')) { 3837d101cc1SGerry Weißbach $this->_convert_media($renderer, $instr[$i], $id); 3847d101cc1SGerry Weißbach } 385a99d6deeSGerry Weißbach else if ((substr($instr[$i][0], 0, 6) == 'header')) { 386a99d6deeSGerry Weißbach $this->_convert_header($renderer, $instr[$i], $depth-1); // -1 because the depth starts at 1 387a99d6deeSGerry Weißbach } 388a99d6deeSGerry Weißbach else if ((substr($instr[$i][0], 0, 12) == 'section_open')) { 389a99d6deeSGerry Weißbach $this->_convert_section($renderer, $instr[$i], $depth-1); // -1 because the depth starts at 1 390a99d6deeSGerry Weißbach } 3917d101cc1SGerry Weißbach } 3927d101cc1SGerry Weißbach 3937d101cc1SGerry Weißbach //if its the document start, cut off the first element(document information) 3947d101cc1SGerry Weißbach if ($instr[0][0] == 'document_start') 3957d101cc1SGerry Weißbach return array_slice($instr, 1, -1); 3967d101cc1SGerry Weißbach else 3977d101cc1SGerry Weißbach return $instr; 3987d101cc1SGerry Weißbach } 3997d101cc1SGerry Weißbach 4007d101cc1SGerry Weißbach /* 4017d101cc1SGerry Weißbach * Convert link of given instruction 4027d101cc1SGerry Weißbach */ 4037d101cc1SGerry Weißbach function _convert_link(&$renderer, &$instr, $id) { 4047d101cc1SGerry Weißbach global $ID; 4057d101cc1SGerry Weißbach 4067d101cc1SGerry Weißbach $exists = false; 4077d101cc1SGerry Weißbach 4087d101cc1SGerry Weißbach resolve_pageid(getNS($id), $instr[1][0], $exists); 4097d101cc1SGerry Weißbach list($pageID, $pageReference) = explode("#", $instr[1][0], 2); 4107d101cc1SGerry Weißbach 4117d101cc1SGerry Weißbach if (in_array($pageID, $this->includedPages)) { 4127d101cc1SGerry Weißbach // Crate new internal Links 4137d101cc1SGerry Weißbach $check = null; 4147d101cc1SGerry Weißbach 4157d101cc1SGerry Weißbach // Either get existing reference or create from first heading. If still not there take the alternate ID 4167d101cc1SGerry Weißbach $pageNameLink = empty($pageReference) ? sectionID($pageID, $check) : $pageReference; 4177d101cc1SGerry Weißbach 4187d101cc1SGerry Weißbach $instr[1][0] = $ID . "#" . $pageNameLink; 4197d101cc1SGerry Weißbach 4207d101cc1SGerry Weißbach } else { 4217d101cc1SGerry Weißbach // Convert external Links to plain Text 4227d101cc1SGerry Weißbach 4237d101cc1SGerry Weißbach $instr = array( 4247d101cc1SGerry Weißbach "cdata", 4257d101cc1SGerry Weißbach array($instr[1][1]), 4267d101cc1SGerry Weißbach $instr[2] 4277d101cc1SGerry Weißbach ); 4287d101cc1SGerry Weißbach } 4297d101cc1SGerry Weißbach } 4307d101cc1SGerry Weißbach 4317d101cc1SGerry Weißbach /* 4327d101cc1SGerry Weißbach * Convert internalmedia of given instruction 4337d101cc1SGerry Weißbach */ 4347d101cc1SGerry Weißbach function _convert_media(&$renderer, &$instr, $id) { 4357d101cc1SGerry Weißbach global $ID; 4367d101cc1SGerry Weißbach 4377d101cc1SGerry Weißbach // Resolvemedia returns the absolute path to media by reference 4387d101cc1SGerry Weißbach $exists = false; 4397d101cc1SGerry Weißbach resolve_mediaid(getNS($id), $instr[1][0], $exists); 4407d101cc1SGerry Weißbach } 4417d101cc1SGerry Weißbach 4420571ece2SScrutinizer Auto-Fixer /** 4430571ece2SScrutinizer Auto-Fixer * @param integer $depth 4440571ece2SScrutinizer Auto-Fixer */ 445a99d6deeSGerry Weißbach function _convert_header(&$renderer, &$instr, $depth) { 446a99d6deeSGerry Weißbach // More Depth! 447a99d6deeSGerry Weißbach $instr[1][1] += $depth; 448a99d6deeSGerry Weißbach } 449a99d6deeSGerry Weißbach 4500571ece2SScrutinizer Auto-Fixer /** 4510571ece2SScrutinizer Auto-Fixer * @param integer $depth 4520571ece2SScrutinizer Auto-Fixer */ 453a99d6deeSGerry Weißbach function _convert_section(&$renderer, &$instr, $depth) { 454a99d6deeSGerry Weißbach // More Depth! 455a99d6deeSGerry Weißbach $instr[1][0] += $depth; 456a99d6deeSGerry Weißbach } 457a99d6deeSGerry Weißbach 458*300ce4a2SGerry Weißbach function _mergeWithHeaders($existing, $newInstructions, $level = 1, $mergeHint = array() ) { 4595321bc23SGerry Weißbach 4605321bc23SGerry Weißbach $returnInstructions = array(); 4615321bc23SGerry Weißbach $preparedInstructions = array(); 4625321bc23SGerry Weißbach $existingStart = $existingEnd = 0; 4635321bc23SGerry Weißbach $firstRun = true; 4645321bc23SGerry Weißbach 4655321bc23SGerry Weißbach while ($this->_findNextHeaderSection($existing, $level, $existingStart, $existingEnd)) { 4665321bc23SGerry Weißbach 4675321bc23SGerry Weißbach if ($firstRun) { 4685321bc23SGerry Weißbach $returnInstructions = array_merge($returnInstructions, array_slice($existing, 0, $existingStart)); 4695321bc23SGerry Weißbach $firstRun = false; 4705321bc23SGerry Weißbach } 4715321bc23SGerry Weißbach 4725321bc23SGerry Weißbach $currentSlice = array_slice($existing, $existingStart, $existingEnd-$existingStart); 4735321bc23SGerry Weißbach 4745321bc23SGerry Weißbach // Find matching part with headername 4755321bc23SGerry Weißbach $newStart = $newEnd = 0; 4765321bc23SGerry Weißbach if ($this->_findNextHeaderSection($newInstructions, $level, $newStart, $newEnd, $currentSlice[0][1][0])) { 4775321bc23SGerry Weißbach 4785321bc23SGerry Weißbach $newSlice = array_slice($newInstructions, $newStart, $newEnd-$newStart); 4795321bc23SGerry Weißbach if ($newSlice[0][0] == 'header') 4805321bc23SGerry Weißbach array_shift($newSlice); // Remove Heading 4815321bc23SGerry Weißbach 4825321bc23SGerry Weißbach // merge found parts on next level. 483*300ce4a2SGerry Weißbach $returnedInstructions = $this->_mergeWithHeaders($currentSlice, $newSlice, $level+1, $mergeHint); 4845321bc23SGerry Weißbach 4855321bc23SGerry Weißbach // Put them at the end! 4865321bc23SGerry Weißbach $preparedInstructions = array_merge($preparedInstructions, $returnedInstructions); 4875321bc23SGerry Weißbach 4885321bc23SGerry Weißbach // Remove from input 4895321bc23SGerry Weißbach array_splice($newInstructions, $newStart, $newEnd-$newStart); 4905321bc23SGerry Weißbach } else { 491*300ce4a2SGerry Weißbach // Nothing else found 4925321bc23SGerry Weißbach $preparedInstructions = array_merge($preparedInstructions, $currentSlice); 4935321bc23SGerry Weißbach } 4945321bc23SGerry Weißbach 4955321bc23SGerry Weißbach $existingStart = $existingEnd; 4965321bc23SGerry Weißbach } 4975321bc23SGerry Weißbach 4985321bc23SGerry Weißbach // Append the rest 4995321bc23SGerry Weißbach $returnInstructions = array_merge($returnInstructions, array_slice($existing, $existingStart)); 5005321bc23SGerry Weißbach 5015321bc23SGerry Weißbach // Check for section close inconsistencies and put one at the very end ... 5025321bc23SGerry Weißbach $section_postpend = array(); 5039490aa3bSAlain if ( 5049490aa3bSAlain ( 5059490aa3bSAlain ($tmp = array_slice($newInstructions, -1)) 5069490aa3bSAlain && ($tmp[0][0] == 'section_close') 5079490aa3bSAlain ) 5089490aa3bSAlain && 5099490aa3bSAlain ( 5109490aa3bSAlain ($tmp = array_slice($newInstructions, -2)) 5119490aa3bSAlain && ($tmp[0][0] == 'section_close') 5129490aa3bSAlain ) 5139490aa3bSAlain ) { 5145321bc23SGerry Weißbach $section_postpend = array_splice($newInstructions, -1); 5155321bc23SGerry Weißbach } 5169490aa3bSAlain if ( 5179490aa3bSAlain ( 5189490aa3bSAlain ($tmp = array_slice($returnInstructions, -1)) 5199490aa3bSAlain && ($tmp[0][0] == 'section_close') 5209490aa3bSAlain ) 5219490aa3bSAlain && 5229490aa3bSAlain ( 5239490aa3bSAlain ($tmp = array_slice($returnInstructions, -2)) 5249490aa3bSAlain && ($tmp[0][0] == 'section_close') 5259490aa3bSAlain ) 5269490aa3bSAlain ) { 5275321bc23SGerry Weißbach $section_postpend = array_merge($section_postpend, array_splice($returnInstructions, -1)); 5285321bc23SGerry Weißbach } 5295321bc23SGerry Weißbach 5305321bc23SGerry Weißbach // What if there are headings left inside the $newInstructions????? 5315321bc23SGerry Weißbach // Find matching part with headername 5325321bc23SGerry Weißbach $newStart = $newEnd = 0; 5335321bc23SGerry Weißbach $section_prepend = array(); 5345321bc23SGerry Weißbach if ($this->_findNextHeaderSection($newInstructions, $level, $newStart, $newEnd)) { 5355321bc23SGerry Weißbach // If there are header in here, build a prepend and have the rest at the end 5365321bc23SGerry Weißbach $section_prepend = array_splice($newInstructions, 0, $newStart); 5375321bc23SGerry Weißbach } else { 5385321bc23SGerry Weißbach // If not, prepend all of it. 5395321bc23SGerry Weißbach $section_prepend = $newInstructions; 5405321bc23SGerry Weißbach $newInstructions = array(); 5415321bc23SGerry Weißbach } 5425321bc23SGerry Weißbach 543*300ce4a2SGerry Weißbach $this->_insertMergeHint( $section_prepend, $mergeHint ); 544*300ce4a2SGerry Weißbach 5455321bc23SGerry Weißbach $returnInstructions = array_merge($returnInstructions, $section_prepend, $preparedInstructions, $newInstructions, $section_postpend); 5465321bc23SGerry Weißbach 5475321bc23SGerry Weißbach return $returnInstructions; 5485321bc23SGerry Weißbach } 5495321bc23SGerry Weißbach 5500571ece2SScrutinizer Auto-Fixer /** 5510571ece2SScrutinizer Auto-Fixer * @param integer $level 5520571ece2SScrutinizer Auto-Fixer */ 5535321bc23SGerry Weißbach function _findNextHeaderSection($section, $level, &$start, &$end, $headerName = null) { 5545321bc23SGerry Weißbach 5555321bc23SGerry Weißbach $inCount = count($section); 5565321bc23SGerry Weißbach $currentSlice = -1; 5575321bc23SGerry Weißbach 5585321bc23SGerry Weißbach // Find Level 1 Header that matches. 5595321bc23SGerry Weißbach for ($i = $start; $i < $inCount; $i++) { 5605321bc23SGerry Weißbach 5615321bc23SGerry Weißbach $instruction = $section[$i]; 5625321bc23SGerry Weißbach $end = $i; // Or it will be lost and a section close will be missing. 5635321bc23SGerry Weißbach 5645321bc23SGerry Weißbach // First Level Header 5655321bc23SGerry Weißbach if ($instruction[0] == 'header' && $instruction[1][1] == $level) { 5665321bc23SGerry Weißbach 5675321bc23SGerry Weißbach if ($currentSlice > 0) { 5685321bc23SGerry Weißbach return true; 5695321bc23SGerry Weißbach } 5705321bc23SGerry Weißbach 5715321bc23SGerry Weißbach if ($headerName == null || ($headerName == $instruction[1][0])) { 5725321bc23SGerry Weißbach // Begin of new slice ... 5735321bc23SGerry Weißbach $start = $currentSlice = $i; 5745321bc23SGerry Weißbach } 5755321bc23SGerry Weißbach } 5765321bc23SGerry Weißbach } 5775321bc23SGerry Weißbach 5785321bc23SGerry Weißbach // Nothing found 5795321bc23SGerry Weißbach $end = $i; // Or it will be lost and a section close will be missing. 5805321bc23SGerry Weißbach return $currentSlice > 0; 5815321bc23SGerry Weißbach } 5825321bc23SGerry Weißbach 5830571ece2SScrutinizer Auto-Fixer /** 5840571ece2SScrutinizer Auto-Fixer * @param string $tag 5850571ece2SScrutinizer Auto-Fixer */ 5865321bc23SGerry Weißbach function _cleanInstructions(&$instructions, $tag) { 5875321bc23SGerry Weißbach 5885321bc23SGerry Weißbach $inCount = count($instructions); 5895321bc23SGerry Weißbach for ($i = 0; $i < $inCount; $i++) { 5905321bc23SGerry Weißbach 5915321bc23SGerry Weißbach // Last instruction 5925321bc23SGerry Weißbach if ($i == $inCount-1) { 5935321bc23SGerry Weißbach break; 5945321bc23SGerry Weißbach } 5955321bc23SGerry Weißbach 5965321bc23SGerry Weißbach if (preg_match($tag, $instructions[$i][0]) && preg_match($tag, $instructions[$i+1][0]) && $instructions[$i][0] != $instructions[$i+1][0]) { 5975321bc23SGerry Weißbach 5985321bc23SGerry Weißbach // found different tags, but both match the expression and follow each other - so they can be elliminated 5995321bc23SGerry Weißbach array_splice($instructions, $i, 2); 6005321bc23SGerry Weißbach $inCount -= 2; 6015321bc23SGerry Weißbach $i--; 6025321bc23SGerry Weißbach } 6035321bc23SGerry Weißbach 6045321bc23SGerry Weißbach } 6055321bc23SGerry Weißbach } 6065321bc23SGerry Weißbach 607*300ce4a2SGerry Weißbach function _insertMergeHint( &$instructions, $mergeHint ) { 608*300ce4a2SGerry Weißbach 609*300ce4a2SGerry Weißbach // Surround new slice with a mergehint 610*300ce4a2SGerry Weißbach if ( empty( $mergeHint ) ) { return; } 611*300ce4a2SGerry Weißbach 612*300ce4a2SGerry Weißbach // only section content should be surrounded. 613*300ce4a2SGerry Weißbach if ( $instructions[0][0] != 'section_open' ) { return; } 614*300ce4a2SGerry Weißbach 615*300ce4a2SGerry Weißbach // save for later use 616*300ce4a2SGerry Weißbach $mergeHints = array(); 617*300ce4a2SGerry Weißbach $mergeHintId = sectionid( $mergeHint, $mergeHints ); 618*300ce4a2SGerry Weißbach $this->merghintIds[$mergeHintId] = $mergeHint; 619*300ce4a2SGerry Weißbach 620*300ce4a2SGerry Weißbach $mergeHintPrepend = array( array( 621*300ce4a2SGerry Weißbach 'plugin', 622*300ce4a2SGerry Weißbach array( 623*300ce4a2SGerry Weißbach 'siteexport_toctools', 624*300ce4a2SGerry Weißbach array( 625*300ce4a2SGerry Weißbach 'mergehint', 626*300ce4a2SGerry Weißbach 'start', 627*300ce4a2SGerry Weißbach $mergeHint, 628*300ce4a2SGerry Weißbach $mergeHintId 629*300ce4a2SGerry Weißbach ) 630*300ce4a2SGerry Weißbach ) 631*300ce4a2SGerry Weißbach )); 632*300ce4a2SGerry Weißbach 633*300ce4a2SGerry Weißbach $mergeHintPostpend = array( array( 634*300ce4a2SGerry Weißbach 'plugin', 635*300ce4a2SGerry Weißbach array( 636*300ce4a2SGerry Weißbach 'siteexport_toctools', 637*300ce4a2SGerry Weißbach array( 638*300ce4a2SGerry Weißbach 'mergehint', 639*300ce4a2SGerry Weißbach 'end', 640*300ce4a2SGerry Weißbach $mergeHint 641*300ce4a2SGerry Weißbach ) 642*300ce4a2SGerry Weißbach ) 643*300ce4a2SGerry Weißbach )); 644*300ce4a2SGerry Weißbach 645*300ce4a2SGerry Weißbach/* 646*300ce4a2SGerry Weißbach print "\n\n#########\n"; 647*300ce4a2SGerry Weißbach print_r($instructions); 648*300ce4a2SGerry Weißbach print "\nn#########\n\n"; 649*300ce4a2SGerry Weißbach*/ 650*300ce4a2SGerry Weißbach $instructions = array_merge( $mergeHintPrepend, $instructions, $mergeHintPostpend ); 651*300ce4a2SGerry Weißbach } 652*300ce4a2SGerry Weißbach 6537d101cc1SGerry Weißbach /** 6547d101cc1SGerry Weißbach * Remove TOC, section edit buttons and tags 6557d101cc1SGerry Weißbach */ 6567d101cc1SGerry Weißbach function _cleanXHTML($xhtml) { 6577d101cc1SGerry Weißbach $replace = array( 6587d101cc1SGerry Weißbach '!<div class="toc">.*?(</div>\n</div>)!s' => '', // remove TOCs 6593dfe6d90SGerry Weißbach '#<!-- SECTION \[(\d*-\d*)\] -->#s' => '', // remove section edit buttons 6607d101cc1SGerry Weißbach '!<div id="tags">.*?(</div>)!s' => '' // remove category tags 6617d101cc1SGerry Weißbach ); 6627d101cc1SGerry Weißbach $xhtml = preg_replace(array_keys($replace), array_values($replace), $xhtml); 6637d101cc1SGerry Weißbach return $xhtml; 6647d101cc1SGerry Weißbach } 6657d101cc1SGerry Weißbach 6667d101cc1SGerry Weißbach /** 6677d101cc1SGerry Weißbach * Allow the plugin to prevent DokuWiki creating a second instance of itself 6687d101cc1SGerry Weißbach * 6697d101cc1SGerry Weißbach * @return bool true if the plugin can not be instantiated more than once 6707d101cc1SGerry Weißbach */ 6717d101cc1SGerry Weißbach function isSingleton() { 6727d101cc1SGerry Weißbach return true; 6737d101cc1SGerry Weißbach } 6747d101cc1SGerry Weißbach} 6757d101cc1SGerry Weißbach// vim:ts=4:sw=4:et:enc=utf-8: 676