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