<?php /** * Dir Plugin: Shows pages in one or namespaces in a table or list * * @license GPL 2 (http://www.gnu.org/licenses/gpl.html) * @author Jacobus Geluk <Jacobus.Geluk@gmail.com> * @based_on "pageindex" plugin by Kite <Kite@puzzlers.org> * @based_on "externallink" plugin by Otto Vainio <plugins@valjakko.net> * @based_on "pagelist" plugin by Esther Brunner <wikidesign@gmail.com> * * Contributions by: * * - Jean-Philippe Prade * - Gunther Hartmann * - Sebastian Menge * - Matthias Schulte * - Geert Janssens * - Gerry Weißbach */ 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'); require_once (DOKU_INC.'inc/search.php'); require_once (DOKU_INC.'inc/pageutils.php'); define ("DIR_PLUGIN_PATTERN", "DIR"); /** * The main DIR plugin class... */ class syntax_plugin_dir extends DokuWiki_Syntax_Plugin { var $debug = false; var $plugins = Array(); var $opts = Array(); var $cols = Array(); var $hdrs = Array(); var $pages = Array(); var $includeTags = Array(); var $excludeTags = Array(); var $hasTags = false; var $style = "default"; var $rdr = NULL; var $rdrMode = NULL; var $start = "start"; var $dformat = NULL; var $sortKeys = Array(); var $nbrOfSortKeys = 0; var $useDefaultTitle = true; var $modeIsXHTML = false; var $modeIsLatex = false; var $processedLatex = false; var $rowNumber = 0; var $ucnames = false; /** * Constructor */ function syntax_plugin_dir() { global $conf; // // In the config you can set allowdebug, but you can also // specify the debug attribute in the ~~DIR~~ line... // if($conf ["allowdebug"] == 1) $this->debug = true; $this->start = $conf ["start"]; $this->dformat = $conf ["dformat"]; $this->style = $this->getConf("style"); } /** * return some info */ function getInfo() { return array( 'author' => 'Jacobus Geluk', 'email' => 'Jacobus.Geluk@gmail.com', 'date' => '2008-06-28', 'name' => 'Dir Plugin', 'desc' => 'Shows pages in one or namespaces in a table or list', 'url' => 'http://www.dokuwiki.org/plugin:dir', ); } /** * What kind of syntax are we? */ function getType() { return "substition"; } /** * Just before build in links */ function getSort() { return 299; } /** * What about paragraphs? */ function getPType() { return "block"; } /** * Register the ~~DIR~~ verb... * Supported signatures: * * 1. ~~DIR~~ * 2. ~~DIR:...~~ * 3. ~~DIR?...~~ */ function connectTo($mode) { $this->Lexer->addSpecialPattern('~~'.DIR_PLUGIN_PATTERN.'~~', $mode, 'plugin_dir'); $this->Lexer->addSpecialPattern('~~'.DIR_PLUGIN_PATTERN.'[:?][^~]*~~', $mode, 'plugin_dir'); } /** * Handle the match */ function handle($match, $state, $pos, Doku_Handler $handler) { return preg_replace("%~~".DIR_PLUGIN_PATTERN.":(=(.*))?~~%", "\\2", $match); } /** * Initialize the current object for each rendering pass */ function _initRender($mode, &$renderer) { $rc = FALSE; $this->rowNumber = 0; $this->opts = Array(); $this->cols = Array(); $this->hdrs = Array(); $this->pages = Array(); $this->hasTags = false; $this->excludeTags = Array(); $this->includeTags = Array(); $this->rdr =& $renderer; $this->rdrMode = $mode; switch($mode) { case 'latex': $this->modeIsXHTML = false; $this->modeIsLatex = true; $rc = TRUE; break; case 'xhtml': $this->modeIsXHTML = true; $this->modeIsLatex = false; $rc = TRUE; break; default: $this->modeIsXHTML = false; $this->modeIsLatex = false; } return $rc; } /** * Create output */ function render($mode, Doku_Renderer $renderer, $data) { if(!$this->_initRender($mode, $renderer)) return false; $rc = $this->_dir($data); if($this->modeIsLatex) $this->processedLatex = true; $this->_showDebugMsg("Leaving syntax_plugin_dir.render()"); return $rc; } /** * Put a debug message on screen... */ function _showDebugMsg($msg) { if(!$this->debug) return; if(is_array($msg)) { foreach($msg as $index => $m) { $this->_showDebugMsg("Array [$index]: ".$m); } return; } $this->_putNewLine(); switch($this->rdrMode) { case 'xhtml': $this->_put(DOKU_LF."<span style=\"color:red;\">~~"); $this->_put(DIR_PLUGIN_PATTERN."~~: ".hsc($msg)."</span>"); break; case 'latex': $this->_put(DOKU_LF."~~"); $this->_put(DIR_PLUGIN_PATTERN."~~: ".$msg); break; } } /** * Load the specified plugin (like the tag or discussion plugin) */ function _loadPlugin($plugin) { if(plugin_isdisabled($plugin)) return false; $plug = plugin_load('helper', $plugin); if(!$plug) { $this->_showDebugMsg("Plugin \"$plugin\" NOT loaded!"); return false; } $this->plugins [$plugin] = $plug; $this->_showDebugMsg("Plugin \"$plugin\" loaded!"); return true; } /** * Let another plugin generate the content... */ function _pluginCell($plugin, $id) { $plug = $this->plugins [$plugin]; if(!$plug) return 'Plugin '.$plugin.' not loaded!'; $html = $plug->td(cleanID($id)); return $html; } /** * Shows parsed options (in debug mode) */ function _parseOptionsShow($data, $dir, $ns) { if(!$this->debug) return; $this->_put(DOKU_LF."<xmp style=\"font-family: Courier; color: red;\">"); $this->_put(DOKU_LF." data = $data"); $this->_put(DOKU_LF." dir = $dir"); $this->_put(DOKU_LF." ns = $ns"); foreach($this->opts as $key => $opt) { if(is_array($opt)) { foreach($opt as $optkey => $optval) { $this->_put(DOKU_LF." opts[$key][$optkey] = $optval"); } } else if(is_bool($opt)) { $this->_put(DOKU_LF." opts[$key] = ".($opt ? "true" : "false")); } else { $this->_put(DOKU_LF." opts[$key] = $opt"); } } $this->_put(DOKU_LF.DOKU_LF."date: ".date("D M j G:i:s T Y")); $this->_put(DOKU_LF."</xmp>".DOKU_LF); } /** * Get the namespace of the parent directory * (always prefixed and postfixed with a colon, root is ':') */ function _getParentNS($id) { // global $ID ; $curNS = getNS($id); if($curNS == '') return ':'; if(substr($curNS, 0, 1) != ':') { $curNS = ':'.$curNS; } return $curNS.':'; } /** * Create a fully qualified namespace from the specified one. * The second parameter must be true when the given namespace * is never a page id. In that case, the returned namespace * always ends with a colon. */ function _parseNS($ns, $mustBeNSnoPage) { global $ID; if(substr($ns, 0, 2) == '.:') { $ns = ':'.getNS($ID).substr($ns, 1); } elseif(substr($ns, 0, 3) == '..:') { $ns = $this->_getParentNS($ID).substr($ns, 3); } elseif($ns == '..') { $ns = $this->_getParentNS($ID); } elseif(substr($ns, 0, 1) == ':') { } elseif($ns == '.' || $ns == '*') { $ns = ':'.getNS($ID); } else { $ns = ':'.getNS($ID).':'.$ns; } if($mustBeNSnoPage && substr($ns, -1) <> ':') $ns .= ':'; return $ns; } /** * Convert namespace to its path */ function _ns2path($ns) { global $conf; if($ns == ':' || $ns == '') return $conf ['datadir']; $ns = trim($ns, ':'); $path = $conf ['datadir'].'/'.utf8_encodeFN(str_replace(':', '/', $ns)); return $path; } /** * Initialize the opts array... */ function _initOpts($flags) { $this->opts = array(); $this->opts ["noheader"] = false; $this->opts ["collapse"] = false; $this->opts ["ego"] = false; $this->opts ["namespacename"] = false; $flags = explode('&', $flags); foreach($flags as $index => $par) { $tmp = explode("=", $par); $key = $tmp [0]; $val = $tmp [1]; switch($key) { case "skip": case "cols": case "hdrs": case "sort": case "tag": $val = explode(';', trim($val, ';')); $this->_loadPlugin("tag"); break; case "noheader": case "nohead": case "nohdr": $key = "noheader"; $val = true; break; case "showheader": case "header": $key = "noheader"; $val = false; break; case "collapse": $key = "collapse"; $val = true; break; case "ego": $key = "ego"; $val = true; break; case "nodefaulttitle": case "ndt": $key = "nodefaulttitle"; $val = true; $this->useDefaultTitle = false; break; case "widedesc": $val = true; break; case "table": $this->style = "table"; break; case "list": $this->style = "list"; break; case "namespacename": $key = "namespacename"; $val = true; break; case "ucnames": $this->ucnames = true; break; case "debug": $this->debug = true; break; case "last": $key = 'maxrows'; $val = intval($val); break; } $this->opts [$key] = $val; } } /** * Check the supplied column names */ function _parseColumnNames() { if(is_array($this->opts ["cols"])) { $this->cols = $this->opts ["cols"]; } else { $this->cols = Array("page"); } if(count($this->cols) == 0) { $cols [] = "page"; $cols [] = "desc"; } $newCols = Array(); foreach($this->cols as $index => $col) { switch($col) { case "page": case "desc": case "user": case "userid": case "mdate": case "cdate": case "rowno": break; case "comments": $this->_loadPlugin("discussion"); break; case "tags": $this->_loadPlugin("tag"); break; case "date": $col = "mdate"; break; case "description": $col = "desc"; break; default: $this->_showDebugMsg("Unrecognized column name: \"$col\""); $col = ''; } if($col != '') { $this->_showDebugMsg("Recognized column name: $col"); $newCols [] = $col; } } $this->cols = $newCols; if(count($this->opts ["hdrs"]) != count($this->cols)) { $this->_showDebugMsg( "The number of specified headers (".count($this->opts ["hdrs"]). ") is not equal to the number of specified columns (". count($this->cols).")!" ); } } /** * Check the supplied tags */ function _parseTags() { $this->hasTags = false; if(is_array($this->opts ["tag"])) { foreach($this->opts ["tag"] as $tag) { if($tag == NULL || $tag == '') continue; $tag = mb_convert_case($tag, MB_CASE_LOWER, "UTF-8"); if(substr($tag, 0, 1) == '!') { $this->excludeTags [] = substr($tag, 1); } else { $this->includeTags [] = $tag; } $this->hasTags = true; } foreach($this->excludeTags as $tag) { $this->_showDebugMsg("Specified exclude tag: $tag"); } foreach($this->includeTags as $tag) { $this->_showDebugMsg("Specified include tag: $tag"); } } } /** * Check the supplied sort keys */ function _parseSortKeys() { if(is_array($this->opts ["sort"])) { $this->sortKeys = $this->opts ["sort"]; } $sortKeys = Array(); foreach($this->sortKeys as $index => $sortKey) { $array = explode('-', strtolower($sortKey)); if(count($array) == 1) { $array = Array($sortKey, "a"); } switch($array [1]) { case NULL: case "a": case "asc": case "ascending": $array [1] = false; break; case "d": case "desc": case "descending": $array [1] = true; break; default: $this->_showDebugMsg( "Unrecognized sort column name modifier: ". $array [1] ); $array [1] = false; } switch($array [0]) { case "page": case "desc": case "user": case "userid": case "mdate": case "cdate": case "rowno": break; case "comments": $this->_loadPlugin("discussion"); break; case "tags": $this->_loadPlugin("tag"); break; case "date": $array [0] = "mdate"; break; case "description": $array [0] = "desc"; break; default: $this->_showDebugMsg( "Unrecognized sort column name: ".$array [0] ); $array [0] = NULL; } if($array [0]) { $this->_showDebugMsg( "Sort column ".$array [0]." ". ($array [1] ? "descending" : "ascending") ); $sortKeys [] = $array; } } $this->sortKeys = $sortKeys; $this->nbrOfSortKeys = count($this->sortKeys); } /** * Add a page to the collection of $pages. Check first if it should * not be skipped... */ function _addFoundPage(&$data, $ns, $id, $type, $level) { global $ID; $fqid = $ns.$id; // Fully qualified id... // // If this file or directory should be skipped, do so // switch($type) { case "f": if(($fqid == ':'.$ID) && !$this->opts ["ego"]) // If we found ourself, skip it return false; $pageName = noNS($id); if($pageName == $this->start) return false; foreach($this->opts ["skipfqid"] as $index => $skipitem) { if($skipitem) { if($skipitem == $fqid) { // // Remove the skip rule, it has no use any more... // $this->opts ["skipfqid"] [$index] = NULL; $this->_showDebugMsg("Skipping $fqid due to skip rule $skipitem"); return false; } } } if($this->opts ["collapse"]) { // With collapse, only show: // - pages within the same namespace as the current page if($this->_getParentNS($fqid) != $this->_getParentNS($ID)) { return false; } } $linkid = $fqid; break; case "d": $fqid .= ':'; foreach($this->opts ["skipns"] as $skipitem) { if($skipitem == $fqid) { $this->_showDebugMsg("Skipping $fqid due to skip rule $skipitem"); return false; } } // Don't add startpages the user isn't authorized to read if(auth_quickaclcheck(substr($linkid, 1)) < AUTH_READ) return false; if($this->opts ["collapse"]) { // With collapse, only show: // - sibling namespaces of the current namespace and it's ancestors $curPathSplit = explode(":", trim(getNS($ID), ":")); $fqidPathSplit = explode(":", trim(getNS($fqid), ":")); // Find the last parent namespace that matches // If there is only one more child namespace in the namespace under evaluation, // Then this is a sibling of one of the parent namespaces of the current page. // Siblings are ok, grandchild namespaces and below should be skipped (for collapse). $clevel = 0; if(count($curPathSplit) > 0) { while(($clevel < count($fqidPathSplit) - 1) && ($clevel < count($curPathSplit))) { if($curPathSplit[$clevel] == $fqidPathSplit[$clevel]) { $clevel++; } else { break; } } } if(count($fqidPathSplit) > $clevel + 1) { return false; } } $linkid = $fqid.$this->start; break; } // $this->_showDebugMsg ("$level $type $ns$id:"); if($this->ucnames) { $fqid = str_replace('_'," ",$fqid); // $fqid = ltrim($fqid , ':'); $fqid = preg_replace_callback( '|:\w|', function ($matches) { return strtoupper($matches[0]); }, $fqid ); $fqid = ucwords($fqid); } $data [] = array( 'id' => $fqid, 'type' => $type, 'level' => $level, 'linkid' => $linkid, 'timestamp' => NULL ); return true; } /** * Callback method for the search function in _parseOptions */ function _searchDir(&$data, $base, $file, $type, $level, $opts) { global $ID; $ns = $opts ["ns"]; switch($type) { case "d": return $this->_addFoundPage($data, $ns, pathID($file), $type, $level); case "f": if(!preg_match('#\.txt$#', $file)) return false; //check ACL $id = pathID($file); if(auth_quickaclcheck($id) < AUTH_READ) return false; $this->_addFoundPage($data, $ns, $id, $type, $level); } return false; } /** * Parse the options after the ~~DIR: string and * return true if the table can be generated... * * A namespace specifaction should start with a colon and the flags * should start with a question mark, like this: * * ~~DIR[[:<namespace>][?<flags>]]~~ * * To not break pages created with an older version of this plugin, this * syntax is also supported: * * ~~DIR:<flags>~~ * * This assumes that no other colon is put in <flags> */ function _parseOptions($data) { global $conf; global $ID; $ns = '.'; $flags = trim($data, '~'); $flags = substr($flags, strlen(DIR_PLUGIN_PATTERN)); $flags = trim($flags); $this->_showDebugMsg("specified arguments=".$flags); if( substr($flags, 0, 1) == ':' && strpos(substr($flags, 1), '?') === FALSE && strpos(substr($flags, 1), ':') === FALSE ) { // // This is the "old" syntax where flags do not start with a question mark // $this->_showDebugMsg("parseOptions A"); $flags = substr($flags, 1); } else if( substr($flags, 0, 1) == ':' && strpos(substr($flags, 1), '?') === FALSE ) { // // There is no questionmark so it's all namespace specification // $this->_showDebugMsg("parseOptions B"); $ns = substr($flags, 1); $flags = ''; } else if(substr($flags, 0, 1) == '?') { $this->_showDebugMsg("parseOptions C"); $flags = substr($flags, 1); } else if(strlen($flags) == 0) { $this->_showDebugMsg("parseOptions D"); } else if( strpos(substr($flags, 1), '?') !== FALSE ) { $this->_showDebugMsg("parseOptions E"); $tmp = explode('?', $flags); if(count($tmp) == 2) { $ns = substr($tmp [0], 1); $flags = $tmp [1]; } else { $this->_showDebugMsg("ERROR: Multiple questionmarks are not supported"); $flags = ''; } } else { $this->_showDebugMsg("parseOptions E"); $ns = $flags; $flags = ''; } $this->_showDebugMsg("specified namespace=$ns"); $this->_showDebugMsg("specified flags=$flags"); $ns = $this->_parseNS($ns, true); $path = $this->_ns2path($ns); $this->_showDebugMsg("path=$path"); $this->_initOpts($flags); $this->_parseColumnNames(); $this->_parseSortKeys(); $this->_parseTags(); // // Check the column headers // $this->hdrs = $this->cols; if(is_array($this->opts ["hdrs"])) { foreach($this->opts ["hdrs"] as $index => $hdr) { $this->hdrs [$index] = $hdr; } } // // Check the skip items // $this->opts ["skipfqid"] = Array(); $this->opts ["skipns"] = Array(); if(is_array($this->opts ["skip"])) { foreach($this->opts ["skip"] as $skipitem) { $item = $this->_parseNS($skipitem, false); if(substr($item, -1) == ":") { $this->opts ["skipns"] [] = $item; } else { $this->opts ["skipfqid"] [] = $item; } } } $this->_parseOptionsShow($data, $path, $ns); // // Search the directory $dir, only if the pages array // is empty, since we can pass here several times (xhtml, latex). // $this->_showDebugMsg("Search directory $path"); $this->_showDebugMsg("for namespace $ns"); if(count($this->pages) == 0) { search( $this->pages, // results $path, // folder root array($this, '_searchDir'), // handler array('ns' => $ns) // namespace ); } $count = count($this->pages); $this->_showDebugMsg("Found ".$count." pages!"); if($count == 0) { $this->_put(DOKU_LF."\t<p>There are no documents to show.</p>".DOKU_LF); return false; } $this->_sortResult(); if ( !empty($this->opts['maxrows']) && $this->opts['maxrows'] > 0 ) { $this->pages = array_slice($this->pages, 0, $this->opts['maxrows']); } return true; } /** * Sort the found pages according to the settings */ function _sortResult() { if($this->nbrOfSortKeys == 0) return; usort($this->pages, array($this, "_sortPage")); } /** * Compare function for usort */ function _sortPage($a, $b) { return $this->_sortPageByKey($a, $b, 0); } function _sortPageByKey(&$a, &$b, $index) { if($index >= $this->nbrOfSortKeys) return 0; $keyType = $this->sortKeys [$index]; $sortKeyA = $this->_getSortKey($a, $keyType [0]); $sortKeyB = $this->_getSortKey($b, $keyType [0]); if($sortKeyA == $sortKeyB) return $this->_sortPageByKey($a, $b, $index + 1); if($keyType [1]) { $tmp = $sortKeyA; $sortKeyA = $sortKeyB; $sortKeyB = $tmp; } return ($sortKeyA < $sortKeyB) ? -1 : 1; } /** * Produces a sortable key */ function _getSortKey(&$page, $keyType) { switch($keyType) { case "page": return html_wikilink($page ["id"]); case "desc": case "widedesc": return $this->_getMeta($page, "description", "abstract"); case "mdate": return $this->_getMeta($page, "date", "modified"); case "cdate": return $this->_getMeta($page, "date", "created"); case "user": $users = $this->_getMeta($page, "contributor"); if(is_array($users)) { $index = 0; foreach($users as $userid => $user) { if($user && $user <> "") { return $user; } } } return $users; case "userid": $users = $this->_getMeta($page, "contributor"); if(is_array($users)) { $index = 0; foreach($users as $userid => $user) { if($userid && $userid <> "") { return $userid; } } } return $users; case "comments": return $this->_pluginCell("discussion", $page ["linkid"]); case "tags": return $this->_pluginCell("tag", $page ["linkid"]); case "rowno": return '0'; } return NULL; } /** * Generate the content for the cell with the page link... */ function _tableCellContentID(&$page) { $fqid = $page ["id"]; $tmplvl = $page ["level"] - 1; $spacerWidth = $tmplvl * 20; $pageid = $fqid; $name = NULL; if($page ["type"] == 'd') { if($this->opts ["namespacename"]) { $pieces = explode(':', trim($pageid, ':')); $name = array_pop($pieces); } $pageid .= ':'.$this->start; } if(!$this->useDefaultTitle) { $name = explode(':', $fqid); $name = ucfirst($name [count($name) - 1]); } switch($this->rdrMode) { case 'latex': $this->rdr->internallink($pageid, $name); break; case 'xhtml': if($spacerWidth > 0) { $this->_put('<div style="margin-left: '.$spacerWidth.'px;">'); } if($page ["type"] == 'd' && $this->ucnames) { $dirlnk = html_wikilink($pageid, $name); $dirlnk = str_replace('wikilink2', 'wikilink',$dirlnk); $this->_put($dirlnk); } else $this->_put(html_wikilink($pageid, $name)); if($spacerWidth > 0) { $this->_put('</div>'); } break; } } /** * Get default value for an unset element */ function _getMeta(&$page, $key1, $key2 = NULL) { if(!isset ($page ["meta"])) $page ["meta"] = p_get_metadata($page ["linkid"], false, true); // // Use "created" instead of "modified" if null // if( $key1 == "date" && $key2 == "modified" && !isset ($page ["meta"]["date"]["modified"]) ) { $key2 = "created"; } // // Return "creator" if "contributor" is null // if($key1 == "contributor" && !isset ($page ["meta"]["contributor"])) { $key1 = "creator"; } if(is_string($key2)) return $page ["meta"] [$key1] [$key2]; return $page ["meta"] [$key1]; } /** * Generate the table cell content... */ function _tableCellContent(&$page, $col) { switch($col) { case "page": $this->_tableCellContentID($page); break; case "desc": case "widedesc": $this->_put($this->_getMeta($page, "description", "abstract")); break; case "mdate": $this->_putDate($this->_getMeta($page, "date", "modified")); break; case "cdate": $this->_putDate($this->_getMeta($page, "date", "created")); break; case "user": $users = $this->_getMeta($page, "contributor"); if(is_array($users)) { $index = 0; foreach($users as $userid => $user) { if($user && $user <> '') { if($index++ > 0) { $this->_putNewLine(); } $this->_put($user); } } } break; case "userid": $users = $this->_getMeta($page, "contributor"); if(is_array($users)) { $index = 0; foreach($users as $userid => $user) { if($userid && $userid <> '') { if($index++ > 0) { $this->_putNewLine(); } $this->_put($userid); } } } break; case "comments": if(!$this->modeIsLatex) $this->_put($this->_pluginCell("discussion", $page ["linkid"])); break; case "tags": if(!$this->modeIsLatex) $this->_put($this->_pluginCell("tag", $page ["linkid"])); break; case "rowno": $this->_put($this->rowNumber); break; default: $this->_put($col); } } /** * Rewrite of renderer->table_open () because of class */ function _tableOpen() { if($this->modeIsLatex) { $rdr = $this->rdr; $rdr->_counter['row_counter'] = 0; $rdr->_current_tab_cols = 0; if($rdr->info ['usetablefigure'] == "on") { $this->_putCmdNl("begin{figure}[h]"); } else { $this->_putCmdNl("vspace{0.8em}"); } $rdr->putcmd("begin{tabular}"); $rdr->put("{"); foreach($this->hdrs as $index => $hdr) { $rdr->put("l"); if($index + 1 < sizeof($this->hdrs)) $rdr->put('|'); } $rdr->putnl("}"); return; } switch($this->style) { case "table": $class = "inline"; break; case "list": $class = "ul"; break; default: $class = "pagelist"; } $this->_showDebugMsg("Style=".$this->style." table class=$class"); $this->rdr->table_open (null, null, null, $class) ; } /** * Rewrite of renderer->table_close () */ function _tableClose() { if($this->modeIsLatex) { $this->rdr->tabular_close(); return; } $this->rdr->table_close () ; } /** * Rewrite of renderer->tableheader_open () because of class */ function _tableHeaderCellOpen($class) { if($this->modeIsLatex) return; $this->_put(DOKU_LF.DOKU_TAB.DOKU_TAB.'<th class="'.$class.'">'); } /** * Rewrite of renderer->tableheader_close () */ function _tableHeaderCellClose($index) { if($this->modeIsLatex) { if(($index + 1) == sizeof($this->hdrs)) { $this->rdr->putnl('\\\\'); } else { $this->rdr->put('&'); } return; } return $this->rdr->tableheader_close(); } /** * Rewrite of renderer->tablecell_open () because of class */ function _tableCellOpen($colspan, $class) { if($this->modeIsLatex) return; $this->_put(DOKU_LF.DOKU_TAB.DOKU_TAB.'<td class="'.$class.'"'); if($colspan > 1) $this->_put(' colspan="'.$colspan.'"'); $this->_put(">"); } /** * Rewrite of renderer->tablecell_close () because of class */ function _tableCellClose($index) { if($this->modeIsLatex) { if(($index + 1) == sizeof($this->hdrs)) { $this->rdr->putnl('\\\\'); } else { $this->rdr->put('&'); } return; } return $this->rdr->tablecell_close(); } /** * Return the class name to be used for the <td> showing $col. */ function _getCellClassForCol($col) { switch($col) { case "page": return "dpage"; case "date": case "user": case "desc": case "comments": case "tags": case "rowno": return $col; case "mdate": case "cdate": return "date"; case "userid": return "user"; case "": return ""; } $this->_showDebugMsg("Unknown style class for col $col"); return "desc"; } function _tableHeaderRowOpen() { if($this->modeIsLatex) { $this->_putCmdNl('hline'); return; } $this->rdr->tablerow_open(); } function _tableHeaderRowClose() { if($this->modeIsLatex) { $this->_putCmdNl('hline'); return; } $this->rdr->tablerow_close(); } function _tableRowOpen() { if($this->modeIsLatex) return; $this->rdr->tablerow_open(); } function _tableRowClose() { if($this->modeIsLatex) return; $this->rdr->tablerow_close(); } /** * Return true if the tag plugin is not loaded, * if the ~~DIR~~ line has no tag attribute or * if the given page has one of the specified tags. */ function _hasTag($page) { if(!$this->hasTags) return true; $plug = $this->plugins ['tag']; if(!$plug) return true; // Get the tags of the current page $tmp = $this->_getMeta($page, "subject"); if(!is_array($tmp)) return false; $tags = Array(); // Convert them to lowercase foreach($tmp as $tag) { $tags [] = mb_convert_case($tag, MB_CASE_LOWER, "UTF-8"); } # # If there is an intersection with the exclude tags then we can not show # the current document # if(count($this->excludeTags) > 0) { if(count(array_intersect($tags, $this->excludeTags)) > 0) { $this->_showDebugMsg('skip'); return false; } } # If the intersection with the include tags is not equal (in size) to the # array of include tags, we must skip the current document. if(count($this->includeTags) > 0) { $intersection = array_intersect($tags, $this->includeTags); if(count($intersection) != count($this->includeTags)) { return false; } } return true; } /** * Generate the actual table content... */ function _tableContent() { $doWideDesc = $this->opts ["widedesc"]; if(!$this->opts ["noheader"]) { $this->_tableHeaderRowOpen(); foreach($this->hdrs as $index => $hdr) { $this->_tableHeaderCellOpen( $this->_getCellClassForCol($this->cols [$index]) ); $this->_put($hdr); $this->_tableHeaderCellClose($index); } $this->_tableHeaderRowClose(); } foreach($this->pages as $page) { if(!$this->_hasTag($page)) continue; $this->rowNumber += 1; $this->_tableRowOpen(); foreach($this->cols as $index => $col) { $this->_tableCellOpen(1, $this->_getCellClassForCol($col)); $this->_tableCellContent($page, $col); $this->_tableCellClose($index); } $this->_tableRowClose(); if($doWideDesc) { $this->_tableRowOpen(); $this->_tableCellOpen(count($this->cols), "desc"); $this->_tableCellContent($page, "widedesc"); $this->_tableCellClose(0); $this->_tableRowClose(); } } } /** * Write data to the output stream */ function _put($data) { if($data == NULL || $data == '') return; switch($this->rdrMode) { case 'xhtml': $this->rdr->doc .= $data; break; case 'latex': $this->rdr->put($data); break; } } /** * Write a date to the output stream */ function _putDate($date) { $this->_put(strftime($this->dformat, $date)); } function _putCmdNl($cmd) { $this->rdr->putcmdnl($cmd); } function _putNewLine() { if($this->modeIsLatex) { $this->_putCmdNl('newline'); } else { $this->_put('<br />'); } } /** * Do the real work */ function _dir($data) { if(!$this->_parseOptions($data)) return false; // // If we already did the latex pass, skip the xhtml pass // if($this->processedLatex && $this->rdrMode == 'xhtml') { //return false ; } // // Generate the actual table... // $this->_tableOpen(); $this->_tableContent(); $this->_tableClose(); return true; } } // syntax_plugin_dir //Setup VIM: ex: et ts=2 enc=utf-8 :