Trace: » plugin_partial_include

    <?php
    /**
     * Partial Include Plugin: displays parts of a wiki page within another
     * Usage:
     * {{subpage>page}} for "page" in same namespace
     * {{subpage>:page}} for "page" in top namespace
     * {{subpage>namespace:page}} for "page" in namespace "namespace"
     * {{subpage>.namespace:page}} for "page" in subnamespace "namespace"
     * {{subpage>page#n_sections;optional_min_level}} for a section of "page"
     *
     * @license    GPL 2 (http://www.gnu.org/licenses/gpl.html)
     * @author     Gwenole Beauchesne <masked-email>
     */
     
    if(!defined('DOKU_INC')) define('DOKU_INC',realpath(dirname(__FILE__).'/../../').'/');
    if(!defined('DOKU_PLUGIN')) define('DOKU_PLUGIN',DOKU_INC.'lib/plugins/');
    require_once(DOKU_PLUGIN.'syntax.php');
     
    /**
     * All DokuWiki plugins to extend the parser/rendering mechanism
     * need to inherit from this class
     */
    class syntax_plugin_partial_include extends DokuWiki_Syntax_Plugin {
     
        /**
         * return some info
         */
        function getInfo(){
            return array(
                'author' => 'Gwenole Beauchesne',
                'email'  => '<masked-email>',
                'date'   => '2005-11-01',
                'name'   => 'Partial Include Plugin',
                'desc'   => 'displays parts of a wiki page within another',
                'url'    => '',
            );
        }
     
        /**
         * What kind of syntax are we?
         */
        function getType(){
            return 'substition';
        }
     
        /**
         * Where to sort in?
         */
        function getSort(){
            return 309;
        }
     
        /**
         * Paragraph Type
         */
        function getPType(){
            return 'block';
        }
     
        /**
         * Connect pattern to lexer
         */
        function connectTo($mode) {
            $this->Lexer->addSpecialPattern('\{\{subpage.+?\}\}',$mode,'plugin_partial_include');
        }
     
        /**
         * Handle the match
         */
        function handle($match, $state, $pos, &$handler){
            global $ID;
            global $filechain;
     
            $match = substr($match,10,-2);                // strip markup
            $match = preg_split('/\#/u',$match,2);        // split hash from filename
            resolve_pageid(getNS($ID),$match[0],$exists); // resolve shortcuts
     
            // check for existence and permission
            if ((!$exists) || (auth_quickaclcheck($match[0]) < 1)) return false;
     
            // check for and establish start of $filechain
            if (!isset($filechain)) $filechain[] = $ID;
     
            // don't allow the same file to be included more than once
            if (in_array($match[0], $filechain)) return false;
     
            // add included page to the filechain
            $filechain[] = $match[0];
     
            // get sections information
            list($num, $level, $type) = explode(';',$match[1],3);
            if ($num == 0)
                $num = 1;
            if ($level == 0)
                $level = 1;
            if ($type == '')
                $type = 'header';
            switch ($type) {
            case 'header': case 'list': break;
            default: return false;
            }
     
            return array($match[0], $num, $level, $type);
        }    
     
        /**
         * Create output
         */
        function render($mode, &$renderer, $data) {
     
            if($mode == 'xhtml'){
                $file = wikiFN($data[0]);
                if (!@file_exists($file)) return false;
     
                // get instructions
                $instr = p_cached_instructions($file, false);
     
                // filter section
                $instr = $this->{'_getSection_'.$data[3]}($data[1], $data[2], $more, $instr);
     
                // correct relative internal links and media
                $instr = $this->_correctRelNS($instr, $data[0]);
     
                // render the instructions on the fly
                $text = p_render('xhtml',$instr,$info);
     
                // remove toc, section edit buttons and category tags
                $patterns = array('!<div class="toc">.*?(</div>\n</div>)!s',
                                  '#<!-- SECTION \[(\d*-\d*)\] -->#e',
                                  '!<div class="category">.*?</div>!s');
                $replace  = array('','','');
                $text = preg_replace($patterns,$replace,$text);
     
                // prevent caching to ensure the included page is always fresh
                $renderer->info['cache'] = FALSE;
     
                // embed the included page
                $renderer->doc .= $text;
     
                // append continuation link
                if ($more) {
                    $level = $data[2];
                    $mlink = $renderer->internallink($data[0],'...','','true');
                    switch ($data[3]) {
                    case 'header':
                        $renderer->doc .= "<div class=\"level$level\">[$mlink]</div>";
                        break;
                    case 'list': // <ul> is open at this stage
                        $renderer->doc .= "<li class=\"level$level\"><div class=\"li\">[$mlink]</div></li></ul>";
                    }
                }
     
                return true;
            }
            return false;
        }
     
        /**
         * Get N 'header' sections including their subsections
         */
        function _getSection_header($max_sections,$min_level,&$more,$instructions){
            $more = 0;
            $n_sections = 0;
            foreach ($instructions as $instruction){
                if ($instruction[0] == 'header'){
                    $level = $instruction[1][1];
                    if ($level >= $min_level) {
                        if ($level == $min_level) {
                            $n_sections += 1;
                            if ($n_sections > $max_sections) {
                                $more = 1;
                                return $i;
                            }
                        }
                        $i[] = $instruction;
                    } elseif ($n_sections && $level < $min_level)
                        return $i;
                } elseif ($n_sections) {
                    $i[] = $instruction;
                }
            }
            return $i;
        }
     
        /**
         * Get N 'list items including their sublists
         * XXX factorisation candidate
         */
        function _getSection_list($max_sections,$min_level,&$more,$instructions){
            $more = 0;
            $n_sections = 0;
            for ($it = 0; $it < sizeof($instructions); $it++){
                $instruction = $instructions[$it];
                if ($instruction[0] == 'listitem_open'){
                    $level = $instruction[1][0];
                    if ($level >= $min_level) {
                        if ($level == $min_level) {
                            $n_sections += 1;
                            if ($n_sections == 1) 
                                $i[] = $instructions[$it-1];
                            elseif ($n_sections > $max_sections) {
                                $more = 1;
                                return $i;
                            }
                        }
                        $i[] = $instruction;
                    } elseif ($n_sections && $level < $min_level)
                        return $i;
                } elseif ($n_sections) {
                    $i[] = $instruction;
                }
            }
            return $i;
        }
     
        /**
         * Corrects relative internal links and media
         */
        function _correctRelNS($instr,$incl){
            global $ID;
     
            // check if included page is in same namespace
            $iNS = getNS($incl);
            if (getNS($ID) == $iNS) return $instr;
     
            // convert internal links and media from relative to absolute
            $n = count($instr);
            for($i = 0; $i < $n; $i++){
                if (substr($instr[$i][0], 0, 8) == 'internal'){
     
                    // relative subnamespace
                    if ($instr[$i][1][0]{0} == '.'){
                        $instr[$i][1][0] = $iNS.':'.substr($instr[$i][1][0], 1);
     
                    // relative link
                    } elseif (strpos($instr[$i][1][0],':') === false) {
                        $instr[$i][1][0] = $iNS.':'.$instr[$i][1][0];
                    }
                }
            }
            return $instr;
        }
    }
     
    //Setup VIM: ex: et ts=4 enc=utf-8 :
     
    Recent changes RSS feed Creative Commons License Powered by PHP Valid XHTML 1.0 Valid CSS Driven by DokuWiki