====== Content plugin ====== ---- plugin ---- description: Derivative of Blog plugin, with certain enhancement and extension author : Adrian Sai-wah Tam email : adrian@ieaa.org type : syntax lastupdate : 2005-09-27 compatible : 2006-03-09 depends : conflicts : similar : blog tags : blog, news, !broken, !experimental ---- ^ :!: This plugin is highly [[:experimental]] :!: ^ By [[http://www.ieaa.org/~adrian/|Adrian Sai-wah Tam]] ===== Description ===== I tried out the [[plugin:Blog|Blog]] plugin by Esther Brunner and it is a wonderful product. However, there is one shortcoming: it looks up the data from the change log. I know it is needed for the performance reason. However, if the namespace is small, it is also reasonable to get the list of new files from the file system directly. And, sometimes, I love this way more! So I wrote this plugin. This Plugin get a list of recently changed wiki pages of a given namespace as the [[plugin:Blog|Blog]] plugin does. However, it has the following syntax: {{content>[namespace]?[number[&options[&options..]]]}} [namespace] is a namespace in your wiki; defaults to the top namespace [number] is the number of entries to show; default is 5 [options] is the option applied. Separated by the & character All the three parameters are optional. The valid list of options are: recursive - Include the pages recursively under the namespace showpage - Show the page content, up to the first horizontal rule noshowpage - Do not show the page content, show only the title filesystem - Scan for the recently changed file from the file system changelog - Scan for the recently changed file from the changelog The title that used by the "showpage" or "noshowpage" options are defined as the first ''%%

%%'' enclosed string. Similar to the [[plugin:Blog|Blog]] plugin and table of contents tags will be stripped and below the entry the username and the date of the last change is displayed if "showpage" option is given. If the "noshowpage" option is given, however, the recently changed wiki pages will be shown as unordered lists. With the title, file name, and change date shown. ===== Code ===== Create a directory ''lib/plugins/content/'' and put the following file as ''syntax.php'' to use. */ 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'); define ('DW_DIR_CONTINUE',1); define ('DW_DIR_NS',2); define ('DW_DIR_PAGE',3); // Reverse sort the pages by date (recents first) function _content_cmp_pages($a,$b) { if ($a[date] == $b[date]) { return 0; } return ($a[date] < $b[date]) ? 1 : -1; } /** * All DokuWiki plugins to extend the parser/rendering mechanism * need to inherit from this class */ class syntax_plugin_content extends DokuWiki_Syntax_Plugin { /** * return some info */ function getInfo(){ return array( 'author' => 'Adrian Sai-wha Tam', 'email' => 'adrian@ieaa.org', 'date' => '2005-09-27', 'name' => 'Content Plugin', 'desc' => 'Displays a number of recent entries from a given namespace, from filesystem or changelog', 'url' => 'http://aipl.ie.cuhk.edu.hk/~adrian/doku.php/project:dokuwiki:content', ); } function getType(){ return 'substition'; } function getPType(){ return 'block'; } function getSort(){ return 307; } function connectTo($mode) { $this->Lexer->addSpecialPattern('\{\{content>.+?\}\}',$mode,'plugin_content'); } /** * Handle the match, syntax: content>[namespace][?num[&options[&options..]]] */ function handle($match, $state, $pos, &$handler){ global $conf; $match = substr($match,10,-2); // strip {{content> from start and }} from end list($ns,$options) = explode('?',$match,2); // Processing the options $options = explode('&',$options); $showpage = $conf['content']['showpage']; $scan = $conf['content']['scanmode']; $recursive = (in_array("recursive",$options))?true:false; $showpage = (in_array("showpage",$options))?true:$showpage; $showpage = (in_array("noshowpage",$options))?false:$showpage; $scan = (in_array("filesystem",$options))?true:$scan; $scan = (in_array("changelog",$options))?false:$scan; $num = $options[0]; // Suppose the first option is the number if (!is_numeric($num)){ // if (is_integer($ns)){ if (is_numeric($ns)){ // reset number of returned entries fix $num = $ns; $ns = ''; } else { $num = 5; } } return array($ns,$num,$recursive,$showpage,$scan); } /** * Create output */ function render($mode, &$renderer, $data) { global $conf; global $ID; global $filechain; global $conf; if($mode == 'xhtml'){ if (!isset($filechain)) $filechain[] = $ID; // list here pages which should not be included in the blog $exclude = array('start','sidebar'); $exclude = array_merge($filechain,$exclude); $comments = 'Comments'; // @todo: localize! // prevent caching to ensure the included page is always fresh // $renderer->info['cache'] = FALSE; // without caching it's to slow $num = $data[1]; $recents = ($data[4])? // Scan filesystem or changelog? $this->_get_pages($data[0],$data[2]) : getRecents(0,$num,$data[0], $data[2]?0:RECENTS_SKIP_SUBSPACES ); if ($num > count($recents)) $num = count($recents); if ($num < count($recents)) $recents = array_slice($recents, 0, $num); // show recent using filesystem method fix if (! $data[3]) { // If showpage is not set, the pages are expressed as lists $renderer->doc .= ''; }; return true; } return false; } /** * Convert a normal page ID to a discussion page ID. * * @author Dave Lawson * @author Esther Brunner */ function _addDiscussionNS($id) { global $conf; $dNS = $conf['discussion']['namespace']; if (!$dNS) return false; if ($this->_isDiscussionID($ID)) return $id; $dID = getNS($id); return $dID.($dID ? ':' : '').$dNS.':'.noNS($id);; } /** * Is specified page ID in a discussion namespace? * * @author Dave Lawson */ function _isDiscussionID($id) { global $conf; $dNS = $conf['discussion']['namespace']; $pID = noNS($id); return strpos($id, $dNS.':'.$pID) !== false; } // Check for the type of directory entry // copied from bin/wantedpages.php function _dir_filter($entry, $basepath) { if ($entry == '.' || $entry == '..' ) { return DW_DIR_CONTINUE; } if ( is_dir($basepath . '/' . $entry) ) { if ( strpos($entry, '_') === 0 ) { return DW_DIR_CONTINUE; } return DW_DIR_NS; } if ( preg_match('/\.txt$/',$entry) ) { return DW_DIR_PAGE; } return DW_DIR_CONTINUE; } // Get a list of pages, without sorting // copied from bin/wantedpages.php with modification function _get_pages($dir,$recursive) { global $conf; static $trunclen = NULL; $fullpath = $conf['datadir'].'/'.$dir; if ( !$trunclen ) { global $conf; $trunclen = strlen($conf['datadir'].':'); }; if ( !is_dir($fullpath) ) { echo "Unable to read directory $dir\n"; exit(1); }; $pages = array(); $dh = opendir($fullpath); while ( FALSE !== ( $entry = readdir($dh) ) ) { $status = $this->_dir_filter($entry, $fullpath); if ( $status == DW_DIR_CONTINUE ) { continue; } else if ( $status == DW_DIR_NS ) { if ($recursive) { $pages = array_merge($pages, $this->_get_pages($dir . '/' . $entry,$recursive)); }; } else { $page = array( 'id'=>$this->pathID($dir . '/' . $entry), 'file'=>$dir . '/' . $entry, 'date'=>filemtime($fullpath . '/' . $entry), ); $pages[] = $page; } } closedir($dh); usort($pages,"_content_cmp_pages"); return $pages; } // copied from inc/search.php function pathID($path,$keeptxt=false){ $id = utf8_decodeFN($path); $id = str_replace('/',':',$id); if(!$keeptxt) $id = preg_replace('#\.txt$#','',$id); $id = preg_replace('#^:+#','',$id); $id = preg_replace('#:+$#','',$id); return $id; } } //Setup VIM: ex: et ts=4 enc=utf-8 : ===== Change History ===== * 2005-09-27: * Initial release. * 2006-08-07: * Updated to include the fixes by Markus Aittola and Johannes Zarl. Now works for the most recent release (2006-03-09b) * 2006-08-08: * Minor bug fix: Changed line 104 (getRecents call) to reflect the change in the function prototype in the recent releases. ===== Options ===== After your creation of ''lib/plugins/content/syntax.php'', make sure you include the following lines into ''conf/local.php'' as defaults options: // Content plugin $conf['content']['showpage'] = true; // By default, show the page $conf['content']['scanmode'] = true; // By default, scan the filesystem for the list ===== Discussion ===== A usable plugin, thank you. I think I found a bugs, though, from handling the number of shown entries. It returns the specified number of entries only if you are using changelog option. Fixed that adding following into the render() function: if ($num < count($recents)) $recents = array_slice($recents, 0, $num); Also using is_integer on line 68 (handle() function) always reset the number of returned entries. Using is_numeric worked better. --- //[[markus.aittola@iki.fi|Markus Aittola]] 2005-10-31 09:15 ---// I confirm this bug fix: I changed the line in the script code to use is_numeric in line 68. I modified the code of this page for the fix. --- //[[jf@lalande.nom.fr|JF L.]] ---// ==== Listed inline ==== By default, the plugin list the pages using ul and li. I changed the behaviour of the plugin for an inline list: Modifications: * Line 109: $renderer->doc .= ''; $renderer->doc .= ' '; Maybe it could be of some use to add a parameter to choose between inline or ul/li list... --- //[[jf@lalande.nom.fr|JF L.]] ---// ==== What's the Advantage ==== You said the reason for creating this plugin is to get the //list of new files from the file system directly.// What is the advantage of this?