1<?php 2 3use dokuwiki\plugin\approve\meta\ApproveConst; 4use dokuwiki\plugin\approve\meta\PageSearch; 5 6// must be run within DokuWiki 7if(!defined('DOKU_INC')) die(); 8 9 10class syntax_plugin_approve_table extends DokuWiki_Syntax_Plugin { 11 12 protected $states = []; 13 14 public function __construct() { 15 $this->states = [$this->getConf('sum approved'), 16 $this->getConf('sum ready for approval'), 17 $this->getConf('sum draft')]; 18 } 19 20 function getType() { 21 return 'substition'; 22 } 23 24 function getSort() { 25 return 20; 26 } 27 28 function PType() { 29 return 'block'; 30 } 31 32 function connectTo($mode) { 33 $this->Lexer->addSpecialPattern('----+ *approve table *-+\n.*?----+', $mode,'plugin_approve_table'); 34 } 35 36 function handle($match, $state, $pos, Doku_Handler $handler){ 37 $lines = explode("\n", $match); 38 array_shift($lines); 39 array_pop($lines); 40 41 $params = []; 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 $value = array_map('ucfirst', $value); 54 foreach ($value as $state) { 55 if (!in_array($state, $this->states)) { 56 msg('approve plugin: unknown state "'.$state.'" should be: ' . 57 implode(', ', $this->states), -1); 58 return false; 59 } 60 } 61 } elseif($key == 'filter' && preg_match($value, null) === false) { 62 msg('approve plugin: invalid filter regex', -1); 63 return false; 64 } elseif ($key == 'summarize') { 65 $value = $value == '0' ? false : true; 66 } 67 $params[$key] = $value; 68 } 69 return $params; 70 } 71 72 function render($mode, Doku_Renderer $renderer, $params) { 73 global $conf; 74 75 if ($mode != 'xhtml') return false; 76 if ($params === false) return false; 77 78 $pageSearch = new PageSearch(); 79 80 $defaults = [ 81 'namespace' => '', 82 'filter' => false, 83 'states' => $this->states, 84 'summarize' => true, 85 ]; 86 87 $params = array_replace($defaults, $params); 88 89 $namespace = cleanID(getNS($params['namespace'] . ":*")); 90 91 $pages = $pageSearch->getPagesFromNamespace($namespace, $params['filter'], $params['states']); 92 93 usort($pages, array($pageSearch, 'pageSorter')); 94 95 // Output Table 96 $renderer->doc .= '<table><tr>'; 97 $renderer->doc .= '<th>' . $this->getLang('hdr_page') . '</th>'; 98 $renderer->doc .= '<th>' . $this->getLang('hdr_state') . '</th>'; 99 $renderer->doc .= '<th>' . $this->getLang('hdr_updated') . '</th>'; 100 $renderer->doc .= '</tr>'; 101 102 103 $all_approved = 0; 104 $all_approved_ready = 0; 105 $all = 0; 106 107 $working_ns = null; 108 foreach($pages as $page) { 109 // $page: 0 -> pagename, 1 -> true -> approved else false, 2 -> last changed date 110 $this_ns = getNS($page[0]); 111 112 if($this_ns != $working_ns) { 113 $name_ns = $this_ns; 114 if($this_ns == '') { $name_ns = 'root'; } 115 $renderer->doc .= '<tr><td colspan="3"><a href="'; 116 $renderer->doc .= wl($this_ns . ':' . $this->getConf('start')); 117 $renderer->doc .= '">'; 118 $renderer->doc .= $name_ns; 119 $renderer->doc .= '</a> '; 120 $renderer->doc .= '</td></tr>'; 121 $working_ns = $this_ns; 122 } 123 124 $updated = '<a href="' . wl($page[0]) . '">' . dformat($page[2]) . '</a>'; 125 126 $class = 'plugin__approve_red'; 127 $state = $this->getLang('draft'); 128 $all += 1; 129 130 if ($page[1] === 'approved') { 131 $class = 'plugin__approve_green'; 132 $state = $this->getLang('approved'); 133 $all_approved += 1; 134 } elseif ($page[1] === 'ready for approval' && $this->getConf('ready_for_approval') === 1) { 135 $class = 'plugin__approve_ready'; 136 $state = $this->getLang('marked_approve_ready'); 137 $all_approved_ready += 1; 138 } 139 140 $renderer->doc .= '<tr class="'.$class.'">'; 141 $renderer->doc .= '<td><a href="'; 142 $renderer->doc .= wl($page[0]); 143 $renderer->doc .= '">'; 144 if ($conf['useheading'] === '1') { 145 $heading = p_get_first_heading($page[0]); 146 if ($heading != '') { 147 $renderer->doc .= $heading; 148 } else { 149 $renderer->doc .= $page[0]; 150 } 151 152 } else { 153 $renderer->doc .= $page[0]; 154 } 155 156 $renderer->doc .= '</a></td><td>'; 157 $renderer->doc .= '<strong>'.$state. '</strong> '. $this->getLang('by'). ' ' . $page[4]; 158 $renderer->doc .= '</td><td>'; 159 $renderer->doc .= $updated; 160 $renderer->doc .= '</td></tr>'; 161 } 162 163 if ($params['summarize']) { 164 if($this->getConf('ready_for_approval') === 1) { 165 $renderer->doc .= '<tr><td><strong>'; 166 $renderer->doc .= $this->getLang('all_approved_ready'); 167 $renderer->doc .= '</strong></td>'; 168 169 $renderer->doc .= '<td colspan="2">'; 170 $percent = 0; 171 if($all > 0) { 172 $percent = $all_approved_ready * 100 / $all; 173 } 174 $renderer->doc .= $all_approved_ready . ' / ' . $all . sprintf(" (%.0f%%)", $percent); 175 $renderer->doc .= '</td></tr>'; 176 } 177 178 $renderer->doc .= '<tr><td><strong>'; 179 $renderer->doc .= $this->getLang('all_approved'); 180 $renderer->doc .= '</strong></td>'; 181 182 $renderer->doc .= '<td colspan="2">'; 183 $percent = 0; 184 if($all > 0) { 185 $percent = $all_approved * 100 / $all; 186 } 187 $renderer->doc .= $all_approved . ' / ' . $all . sprintf(" (%.0f%%)", $percent); 188 $renderer->doc .= '</td></tr>'; 189 } 190 191 $renderer->doc .= '</table>'; 192 return true; 193 } 194} 195