xref: /plugin/approve/syntax/table.php (revision 99eaf3e2f5892270345af3865c95e0c55f3cc762)
1b81b1128SSzymon Olewniczak<?php
2b81b1128SSzymon Olewniczak
3b81b1128SSzymon Olewniczakuse dokuwiki\plugin\approve\meta\ApproveConst;
4b81b1128SSzymon Olewniczak
5b81b1128SSzymon Olewniczak// must be run within DokuWiki
6b81b1128SSzymon Olewniczakif(!defined('DOKU_INC')) die();
7b81b1128SSzymon Olewniczak
8b81b1128SSzymon Olewniczak
9b81b1128SSzymon Olewniczakclass syntax_plugin_approve_table extends DokuWiki_Syntax_Plugin {
10b81b1128SSzymon Olewniczak
11*99eaf3e2SSzymon Olewniczak    protected $states = [];
12*99eaf3e2SSzymon Olewniczak
13*99eaf3e2SSzymon Olewniczak    public function __construct() {
14*99eaf3e2SSzymon Olewniczak        $this->states = [$this->getConf('sum approved'),
15*99eaf3e2SSzymon Olewniczak                         $this->getConf('sum ready for approval'),
16*99eaf3e2SSzymon Olewniczak                         $this->getConf('sum draft')];
17*99eaf3e2SSzymon Olewniczak    }
18b81b1128SSzymon Olewniczak
19b81b1128SSzymon Olewniczak    function getType() {
20b81b1128SSzymon Olewniczak        return 'substition';
21b81b1128SSzymon Olewniczak    }
22b81b1128SSzymon Olewniczak
23b81b1128SSzymon Olewniczak    function getSort() {
24b81b1128SSzymon Olewniczak        return 20;
25b81b1128SSzymon Olewniczak    }
26b81b1128SSzymon Olewniczak
27b81b1128SSzymon Olewniczak    function PType() {
28b81b1128SSzymon Olewniczak        return 'block';
29b81b1128SSzymon Olewniczak    }
30b81b1128SSzymon Olewniczak
31b81b1128SSzymon Olewniczak    function connectTo($mode) {
32b81b1128SSzymon Olewniczak        $this->Lexer->addSpecialPattern('----+ *approve table *-+\n.*?----+', $mode,'plugin_approve_table');
33b81b1128SSzymon Olewniczak    }
34b81b1128SSzymon Olewniczak
35b81b1128SSzymon Olewniczak    function handle($match, $state, $pos, Doku_Handler $handler){
36b81b1128SSzymon Olewniczak        $lines = explode("\n", $match);
37b81b1128SSzymon Olewniczak        array_shift($lines);
38b81b1128SSzymon Olewniczak        array_pop($lines);
39b81b1128SSzymon Olewniczak
40b81b1128SSzymon Olewniczak        $params = [];
41b81b1128SSzymon Olewniczak        foreach ($lines as $line) {
42b81b1128SSzymon Olewniczak            $pair = explode(':', $line, 2);
43b81b1128SSzymon Olewniczak            if (count($pair) < 2) {
44b81b1128SSzymon Olewniczak                continue;
45b81b1128SSzymon Olewniczak            }
46b81b1128SSzymon Olewniczak            $key = trim($pair[0]);
47b81b1128SSzymon Olewniczak            $value = trim($pair[1]);
48b81b1128SSzymon Olewniczak            if ($key == 'states') {
49b81b1128SSzymon Olewniczak                $value = array_map('trim', explode(',', $value));
50b81b1128SSzymon Olewniczak                //normalize
51b81b1128SSzymon Olewniczak                $value = array_map('strtolower', $value);
52b81b1128SSzymon Olewniczak                $value = array_map('ucfirst', $value);
53b81b1128SSzymon Olewniczak                foreach ($value as $state) {
54*99eaf3e2SSzymon Olewniczak                    if (!in_array($state, $this->states)) {
55b81b1128SSzymon Olewniczak                        msg('approve plugin: unknown state "'.$state.'" should be: ' .
56*99eaf3e2SSzymon Olewniczak                            implode(', ', $this->states), -1);
57b81b1128SSzymon Olewniczak                        return false;
58b81b1128SSzymon Olewniczak                    }
59b81b1128SSzymon Olewniczak                }
60b81b1128SSzymon Olewniczak            } elseif($key == 'filter' && preg_match($value, null) === false) {
61b81b1128SSzymon Olewniczak                msg('approve plugin: invalid filter regex', -1);
62b81b1128SSzymon Olewniczak                return false;
635f33cda2SSzymon Olewniczak            } elseif ($key == 'summarize') {
645f33cda2SSzymon Olewniczak                $value = $value == '0' ? false : true;
65b81b1128SSzymon Olewniczak            }
66b81b1128SSzymon Olewniczak            $params[$key] = $value;
67b81b1128SSzymon Olewniczak        }
68b81b1128SSzymon Olewniczak        return $params;
69b81b1128SSzymon Olewniczak    }
70b81b1128SSzymon Olewniczak
71b81b1128SSzymon Olewniczak    function render($mode, Doku_Renderer $renderer, $params) {
72b81b1128SSzymon Olewniczak        global $conf;
73b81b1128SSzymon Olewniczak
74b81b1128SSzymon Olewniczak        if ($mode != 'xhtml') return false;
75b81b1128SSzymon Olewniczak        if ($params === false) return false;
76b81b1128SSzymon Olewniczak
77b81b1128SSzymon Olewniczak        $defaults = [
78b81b1128SSzymon Olewniczak            'namespace' => '',
79b81b1128SSzymon Olewniczak            'filter' => false,
80*99eaf3e2SSzymon Olewniczak            'states' => $this->states,
815f33cda2SSzymon Olewniczak            'summarize' => true,
82b81b1128SSzymon Olewniczak        ];
83b81b1128SSzymon Olewniczak
84b81b1128SSzymon Olewniczak        $params = array_replace($defaults, $params);
85b81b1128SSzymon Olewniczak
86b81b1128SSzymon Olewniczak        $namespace = cleanID(getNS($params['namespace'] . ":*"));
87b81b1128SSzymon Olewniczak
88b81b1128SSzymon Olewniczak        $pages = $this->_getPagesFromNamespace($namespace, $params['filter'], $params['states']);
89b81b1128SSzymon Olewniczak
90b81b1128SSzymon Olewniczak        usort($pages, array($this,'_pagesorter'));
91b81b1128SSzymon Olewniczak
92b81b1128SSzymon Olewniczak        // Output Table
93b81b1128SSzymon Olewniczak        $renderer->doc .= '<table><tr>';
94b81b1128SSzymon Olewniczak        $renderer->doc .= '<th>' . $this->getLang('hdr_page') . '</th>';
95b81b1128SSzymon Olewniczak        $renderer->doc .= '<th>' . $this->getLang('hdr_state') . '</th>';
96b81b1128SSzymon Olewniczak        $renderer->doc .= '<th>' . $this->getLang('hdr_updated') . '</th>';
97b81b1128SSzymon Olewniczak        $renderer->doc .= '</tr>';
98b81b1128SSzymon Olewniczak
99b81b1128SSzymon Olewniczak
100b81b1128SSzymon Olewniczak        $all_approved = 0;
101b81b1128SSzymon Olewniczak        $all_approved_ready = 0;
102b81b1128SSzymon Olewniczak        $all = 0;
103b81b1128SSzymon Olewniczak
104b81b1128SSzymon Olewniczak        $working_ns = null;
105b81b1128SSzymon Olewniczak        foreach($pages as $page) {
106b81b1128SSzymon Olewniczak            // $page: 0 -> pagename, 1 -> true -> approved else false, 2 -> last changed date
107b81b1128SSzymon Olewniczak            $this_ns = getNS($page[0]);
108b81b1128SSzymon Olewniczak
109b81b1128SSzymon Olewniczak            if($this_ns != $working_ns) {
110b81b1128SSzymon Olewniczak                $name_ns = $this_ns;
111b81b1128SSzymon Olewniczak                if($this_ns == '') { $name_ns = 'root'; }
112b81b1128SSzymon Olewniczak                $renderer->doc .= '<tr><td colspan="3"><a href="';
113b81b1128SSzymon Olewniczak                $renderer->doc .= wl($this_ns . ':' . $this->getConf('start'));
114b81b1128SSzymon Olewniczak                $renderer->doc .= '">';
115b81b1128SSzymon Olewniczak                $renderer->doc .= $name_ns;
116b81b1128SSzymon Olewniczak                $renderer->doc .= '</a> ';
117b81b1128SSzymon Olewniczak                $renderer->doc .= '</td></tr>';
118b81b1128SSzymon Olewniczak                $working_ns = $this_ns;
119b81b1128SSzymon Olewniczak            }
120b81b1128SSzymon Olewniczak
121b81b1128SSzymon Olewniczak            $updated = '<a href="' . wl($page[0]) . '">' . dformat($page[2]) . '</a>';
122b81b1128SSzymon Olewniczak
123b81b1128SSzymon Olewniczak            $class = 'plugin__approve_red';
124b81b1128SSzymon Olewniczak            $state = $this->getLang('draft');
125b81b1128SSzymon Olewniczak            $all += 1;
126b81b1128SSzymon Olewniczak
127b81b1128SSzymon Olewniczak            if ($page[1] === 'approved') {
128b81b1128SSzymon Olewniczak                $class = 'plugin__approve_green';
129b81b1128SSzymon Olewniczak                $state = $this->getLang('approved');
130b81b1128SSzymon Olewniczak                $all_approved += 1;
131b81b1128SSzymon Olewniczak            } elseif ($page[1] === 'ready for approval' && $this->getConf('ready_for_approval') === 1) {
132b81b1128SSzymon Olewniczak                $class = 'plugin__approve_ready';
133b81b1128SSzymon Olewniczak                $state = $this->getLang('marked_approve_ready');
134b81b1128SSzymon Olewniczak                $all_approved_ready += 1;
135b81b1128SSzymon Olewniczak            }
136b81b1128SSzymon Olewniczak
137b81b1128SSzymon Olewniczak            $renderer->doc .= '<tr class="'.$class.'">';
138b81b1128SSzymon Olewniczak            $renderer->doc .= '<td><a href="';
139b81b1128SSzymon Olewniczak            $renderer->doc .= wl($page[0]);
140b81b1128SSzymon Olewniczak            $renderer->doc .= '">';
141b81b1128SSzymon Olewniczak            if ($conf['useheading'] === '1') {
142b81b1128SSzymon Olewniczak                $heading = p_get_first_heading($page[0]);
143b81b1128SSzymon Olewniczak                if ($heading != '') {
144b81b1128SSzymon Olewniczak                    $renderer->doc .= $heading;
145b81b1128SSzymon Olewniczak                } else {
146b81b1128SSzymon Olewniczak                    $renderer->doc .= $page[0];
147b81b1128SSzymon Olewniczak                }
148b81b1128SSzymon Olewniczak
149b81b1128SSzymon Olewniczak            } else {
150b81b1128SSzymon Olewniczak                $renderer->doc .= $page[0];
151b81b1128SSzymon Olewniczak            }
152b81b1128SSzymon Olewniczak
153b81b1128SSzymon Olewniczak            $renderer->doc .= '</a></td><td>';
154b81b1128SSzymon Olewniczak            $renderer->doc .= '<strong>'.$state. '</strong> '. $this->getLang('by'). ' ' . $page[4];
155b81b1128SSzymon Olewniczak            $renderer->doc .= '</td><td>';
156b81b1128SSzymon Olewniczak            $renderer->doc .= $updated;
157b81b1128SSzymon Olewniczak            $renderer->doc .= '</td></tr>';
158b81b1128SSzymon Olewniczak        }
159b81b1128SSzymon Olewniczak
1605f33cda2SSzymon Olewniczak        if ($params['summarize']) {
161b81b1128SSzymon Olewniczak            if($this->getConf('ready_for_approval') === 1) {
162b81b1128SSzymon Olewniczak                $renderer->doc .= '<tr><td><strong>';
163b81b1128SSzymon Olewniczak                $renderer->doc .= $this->getLang('all_approved_ready');
164b81b1128SSzymon Olewniczak                $renderer->doc .= '</strong></td>';
165b81b1128SSzymon Olewniczak
166b81b1128SSzymon Olewniczak                $renderer->doc .= '<td colspan="2">';
167b81b1128SSzymon Olewniczak                $percent       = 0;
168b81b1128SSzymon Olewniczak                if($all > 0) {
169b81b1128SSzymon Olewniczak                    $percent = $all_approved_ready * 100 / $all;
170b81b1128SSzymon Olewniczak                }
171b81b1128SSzymon Olewniczak                $renderer->doc .= $all_approved_ready . ' / ' . $all . sprintf(" (%.0f%%)", $percent);
172b81b1128SSzymon Olewniczak                $renderer->doc .= '</td></tr>';
173b81b1128SSzymon Olewniczak            }
174b81b1128SSzymon Olewniczak
175b81b1128SSzymon Olewniczak            $renderer->doc .= '<tr><td><strong>';
176b81b1128SSzymon Olewniczak            $renderer->doc .= $this->getLang('all_approved');
177b81b1128SSzymon Olewniczak            $renderer->doc .= '</strong></td>';
178b81b1128SSzymon Olewniczak
179b81b1128SSzymon Olewniczak            $renderer->doc .= '<td colspan="2">';
180b81b1128SSzymon Olewniczak            $percent       = 0;
181b81b1128SSzymon Olewniczak            if($all > 0) {
182b81b1128SSzymon Olewniczak                $percent = $all_approved * 100 / $all;
183b81b1128SSzymon Olewniczak            }
184b81b1128SSzymon Olewniczak            $renderer->doc .= $all_approved . ' / ' . $all . sprintf(" (%.0f%%)", $percent);
185b81b1128SSzymon Olewniczak            $renderer->doc .= '</td></tr>';
1865f33cda2SSzymon Olewniczak        }
187b81b1128SSzymon Olewniczak
188b81b1128SSzymon Olewniczak        $renderer->doc .= '</table>';
189b81b1128SSzymon Olewniczak        return true;
190b81b1128SSzymon Olewniczak    }
191b81b1128SSzymon Olewniczak
192b81b1128SSzymon Olewniczak    function _search_helper(&$data, $base, $file, $type, $lvl, $opts) {
193b81b1128SSzymon Olewniczak        global $lang;
194b81b1128SSzymon Olewniczak
195b81b1128SSzymon Olewniczak        $ns = $opts[0];
196b81b1128SSzymon Olewniczak        $invalid_ns = $opts[1];
197b81b1128SSzymon Olewniczak        $page_regex = $opts[2];
198b81b1128SSzymon Olewniczak        $states = $opts[3];
199b81b1128SSzymon Olewniczak
200b81b1128SSzymon Olewniczak        if ($type == 'd') {
201b81b1128SSzymon Olewniczak            return true;
202b81b1128SSzymon Olewniczak        }
203b81b1128SSzymon Olewniczak
204b81b1128SSzymon Olewniczak        if (!preg_match('#\.txt$#', $file)) {
205b81b1128SSzymon Olewniczak            return false;
206b81b1128SSzymon Olewniczak        }
207b81b1128SSzymon Olewniczak
208b81b1128SSzymon Olewniczak        $id = pathID($ns . $file);
209b81b1128SSzymon Olewniczak        if (!empty($invalid_ns) && $this->hlp->in_namespace($invalid_ns, $id)) {
210b81b1128SSzymon Olewniczak            return false;
211b81b1128SSzymon Olewniczak        }
212b81b1128SSzymon Olewniczak
213b81b1128SSzymon Olewniczak        //check page_regex
214b81b1128SSzymon Olewniczak        if ($page_regex && !preg_match($page_regex, $id)) {
215b81b1128SSzymon Olewniczak            return false;
216b81b1128SSzymon Olewniczak        }
217b81b1128SSzymon Olewniczak
218b81b1128SSzymon Olewniczak        //check states
219b81b1128SSzymon Olewniczak
220b81b1128SSzymon Olewniczak
221b81b1128SSzymon Olewniczak        $meta = p_get_metadata($id);
222b81b1128SSzymon Olewniczak
223b81b1128SSzymon Olewniczak
224b81b1128SSzymon Olewniczak        //check states
225b81b1128SSzymon Olewniczak        $sum = $meta['last_change']['sum'];
226*99eaf3e2SSzymon Olewniczak        if ($sum == $this->getConf('sum approved') && !in_array($this->getConf('sum approved'), $states)) {
227b81b1128SSzymon Olewniczak            return false;
228b81b1128SSzymon Olewniczak        }
229b81b1128SSzymon Olewniczak
230*99eaf3e2SSzymon Olewniczak        if ($sum == $this->getConf('sum ready for approval') &&
231*99eaf3e2SSzymon Olewniczak            !in_array($this->getConf('sum ready for approval'), $states)) {
232b81b1128SSzymon Olewniczak            return false;
233b81b1128SSzymon Olewniczak        }
234b81b1128SSzymon Olewniczak
235*99eaf3e2SSzymon Olewniczak        if ($sum != $this->getConf('sum approved') &&
236*99eaf3e2SSzymon Olewniczak            $sum != $this->getConf('sum ready for approval') &&
237*99eaf3e2SSzymon Olewniczak            !in_array($this->getConf('sum draft'), $states)) {
238b81b1128SSzymon Olewniczak            return false;
239b81b1128SSzymon Olewniczak        }
240b81b1128SSzymon Olewniczak
241b81b1128SSzymon Olewniczak        $date = $meta['date']['modified'];
242*99eaf3e2SSzymon Olewniczak        if (isset($meta['last_change']) && $meta['last_change']['sum'] === $this->getConf('sum approved')) {
243b81b1128SSzymon Olewniczak            $approved = 'approved';
244*99eaf3e2SSzymon Olewniczak        } elseif (isset($meta['last_change']) && $meta['last_change']['sum'] === $this->getConf('sum ready for approval')) {
245b81b1128SSzymon Olewniczak            $approved = 'ready for approval';
246b81b1128SSzymon Olewniczak        } else {
247b81b1128SSzymon Olewniczak            $approved = 'not approved';
248b81b1128SSzymon Olewniczak        }
249b81b1128SSzymon Olewniczak
250b81b1128SSzymon Olewniczak        if (isset($meta['last_change'])) {
251b81b1128SSzymon Olewniczak            $user = $meta['last_change']['user'];
252b81b1128SSzymon Olewniczak
253b81b1128SSzymon Olewniczak            if (isset($meta['contributor'][$user])) {
254b81b1128SSzymon Olewniczak                $full_name = $meta['contributor'][$user];
255b81b1128SSzymon Olewniczak            } else {
256b81b1128SSzymon Olewniczak                $full_name = $meta['creator'];
257b81b1128SSzymon Olewniczak            }
258b81b1128SSzymon Olewniczak        } else {
259b81b1128SSzymon Olewniczak            $user = '';
260b81b1128SSzymon Olewniczak            $full_name = '('.$lang['external_edit'].')';
261b81b1128SSzymon Olewniczak        }
262b81b1128SSzymon Olewniczak
263b81b1128SSzymon Olewniczak
264b81b1128SSzymon Olewniczak        $data[] = array($id, $approved, $date, $user, $full_name);
265b81b1128SSzymon Olewniczak
266b81b1128SSzymon Olewniczak        return false;
267b81b1128SSzymon Olewniczak    }
268b81b1128SSzymon Olewniczak
269b81b1128SSzymon Olewniczak    function _getPagesFromNamespace($namespace, $page_regex=false, $states=[]) {
270b81b1128SSzymon Olewniczak        global $conf;
271b81b1128SSzymon Olewniczak        $dir = $conf['datadir'] . '/' . str_replace(':', '/', $namespace);
272b81b1128SSzymon Olewniczak        $pages = array();
273b81b1128SSzymon Olewniczak        search($pages, $dir, array($this,'_search_helper'),
274b81b1128SSzymon Olewniczak               array($namespace, $this->getConf('no_apr_namespaces'), $page_regex, $states));
275b81b1128SSzymon Olewniczak
276b81b1128SSzymon Olewniczak        return $pages;
277b81b1128SSzymon Olewniczak    }
278b81b1128SSzymon Olewniczak
279b81b1128SSzymon Olewniczak
280b81b1128SSzymon Olewniczak
281b81b1128SSzymon Olewniczak    /**
282b81b1128SSzymon Olewniczak     * Custom sort callback
283b81b1128SSzymon Olewniczak     */
284b81b1128SSzymon Olewniczak    function _pagesorter($a, $b){
285b81b1128SSzymon Olewniczak        $ac = explode(':',$a[0]);
286b81b1128SSzymon Olewniczak        $bc = explode(':',$b[0]);
287b81b1128SSzymon Olewniczak        $an = count($ac);
288b81b1128SSzymon Olewniczak        $bn = count($bc);
289b81b1128SSzymon Olewniczak
290b81b1128SSzymon Olewniczak        // Same number of elements, can just string sort
291b81b1128SSzymon Olewniczak        if($an == $bn) { return strcmp($a[0], $b[0]); }
292b81b1128SSzymon Olewniczak
293b81b1128SSzymon Olewniczak        // For each level:
294b81b1128SSzymon Olewniczak        // If this is not the last element in either list:
295b81b1128SSzymon Olewniczak        //   same -> continue
296b81b1128SSzymon Olewniczak        //   otherwise strcmp
297b81b1128SSzymon Olewniczak        // If this is the last element in either list, it wins
298b81b1128SSzymon Olewniczak        $n = 0;
299b81b1128SSzymon Olewniczak        while(true) {
300b81b1128SSzymon Olewniczak            if($n + 1 == $an) { return -1; }
301b81b1128SSzymon Olewniczak            if($n + 1 == $bn) { return 1; }
302b81b1128SSzymon Olewniczak            $s = strcmp($ac[$n], $bc[$n]);
303b81b1128SSzymon Olewniczak            if($s != 0) { return $s; }
304b81b1128SSzymon Olewniczak            $n += 1;
305b81b1128SSzymon Olewniczak        }
306b81b1128SSzymon Olewniczak    }
307b81b1128SSzymon Olewniczak
308b81b1128SSzymon Olewniczak}
309