1<?php
2// must be run within DokuWiki
3if (!defined('DOKU_INC')) die();
4
5/**
6 * All DokuWiki plugins to extend the parser/rendering mechanism
7 * need to inherit from this class
8 */
9class action_plugin_ireadit_ireadit extends DokuWiki_Action_Plugin
10{
11    public function register(Doku_Event_Handler $controller)
12    {
13        $controller->register_hook('TPL_CONTENT_DISPLAY', 'AFTER', $this, 'render_list');
14        $controller->register_hook('ACTION_ACT_PREPROCESS', 'BEFORE', $this, 'handle_ireadit_action');
15        $controller->register_hook('COMMON_WIKIPAGE_SAVE', 'AFTER', $this, 'handle_pagesave_after');
16        $controller->register_hook('INDEXER_VERSION_GET', 'BEFORE', $this, 'set_ireadit_index_version');
17        $controller->register_hook('INDEXER_PAGE_ADD', 'BEFORE', $this, 'add_readers_to_index');
18    }
19
20    public function render_list()
21    {
22        global $INFO, $ACT;
23
24        if ($ACT != 'show') return;
25        if (!isset($INFO['meta']['plugin_ireadit=0.2'])) return;
26        $ireadit_data = $INFO['meta']['plugin_ireadit=0.2'];
27
28        echo '<div';
29        if ($this->getConf('print') == 0) {
30            echo' class="no-print"';
31        }
32        echo '>';
33
34        /** @var helper_plugin_ireadit $helper */
35        $helper = $this->loadHelper('ireadit');
36
37        // we use 'lastmod' insetead of 'rev' to get the timestamp also for the current revision
38        if ($helper->user_can_read_page($ireadit_data, $INFO['id'], $INFO['lastmod'], $INFO['client'])) {
39            echo '<a href="' . wl($INFO['id'], ['do' => 'ireadit', 'rev' => $INFO['lastmod']]) . '">' . $this->getLang('ireadit') . '</a>';
40        }
41
42        try {
43            /** @var \helper_plugin_ireadit_db $db_helper */
44            $db_helper = plugin_load('helper', 'ireadit_db');
45            $sqlite = $db_helper->getDB();
46        } catch (Exception $e) {
47            msg($e->getMessage(), -1);
48            return;
49        }
50
51        $res = $sqlite->query('SELECT user, timestamp FROM ireadit
52                                        WHERE page = ?
53                                        AND rev = ?
54                                        ORDER BY timestamp', $INFO['id'], $INFO['lastmod']);
55        $readers = $sqlite->res2arr($res);
56
57        if (count($readers) > 0) {
58            echo '<h3>' . $this->getLang('readit_header') . '</h3>';
59            echo '<ul>';
60            foreach ($readers as $reader) {
61                $time = strtotime($reader['timestamp']);
62                echo '<li>' . userlink($reader['user']) . ' - ' . dformat($time) . '</li>';
63            }
64            echo '</ul>';
65        }
66
67        if ($this->getConf('show_not_read_list') && $helper->use_ireadit_here($INFO['id'], $INFO['lastmod'])) {
68            $not_read = array_diff($helper->users_set($ireadit_data), array_column($readers, 'user'));
69            $not_read_userlinks = array_map('userlink', $not_read);
70            sort($not_read_userlinks);
71            if (count($not_read) > 0) {
72                echo '<h3>' . $this->getLang('not_read_header') . '</h3>';
73                echo '<ul>';
74                foreach ($not_read_userlinks as $userlink) {
75                    echo '<li>' . $userlink . '</li>';
76                }
77                echo '</ul>';
78            }
79        }
80
81        echo '</div>';
82    }
83
84    public function handle_ireadit_action(Doku_Event $event)
85    {
86        global $INFO;
87        if ($event->data != 'ireadit') return;
88        if (!$INFO['client']) return;
89        if (!isset($INFO['meta']['plugin_ireadit=0.2'])) return;
90        $ireadit_data = $INFO['meta']['plugin_ireadit=0.2'];
91
92        /** @var helper_plugin_ireadit $helper */
93        $helper = $this->loadHelper('ireadit');
94        if ($helper->user_can_read_page($ireadit_data, $INFO['id'], $INFO['lastmod'], $INFO['client'])) {
95            try {
96                /** @var \helper_plugin_ireadit_db $db_helper */
97                $db_helper = plugin_load('helper', 'ireadit_db');
98                $sqlite = $db_helper->getDB();
99            } catch (Exception $e) {
100                msg($e->getMessage(), -1);
101                return;
102            }
103            $sqlite->storeEntry('ireadit', [
104                'page' => $INFO['id'],
105                'rev' => $INFO['lastmod'], // we use 'lastmod' inseted of 'rev' to get the timestamp also for the current revision
106                'user' => $INFO['client'],
107                'timestamp' => date('c')
108            ]);
109        }
110        $go = wl($INFO['id'], ['rev' => $INFO['lastmod']], true, '&');
111        send_redirect($go);
112    }
113
114    public function handle_pagesave_after(Doku_Event $event)
115    {
116        global $INFO;
117        if (!isset($INFO['meta']['plugin_ireadit=0.2'])) return;
118
119        if ($this->getConf('minor_edit_keeps_readers') &&
120            $event->data['changeType'] == DOKU_CHANGE_TYPE_MINOR_EDIT) {
121            try {
122                /** @var \helper_plugin_ireadit_db $db_helper */
123                $db_helper = plugin_load('helper', 'ireadit_db');
124                $sqlite = $db_helper->getDB();
125            } catch (Exception $e) {
126                msg($e->getMessage(), -1);
127                return;
128            }
129            $sqlite->query('INSERT INTO ireadit (page,rev,user,timestamp)
130                            SELECT page, ?, user, timestamp FROM ireadit WHERE rev=? AND page=?',
131                $event->data['newRevision'], $event->data['oldRevision'], $event->data['id']);
132        }
133    }
134
135    /**
136     * Add a version string to the index so it is rebuilt
137     * whenever the stored data format changes.
138     */
139    public function set_ireadit_index_version(Doku_Event $event) {
140        $event->data['plugin_ireadit'] = '0.2';
141    }
142
143    /**
144     * Add all data of the readers metadata to the metadata index.
145     */
146    public function add_readers_to_index(Doku_Event $event, $param) {
147        $ireadit_data = p_get_metadata($event->data['page'], 'plugin_ireadit=0.2');
148        if (!$ireadit_data) return;
149
150        /** @var helper_plugin_ireadit $helper */
151        $helper = $this->loadHelper('ireadit');
152        $event->data['metadata']['ireadit'] = $helper->users_set($ireadit_data);
153    }
154}
155