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