xref: /plugin/siteexport/syntax/toc.php (revision 300ce4a20f600a2031826a8c1d16bf3aa359b53d)
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