xref: /plugin/ireadit/helper.php (revision 13f6c79932364942534c54835bbbb6b994d388d9)
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 get_approved_revs($id) {
63        try {
64            /** @var \helper_plugin_approve_db $db_helper */
65            $approve_db_helper = plugin_load('helper', 'approve_db');
66            if ($approve_db_helper == null) {
67                msg('You must install approve plugin to use ireadit-approve integration.', -1);
68                return [];
69            }
70            $approve_sqlite = $approve_db_helper->getDB();
71        } catch (Exception $e) {
72            msg($e->getMessage(), -1);
73            return [];
74        }
75
76        $res = $approve_sqlite->query('SELECT rev FROM revision WHERE page=? AND approved IS NOT NULL', $id);
77        return array_map(function ($row) {
78            return (int) $row['rev'];
79        }, $approve_sqlite->res2arr($res));
80    }
81
82    public function user_can_read_page($ireadit_data, $id, $rev, $user) {
83        if ($this->getConf('approve_integration')) { // check if this is newest approve page
84            $last_approved_rev = $this->find_last_approved($id);
85            if ($rev != $last_approved_rev) { // this is not last approved version
86                return false;
87            }
88        } elseif ($rev != p_get_metadata($id, 'last_change date')) { // check if it is last page revision
89            return false;
90        }
91
92        try {
93            /** @var \helper_plugin_ireadit_db $db_helper */
94            $db_helper = plugin_load('helper', 'ireadit_db');
95            $sqlite = $db_helper->getDB();
96        } catch (Exception $e) {
97            msg($e->getMessage(), -1);
98            return false;
99        }
100
101        $res = $sqlite->query('SELECT user, timestamp FROM ireadit
102                                        WHERE page = ?
103                                        AND rev = ?
104                                        ORDER BY timestamp', $id, $rev);
105        $readers = $sqlite->res2arr($res);
106        $users_set = $this->users_set($ireadit_data);
107        return in_array($user, $users_set) && !in_array($user, array_column($readers, 'user'));
108    }
109
110    /**
111     * @param $user NULL means overview mode
112     * @return array
113     */
114    public function get_list($user=NULL) {
115        try {
116            /** @var \helper_plugin_ireadit_db $db_helper */
117            $db_helper = plugin_load('helper', 'ireadit_db');
118            $sqlite = $db_helper->getDB();
119        } catch (Exception $e) {
120            msg($e->getMessage(), -1);
121            return [];
122        }
123
124        $indexer = idx_get_indexer();
125        if ($user) {
126            $current_user_pages = $indexer->lookupKey('ireadit', $user);
127        } else {
128            $current_user_pages = $indexer->getPages('ireadit');
129        }
130
131        $pages = [];
132        if ($this->getConf('approve_integration')) {
133            foreach ($current_user_pages as $page) {
134                $approved_revs = $this->get_approved_revs($page);
135                if (count($approved_revs) == 0) { // page was never approved - don't list it
136                    continue;
137                }
138                $current_rev = max($approved_revs);
139                if ($user) {
140                    $res = $sqlite->query('SELECT rev, timestamp FROM ireadit WHERE user=? AND page=? ORDER BY rev DESC',
141                        $user, $page);
142                } else {
143                    $res = $sqlite->query('SELECT rev, timestamp FROM ireadit WHERE page=? ORDER BY rev DESC', $page);
144                }
145                $user_reads = $sqlite->res2arr($res);
146                $last_read_rev = NULL;
147                $last_read_timestamp = NULL;
148                foreach ($user_reads as $row) {
149                    $rev = (int) $row['rev'];
150                    if (in_array($rev, $approved_revs)) {
151                        $last_read_rev = $rev;
152                        $last_read_timestamp = $row['timestamp'];
153                        break;
154                    }
155                }
156
157                $pages[$page] = [
158                    'current_rev' => $current_rev,
159                    'last_read_rev' => $last_read_rev,
160                    'timestamp' => $last_read_timestamp
161                ];
162            }
163        } else {
164            foreach ($current_user_pages as $page) {
165                $current_rev = p_get_metadata($page, 'last_change date');
166
167                $pages[$page] = [
168                    'current_rev' => $current_rev,
169                    'last_read_rev' => NULL,
170                    'timestamp' => NULL
171                ];
172            }
173            if ($user) {
174                $res = $sqlite->query('SELECT page, MAX(rev) as "rev", timestamp FROM ireadit WHERE user=? GROUP BY page',
175                    $user);
176            } else {
177                $res = $sqlite->query('SELECT page, MAX(rev) as "rev", timestamp FROM ireadit GROUP BY page');
178            }
179            while ($row = $sqlite->res_fetch_assoc($res)) {
180                $page = $row['page'];
181                $rev = (int) $row['rev'];
182                $timestamp = $row['timestamp'];
183                if (isset($pages[$page])) {
184                    $pages[$page]['last_read_rev'] = $rev;
185                    $pages[$page]['timestamp'] = $timestamp;
186                }
187            }
188        }
189
190        // apply states to pages
191        foreach ($pages as &$page) {
192            if ($page['current_rev'] == $page['last_read_rev']) {
193                $page['state'] = 'read';
194            } elseif ($page['last_read_rev'] == NULL) {
195                $page['state'] = 'unread';
196            } else {
197                $page['state'] = 'outdated';
198            }
199        }
200        return $pages;
201    }
202}
203