<?php
/**
 *  Add smart navigation capability to dokuwiki
 *
 *  Roland Hellebart's tree plugin ( his http://wiki.splitbrain.org/plugin:tree )
 *  was used as a base for this.
 *
 *  Documentation is located at http://wiki.splitbrain.org/plugin:navilevel
 *
 *  @license    GNU_GPL_v2
 *  @author     Thanos Massias
 */

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_navilevel extends DokuWiki_Syntax_Plugin {
 
  
    function getInfo(){
        return array(
            'author' => 'Thanos Massias',
            'email'  => 'thanos.massias@gmail.com',
            'date'   => '2007-06-14',
            'name'   => 'navilevel Plugin',
            'desc'   => 'Add smart Navigation Capability',
            'url'    => 'http://www.acsys.gr/plugins/navilevel/',
        );
    }
  
    /**
     *  What kind of syntax are we?
     */
    function getType(){
        return 'protected';
    }
 
    /**
     *  What kind of syntax do we allow (optional)
     */
    function getAllowedTypes() {
        return array('protected');
    }
 
    /**
     *  What about paragraphs? (optional)
     */
    function getPType(){
        return 'block';
    }

    /**
     *  Where to sort in?
     */
    function getSort(){
        return 203;
    }

    /**
     *  Connect pattern to lexer
     */
    function connectTo($mode) {
        $this->Lexer->addEntryPattern('<navilevel.*?>(?=.*?</navilevel>)',$mode,'plugin_navilevel');
    }
    
    function postConnect() {
        $this->Lexer->addExitPattern('</navilevel>','plugin_navilevel');
    }
 
    /**
     *  Handle the match
     */
    function handle($match, $state, $pos, &$handler){
        switch ($state) {
          case DOKU_LEXER_ENTER :
            break;
          case DOKU_LEXER_MATCHED :
            break;
          case DOKU_LEXER_UNMATCHED :
            break;
          case DOKU_LEXER_EXIT :
            break;
          case DOKU_LEXER_SPECIAL :
            break;
        }
        return array($match, $state);
    }
 
    /**
     *  Create output
     */
    function render($mode, &$renderer, $data) {
        // You may have to configure $rellevel to suite your site
        //
        // $lowlevel = 1;  --> sites not based on per-namespace start pages (default)
        // $lowlevel = 2;  --> sites     based on per-namespace start pages
        //
        $lowlevel = 1;

        global $ID;
        global $ullevellast; 
        $linklineID = ':'.$ID;
        //  In case you want the plugin to work correctly within a sidebar add the 
        //  following two lines in '/dokuwiki_home/lib/tpl/template_name/main.php':
        //  ---------------------
        //  global $PPID;
        //  $PPID = $ID;
        //  ---------------------
        global $PPID;
        if ('X'.$PPID != 'X'){
            if ($ID != $PPID){
                $linklineID = ':'.$PPID;
            }
        }
        $partsID = explode(':', $linklineID);
        $countpartsID = count($partsID);

        $showall = 0;
        if (($countpartsID == 2) && ($partsID[1] == 'sitemap')){
          $showall = 1;
        } 

        if($mode == 'xhtml'){
            switch ($data[1]) {
                case DOKU_LEXER_ENTER :
                  $renderer->doc .= "\n";
                  break;
    
                case DOKU_LEXER_MATCHED :
                  break;
      
                case DOKU_LEXER_UNMATCHED :
                    $content = $data[0];

                    //  clean up the input data
                    //  clear any trailing or leading empty lines from the data set
                    $content = preg_replace("/[\r\n]*$/","",$content);
                    $content = preg_replace("/^\s*[\r\n]*/","",$content);
     
                    //  Not sure if PHP handles the DOS \r\n or Mac \r, so being paranoid
                    //  and converting them if they exist to \n
                    $content = preg_replace("/\r\n/","\n",$content);
                    $content = preg_replace("/\r/","\n",$content);
                    $result = $this->tree_explode_node($content);

                    $ullevellast = 0;
    
                    foreach ($result as $input){
                        $arrinput = explode('|', $input);
                        $linkline = $arrinput[0];
                        $linkline = trim($linkline);
                        $linktext_before = $arrinput[1];
                        $linktext_before = trim($linktext_before);
                        $linkname = $arrinput[2];
                        $linkname = trim($linkname);
                        $linktext_after = $arrinput[3];
                        $linktext_after = trim($linktext_after);
                        if (strlen($linkline) > 0) {
                            $linkline = cleanID($linkline);
                            if (substr($linkline,0,1) != ':'){
                                $linkline = ':'.$linkline;
                            }

                            $parts = explode(':', $linkline);
                            $countparts = count($parts);
            
                            $listlink = 0;
                            //  low level links
                            if ($countparts < (2 + $lowlevel)){
                                $listlink = 1;
                            }else{
                                //  children, yes - grandchildren and beyond, no
                                if ($countparts <= $countpartsID + 1){
                                    $listlink = 1;
                                    $tmppathID = '';
                                    $tmppath   = '';
                                    $i = 0;
                                    foreach ($parts as $part){
                                        if (($i > 0) && ($i < $countparts - 2)){
                                            if ('X'.$partsID[$i] != 'X') {
                                                $tmppathID .= ':'.$partsID[$i];
                                                $tmppath   .= ':'.$parts[$i];
                                                if ($tmppathID !== $tmppath){
                                                    $listlink = 0;
                                                }
                                            }
                                        }
                                        $i++;
                                    }
                                }
                            }
        
                            if ($listlink || $showall){
                                $ullevel = $countparts - 1;
                                if ($ullevel == $ullevellast){
                                    $renderer->doc .= "\n</li>";
                                }
                                if ($ullevel > $ullevellast){
                                    $renderer->doc .= "\n<ul>";
                                }
                                if ($ullevel < $ullevellast){
                                    for ($j = 0; $j < ($ullevellast - $ullevel); $j++){
                                        $renderer->doc .= "\n</li>\n</ul>";
                                    }
                                    $renderer->doc .= "\n</li>";
                                }
                                $ullevellast = $ullevel;
                                $renderer->doc .= "\n".'<li class="level'.$ullevel.'"><div class="li"> '; 
                                if (strlen($linktext_before) > 0) {
                                    $renderer->doc .= $linktext_before.' ';
                                }
                                if (strlen($linkname) > 0) {
                                    $renderer->doc .= $renderer->internallink($linkline,$linkname);
                                }else{
                                    $renderer->doc .= $renderer->internallink($linkline);
                                }
                                if (strlen($linktext_after) > 0) {
                                    $renderer->doc .= ' '.$linktext_after;
                                }
                                $renderer->doc .= "</div>";
                            }else{
                                $renderer->doc .= "";
                            }
                        }
                    } 
                    break;
  
                case DOKU_LEXER_EXIT :
                    $ullevel = 1;
                    if ($ullevel == $ullevellast){
                        $renderer->doc .= "\n</li>";
                    }
                    if ($ullevel > $ullevellast){
                        $renderer->doc .= "\n<ul>";
                    }
                    if ($ullevel < $ullevellast){
                        for ($j = 0; $j < ($ullevellast - $ullevel); $j++) {
                            $renderer->doc .= "\n</li>\n</ul>";
                        }
                        $renderer->doc .= "\n</li>";
                    }
                    $renderer->doc .= "\n</ul>";
                    break;

                case DOKU_LEXER_SPECIAL :
                    break;
            }
            return false;
        }
        
        // unsupported $mode
        return false;
    } 

    function tree_explode_node(&$str) {
        $len = strlen($str) + 1;
        $inside = false;
        $word = '';
        for ($i = 0; $i < $len; ++$i) {
            $next = $i+1;
            if ($str[$i] == "\n") {
                $out[] = $word;
                $word = '';
            } elseif ($next == $len) {
                $out[] = $word;
                $word = '';
            } else {
                $word .= $str[$i];
            }
        }
        $str = substr($str, $next);
        $out[] = $word;
        return $out;
    }
}
 
//Setup VIM: ex: et ts=4 enc=utf-8 :
?>
