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' => '%' 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 $q = "SELECT page.page, page.maintainer, revision.rev, revision.approved, revision.approved_by, 133 revision.ready_for_approval, revision.ready_for_approval_by, 134 LENGTH(page.page) - LENGTH(REPLACE(page.page, ':', '')) AS colons 135 FROM page INNER JOIN revision ON page.page = revision.page 136 WHERE page.hidden = 0 AND revision.current=1 AND page.page LIKE ? ESCAPE '_' 137 AND page.maintainer LIKE ? 138 ORDER BY colons, page.page"; 139 $res = $sqlite->query($q, $params['namespace'].'%', $params['maintainer']); 140 $pages = $sqlite->res2arr($res); 141 142 // Output Table 143 $renderer->doc .= '<table><tr>'; 144 $renderer->doc .= '<th>' . $this->getLang('hdr_page') . '</th>'; 145 $renderer->doc .= '<th>' . $this->getLang('hdr_state') . '</th>'; 146 $renderer->doc .= '<th>' . $this->getLang('hdr_updated') . '</th>'; 147 $renderer->doc .= '<th>' . $this->getLang('hdr_maintainer') . '</th>'; 148 $renderer->doc .= '</tr>'; 149 150 151 $all_approved = 0; 152 $all_approved_ready = 0; 153 $all = 0; 154 155 $curNS = ''; 156 foreach($pages as $page) { 157 $id = $page['page']; 158 $maintainer = $page['maintainer']; 159 $rev = $page['rev']; 160 $approved = strtotime($page['approved']); 161 $approved_by = $page['approved_by']; 162 $ready_for_approval = strtotime($page['ready_for_approval']); 163 $ready_for_approval_by = $page['ready_for_approval_by']; 164 165 $pageNS = getNS($id); 166 167 if($pageNS != '' && $pageNS != $curNS) { 168 $curNS = $pageNS; 169 170 $renderer->doc .= '<tr><td colspan="4"><a href="'; 171 $renderer->doc .= wl($curNS); 172 $renderer->doc .= '">'; 173 $renderer->doc .= $curNS; 174 $renderer->doc .= '</a> '; 175 $renderer->doc .= '</td></tr>'; 176 } 177 178 $all += 1; 179 if ($approved) { 180 $class = 'plugin__approve_green'; 181 $state = $this->getLang('approved'); 182 $date = $approved; 183 $by = $approved_by; 184 185 $all_approved += 1; 186 } elseif ($this->getConf('ready_for_approval') && $ready_for_approval) { 187 $class = 'plugin__approve_ready'; 188 $state = $this->getLang('marked_approve_ready'); 189 $date = $ready_for_approval; 190 $by = $ready_for_approval_by; 191 192 $all_approved_ready += 1; 193 } else { 194 $class = 'plugin__approve_red'; 195 $state = $this->getLang('draft'); 196 $date = $rev; 197 $by = p_get_metadata($id, 'last_change user'); 198 } 199 200 $renderer->doc .= '<tr class="'.$class.'">'; 201 $renderer->doc .= '<td><a href="'; 202 $renderer->doc .= wl($id); 203 $renderer->doc .= '">'; 204 if ($conf['useheading'] == '1') { 205 $heading = p_get_first_heading($id); 206 if ($heading != '') { 207 $renderer->doc .= $heading; 208 } else { 209 $renderer->doc .= $id; 210 } 211 } else { 212 $renderer->doc .= $id; 213 } 214 215 $renderer->doc .= '</a></td><td>'; 216 $renderer->doc .= '<strong>'.$state. '</strong> '; 217 218 $user = $auth->getUserData($by); 219 if ($user) { 220 $renderer->doc .= $this->getLang('by'). ' ' . $user['name']; 221 } 222 $renderer->doc .= '</td><td>'; 223 $renderer->doc .= '<a href="' . wl($id) . '">' . dformat($date) . '</a>';; 224 $renderer->doc .= '</td><td>'; 225 if ($maintainer) { 226 $user = $auth->getUserData($maintainer); 227 if ($user) { 228 $renderer->doc .= $user['name']; 229 } else { 230 $renderer->doc .= $maintainer; 231 } 232 } else { 233 $renderer->doc .= '---'; 234 } 235 $renderer->doc .= '</td></tr>'; 236 } 237 238 if ($params['summarize']) { 239 if($this->getConf('ready_for_approval')) { 240 $renderer->doc .= '<tr><td><strong>'; 241 $renderer->doc .= $this->getLang('all_approved_ready'); 242 $renderer->doc .= '</strong></td>'; 243 244 $renderer->doc .= '<td colspan="3">'; 245 $percent = 0; 246 if($all > 0) { 247 $percent = $all_approved_ready * 100 / $all; 248 } 249 $renderer->doc .= $all_approved_ready . ' / ' . $all . sprintf(" (%.0f%%)", $percent); 250 $renderer->doc .= '</td></tr>'; 251 } 252 253 $renderer->doc .= '<tr><td><strong>'; 254 $renderer->doc .= $this->getLang('all_approved'); 255 $renderer->doc .= '</strong></td>'; 256 257 $renderer->doc .= '<td colspan="3">'; 258 $percent = 0; 259 if($all > 0) { 260 $percent = $all_approved * 100 / $all; 261 } 262 $renderer->doc .= $all_approved . ' / ' . $all . sprintf(" (%.0f%%)", $percent); 263 $renderer->doc .= '</td></tr>'; 264 } 265 266 $renderer->doc .= '</table>'; 267 } 268} 269