xref: /dokuwiki/lib/plugins/revert/admin.php (revision 884caed926ca0aa0af6ce3f34ae3aa7317a3361a)
1<?php
2
3use dokuwiki\Extension\AdminPlugin;
4use dokuwiki\ChangeLog\PageChangeLog;
5
6/**
7 * All DokuWiki plugins to extend the admin function
8 * need to inherit from this class
9 */
10class admin_plugin_revert extends AdminPlugin
11{
12    protected $cmd;
13    // some vars which might need tuning later
14    protected $max_lines = 800; // lines to read from changelog
15    protected $max_revs  = 20;  // numer of old revisions to check
16
17
18    /**
19     * Constructor
20     */
21    public function __construct()
22    {
23        $this->setupLocale();
24    }
25
26    /**
27     * access for managers
28     */
29    public function forAdminOnly()
30    {
31        return false;
32    }
33
34    /**
35     * return sort order for position in admin menu
36     */
37    public function getMenuSort()
38    {
39        return 40;
40    }
41
42    /**
43     * handle user request
44     */
45    public function handle()
46    {
47    }
48
49    /**
50     * output appropriate html
51     */
52    public function html()
53    {
54        global $INPUT;
55
56        echo $this->locale_xhtml('intro');
57
58        $this->printSearchForm();
59
60        if (is_array($INPUT->param('revert')) && checkSecurityToken()) {
61            $this->revertEdits($INPUT->arr('revert'), $INPUT->str('filter'));
62        } elseif ($INPUT->has('filter')) {
63            $this->listEdits($INPUT->str('filter'));
64        }
65    }
66
67    /**
68     * Display the form for searching spam pages
69     */
70    protected function printSearchForm()
71    {
72        global $lang, $INPUT;
73        echo '<form action="" method="post"><div class="no">';
74        echo '<label>' . $this->getLang('filter') . ': </label>';
75        echo '<input type="text" name="filter" class="edit" value="' . hsc($INPUT->str('filter')) . '" /> ';
76        echo '<button type="submit">' . $lang['btn_search'] . '</button> ';
77        echo '<span>' . $this->getLang('note1') . '</span>';
78        echo '</div></form><br /><br />';
79    }
80
81    /**
82     * Start the reversion process
83     */
84    protected function revertEdits($revert, $filter)
85    {
86        echo '<hr /><br />';
87        echo '<p>' . $this->getLang('revstart') . '</p>';
88
89        echo '<ul>';
90        foreach ($revert as $id) {
91            global $REV;
92
93            // Managers can reach this tool without holding edit rights on every
94            // namespace. Normalize the submitted id and enforce per-page edit
95            // permission so pages the user is denied cannot be reverted or blanked.
96            // The listing only offers editable pages, so this guard is reached
97            // only by a hand-crafted request; such ids are silently skipped.
98            $id = cleanID($id);
99            if (auth_quickaclcheck($id) < AUTH_EDIT) {
100                continue;
101            }
102
103            // find the last non-spammy revision
104            $data = '';
105            $pagelog = new PageChangeLog($id);
106            $old  = $pagelog->getRevisions(0, $this->max_revs);
107            if ($old !== []) {
108                foreach ($old as $REV) {
109                    $data = rawWiki($id, $REV);
110                    if (!str_contains($data, (string) $filter)) break;
111                }
112            }
113
114            if ($data) {
115                saveWikiText($id, $data, 'old revision restored', false);
116                printf('<li><div class="li">' . $this->getLang('reverted') . '</div></li>', $id, $REV);
117            } else {
118                saveWikiText($id, '', '', false);
119                printf('<li><div class="li">' . $this->getLang('removed') . '</div></li>', $id);
120            }
121            @set_time_limit(10);
122            flush();
123        }
124        echo '</ul>';
125
126        echo '<p>' . $this->getLang('revstop') . '</p>';
127    }
128
129    /**
130     * List recent edits matching the given filter
131     */
132    protected function listEdits($filter)
133    {
134        global $conf;
135        global $lang;
136        echo '<hr /><br />';
137        echo '<form action="" method="post"><div class="no">';
138        echo '<input type="hidden" name="filter" value="' . hsc($filter) . '" />';
139        formSecurityToken();
140
141        $recents = getRecents(0, $this->max_lines);
142        echo '<ul>';
143
144        $cnt = 0;
145        foreach ($recents as $recent) {
146            // only offer pages the user may actually revert; getRecents() already
147            // filtered to read permission, this narrows it to edit permission
148            if ($recent['perms'] < AUTH_EDIT) continue;
149            if ($filter) {
150                if (!str_contains(rawWiki($recent['id']), (string) $filter)) continue;
151            }
152
153            $cnt++;
154            $date = dformat($recent['date']);
155
156            echo ($recent['type'] === DOKU_CHANGE_TYPE_MINOR_EDIT) ? '<li class="minor">' : '<li>';
157            echo '<div class="li">';
158            echo '<input type="checkbox" name="revert[]" value="' . hsc($recent['id']) .
159                '" checked="checked" id="revert__' . $cnt . '" />';
160            echo ' <label for="revert__' . $cnt . '">' . $date . '</label> ';
161
162            echo '<a href="' . wl($recent['id'], "do=diff") . '">';
163            $p = [];
164            $p['src']    = DOKU_BASE . 'lib/images/diff.png';
165            $p['width']  = 15;
166            $p['height'] = 11;
167            $p['title']  = $lang['diff'];
168            $p['alt']    = $lang['diff'];
169            $att = buildAttributes($p);
170            echo "<img $att />";
171            echo '</a> ';
172
173            echo '<a href="' . wl($recent['id'], "do=revisions") . '">';
174            $p = [];
175            $p['src']    = DOKU_BASE . 'lib/images/history.png';
176            $p['width']  = 12;
177            $p['height'] = 14;
178            $p['title']  = $lang['btn_revs'];
179            $p['alt']    = $lang['btn_revs'];
180            $att = buildAttributes($p);
181            echo "<img $att />";
182            echo '</a> ';
183
184            echo html_wikilink(':' . $recent['id'], (useHeading('navigation')) ? null : $recent['id']);
185            echo ' – ' . htmlspecialchars($recent['sum']);
186
187            echo ' <span class="user">';
188                echo $recent['user'] . ' ' . $recent['ip'];
189            echo '</span>';
190
191            echo '</div>';
192            echo '</li>';
193
194            @set_time_limit(10);
195            flush();
196        }
197        echo '</ul>';
198
199        echo '<p>';
200        echo '<button type="submit">' . $this->getLang('revert') . '</button> ';
201        printf($this->getLang('note2'), hsc($filter));
202        echo '</p>';
203
204        echo '</div></form>';
205    }
206}
207//Setup VIM: ex: et ts=4 :
208