xref: /plugin/approve/helper.php (revision 07b13373c9061ad4e017109e3ec97762e7ea5070)
1<?php
2
3// must be run within Dokuwiki
4if (!defined('DOKU_INC')) die();
5class helper_plugin_approve extends DokuWiki_Plugin {
6
7    /** @var helper_plugin_sqlite */
8    protected $sqlite;
9
10    /**
11     * @return helper_plugin_sqlite
12     */
13    protected function sqlite() {
14        if (!$this->sqlite) {
15            /** @var helper_plugin_approve_db $db_helper */
16            $db_helper = plugin_load('helper', 'approve_db');
17            $this->sqlite = $db_helper->getDB();
18        }
19        return $this->sqlite;
20    }
21
22    /**
23     * @return string
24     */
25    public function no_apr_namespace() {
26        //check for config update
27        $key = 'no_apr_namespaces';
28        $res = $this->sqlite()->query('SELECT value FROM config WHERE key=?', $key);
29        $no_apr_namespaces_db = $this->sqlite()->res2single($res);
30        $no_apr_namespaces_conf = $this->getConf($key);
31        //update internal config
32        if ($no_apr_namespaces_db != $no_apr_namespaces_conf) {
33            $this->sqlite()->query('UPDATE config SET value=? WHERE key=?', $no_apr_namespaces_conf, $key);
34
35            $res = $this->sqlite()->query('SELECT page, hidden FROM page');
36            $pages = $this->sqlite()->res2arr($res);
37            foreach ($pages as $page) {
38                $id = $page['page'];
39                $hidden = $page['hidden'];
40                $in_hidden_namespace = $this->in_hidden_namespace($id, $no_apr_namespaces_conf);
41                $new_hidden = $in_hidden_namespace ? '1' : '0';
42
43                if ($hidden != $new_hidden) {
44                    $this->sqlite()->query('UPDATE page SET hidden=? WHERE page=?', $new_hidden, $id);
45                }
46            }
47        }
48
49        return $no_apr_namespaces_conf;
50    }
51
52    /**
53     * @param $id
54     * @param null $approver
55     * @return bool
56     */
57    public function use_approve_here($id, &$approver=null) {
58
59        //check if we should update no_apr_namespace
60        $this->no_apr_namespace();
61
62        $res = $this->sqlite()->query('SELECT page, approver FROM page WHERE page=? AND hidden=0', $id);
63        $row = $this->sqlite()->res2row($res);
64        $approver = $row['approver'];
65        if ($row) {
66            return true;
67        }
68        return false;
69    }
70
71    /**
72     * @param $id
73     * @return bool|string
74     */
75    public function find_last_approved($id) {
76        $res = $this->sqlite()->query('SELECT rev FROM revision
77                                WHERE page=? AND approved IS NOT NULL
78                                ORDER BY rev DESC LIMIT 1', $id);
79        return $this->sqlite()->res2single($res);
80    }
81
82    public function get_hidden_namespaces_list($no_apr_namespaces=null) {
83        if (!$no_apr_namespaces) {
84            $no_apr_namespaces = $this->no_apr_namespace();
85        }
86
87        $no_apr_namespaces_list = preg_split('/\s+/', $no_apr_namespaces,-1,
88            PREG_SPLIT_NO_EMPTY);
89        $no_apr_namespaces_list = array_map(function ($namespace) {
90            return ltrim($namespace, ':');
91        }, $no_apr_namespaces_list);
92
93        return $no_apr_namespaces_list;
94    }
95
96    /**
97     * @param $id
98     * @param null $no_apr_namespaces
99     * @return bool|string
100     */
101    public function in_hidden_namespace($id, $no_apr_namespaces=null) {
102        $no_apr_namespaces_list = $this->get_hidden_namespaces_list($no_apr_namespaces);
103        $id = ltrim($id, ':');
104        foreach ($no_apr_namespaces_list as $namespace) {
105            if (substr($id, 0, strlen($namespace)) == $namespace) {
106                return true;
107            }
108        }
109        return false;
110    }
111
112    /**
113     * @return array
114     */
115    public function weighted_assignments() {
116        $res = $this->sqlite()->query('SELECT id,namespace,approver FROM maintainer');
117        $assignments = $this->sqlite()->res2arr($res);
118
119        $weighted_assignments = [];
120        foreach ($assignments as $assignment) {
121            $ns = $assignment['namespace'];
122            //more general namespaces are overridden by more specific ones.
123            if (substr($ns, -1) == '*') {
124                $weight = substr_count($ns, ':');
125            } else {
126                $weight = PHP_INT_MAX;
127            }
128
129            $assignment['weight'] = $weight;
130            $weighted_assignments[] = $assignment;
131        }
132        array_multisort(array_column($weighted_assignments, 'weight'), $weighted_assignments);
133
134        return $weighted_assignments;
135    }
136
137    /**
138     * @param $id
139     * @param null $pageApprover
140     * @return bool
141     */
142    public function isPageAssigned($id, &$pageApprover=null, $weighted_assignments=null) {
143        if (!$weighted_assignments) {
144            $weighted_assignments = $this->weighted_assignments();
145        }
146        foreach ($weighted_assignments as $assignment) {
147            $ns = ltrim($assignment['namespace'], ':');
148            $approver = $assignment['approver'];
149            if (substr($ns, -2) == '**') {
150                //remove '**'
151                $ns = substr($ns, 0, -2);
152                if (substr($id, 0, strlen($ns)) == $ns) {
153                    $newAssignment = true;
154                    $pageApprover = $approver;
155                }
156            } elseif (substr($ns, -1) == '*') {
157                //remove '*'
158                $ns = substr($ns, 0, -1);
159                $noNS = substr($id, strlen($id));
160                if (strpos($noNS, ':') === FALSE &&
161                    substr($id, 0, strlen($ns)) == $ns) {
162                    $newAssignment = true;
163                    $pageApprover = $approver;
164                }
165            } elseif($id == $ns) {
166                $newAssignment = true;
167                $pageApprover = $approver;
168            }
169        }
170        return $newAssignment;
171    }
172
173    /**
174     * @param $id
175     * @param string $pageApprover
176     * @return bool
177     */
178    public function client_can_approve($id, $pageApprover) {
179        global $INFO;
180        //user not log in
181        if (!isset($INFO['userinfo'])) return false;
182
183        //no approver provided, check if approve plugin apply here
184        if ($pageApprover == $INFO['client']) {
185            return true;
186        } elseif(!$this->getConf('strict_approver') && auth_quickaclcheck($id) >= AUTH_DELETE) {
187            return true;
188        }
189
190        return false;
191    }
192
193    /**
194     * @param $id
195     * @return bool
196     */
197    public function client_can_mark_ready_for_approval($id) {
198        return auth_quickaclcheck($id) >= AUTH_EDIT;
199    }
200
201    /**
202     * @param $id
203     * @return bool
204     */
205    public function client_can_see_drafts($id, $pageApprover=false) {
206        if (auth_quickaclcheck($id) >= AUTH_EDIT) return true;
207        if ($this->client_can_approve($id, $pageApprover)) return true;
208
209        return false;
210    }
211}
212