1 2<?php 3/** 4 * Discussion Plugin, threads component: displays a list of recently active discussions 5 * 6 * @license GPL 2 (http://www.gnu.org/licenses/gpl.html) 7 * @author Esther Brunner <wikidesign@gmail.com> 8 */ 9 10// must be run within Dokuwiki 11if(!defined('DOKU_INC')) die(); 12 13/** 14 * Class syntax_plugin_discussion_threads 15 */ 16class syntax_plugin_discussion_threads extends DokuWiki_Syntax_Plugin { 17 18 /** 19 * Syntax Type 20 * 21 * @return string 22 */ 23 function getType() { return 'substition'; } 24 25 /** 26 * Paragraph Type 27 * 28 * @see Doku_Handler_Block 29 * @return string 30 */ 31 function getPType() { return 'block'; } 32 33 /** 34 * Sort for applying this mode 35 * 36 * @return int 37 */ 38 function getSort() { return 306; } 39 40 /** 41 * @param string $mode 42 */ 43 function connectTo($mode) { 44 $this->Lexer->addSpecialPattern('\{\{threads>.+?\}\}', $mode, 'plugin_discussion_threads'); 45 } 46 47 /** 48 * Handler to prepare matched data for the rendering process 49 * 50 * @param string $match The text matched by the patterns 51 * @param int $state The lexer state for the match 52 * @param int $pos The character position of the matched text 53 * @param Doku_Handler $handler The Doku_Handler object 54 * @return array Return an array with all data you want to use in render 55 */ 56 function handle($match, $state, $pos, Doku_Handler $handler) { 57 global $ID; 58 $customFlags = array(); 59 60 $match = substr($match, 10, -2); // strip {{threads> from start and }} from end 61 list($match, $flags) = explode('&', $match, 2); 62 $flags = explode('&', $flags); 63 64 // Identify the count/skipempty flag and remove it before passing it to pagelist 65 foreach($flags as $key => $flag) { 66 if (substr($flag, 0, 5) == "count") { 67 $tmp = explode('=', $flag); 68 $customFlags['count'] = $tmp[1]; 69 unset($flags[$key]); 70 } elseif (substr($flag, 0, 9) == "skipempty") { 71 $customFlags['skipempty'] = true; 72 unset($flags[$key]); 73 } elseif (substr($flag, 0, 15) == "nonewthreadform") { 74 $customFlags['nonewthreadform'] = true; 75 unset($flags[$key]); 76 } 77 } 78 79 // Ignore params if invalid values have been passed 80 if(!array_key_exists('count', $customFlags) || $customFlags['count'] <= 0 || !is_numeric($customFlags['count'])) $customFlags['count'] = false; 81 if(!array_key_exists('skipempty', $customFlags) && !$customFlags['skipempty']) $customFlags['skipempty'] = false; 82 83 list($ns, $refine) = explode(' ', $match, 2); 84 85 if (($ns == '*') || ($ns == ':')) $ns = ''; 86 elseif ($ns == '.') $ns = getNS($ID); 87 else $ns = cleanID($ns); 88 89 return array($ns, $flags, $refine, $customFlags); 90 } 91 92 /** 93 * Handles the actual output creation. 94 * 95 * @param $mode string output format being rendered 96 * @param $renderer Doku_Renderer the current renderer object 97 * @param $data array data created by handler() 98 * @return boolean rendered correctly? 99 */ 100 function render($mode, Doku_Renderer $renderer, $data) { 101 list($ns, $flags, $refine, $customFlags) = $data; 102 $count = $customFlags['count']; 103 $skipEmpty = $customFlags['skipempty']; 104 $noNewThreadForm = $customFlags['nonewthreadform']; 105 $i = 0; 106 107 $pages = array(); 108 /** @var helper_plugin_discussion $my */ 109 if ($my =& plugin_load('helper', 'discussion')) $pages = $my->getThreads($ns, null, $skipEmpty); 110 111 // use tag refinements? 112 if ($refine) { 113 /** @var helper_plugin_tag $tag */ 114 if (plugin_isdisabled('tag') || (!$tag = plugin_load('helper', 'tag'))) { 115 msg('The Tag Plugin must be installed to use tag refinements.', -1); 116 } else { 117 $pages = $tag->tagRefine($pages, $refine); 118 } 119 } 120 121 if (!$pages) { 122 if ((auth_quickaclcheck($ns.':*') >= AUTH_CREATE) && ($mode == 'xhtml')) { 123 $renderer->info['cache'] = false; 124 if ($noNewThreadForm !== true) { 125 $renderer->doc .= $this->_newThreadForm($ns); 126 } 127 } 128 return true; // nothing to display 129 } 130 131 if ($mode == 'xhtml') { 132 /** @var $renderer Doku_Renderer_xhtml */ 133 // prevent caching to ensure content is always fresh 134 $renderer->info['cache'] = false; 135 136 // show form to start a new discussion thread? 137 if ($noNewThreadForm !== true) { 138 $perm_create = (auth_quickaclcheck($ns.':*') >= AUTH_CREATE); 139 if ($perm_create && ($this->getConf('threads_formposition') == 'top')) { 140 $renderer->doc .= $this->_newThreadForm($ns); 141 } 142 } 143 144 // let Pagelist Plugin do the work for us 145 /** @var $pagelist helper_plugin_pagelist */ 146 if (plugin_isdisabled('pagelist') 147 || (!$pagelist =& plugin_load('helper', 'pagelist'))) { 148 msg('The Pagelist Plugin must be installed for threads lists to work.', -1); 149 return false; 150 } 151 $pagelist->column['comments'] = true; 152 $pagelist->setFlags($flags); 153 $pagelist->startList(); 154 foreach ($pages as $page) { 155 $page['class'] = 'discussion_status'.$page['status']; 156 $pagelist->addPage($page); 157 158 $i++; 159 if($count != false && $i >= $count) break; // Only display the n discussion threads specified by the count flag 160 } 161 $renderer->doc .= $pagelist->finishList(); 162 163 // show form to start a new discussion thread? 164 if ($noNewThreadForm !== true) { 165 if ($perm_create && ($this->getConf('threads_formposition') == 'bottom')) { 166 $renderer->doc .= $this->_newThreadForm($ns); 167 } 168 } 169 170 return true; 171 172 // for metadata renderer 173 } elseif ($mode == 'metadata') { 174 /** @var $renderer Doku_Renderer_metadata */ 175 foreach ($pages as $page) { 176 $renderer->meta['relation']['references'][$page['id']] = true; 177 } 178 179 return true; 180 } 181 return false; 182 } 183 184 /* ---------- (X)HTML Output Functions ---------- */ 185 186 /** 187 * Show the form to start a new discussion thread 188 * 189 * @param string $ns 190 * @return string 191 */ 192 function _newThreadForm($ns) { 193 global $ID; 194 global $lang; 195 196 return '<div class="newthread_form">'.DOKU_LF. 197 '<form id="discussion__newthread_form" method="post" action="'.script().'" accept-charset="'.$lang['encoding'].'">'.DOKU_LF. 198 DOKU_TAB.'<fieldset>'.DOKU_LF. 199 DOKU_TAB.DOKU_TAB.'<legend> '.$this->getLang('newthread').': </legend>'.DOKU_LF. 200 DOKU_TAB.DOKU_TAB.'<input type="hidden" name="id" value="'.$ID.'" />'.DOKU_LF. 201 DOKU_TAB.DOKU_TAB.'<input type="hidden" name="do" value="newthread" />'.DOKU_LF. 202 DOKU_TAB.DOKU_TAB.'<input type="hidden" name="ns" value="'.$ns.'" />'.DOKU_LF. 203 DOKU_TAB.DOKU_TAB.'<input class="edit" type="text" name="title" id="discussion__newthread_title" size="40" tabindex="1" />'.DOKU_LF. 204 DOKU_TAB.DOKU_TAB.'<input class="button" type="submit" value="'.$lang['btn_create'].'" tabindex="2" />'.DOKU_LF. 205 DOKU_TAB.'</fieldset>'.DOKU_LF. 206 '</form>'.DOKU_LF. 207 '</div>'.DOKU_LF; 208 } 209} 210// vim:ts=4:sw=4:et:enc=utf-8: 211