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