xref: /plugin/ireadit/helper.php (revision 8e64640b884a2b3ebc0b5a2b440fba4bb22ee4b8)
1<?php
2/**
3 * DokuWiki Plugin struct (Helper Component)
4 *
5 * @license GPL 2 http://www.gnu.org/licenses/gpl-2.0.html
6 * @author  Szymon Olewniczak <dokuwiki@cosmocode.de>
7 */
8
9// must be run within Dokuwiki
10if (!defined('DOKU_INC')) {
11    die();
12}
13
14class helper_plugin_ireadit extends DokuWiki_Plugin
15{
16    /**
17     * @param array $users
18     * @param array $groups
19     * @return array
20     */
21    public function users_set($ireadit_data) {
22        global $auth;
23
24        $users = $ireadit_data['users'];
25        $groups = $ireadit_data['groups'];
26        $set = [];
27        if (empty($users) && empty($groups)) {
28            $set = $auth->retrieveUsers();
29        } else {
30            $all_users = $auth->retrieveUsers();
31            foreach ($all_users as $user => $info) {
32                if (in_array($user, $users)) {
33                    $set[$user] = true;
34                } elseif (array_intersect($groups, $info['grps'])) {
35                    $set[$user] = true;
36                }
37            }
38        }
39        return array_keys($set);
40    }
41
42    public function find_last_approved($id) {
43        /** @var helper_plugin_approve $approve_helper */
44        $approve_helper = plugin_load('helper', 'approve');
45        if ($approve_helper == null) {
46            msg('You must install approve plugin to use ireadit-approve integration.', -1);
47            return null;
48        }
49
50        try {
51            /** @var \helper_plugin_approve_db $db_helper */
52            $approve_db_helper = plugin_load('helper', 'approve_db');
53            $approve_sqlite = $approve_db_helper->getDB();
54        } catch (Exception $e) {
55            msg($e->getMessage(), -1);
56            return null;
57        }
58
59        return $approve_helper->find_last_approved($approve_sqlite, $id);
60    }
61
62    public function use_approve_here($id) {
63        /** @var helper_plugin_approve $approve_helper */
64        $approve_helper = plugin_load('helper', 'approve');
65        if ($approve_helper == null) {
66            msg('You must install approve plugin to use ireadit-approve integration.', -1);
67            return null;
68        }
69
70        try {
71            /** @var \helper_plugin_approve_db $db_helper */
72            $approve_db_helper = plugin_load('helper', 'approve_db');
73            $approve_sqlite = $approve_db_helper->getDB();
74        } catch (Exception $e) {
75            msg($e->getMessage(), -1);
76            return null;
77        }
78
79        return $approve_helper->use_approve_here($approve_sqlite, $id);
80    }
81
82    public function get_approved_revs($id) {
83        try {
84            /** @var \helper_plugin_approve_db $db_helper */
85            $approve_db_helper = plugin_load('helper', 'approve_db');
86            if ($approve_db_helper == null) {
87                msg('You must install approve plugin to use ireadit-approve integration.', -1);
88                return [];
89            }
90            $approve_sqlite = $approve_db_helper->getDB();
91        } catch (Exception $e) {
92            msg($e->getMessage(), -1);
93            return [];
94        }
95
96        $res = $approve_sqlite->query('SELECT rev FROM revision WHERE page=? AND approved IS NOT NULL', $id);
97        return array_map(function ($row) {
98            return (int) $row['rev'];
99        }, $approve_sqlite->res2arr($res));
100    }
101
102    public function user_can_read_page($ireadit_data, $id, $rev, $user) {
103        if ($this->getConf('approve_integration') && $this->use_approve_here($id)) { // check if this is newest approve page
104            $last_approved_rev = $this->find_last_approved($id);
105            if ($rev != $last_approved_rev) { // this is not last approved version
106                return false;
107            }
108        } elseif ($rev != p_get_metadata($id, 'last_change date')) { // check if it is last page revision
109            return false;
110        }
111
112        try {
113            /** @var \helper_plugin_ireadit_db $db_helper */
114            $db_helper = plugin_load('helper', 'ireadit_db');
115            $sqlite = $db_helper->getDB();
116        } catch (Exception $e) {
117            msg($e->getMessage(), -1);
118            return false;
119        }
120
121        $res = $sqlite->query('SELECT user, timestamp FROM ireadit
122                                        WHERE page = ?
123                                        AND rev = ?
124                                        ORDER BY timestamp', $id, $rev);
125        $readers = $sqlite->res2arr($res);
126        $users_set = $this->users_set($ireadit_data);
127        return in_array($user, $users_set) && !in_array($user, array_column($readers, 'user'));
128    }
129
130    /**
131     * @param $user NULL means overview mode
132     * @return array
133     */
134    public function get_list($user=NULL) {
135        try {
136            /** @var \helper_plugin_ireadit_db $db_helper */
137            $db_helper = plugin_load('helper', 'ireadit_db');
138            $sqlite = $db_helper->getDB();
139        } catch (Exception $e) {
140            msg($e->getMessage(), -1);
141            return [];
142        }
143
144        $indexer = idx_get_indexer();
145        if ($user) {
146            $current_user_pages = $indexer->lookupKey('ireadit', $user);
147        } else {
148            $current_user_pages = $indexer->getPages('ireadit');
149        }
150
151        $pages = [];
152        foreach ($current_user_pages as $page) {
153            $current_rev = p_get_metadata($page, 'last_change date');
154
155            $pages[$page] = [
156                'current_rev' => $current_rev,
157                'last_read_rev' => NULL,
158                'timestamp' => NULL
159            ];
160        }
161        if ($user) {
162            $res = $sqlite->query('SELECT page, MAX(rev) as "rev", timestamp FROM ireadit WHERE user=? GROUP BY page',
163                $user);
164        } else {
165            $res = $sqlite->query('SELECT page, MAX(rev) as "rev", timestamp FROM ireadit GROUP BY page');
166        }
167        while ($row = $sqlite->res_fetch_assoc($res)) {
168            $page = $row['page'];
169            $rev = (int) $row['rev'];
170            $timestamp = $row['timestamp'];
171            if (isset($pages[$page])) {
172                $pages[$page]['last_read_rev'] = $rev;
173                $pages[$page]['timestamp'] = $timestamp;
174            }
175        }
176
177        if ($this->getConf('approve_integration')) {
178            foreach ($current_user_pages as $page) {
179                if (!$this->use_approve_here($page)) continue; // ignore the pages where approve doesn't apply
180                $approved_revs = $this->get_approved_revs($page);
181                if (count($approved_revs) == 0) unset($pages[$page]); // page was never approved - don't list it
182
183                $current_rev = max($approved_revs);
184                if ($user) {
185                    $res = $sqlite->query('SELECT rev, timestamp FROM ireadit WHERE user=? AND page=? ORDER BY rev DESC',
186                        $user, $page);
187                } else {
188                    $res = $sqlite->query('SELECT rev, timestamp FROM ireadit WHERE page=? ORDER BY rev DESC', $page);
189                }
190                $user_reads = $sqlite->res2arr($res);
191                $last_read_rev = NULL;
192                $last_read_timestamp = NULL;
193                foreach ($user_reads as $row) {
194                    $rev = (int) $row['rev'];
195                    if (in_array($rev, $approved_revs)) {
196                        $last_read_rev = $rev;
197                        $last_read_timestamp = $row['timestamp'];
198                        break;
199                    }
200                }
201
202                $pages[$page] = [
203                    'current_rev' => $current_rev,
204                    'last_read_rev' => $last_read_rev,
205                    'timestamp' => $last_read_timestamp
206                ]; // override default values
207            }
208        }
209
210        // apply states to pages
211        foreach ($pages as &$page) {
212            if ($page['current_rev'] == $page['last_read_rev']) {
213                $page['state'] = 'read';
214            } elseif ($page['last_read_rev'] == NULL) {
215                $page['state'] = 'unread';
216            } else {
217                $page['state'] = 'outdated';
218            }
219        }
220        return $pages;
221    }
222}
223