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