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