1<?php 2 3// must be run within DokuWiki 4if(!defined('DOKU_INC')) die(); 5 6 7class syntax_plugin_approve_table extends DokuWiki_Syntax_Plugin { 8 9 protected $states = ['approved', 'draft', 'ready for approval']; 10// 11// public function __construct() { 12// $this->states = [$this->getConf('sum approved'), 13// $this->getConf('sum ready for approval'), 14// $this->getConf('sum draft')]; 15// } 16 17 function getType() { 18 return 'substition'; 19 } 20 21 function getSort() { 22 return 20; 23 } 24 25 function PType() { 26 return 'block'; 27 } 28 29 function connectTo($mode) { 30 $this->Lexer->addSpecialPattern('----+ *approve table *-+\n.*?----+', $mode,'plugin_approve_table'); 31 } 32 33 function handle($match, $state, $pos, Doku_Handler $handler){ 34 $lines = explode("\n", $match); 35 array_shift($lines); 36 array_pop($lines); 37 38 $params = [ 39 'namespace' => '', 40 'filter' => false, 41 'states' => $this->states, 42 'summarize' => true, 43 'maintainer' => null 44 ]; 45 46 foreach ($lines as $line) { 47 $pair = explode(':', $line, 2); 48 if (count($pair) < 2) { 49 continue; 50 } 51 $key = trim($pair[0]); 52 $value = trim($pair[1]); 53 if ($key == 'states') { 54 $value = array_map('trim', explode(',', $value)); 55 //normalize 56 $value = array_map('strtolower', $value); 57 $value = array_map('ucfirst', $value); 58 foreach ($value as $state) { 59 if (!in_array($state, $this->states)) { 60 msg('approve plugin: unknown state "'.$state.'" should be: ' . 61 implode(', ', $this->states), -1); 62 return false; 63 } 64 } 65 } elseif($key == 'filter' && preg_match($value, null) === false) { 66 msg('approve plugin: invalid filter regex', -1); 67 return false; 68 } elseif ($key == 'summarize') { 69 $value = $value == '0' ? false : true; 70 } elseif ($key == 'namespace') { 71 $value = trim(cleanID($value), ':'); 72 } 73 $params[$key] = $value; 74 } 75 return $params; 76 } 77 78 /** 79 * Render xhtml output or metadata 80 * 81 * @param string $mode Renderer mode (supported modes: xhtml) 82 * @param Doku_Renderer $renderer The renderer 83 * @param array $data The data from the handler() function 84 * 85 * @return bool If rendering was successful. 86 */ 87 88 public function render($mode, Doku_Renderer $renderer, $data) 89 { 90 $method = 'render' . ucfirst($mode); 91 if (method_exists($this, $method)) { 92 call_user_func([$this, $method], $renderer, $data); 93 return true; 94 } 95 return false; 96 } 97 98 /** 99 * Render metadata 100 * 101 * @param Doku_Renderer $renderer The renderer 102 * @param array $data The data from the handler() function 103 */ 104 public function renderMetadata(Doku_Renderer $renderer, $params) 105 { 106 $plugin_name = $this->getPluginName(); 107 $renderer->meta['plugin'][$plugin_name] = []; 108 109 if ($params['maintainer'] == '$USER$') { 110 $renderer->meta['plugin'][$plugin_name]['dynamic_maintainer'] = true; 111 } 112 113 $renderer->meta['plugin'][$plugin_name]['approve_table'] = true; 114 } 115 116 public function renderXhtml(Doku_Renderer $renderer, $params) 117 { 118 global $INFO; 119 120 global $conf; 121 /** @var DokuWiki_Auth_Plugin $auth */ 122 global $auth; 123 124 /** @var \helper_plugin_ireadit_db $db_helper */ 125 $db_helper = plugin_load('helper', 'approve_db'); 126 $sqlite = $db_helper->getDB(); 127 128 if ($params['maintainer'] == '$USER$') { 129 $params['maintainer'] = $INFO['client']; 130 } 131 132 $maintainer_query = ''; 133 $query_args = [$params['namespace'].'%']; 134 if ($params['maintainer']) { 135 $maintainer_query = "AND page.maintainer LIKE ?"; 136 $query_args[] = $params['maintainer']; 137 } 138 139 $q = "SELECT page.page, page.maintainer, revision.rev, revision.approved, revision.approved_by, 140 revision.ready_for_approval, revision.ready_for_approval_by, 141 LENGTH(page.page) - LENGTH(REPLACE(page.page, ':', '')) AS colons 142 FROM page INNER JOIN revision ON page.page = revision.page 143 WHERE page.hidden = 0 AND revision.current=1 AND page.page LIKE ? ESCAPE '_' 144 $maintainer_query 145 ORDER BY colons, page.page"; 146 147 $res = $sqlite->query($q, $query_args); 148 $pages = $sqlite->res2arr($res); 149 150 // Output Table 151 $renderer->doc .= '<table><tr>'; 152 $renderer->doc .= '<th>' . $this->getLang('hdr_page') . '</th>'; 153 $renderer->doc .= '<th>' . $this->getLang('hdr_state') . '</th>'; 154 $renderer->doc .= '<th>' . $this->getLang('hdr_updated') . '</th>'; 155 $renderer->doc .= '<th>' . $this->getLang('hdr_maintainer') . '</th>'; 156 $renderer->doc .= '</tr>'; 157 158 159 $all_approved = 0; 160 $all_approved_ready = 0; 161 $all = 0; 162 163 $curNS = ''; 164 foreach($pages as $page) { 165 $id = $page['page']; 166 $maintainer = $page['maintainer']; 167 $rev = $page['rev']; 168 $approved = strtotime($page['approved']); 169 $approved_by = $page['approved_by']; 170 $ready_for_approval = strtotime($page['ready_for_approval']); 171 $ready_for_approval_by = $page['ready_for_approval_by']; 172 173 $pageNS = getNS($id); 174 175 if($pageNS != '' && $pageNS != $curNS) { 176 $curNS = $pageNS; 177 178 $renderer->doc .= '<tr><td colspan="4"><a href="'; 179 $renderer->doc .= wl($curNS); 180 $renderer->doc .= '">'; 181 $renderer->doc .= $curNS; 182 $renderer->doc .= '</a> '; 183 $renderer->doc .= '</td></tr>'; 184 } 185 186 $all += 1; 187 if ($approved) { 188 $class = 'plugin__approve_green'; 189 $state = $this->getLang('approved'); 190 $date = $approved; 191 $by = $approved_by; 192 193 $all_approved += 1; 194 } elseif ($this->getConf('ready_for_approval') && $ready_for_approval) { 195 $class = 'plugin__approve_ready'; 196 $state = $this->getLang('marked_approve_ready'); 197 $date = $ready_for_approval; 198 $by = $ready_for_approval_by; 199 200 $all_approved_ready += 1; 201 } else { 202 $class = 'plugin__approve_red'; 203 $state = $this->getLang('draft'); 204 $date = $rev; 205 $by = p_get_metadata($id, 'last_change user'); 206 } 207 208 $renderer->doc .= '<tr class="'.$class.'">'; 209 $renderer->doc .= '<td><a href="'; 210 $renderer->doc .= wl($id); 211 $renderer->doc .= '">'; 212 if ($conf['useheading'] == '1') { 213 $heading = p_get_first_heading($id); 214 if ($heading != '') { 215 $renderer->doc .= $heading; 216 } else { 217 $renderer->doc .= $id; 218 } 219 } else { 220 $renderer->doc .= $id; 221 } 222 223 $renderer->doc .= '</a></td><td>'; 224 $renderer->doc .= '<strong>'.$state. '</strong> '; 225 226 $user = $auth->getUserData($by); 227 if ($user) { 228 $renderer->doc .= $this->getLang('by'). ' ' . $user['name']; 229 } 230 $renderer->doc .= '</td><td>'; 231 $renderer->doc .= '<a href="' . wl($id) . '">' . dformat($date) . '</a>';; 232 $renderer->doc .= '</td><td>'; 233 if ($maintainer) { 234 $user = $auth->getUserData($maintainer); 235 if ($user) { 236 $renderer->doc .= $user['name']; 237 } else { 238 $renderer->doc .= $maintainer; 239 } 240 } else { 241 $renderer->doc .= '---'; 242 } 243 $renderer->doc .= '</td></tr>'; 244 } 245 246 if ($params['summarize']) { 247 if($this->getConf('ready_for_approval')) { 248 $renderer->doc .= '<tr><td><strong>'; 249 $renderer->doc .= $this->getLang('all_approved_ready'); 250 $renderer->doc .= '</strong></td>'; 251 252 $renderer->doc .= '<td colspan="3">'; 253 $percent = 0; 254 if($all > 0) { 255 $percent = $all_approved_ready * 100 / $all; 256 } 257 $renderer->doc .= $all_approved_ready . ' / ' . $all . sprintf(" (%.0f%%)", $percent); 258 $renderer->doc .= '</td></tr>'; 259 } 260 261 $renderer->doc .= '<tr><td><strong>'; 262 $renderer->doc .= $this->getLang('all_approved'); 263 $renderer->doc .= '</strong></td>'; 264 265 $renderer->doc .= '<td colspan="3">'; 266 $percent = 0; 267 if($all > 0) { 268 $percent = $all_approved * 100 / $all; 269 } 270 $renderer->doc .= $all_approved . ' / ' . $all . sprintf(" (%.0f%%)", $percent); 271 $renderer->doc .= '</td></tr>'; 272 } 273 274 $renderer->doc .= '</table>'; 275 } 276} 277