*/ if(!defined('DOKU_INC')) die(); class action_plugin_indexmenu extends DokuWiki_Action_Plugin { /** * plugin should use this method to register its handlers with the dokuwiki's event controller * * @param Doku_Event_Handler $controller DokuWiki's event controller object. */ function register(Doku_Event_Handler $controller) { if($this->getConf('only_admins')) $controller->register_hook('IO_WIKIPAGE_WRITE', 'BEFORE', $this, '_checkperm'); if($this->getConf('page_index') != '') $controller->register_hook('TPL_ACT_RENDER', 'BEFORE', $this, '_loadindex'); $controller->register_hook('DOKUWIKI_STARTED', 'AFTER', $this, '_extendJSINFO'); $controller->register_hook('PARSER_CACHE_USE', 'BEFORE', $this, '_purgecache'); if($this->getConf('show_sort')) $controller->register_hook('TPL_CONTENT_DISPLAY', 'BEFORE', $this, '_showsort'); $controller->register_hook('AJAX_CALL_UNKNOWN', 'BEFORE', $this, '_ajax_call'); } /** * Check if user has permission to insert indexmenu * * @author Samuele Tognini * * @param Doku_Event $event * @param mixed $param not defined */ function _checkperm(&$event, $param) { global $INFO; if(!$INFO['isadmin']) { $event->data[0][1] = preg_replace("/{{indexmenu(|_n)>.+?}}/", "", $event->data[0][1]); } } /** * Add additional info to $JSINFO * * @author Samuele Tognini * @author Gerrit Uitslag * * @param Doku_Event $event * @param mixed $param not defined */ function _extendJSINFO(&$event, $param) { global $INFO, $JSINFO; $JSINFO['isadmin'] = (int) $INFO['isadmin']; $JSINFO['isauth'] = (int) $INFO['userinfo']; } /** * Check for pages changes and eventually purge cache. * * @author Samuele Tognini * * @param Doku_Event $event * @param mixed $param not defined */ function _purgecache(&$event, $param) { global $ID; global $conf; /** @var cache_parser $cache */ $cache = &$event->data; if(!isset($cache->page)) return; //purge only xhtml cache if($cache->mode != "xhtml") return; //Check if it is an indexmenu page if(!p_get_metadata($ID, 'indexmenu')) return; $aclcache = $this->getConf('aclcache'); if($conf['useacl']) { $newkey = false; if($aclcache == 'user') { //Cache per user if($_SERVER['REMOTE_USER']) $newkey = $_SERVER['REMOTE_USER']; } else if($aclcache == 'groups') { //Cache per groups global $INFO; if($INFO['userinfo']['grps']) $newkey = implode('#', $INFO['userinfo']['grps']); } if($newkey) { $cache->key .= "#".$newkey; $cache->cache = getCacheName($cache->key, $cache->ext); } } //Check if a page is more recent than purgefile. if(@filemtime($cache->cache) < @filemtime($conf['cachedir'].'/purgefile')) { $event->preventDefault(); $event->stopPropagation(); $event->result = false; } } /** * Render a defined page as index. * * @author Samuele Tognini * * @param Doku_Event $event * @param mixed $param not defined */ function _loadindex(&$event, $param) { if('index' != $event->data) return; if(!file_exists(wikiFN($this->getConf('page_index')))) return; global $lang; print '

'.$lang['btn_index']."

\n"; print p_wiki_xhtml($this->getConf('page_index')); $event->preventDefault(); $event->stopPropagation(); } /** * Display the indexmenu sort number. * * @author Samuele Tognini * * @param Doku_Event $event * @param mixed $param not defined */ function _showsort(&$event, $param) { global $ID, $ACT, $INFO; if($INFO['isadmin'] && $ACT == 'show') { if($n = p_get_metadata($ID, 'indexmenu_n')) { ptln('
'); ptln($this->getLang('showsort').$n); ptln('
'); } } } /** * Handles ajax requests for indexmenu * * @param Doku_Event $event * @param mixed $param not defined */ function _ajax_call(&$event, $param) { if($event->data !== 'indexmenu') { return; } //no other ajax call handlers needed $event->stopPropagation(); $event->preventDefault(); switch($_REQUEST['req']) { case 'local': //list themes header('Content-Type: application/json'); $data = $this->_getlocalThemes(); require_once DOKU_INC.'inc/JSON.php'; $json = new JSON(); echo ''.$json->encode($data).''; break; case 'toc': //print toc preview if(isset($_REQUEST['id'])) print $this->print_toc($_REQUEST['id']); break; case 'index': //print index if(isset($_REQUEST['idx'])) print $this->print_index($_REQUEST['idx']); break; } } /** * Print a list of local themes * * @author Samuele Tognini * @author Gerrit Uitslag */ private function _getlocalThemes() { $themebase = 'lib/plugins/indexmenu/images'; $handle = @opendir(DOKU_INC.$themebase); $themes = array(); while(false !== ($file = readdir($handle))) { if(is_dir(DOKU_INC.$themebase.'/'.$file) && $file != "." && $file != ".." && $file != "repository" && $file != "tmp" && $file != ".svn" ) { $themes[] = $file; } } closedir($handle); sort($themes); return array( 'themebase' => $themebase, 'themes' => $themes ); } /** * Print a toc preview * * @author Samuele Tognini * @author Andreas Gohr */ function print_toc($id) { require_once(DOKU_INC.'inc/parser/xhtml.php'); $id = cleanID($id); if(auth_quickaclcheck($id) < AUTH_READ) return ''; $meta = p_get_metadata($id); $toc = $meta['description']['tableofcontents']; if(count($toc) > 1) { //display ToC of two or more headings $out = $this->render_toc($toc); } else { //display page abstract $out = $this->render_abstract($id, $meta); } return $out; } /** * Return the TOC rendered to XHTML * * @author Andreas Gohr * @author Gerrit Uitslag */ function render_toc($toc) { global $lang; $out = '
'.DOKU_LF; $out .= $lang['toc']; $out .= '
'.DOKU_LF; $out .= '
'.DOKU_LF; $out .= html_buildlist($toc, 'toc', array($this, '_indexmenu_list_toc'), 'html_li_default', true); $out .= '
'.DOKU_LF; return $out; } /** * Return the page abstract rendered to XHTML */ function render_abstract($id, &$meta) { $out = ''.DOKU_LF; if($meta['description']['abstract']) { $out .= '
'.DOKU_LF; $out .= p_render('xhtml', p_get_instructions($meta['description']['abstract']), $info); $out .= '
'.DOKU_LF.''.DOKU_LF; } return $out; } /** * Callback for html_buildlist */ function _indexmenu_list_toc($item) { $id = cleanID($_REQUEST['id']); if(isset($item['hid'])) { $link = '#'.$item['hid']; } else { $link = $item['link']; } //prefix anchers with page id if($link[0] == '#') { $link = wl($id, $link, false, ''); } return ''.hsc($item['title']).''; } /** * Print index nodes * * @author Samuele Tognini * @author Andreas Gohr * @author Rene Hadler */ function print_index($ns) { require_once(DOKU_PLUGIN.'indexmenu/syntax/indexmenu.php'); global $conf; $idxm = new syntax_plugin_indexmenu_indexmenu(); $ns = $idxm->_parse_ns(rawurldecode($ns)); $level = -1; $max = 0; $data = array(); $skipfile = array(); $skipns = array(); if($_REQUEST['max'] > 0) { $max = $_REQUEST['max']; $level = $max; } $nss = ($_REQUEST['nss']) ? cleanID($_REQUEST['nss']) : ''; $idxm->sort = $_REQUEST['sort']; $idxm->msort = $_REQUEST['msort']; $idxm->rsort = $_REQUEST['rsort']; $idxm->nsort = $_REQUEST['nsort']; $idxm->hsort = $_REQUEST['hsort']; $fsdir = "/".utf8_encodeFN(str_replace(':', '/', $ns)); $skipf = utf8_decodeFN($_REQUEST['skipfile']); $skipfile[] = $this->getConf('skip_file'); if(isset($skipf)) { $index = 0; if($skipf[1] == '+') { $index = 1; } $skipfile[$index] = substr($skipf, 1); } $skipn = utf8_decodeFN($_REQUEST['skipns']); $skipns[] = $this->getConf('skip_index'); if(isset($skipn)) { $index = 0; if($skipn[1] == '+') { $index = 1; } $skipns[$index] = substr($skipn, 1); } $opts = array( 'level' => $level, 'nons' => $_REQUEST['nons'], 'nss' => array(array($nss, 1)), 'max' => $max, 'js' => false, 'nopg' => $_REQUEST['nopg'], 'skip_index' => $skipns, 'skip_file' => $skipfile, 'headpage' => $idxm->getConf('headpage'), 'hide_headpage' => $idxm->getConf('hide_headpage') ); if($idxm->sort || $idxm->msort || $idxm->rsort || $idxm->hsort) { $idxm->_search($data, $conf['datadir'], array($idxm, '_search_index'), $opts, $fsdir); } else { search($data, $conf['datadir'], array($idxm, '_search_index'), $opts, $fsdir); } $out = ''; if($_REQUEST['nojs']) { require_once(DOKU_INC.'inc/html.php'); $out_tmp = html_buildlist($data, 'idx', array($idxm, "_html_list_index"), "html_li_index"); $out .= preg_replace('/
    (.*)<\/ul>/s', "$1", $out_tmp); } else { $nodes = $idxm->_jsnodes($data, '', 0); $out = "ajxnodes = ["; $out .= rtrim($nodes[0], ","); $out .= "];"; } return $out; } }