xref: /dokuwiki/_test/tests/inc/common_pageinfo.test.php (revision b12755b032df1a0019d53c62e9c655ea852928f3)
1<?php
2/**
3 * Unit Test for inc/common.php - pageinfo()
4 *
5 * @author Christopher Smith <chris@jalakai.co.uk>
6 */
7class common_pageinfo_test extends DokuWikiTest {
8
9    public function setup() : void {
10        parent::setup();
11
12        global $USERINFO;
13        $USERINFO = [
14           'pass' => '179ad45c6ce2cb97cf1029e212046e81',
15           'name' => 'Arthur Dent',
16           'mail' => 'arthur@example.com',
17           'grps' => ['admin', 'user'],
18        ];
19        $_SERVER['REMOTE_USER'] = 'testuser';
20        $_SERVER['REMOTE_ADDR'] = '1.2.3.4';
21    }
22
23    protected function get_expected_pageinfo() {
24        global $USERINFO;
25        $info = [
26          'isadmin' => true,
27          'ismanager' => true,
28          'userinfo' => $USERINFO,
29          'perm' => 255,
30          'namespace' => false,
31          'ismobile' => false,
32          'client' => 'testuser',
33        ];
34        $info['rev'] = null;
35        $info['subscribed'] = false;
36        $info['locked'] = false;
37        $info['exists'] = false;
38        $info['writable'] = true;
39        $info['editable'] = true;
40        $info['lastmod'] = false;
41        $info['currentrev'] = false;
42        $info['meta'] = [];
43        $info['ip'] = null;
44        $info['user'] = null;
45        $info['sum'] = null;
46        $info['editor'] = null;
47
48        return $info;
49    }
50
51    /**
52     *  check info keys and values for a non-existent page & admin user
53     */
54    public function test_basic_nonexistentpage() {
55        global $ID,$conf;
56        $ID = 'wiki:start';
57
58        $info = $this->get_expected_pageinfo();
59        $info['id'] = 'wiki:start';
60        $info['namespace'] = 'wiki';
61        $info['filepath'] = $conf['datadir'].'/wiki/start.txt';
62
63        $this->assertEquals($info, pageinfo());
64    }
65
66    /**
67     *  check info keys and values for a existing page & admin user
68     */
69    public function test_basic_existingpage() {
70        global $ID,$conf;
71        $ID = 'wiki:syntax';
72        $filename = $conf['datadir'].'/wiki/syntax.txt';
73        $rev = filemtime($filename);
74
75        // pageinfo() adds the meta['last_change'] entry on first access; capture the
76        // result before reading the expected metadata so it reflects that entry
77        $result = pageinfo();
78
79        $info = $this->get_expected_pageinfo();
80        $info['id'] = 'wiki:syntax';
81        $info['namespace'] = 'wiki';
82        $info['filepath'] = $filename;
83        $info['exists'] = true;
84        $info['lastmod'] = $rev;
85        $info['currentrev'] = $rev;
86        $info['meta'] = p_get_metadata($ID);
87        // set from revinfo, $pagelog->getRevisionInfo($info['lastmod'])
88        $info = array_merge($info, [
89            'ip' => '127.0.0.1',
90            'user' => '',
91            'sum' => 'created - external edit',
92        ]);
93        $info['editor'] = '127.0.0.1';
94
95        $this->assertEquals($info, $result);
96    }
97
98    /**
99     *  check info keys and values for anonymous user
100     */
101    public function test_anonymoususer() {
102        global $ID,$conf,$REV;
103
104        unset($_SERVER['REMOTE_USER']);
105        global $USERINFO; $USERINFO = [];
106
107        $ID = 'wiki:syntax';
108        $filename = $conf['datadir'].'/wiki/syntax.txt';
109        $rev = filemtime($filename);
110
111        // pageinfo() adds the meta['last_change'] entry on first access; capture the
112        // result before building the expectation so p_get_metadata() sees that entry
113        $result = pageinfo();
114
115        $info = $this->get_expected_pageinfo();
116        $info['id'] = 'wiki:syntax';
117        $info['namespace'] = 'wiki';
118        $info['filepath'] = $filename;
119        $info['exists'] = true;
120        $info['lastmod'] = $rev;
121        $info['currentrev'] = $rev;
122        $info['meta'] = p_get_metadata($ID);
123        // set from revinfo, $pagelog->getRevisionInfo($info['lastmod'])
124        $info = array_merge($info, [
125            'ip' => '127.0.0.1',
126            'user' => '',
127            'sum' => 'created - external edit',
128        ]);
129        $info['editor'] = '127.0.0.1';
130
131        // anonymous user
132        $info = array_merge($info, [
133          'isadmin' => false,
134          'ismanager' => false,
135          'perm' => 8,
136          'client' => '1.2.3.4',
137        ]);
138        unset($info['userinfo']);
139
140        $this->assertEquals($info, $result);
141    }
142
143    /**
144     *  check info keys and values with $REV
145     *  (also see $RANGE tests)
146     */
147    public function test_rev() {
148        global $ID,$conf,$REV;
149
150        $ID = 'wiki:syntax';
151        $filename = $conf['datadir'].'/wiki/syntax.txt';
152        $rev = filemtime($filename);
153        $REV = $rev - 100;
154        $ext = '.txt';
155        if ($conf['compression']) {
156            //compression in $info['filepath'] determined by wikiFN depends also on if the page exist
157            $ext .= "." . $conf['compression']; //.gz or .bz2
158        }
159
160        $info = $this->get_expected_pageinfo();
161        $info['id'] = 'wiki:syntax';
162        $info['namespace'] = 'wiki';
163        $info['meta'] = p_get_metadata($ID);
164        $info['rev'] = $REV;
165        $info['currentrev'] = $rev;
166        $info['filepath'] = str_replace('pages','attic',substr($filename,0,-3).$REV.$ext);
167
168        $this->assertEquals($info, pageinfo());
169        $this->assertEquals($rev-100, $REV);
170    }
171
172    /**
173     *  check info keys and values with $RANGE
174     */
175    public function test_range() {
176        global $ID,$conf,$REV,$RANGE;
177
178        $ID = 'wiki:syntax';
179        $filename = $conf['datadir'].'/wiki/syntax.txt';
180        $rev = filemtime($filename);
181        $range = '1000-2000';
182
183        $info = $this->get_expected_pageinfo();
184        $info['id'] = 'wiki:syntax';
185        $info['namespace'] = 'wiki';
186        $info['exists'] = true;
187        $info['lastmod'] = $rev;
188        $info['currentrev'] = $rev;
189        $info['filepath'] = $filename;
190        // set from revinfo, $pagelog->getRevisionInfo($info['lastmod'])
191        $info = array_merge($info, [
192            'ip' => '127.0.0.1',
193            'user' => '',
194            'sum' => 'created - external edit',
195        ]);
196        $info['editor'] = '127.0.0.1';
197
198        // check $RANGE without $REV
199        // expected result $RANGE unchanged
200        $RANGE = $range;
201
202        // pageinfo() adds the meta['last_change'] entry on first access; capture the
203        // result before reading the expected metadata so it reflects that entry
204        $result = pageinfo();
205        $info['meta'] = p_get_metadata($ID);
206
207        $this->assertEquals($info, $result);
208        $this->assertFalse(isset($REV));
209        $this->assertEquals($range, $RANGE);
210
211        // check $RANGE with $REV = current
212        // expected result: $RANGE unchanged, $REV cleared
213        $REV = $rev;
214        $info['rev'] = '';
215
216        $this->assertEquals($info, pageinfo());
217        $this->assertEquals('',$REV);
218        $this->assertEquals($range, $RANGE);
219
220        // check with a real $REV
221        // expected result: $REV and $RANGE are cleared
222        $REV = $rev - 100;
223
224        $this->assertEquals($info, pageinfo());
225        $this->assertEquals('', $REV);
226        $this->assertEquals('', $RANGE);
227    }
228
229    /**
230     *  test editor entry and external edit
231     */
232    public function test_editor_and_externaledits() {
233        global $ID,$conf;
234        // use a dedicated page here: this test mutates the changelog and file mtime
235        // (adds a changelog entry and touch()es the file), so it must not run against
236        // wiki:syntax which the other tests rely on being pristine
237        $ID = 'wiki:dokuwiki';
238        $filename = $conf['datadir'].'/wiki/dokuwiki.txt';
239        $rev = filemtime($filename);
240
241        $info = $this->get_expected_pageinfo();
242        $info['id'] = 'wiki:dokuwiki';
243        $info['namespace'] = 'wiki';
244        $info['filepath'] = $filename;
245        $info['exists'] = true;
246        $info['lastmod'] = $rev;
247        $info['currentrev'] = $rev;
248        $info['meta'] = p_get_metadata($ID);  // need $INFO set correctly for updateMetadata()
249
250        global $INFO;
251        $INFO = $info;
252
253        // add an editor for the current version of $ID using the PageFile API
254        $pageFile = new \dokuwiki\File\PageFile($ID);
255        $logEntry = $pageFile->changelog->addLogEntry([
256            'date'       => $rev,
257            'ip'         => $_SERVER['REMOTE_ADDR'],
258            'type'       => DOKU_CHANGE_TYPE_EDIT,
259            'id'         => $ID,
260            'user'       => $_SERVER['REMOTE_USER'],
261            'sum'        => '',
262            'extra'      => '',
263            'sizechange' => '',
264        ]);
265        $pageFile->updateMetadata($logEntry);
266
267        $info['meta'] = p_get_metadata($ID);
268        $info['ip'] = $_SERVER['REMOTE_ADDR'];
269        $info['user'] = $_SERVER['REMOTE_USER'];
270        $info['sum'] = '';
271        $info['editor'] = $info['user'];
272
273        // with an editor ...
274        $this->assertEquals($info, pageinfo());
275
276        // clear the meta['last_change'] value, pageinfo should restore it
277        p_set_metadata($ID, ['last_change' => false]);
278
279        $this->assertEquals($info, pageinfo());
280        $this->assertEquals($info['meta']['last_change'], p_get_metadata($ID,'last_change'));
281
282        // fake an external edit, pageinfo should clear the last change from meta data
283        // and not return any editor data
284        $now = time() + 10;
285        touch($filename, $now);
286
287        $info['lastmod'] = $now;
288        $info['currentrev'] = $now;
289        $info['meta']['last_change'] = false;
290        $info['ip'] = null;
291        $info['user'] = null;
292        $info['sum'] = null;
293        $info['editor'] = null;
294
295        $this->assertEquals($info, pageinfo());
296        $this->assertEquals($info['meta'], p_get_metadata($ID));   // check metadata has been updated correctly
297    }
298
299    /**
300     *  check draft
301     */
302    public function test_draft() {
303        global $ID,$conf;
304        $ID = 'wiki:syntax';
305        $filename = $conf['datadir'].'/wiki/syntax.txt';
306        $rev = filemtime($filename);
307
308        $info = $this->get_expected_pageinfo();
309        $info['id'] = 'wiki:syntax';
310        $info['namespace'] = 'wiki';
311        $info['filepath'] = $filename;
312        $info['exists'] = true;
313        $info['lastmod'] = $rev;
314        $info['currentrev'] = $rev;
315        // set from revinfo, $pagelog->getRevisionInfo($info['lastmod'])
316        $info = array_merge($info, [
317            'ip' => '127.0.0.1',
318            'user' => '',
319            'sum' => 'created - external edit',
320        ]);
321        $info['editor'] = '127.0.0.1';
322
323        // setup a draft, make it more recent than the current page
324        // - pageinfo should recognise it and keep it
325
326        $draft = getCacheName($info['client']."\n".$ID,'.draft');
327        touch($draft, $rev + 10);
328
329        $info['draft'] = $draft;
330
331        // pageinfo() adds the meta['last_change'] entry on first access; capture the
332        // result before reading the expected metadata so it reflects that entry
333        $result = pageinfo();
334        $info['meta'] = p_get_metadata($ID);
335
336        $this->assertEquals($info, $result);
337        $this->assertFileExists($draft);
338
339        // make the draft older than the current page
340        // - pageinfo should remove it and not return the 'draft' key
341        touch($draft,$rev - 10);
342        unset($info['draft']);
343
344        $this->assertEquals($info, pageinfo());
345        $this->assertFalse(file_exists($draft));
346    }
347
348    /**
349     *  check ismobile
350     */
351    public function test_ismobile() {
352        global $ID,$conf;
353        $ID = 'wiki:start';
354
355        $info = $this->get_expected_pageinfo();
356        $info['id'] = 'wiki:start';
357        $info['namespace'] = 'wiki';
358        $info['filepath'] = $conf['datadir'].'/wiki/start.txt';
359
360        // overkill, ripped from clientismobile() as we aren't testing detection - but forcing it
361        $_SERVER['HTTP_X_WAP_PROFILE'] = 'a fake url';
362        $_SERVER['HTTP_ACCEPT'] .= ';wap';
363        $_SERVER['HTTP_USER_AGENT'] = 'blackberry,symbian,hand,mobi,phone';
364
365        $info['ismobile'] = clientismobile();
366
367        $this->assertTrue(clientismobile());     // ensure THIS test fails if clientismobile() returns false
368        $this->assertEquals($info, pageinfo());  // it would be a test failure not a pageinfo failure.
369    }
370}
371