xref: /plugin/publish/helper.php (revision 4e55e2a150e6f7573f375cf59f24812ce94643ec)
1f576111dSAndreas Gohr<?php
2f576111dSAndreas Gohr/**
3f576111dSAndreas Gohr * DokuWiki Plugin publish (Helper 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 */
9f576111dSAndreas Gohr
10f576111dSAndreas Gohr// must be run within Dokuwiki
11f576111dSAndreas Gohrif (!defined('DOKU_INC')) die();
12f576111dSAndreas Gohr
13f576111dSAndreas Gohrclass helper_plugin_publish extends DokuWiki_Plugin {
14f576111dSAndreas Gohr
151794c5faSDominik Eckelmann    private $sortedApprovedRevisions = null;
161794c5faSDominik Eckelmann
17f576111dSAndreas Gohr    // FIXME find out what this is supposed to do and how it can be done better
18f576111dSAndreas Gohr    function in_namespace($valid, $check) {
19f576111dSAndreas Gohr        // PHP apparantly does not have closures -
20f576111dSAndreas Gohr        // so we will parse $valid ourselves. Wasteful.
21f576111dSAndreas Gohr        $valid = preg_split('/\s+/', $valid);
22f576111dSAndreas Gohr        //if(count($valid) == 0) { return true; }//whole wiki matches
23f576111dSAndreas Gohr        if((count($valid)==1) and ($valid[0]=="")) { return true; }//whole wiki matches
24f576111dSAndreas Gohr        $check = trim($check, ':');
25f576111dSAndreas Gohr        $check = explode(':', $check);
26f576111dSAndreas Gohr
27f576111dSAndreas Gohr        // Check against all possible namespaces
28f576111dSAndreas Gohr        foreach($valid as $v) {
29f576111dSAndreas Gohr            $v = explode(':', $v);
30f576111dSAndreas Gohr            $n = 0;
31f576111dSAndreas Gohr            $c = count($v);
32f576111dSAndreas Gohr            $matching = 1;
33f576111dSAndreas Gohr
34f576111dSAndreas Gohr            // Check each element, untill all elements of $v satisfied
35f576111dSAndreas Gohr            while($n < $c) {
36f576111dSAndreas Gohr                if($v[$n] != $check[$n]) {
37f576111dSAndreas Gohr                    // not a match
38f576111dSAndreas Gohr                    $matching = 0;
39f576111dSAndreas Gohr                    break;
40f576111dSAndreas Gohr                }
41f576111dSAndreas Gohr                $n += 1;
42f576111dSAndreas Gohr            }
43f576111dSAndreas Gohr            if($matching == 1) { return true; } // a match
44f576111dSAndreas Gohr        }
45f576111dSAndreas Gohr        return false;
46f576111dSAndreas Gohr    }
47f576111dSAndreas Gohr
48f576111dSAndreas Gohr    // FIXME find out what this is supposed to do and how it can be done better
49f576111dSAndreas Gohr    function in_sub_namespace($valid, $check) {
50f576111dSAndreas Gohr        // is check a dir which contains any valid?
51f576111dSAndreas Gohr        // PHP apparantly does not have closures -
52f576111dSAndreas Gohr        // so we will parse $valid ourselves. Wasteful.
53f576111dSAndreas Gohr        $valid = preg_split('/\s+/', $valid);
54f576111dSAndreas Gohr        //if(count($valid) == 0) { return true; }//whole wiki matches
55f576111dSAndreas Gohr        if((count($valid)==1) and ($valid[0]=="")) { return true; }//whole wiki matches
56f576111dSAndreas Gohr        $check = trim($check, ':');
57f576111dSAndreas Gohr        $check = explode(':', $check);
58f576111dSAndreas Gohr
59f576111dSAndreas Gohr        // Check against all possible namespaces
60f576111dSAndreas Gohr        foreach($valid as $v) {
61f576111dSAndreas Gohr            $v = explode(':', $v);
62f576111dSAndreas Gohr            $n = 0;
63f576111dSAndreas Gohr            $c = count($check); //this is what is different from above!
64f576111dSAndreas Gohr            $matching = 1;
65f576111dSAndreas Gohr
66f576111dSAndreas Gohr            // Check each element, untill all elements of $v satisfied
67f576111dSAndreas Gohr            while($n < $c) {
68f576111dSAndreas Gohr                if($v[$n] != $check[$n]) {
69f576111dSAndreas Gohr                    // not a match
70f576111dSAndreas Gohr                    $matching = 0;
71f576111dSAndreas Gohr                    break;
72f576111dSAndreas Gohr                }
73f576111dSAndreas Gohr                $n += 1;
74f576111dSAndreas Gohr            }
75f576111dSAndreas Gohr            if($matching == 1) { return true; } // a match
76f576111dSAndreas Gohr        }
77f576111dSAndreas Gohr        return false;
78f576111dSAndreas Gohr    }
79f576111dSAndreas Gohr
801794c5faSDominik Eckelmann    function canApprove() {
811794c5faSDominik Eckelmann        global $INFO;
821794c5faSDominik Eckelmann        global $ID;
831794c5faSDominik Eckelmann
841794c5faSDominik Eckelmann        if (!$this->in_namespace($this->getConf('apr_namespaces'), $ID)) {
851794c5faSDominik Eckelmann            return false;
861794c5faSDominik Eckelmann        }
871794c5faSDominik Eckelmann
881794c5faSDominik Eckelmann        return ($INFO['perm'] >= AUTH_DELETE);
891794c5faSDominik Eckelmann    }
901794c5faSDominik Eckelmann
9181e0fa51SDominik Eckelmann    function getRevision($id = null) {
9281e0fa51SDominik Eckelmann        global $REV;
9381e0fa51SDominik Eckelmann        if (isset($REV) && !empty($REV)) {
9481e0fa51SDominik Eckelmann            return $REV;
951794c5faSDominik Eckelmann        }
9681e0fa51SDominik Eckelmann        $meta = $this->getMeta($id);
9781e0fa51SDominik Eckelmann        if (isset($meta['last_change']['date'])) {
9881e0fa51SDominik Eckelmann            return $meta['last_change']['date'];
9981e0fa51SDominik Eckelmann        }
10081e0fa51SDominik Eckelmann        return $meta['date']['modified'];
1011794c5faSDominik Eckelmann    }
1021794c5faSDominik Eckelmann
10314c32fa0SDominik Eckelmann    function getApprovals($id = null) {
10414c32fa0SDominik Eckelmann        $meta = $this->getMeta($id);
10581e0fa51SDominik Eckelmann        if (!isset($meta['approval'])) {
1061794c5faSDominik Eckelmann            return array();
1071794c5faSDominik Eckelmann        }
10881e0fa51SDominik Eckelmann        $approvals = $meta['approval'];
109*4e55e2a1SDominik Eckelmann        if (!is_array($approvals)) {
110*4e55e2a1SDominik Eckelmann            return array();
111*4e55e2a1SDominik Eckelmann        }
1121794c5faSDominik Eckelmann        return $approvals;
1131794c5faSDominik Eckelmann    }
1141794c5faSDominik Eckelmann
11514c32fa0SDominik Eckelmann    function getMeta($id = null) {
11614c32fa0SDominik Eckelmann        global $ID;
11714c32fa0SDominik Eckelmann        if ($id === null || $ID === $id) {
11814c32fa0SDominik Eckelmann            global $INFO;
1191317c887SDominik Eckelmann            $meta = $INFO['meta'];
1201317c887SDominik Eckelmann            $id = $ID;
12114c32fa0SDominik Eckelmann        } else {
1221317c887SDominik Eckelmann            $meta = p_get_metadata($id);
12314c32fa0SDominik Eckelmann        }
1241317c887SDominik Eckelmann
1251317c887SDominik Eckelmann        $this->checkApprovalFormat($meta, $id);
1261317c887SDominik Eckelmann
1271317c887SDominik Eckelmann        return $meta;
1281317c887SDominik Eckelmann    }
1291317c887SDominik Eckelmann
1301317c887SDominik Eckelmann    function checkApprovalFormat($meta, $id) {
1311317c887SDominik Eckelmann        if (isset($meta['approval_version']) && $meta['approval_version'] >= 2) {
1321317c887SDominik Eckelmann            return;
1331317c887SDominik Eckelmann        }
1341317c887SDominik Eckelmann
1351317c887SDominik Eckelmann        if (!$this->hasApprovals($meta)) {
1361317c887SDominik Eckelmann            return;
1371317c887SDominik Eckelmann        }
1381317c887SDominik Eckelmann
1391317c887SDominik Eckelmann        $approvals = $meta['approval'];
1401317c887SDominik Eckelmann        foreach (array_keys($approvals) as $approvedId) {
1411317c887SDominik Eckelmann            $keys = array_keys($approvals[$approvedId]);
1421317c887SDominik Eckelmann
1431317c887SDominik Eckelmann            if (is_array($approvals[$approvedId][$keys[0]])) {
1441317c887SDominik Eckelmann                continue; // current format
1451317c887SDominik Eckelmann            }
1461317c887SDominik Eckelmann
1471317c887SDominik Eckelmann            $newEntry = $approvals[$approvedId];
1481317c887SDominik Eckelmann            if (count($newEntry) !== 3) {
1491317c887SDominik Eckelmann                //continue; // some messed up format...
1501317c887SDominik Eckelmann            }
1511317c887SDominik Eckelmann            $newEntry[] = intval($approvedId); // revision is the time of page edit
1521317c887SDominik Eckelmann
1531317c887SDominik Eckelmann            $approvals[$approvedId] = array();
1541317c887SDominik Eckelmann            $approvals[$approvedId][$newEntry[0]] = $newEntry;
1551317c887SDominik Eckelmann        }
1561317c887SDominik Eckelmann        p_set_metadata($id, array('approval' => $approvals), true, true);
1571317c887SDominik Eckelmann        p_set_metadata($id, array('approval_version' => 2), true, true);
1581317c887SDominik Eckelmann    }
1591317c887SDominik Eckelmann
1601317c887SDominik Eckelmann    function hasApprovals($meta) {
1611317c887SDominik Eckelmann        return isset($meta['approval']) && !empty($meta['approval']);
16214c32fa0SDominik Eckelmann    }
16314c32fa0SDominik Eckelmann
1641794c5faSDominik Eckelmann    function getApprovalsOnRevision($revision) {
1651794c5faSDominik Eckelmann        $approvals = $this->getApprovals();
1661794c5faSDominik Eckelmann
1671794c5faSDominik Eckelmann        if (isset($approvals[$revision])) {
1681794c5faSDominik Eckelmann            return $approvals[$revision];
1691794c5faSDominik Eckelmann        }
1701794c5faSDominik Eckelmann        return array();
1711794c5faSDominik Eckelmann    }
1721794c5faSDominik Eckelmann
1731794c5faSDominik Eckelmann    function getSortedApprovedRevisions() {
1741794c5faSDominik Eckelmann        if ($this->sortedApprovedRevisions === null) {
1751794c5faSDominik Eckelmann            $approvals = $this->getApprovals();
1761794c5faSDominik Eckelmann            krsort($approvals);
1771794c5faSDominik Eckelmann            $this->sortedApprovedRevisions = $approvals;
1781794c5faSDominik Eckelmann        }
1791794c5faSDominik Eckelmann        return $this->sortedApprovedRevisions;
1801794c5faSDominik Eckelmann    }
1811794c5faSDominik Eckelmann
18214c32fa0SDominik Eckelmann    function isRevisionApproved($revision, $id = null) {
18314c32fa0SDominik Eckelmann        $approvals = $this->getApprovals($id);
1841794c5faSDominik Eckelmann        if (!isset($approvals[$revision])) {
1851794c5faSDominik Eckelmann            return false;
1861794c5faSDominik Eckelmann        }
1871794c5faSDominik Eckelmann        return (count($approvals[$revision]) >= $this->getConf('number_of_approved'));
1881794c5faSDominik Eckelmann    }
1891794c5faSDominik Eckelmann
19081e0fa51SDominik Eckelmann    function isCurrentRevisionApproved($id = null) {
19181e0fa51SDominik Eckelmann        return $this->isRevisionApproved($this->getRevision($id), $id);
1921794c5faSDominik Eckelmann    }
1931794c5faSDominik Eckelmann
1941794c5faSDominik Eckelmann    function getLatestApprovedRevision() {
1951794c5faSDominik Eckelmann        $approvals = $this->getSortedApprovedRevisions();
1961794c5faSDominik Eckelmann        foreach ($approvals as $revision => $ignored) {
1971794c5faSDominik Eckelmann            if ($this->isRevisionApproved($revision)) {
1981794c5faSDominik Eckelmann                return $revision;
1991794c5faSDominik Eckelmann            }
2001794c5faSDominik Eckelmann        }
2011794c5faSDominik Eckelmann        return 0;
2021794c5faSDominik Eckelmann    }
2031794c5faSDominik Eckelmann
2041794c5faSDominik Eckelmann    function getLastestRevision() {
2051794c5faSDominik Eckelmann        global $INFO;
2061794c5faSDominik Eckelmann        return $INFO['meta']['date']['modified'];
2071794c5faSDominik Eckelmann    }
2081794c5faSDominik Eckelmann
2091794c5faSDominik Eckelmann    function getApprovalDate() {
2101794c5faSDominik Eckelmann        if (!$this->isCurrentRevisionApproved()) {
2111794c5faSDominik Eckelmann            return -1;
2121794c5faSDominik Eckelmann        }
2131794c5faSDominik Eckelmann
2141794c5faSDominik Eckelmann        $approvals = $this->getApprovalsOnRevision($this->getRevision());
2151794c5faSDominik Eckelmann        uasort($approvals, array(&$this, 'cmpApprovals'));
2161794c5faSDominik Eckelmann        $keys = array_keys($approvals);
2171794c5faSDominik Eckelmann        return $approvals[$keys[$this->getConf('number_of_approved') -1]][3];
2181794c5faSDominik Eckelmann
2191794c5faSDominik Eckelmann    }
2201794c5faSDominik Eckelmann
2211794c5faSDominik Eckelmann    function cmpApprovals($left, $right) {
2221794c5faSDominik Eckelmann        if ($left[3] == $right[3]) {
2231794c5faSDominik Eckelmann            return 0;
2241794c5faSDominik Eckelmann        }
2251794c5faSDominik Eckelmann        return ($left[3] < $right[3]) ? -1 : 1;
2261794c5faSDominik Eckelmann    }
2271794c5faSDominik Eckelmann
2281794c5faSDominik Eckelmann    function getApprovers() {
2291794c5faSDominik Eckelmann        $approvers = $this->getApprovalsOnRevision($this->getRevision());
2301317c887SDominik Eckelmann        if (count($approvers) === 0) {
2311317c887SDominik Eckelmann            return;
2321317c887SDominik Eckelmann        }
2331317c887SDominik Eckelmann
2341794c5faSDominik Eckelmann        $result = array();
2351794c5faSDominik Eckelmann        foreach ($approvers as $approver) {
2361794c5faSDominik Eckelmann            $result[] = editorinfo($this->getApproverName($approver));
2371794c5faSDominik Eckelmann        }
2381794c5faSDominik Eckelmann        return $result;
2391794c5faSDominik Eckelmann    }
2401794c5faSDominik Eckelmann
2411794c5faSDominik Eckelmann    function getApproverName($approver) {
2421794c5faSDominik Eckelmann        if ($approver[1]) {
2431794c5faSDominik Eckelmann            return $approver[1];
2441794c5faSDominik Eckelmann        }
2451794c5faSDominik Eckelmann        if ($approver[2]) {
2461794c5faSDominik Eckelmann            return $approver[2];
2471794c5faSDominik Eckelmann        }
2481794c5faSDominik Eckelmann        return $approver[0];
2491794c5faSDominik Eckelmann    }
2501794c5faSDominik Eckelmann
2511794c5faSDominik Eckelmann    function getPreviousApprovedRevision() {
2521794c5faSDominik Eckelmann        $currentRevision = $this->getRevision();
2531794c5faSDominik Eckelmann        $approvals = $this->getSortedApprovedRevisions();
2541794c5faSDominik Eckelmann        foreach ($approvals as $revision => $ignored) {
2551794c5faSDominik Eckelmann            if ($revision >= $currentRevision) {
2561794c5faSDominik Eckelmann                continue;
2571794c5faSDominik Eckelmann            }
2581794c5faSDominik Eckelmann            if ($this->isRevisionApproved($revision)) {
2591794c5faSDominik Eckelmann                return $revision;
2601794c5faSDominik Eckelmann            }
2611794c5faSDominik Eckelmann        }
2621794c5faSDominik Eckelmann        return 0;
2631794c5faSDominik Eckelmann    }
2641794c5faSDominik Eckelmann
265c2a737a8SDominik Eckelmann    function isHidden() {
266c2a737a8SDominik Eckelmann        global $ID;
267c2a737a8SDominik Eckelmann
268c2a737a8SDominik Eckelmann        if (!$this->getConf('hide drafts')) {
269c2a737a8SDominik Eckelmann            return false;
270c2a737a8SDominik Eckelmann        }
271c2a737a8SDominik Eckelmann
272c2a737a8SDominik Eckelmann        if ($this->getLatestApprovedRevision()) {
273c2a737a8SDominik Eckelmann            return false;
274c2a737a8SDominik Eckelmann        }
2752b00c146SDominik Eckelmann        return true;
2762b00c146SDominik Eckelmann    }
277c2a737a8SDominik Eckelmann
2782b00c146SDominik Eckelmann    function isHiddenForUser() {
2792b00c146SDominik Eckelmann        if (!$this->isHidden()) {
2802b00c146SDominik Eckelmann            return false;
2812b00c146SDominik Eckelmann        }
2822b00c146SDominik Eckelmann
2832b00c146SDominik Eckelmann        global $ID;
284c2a737a8SDominik Eckelmann        $allowedGroups = array_filter(explode(' ', trim($this->getConf('author groups'))));
285c2a737a8SDominik Eckelmann        if (empty($allowedGroups)) {
286c2a737a8SDominik Eckelmann            return auth_quickaclcheck($ID) < AUTH_EDIT;
287c2a737a8SDominik Eckelmann        }
288c2a737a8SDominik Eckelmann
289c2a737a8SDominik Eckelmann        if (!$_SERVER['REMOTE_USER']) {
290c2a737a8SDominik Eckelmann            return true;
291c2a737a8SDominik Eckelmann        }
292c2a737a8SDominik Eckelmann
293c2a737a8SDominik Eckelmann        global $USERINFO;
294c2a737a8SDominik Eckelmann        foreach ($allowedGroups as $allowedGroup) {
295c2a737a8SDominik Eckelmann            $allowedGroup = trim($allowedGroup);
296c2a737a8SDominik Eckelmann            if (in_array($allowedGroup, $USERINFO['grps'])) {
297c2a737a8SDominik Eckelmann                return false;
298c2a737a8SDominik Eckelmann            }
299c2a737a8SDominik Eckelmann        }
300c2a737a8SDominik Eckelmann        return true;
301c2a737a8SDominik Eckelmann    }
302f576111dSAndreas Gohr}
303