xref: /plugin/publish/syntax.php (revision f576111d5af49277c97c42826e00d53e6dd22713)
1ff9bc75fSJarrod Lowe<?php
2*f576111dSAndreas Gohr/**
3*f576111dSAndreas Gohr * DokuWiki Plugin publish (Syntax Component)
4*f576111dSAndreas Gohr *
5*f576111dSAndreas Gohr * @license GPL 2 http://www.gnu.org/licenses/gpl-2.0.html
6*f576111dSAndreas Gohr * @author  Jarrod Lowe <dokuwiki@rrod.net>
7*f576111dSAndreas Gohr * @author  Andreas Gohr <gohr@cosmocode.de>
8*f576111dSAndreas Gohr */
9ff9bc75fSJarrod Lowe
10ff9bc75fSJarrod Lowe
11ff9bc75fSJarrod Lowe// must be run within DokuWiki
12ff9bc75fSJarrod Loweif(!defined('DOKU_INC')) die();
13ff9bc75fSJarrod Lowe
14ff9bc75fSJarrod Lowe
15ff9bc75fSJarrod Loweclass syntax_plugin_publish extends DokuWiki_Syntax_Plugin {
16*f576111dSAndreas Gohr    private $hlp;
17ff9bc75fSJarrod Lowe
18*f576111dSAndreas Gohr    function syntax_plugin_publish(){
19*f576111dSAndreas Gohr        $this->hlp = plugin_load('helper','publish');
20*f576111dSAndreas Gohr    }
21ff9bc75fSJarrod Lowe
22ff9bc75fSJarrod Lowe    function pattern() { return '\[APPROVALS.*?\]'; }
23ff9bc75fSJarrod Lowe    function getType() { return 'substition'; }
24ff9bc75fSJarrod Lowe    function getSort() { return 20; }
25ff9bc75fSJarrod Lowe    function PType() { return 'block'; }
26ff9bc75fSJarrod Lowe    function connectTo($mode) { $this->Lexer->addSpecialPattern($this->pattern(),$mode,'plugin_publish'); }
27ff9bc75fSJarrod Lowe    function handle($match, $state, $pos, &$handler){
28ff9bc75fSJarrod Lowe        $namespace = substr($match, 11, -1);
29ff9bc75fSJarrod Lowe        return array($match, $state, $pos, $namespace);
30ff9bc75fSJarrod Lowe    }
31ff9bc75fSJarrod Lowe
32ff9bc75fSJarrod Lowe    function render($mode, &$renderer, $data) {
33ff9bc75fSJarrod Lowe        global $conf;
34ff9bc75fSJarrod Lowe
35ff9bc75fSJarrod Lowe        if($mode == 'xhtml'){
36*f576111dSAndreas Gohr            $ns = cleanID(getNS($data[3] . ":*"));
37ff9bc75fSJarrod Lowe            $dir = $conf['datadir'] . '/' . str_replace(':', '/', $ns);
38ff9bc75fSJarrod Lowe            $pages = array();
39*f576111dSAndreas Gohr            search($pages, $dir, array($this,'search_helper'), array($ns, $this->getConf('apr_namespaces')));
40ff9bc75fSJarrod Lowe            if(count($pages) == 0) {
41ff9bc75fSJarrod Lowe                $renderer->doc .= '<p class="apr_none">' . $this->getLang('apr_p_none') . '</p>';
42ff9bc75fSJarrod Lowe                return true;
43ff9bc75fSJarrod Lowe            }
44*f576111dSAndreas Gohr            usort($pages, array($this,'_pagesorter'));
45ff9bc75fSJarrod Lowe
46*f576111dSAndreas Gohr            // Output Table
47ff9bc75fSJarrod Lowe            $renderer->doc .= '<table class="apr_table"><tr class="apr_head">';
48ff9bc75fSJarrod Lowe            $renderer->doc .= '<th class="apr_page">' . $this->getLang('apr_p_hdr_page') . '</th>';
49ff9bc75fSJarrod Lowe            $renderer->doc .= '<th class="apr_prev">' . $this->getLang('apr_p_hdr_previous') . '</th>';
50ff9bc75fSJarrod Lowe            $renderer->doc .= '<th class="apr_upd">' . $this->getLang('apr_p_hdr_updated') . '</th>';
51ff9bc75fSJarrod Lowe            $renderer->doc .= '</tr>';
52ff9bc75fSJarrod Lowe            $working_ns = null;
53ff9bc75fSJarrod Lowe            foreach($pages as $page) {
54*f576111dSAndreas Gohr                // $page: 0 -> pagename, 1 -> approval metadata, 2 -> last changed date
55ff9bc75fSJarrod Lowe                $this_ns = getNS($page[0]);
56ff9bc75fSJarrod Lowe                if($this_ns != $working_ns) {
57ff9bc75fSJarrod Lowe                    $name_ns = $this_ns;
58ff9bc75fSJarrod Lowe                    if($this_ns == '') { $name_ns = 'root'; }
59ff9bc75fSJarrod Lowe                    $renderer->doc .= '<tr class="apr_ns"><td colspan="3"><a href="';
60ff9bc75fSJarrod Lowe                    $renderer->doc .= wl($this_ns . ':' . $this->getConf('start'));
61ff9bc75fSJarrod Lowe                    $renderer->doc .= '">';
62ff9bc75fSJarrod Lowe                    $renderer->doc .= $name_ns;
63ff9bc75fSJarrod Lowe                    $renderer->doc .= '</a></td></tr>';
64ff9bc75fSJarrod Lowe                    $working_ns = $this_ns;
65ff9bc75fSJarrod Lowe                }
66ff9bc75fSJarrod Lowe                $updated = '<a href="' . wl($page[0]) . '">' . date('d/m/Y H:i', $page[2]) . '</a>';
67ff9bc75fSJarrod Lowe                if($page[1] == null || count($page[1]) == 0) {
68*f576111dSAndreas Gohr                    // Has never been approved
69ff9bc75fSJarrod Lowe                    $approved = '';
70ff9bc75fSJarrod Lowe                }else{
71ff9bc75fSJarrod Lowe                    $keys = array_keys($page[1]);
72ff9bc75fSJarrod Lowe                    sort($keys);
73ff9bc75fSJarrod Lowe                    $last = $keys[count($keys)-1];
74ff9bc75fSJarrod Lowe                    $approved .= sprintf($this->getLang('apr_p_approved'),
75ff9bc75fSJarrod Lowe                            $page[1][$last][1],
76ff9bc75fSJarrod Lowe                            wl($page[0], 'rev=' . $last),
77ff9bc75fSJarrod Lowe                            date('d/m/Y H:i', $last));
78ff9bc75fSJarrod Lowe                    if($last == $page[2]) { $updated = 'Unchanged'; } //shouldn't be possible:
79ff9bc75fSJarrod Lowe                    //the search_helper should have
80ff9bc75fSJarrod Lowe                    //excluded this
81ff9bc75fSJarrod Lowe                }
82ff9bc75fSJarrod Lowe
83ff9bc75fSJarrod Lowe                $renderer->doc .= '<tr class="apr_table';
84ff9bc75fSJarrod Lowe                if($approved == '') { $renderer->doc .= ' apr_never'; }
85ff9bc75fSJarrod Lowe                $renderer->doc .= '"><td class="apr_page"><a href="';
86ff9bc75fSJarrod Lowe                $renderer->doc .= wl($page[0]);
87ff9bc75fSJarrod Lowe                $renderer->doc .= '">';
88ff9bc75fSJarrod Lowe                $renderer->doc .= $page[0];
89ff9bc75fSJarrod Lowe                $renderer->doc .= '</a></td><td class="apr_prev">';
90ff9bc75fSJarrod Lowe                $renderer->doc .= $approved;
91ff9bc75fSJarrod Lowe                $renderer->doc .= '</td><td class="apr_upd">';
92ff9bc75fSJarrod Lowe                $renderer->doc .= $updated;
93ff9bc75fSJarrod Lowe                $renderer->doc .= '</td></tr>';
94ff9bc75fSJarrod Lowe
95*f576111dSAndreas Gohr                //$renderer->doc .= '<tr><td colspan="3">' . print_r($page, true) . '</td></tr>';
96ff9bc75fSJarrod Lowe            }
97ff9bc75fSJarrod Lowe            $renderer->doc .= '</table>';
98ff9bc75fSJarrod Lowe            return true;
99ff9bc75fSJarrod Lowe        }
100ff9bc75fSJarrod Lowe        return false;
101ff9bc75fSJarrod Lowe    }
102ff9bc75fSJarrod Lowe
103*f576111dSAndreas Gohr    /**
104*f576111dSAndreas Gohr     * search callback function
105*f576111dSAndreas Gohr     *
106*f576111dSAndreas Gohr     * filter out pages which can't be approved by the current user
107*f576111dSAndreas Gohr     * then check if they need approving
108*f576111dSAndreas Gohr     */
109*f576111dSAndreas Gohr    function _search_helper(&$data, $base, $file, $type, $lvl, $opts) {
110*f576111dSAndreas Gohr        $ns = $opts[0];
111*f576111dSAndreas Gohr        $valid_ns = $opts[1];
112*f576111dSAndreas Gohr        if($type == 'd') { return $this->hlp->in_sub_namespace($valid_ns, $ns . ':' . str_replace('/', ':', $file)); }
113*f576111dSAndreas Gohr        if(!preg_match('#\.txt$#', $file)) { return false; }
114*f576111dSAndreas Gohr        $id = pathID($ns . $file);
115*f576111dSAndreas Gohr        if(!in_namespace($valid_ns, $id)) { return false; }
116*f576111dSAndreas Gohr        if(auth_quickaclcheck($id) < AUTH_DELETE) { return false; } //insufficent permissions
117*f576111dSAndreas Gohr        $meta = p_get_metadata($id);
118*f576111dSAndreas Gohr        if($meta['approval'][$meta['last_change']['date']]) {
119*f576111dSAndreas Gohr            // Already approved
120*f576111dSAndreas Gohr            return false;
121*f576111dSAndreas Gohr        }
122*f576111dSAndreas Gohr        $data[] = array($id, $meta['approval'], $meta['last_change']['date']);
123*f576111dSAndreas Gohr        return false;
124*f576111dSAndreas Gohr    }
125*f576111dSAndreas Gohr
126*f576111dSAndreas Gohr    /**
127*f576111dSAndreas Gohr     * Custom sort callback
128*f576111dSAndreas Gohr     */
129*f576111dSAndreas Gohr    function _pagesorter($a, $b){
130*f576111dSAndreas Gohr        $ac = explode(':',$a[0]);
131*f576111dSAndreas Gohr        $bc = explode(':',$b[0]);
132*f576111dSAndreas Gohr        $an = count($ac);
133*f576111dSAndreas Gohr        $bn = count($bc);
134*f576111dSAndreas Gohr
135*f576111dSAndreas Gohr        // Same number of elements, can just string sort
136*f576111dSAndreas Gohr        if($an == $bn) { return strcmp($a[0], $b[0]); }
137*f576111dSAndreas Gohr
138*f576111dSAndreas Gohr        // For each level:
139*f576111dSAndreas Gohr        // If this is not the last element in either list:
140*f576111dSAndreas Gohr        //   same -> continue
141*f576111dSAndreas Gohr        //   otherwise strcmp
142*f576111dSAndreas Gohr        // If this is the last element in either list, it wins
143*f576111dSAndreas Gohr        $n = 0;
144*f576111dSAndreas Gohr        while(true) {
145*f576111dSAndreas Gohr            if($n + 1 == $an) { return -1; }
146*f576111dSAndreas Gohr            if($n + 1 == $bn) { return 1; }
147*f576111dSAndreas Gohr            $s = strcmp($ac[$n], $bc[$n]);
148*f576111dSAndreas Gohr            if($s != 0) { return $s; }
149*f576111dSAndreas Gohr            $n += 1;
150*f576111dSAndreas Gohr        }
151*f576111dSAndreas Gohr    }
152ff9bc75fSJarrod Lowe
153ff9bc75fSJarrod Lowe
154ff9bc75fSJarrod Lowe}
155ff9bc75fSJarrod Lowe
156