xref: /dokuwiki/_test/tests/Remote/ApiCoreTest.php (revision d1f06eb4f0e4febc5434c97e319fce6d0253e533)
1<?php
2
3namespace dokuwiki\test\Remote;
4
5use dokuwiki\Extension\Event;
6use dokuwiki\Remote\AccessDeniedException;
7use dokuwiki\Remote\Api;
8use dokuwiki\Remote\ApiCore;
9use dokuwiki\Remote\RemoteException;
10use dokuwiki\test\mock\AuthDeletePlugin;
11use dokuwiki\test\mock\AuthPlugin;
12
13
14/**
15 * Class remoteapicore_test
16 */
17class ApiCoreTest extends \DokuWikiTest
18{
19
20    protected $userinfo;
21    protected $oldAuthAcl;
22    /** @var  Api */
23    protected $remote;
24
25    public function setUp(): void
26    {
27        // we need a clean setup before each single test:
28        \DokuWikiTest::setUpBeforeClass();
29
30        parent::setUp();
31        global $conf;
32        global $USERINFO;
33        global $AUTH_ACL;
34        global $auth;
35        $this->oldAuthAcl = $AUTH_ACL;
36        $this->userinfo = $USERINFO;
37        $auth = new AuthPlugin();
38
39        $conf['remote'] = 1;
40        $conf['remoteuser'] = '@user';
41        $conf['useacl'] = 0;
42
43        $this->remote = new Api();
44    }
45
46    public function tearDown(): void
47    {
48        parent::tearDown();
49
50        global $USERINFO;
51        global $AUTH_ACL;
52
53        $USERINFO = $this->userinfo;
54        $AUTH_ACL = $this->oldAuthAcl;
55    }
56
57    /**
58     * Do an assertion that converts to JSON inbetween
59     *
60     * This lets us compare result objects with arrays
61     */
62    protected function assertEqualResult($expected, $actual, $msg = '')
63    {
64        // sort object arrays
65        if (is_array($actual) && array_key_exists(0, $actual) && is_object($actual[0])) {
66            sort($actual);
67            sort($expected);
68        }
69
70        $expected = json_decode(json_encode($expected), true);
71        $actual = json_decode(json_encode($actual), true);
72        $this->assertEquals($expected, $actual, $msg);
73    }
74
75    // region info
76
77    // core.getAPIVersion
78    public function testGetAPIVersion()
79    {
80        $this->assertEqualResult(
81            ApiCore::API_VERSION,
82            $this->remote->call('core.getAPIVersion')
83        );
84    }
85
86    // core.getWikiVersion
87    public function testGetWikiVersion()
88    {
89        $this->assertEqualResult(
90            getVersion(),
91            $this->remote->call('core.getWikiVersion')
92        );
93    }
94
95    // core.getWikiTitle
96    public function testGetWikiTitle()
97    {
98        global $conf;
99        $this->assertEqualResult(
100            $conf['title'],
101            $this->remote->call('core.getWikiTitle')
102        );
103    }
104
105    // core.getWikiTime
106    public function testGetWikiTime()
107    {
108        $this->assertEqualsWithDelta(
109            time(),
110            $this->remote->call('core.getWikiTime'),
111            1 // allow 1 second difference
112        );
113    }
114
115    // endregion
116
117    // region user
118
119    // core.login
120    public function testLogin()
121    {
122        $this->markTestIncomplete('Missing test for core.login API Call');
123    }
124
125    // core.logoff
126    public function testLogoff()
127    {
128        $this->markTestIncomplete('Missing test for core.logoff API Call');
129    }
130
131    // core.whoAmI
132    public function testWhoAmI()
133    {
134        $this->markTestIncomplete('Missing test for core.whoAmI API Call');
135    }
136
137    // core.aclCheck -> See also ApiCoreAclCheckTest.php
138    public function testAclCheck()
139    {
140        $id = 'aclpage';
141
142        $this->assertEquals(AUTH_UPLOAD, $this->remote->call('core.aclCheck', ['page' => $id]));
143
144        global $conf;
145        global $AUTH_ACL;
146        global $USERINFO;
147        $conf['useacl'] = 1;
148        $_SERVER['REMOTE_USER'] = 'john';
149        $USERINFO['grps'] = ['user'];
150        $AUTH_ACL = [
151            '*                  @ALL           0',
152            '*                  @user          2', //edit
153        ];
154
155        $this->assertEquals(AUTH_EDIT, $this->remote->call('core.aclCheck', ['page' => $id]));
156    }
157
158
159    // endregion
160
161    // region pages
162
163    // core.listPages
164    public function testlistPagesAll()
165    {
166        // all pages depends on index
167        idx_addPage('wiki:syntax');
168        idx_addPage('wiki:dokuwiki');
169
170        $file1 = wikiFN('wiki:syntax');
171        $file2 = wikiFN('wiki:dokuwiki');
172
173        $expected = [
174            [
175                'id' => 'wiki:syntax',
176                'title' => 'wiki:syntax',
177                'permission' => 8,
178                'size' => filesize($file1),
179                'revision' => filemtime($file1),
180                'hash' => md5(io_readFile($file1)),
181                'author' => '',
182            ],
183            [
184                'id' => 'wiki:dokuwiki',
185                'title' => 'wiki:dokuwiki',
186                'permission' => 8,
187                'size' => filesize($file2),
188                'revision' => filemtime($file2),
189                'hash' => md5(io_readFile($file2)),
190                'author' => '',
191            ]
192        ];
193        $this->assertEqualResult(
194            $expected,
195            $this->remote->call(
196                'core.listPages',
197                [
198                    'namespace' => '',
199                    'depth' => 0, // 0 for all
200                    'hash' => true
201                ]
202            )
203        );
204    }
205
206    // core.listPages
207    public function testListPagesNamespace()
208    {
209        $file1 = wikiFN('wiki:syntax');
210        $file2 = wikiFN('wiki:dokuwiki');
211        // no indexing needed here
212
213        global $conf;
214        $conf['useheading'] = 1;
215
216        $expected = [
217            [
218                'id' => 'wiki:syntax',
219                'title' => 'Formatting Syntax',
220                'permission' => 8,
221                'size' => filesize($file1),
222                'revision' => filemtime($file1),
223                'hash' => '',
224                'author' => '',
225            ],
226            [
227                'id' => 'wiki:dokuwiki',
228                'title' => 'DokuWiki',
229                'permission' => 8,
230                'size' => filesize($file2),
231                'revision' => filemtime($file2),
232                'hash' => '',
233                'author' => '',
234            ],
235        ];
236
237        $this->assertEqualResult(
238            $expected,
239            $this->remote->call(
240                'core.listPages',
241                [
242                    'namespace' => 'wiki:',
243                    'depth' => 1,
244                ]
245            )
246        );
247    }
248
249    // core.searchPages
250    public function testSearchPages()
251    {
252        $id = 'wiki:syntax';
253        $file = wikiFN($id);
254
255        idx_addPage($id); //full text search depends on index
256        $expected = [
257            [
258                'id' => $id,
259                'score' => 1,
260                'revision' => filemtime($file),
261                'permission' => 8,
262                'size' => filesize($file),
263                'snippet' => ' a footnote)) by using double parentheses.
264
265===== <strong class="search_hit">Sectioning</strong> =====
266
267You can use up to five different levels of',
268                'title' => 'wiki:syntax',
269                'author' => '',
270                'hash' => '',
271            ]
272        ];
273
274        $this->assertEqualResult(
275            $expected,
276            $this->remote->call(
277                'core.searchPages',
278                [
279                    'query' => 'Sectioning'
280                ]
281            )
282        );
283    }
284
285    //core.getRecentPageChanges
286    public function testGetRecentPageChanges()
287    {
288        $_SERVER['REMOTE_USER'] = 'testuser';
289
290        saveWikiText('pageone', 'test', 'test one');
291        $rev1 = filemtime(wikiFN('pageone'));
292        saveWikiText('pagetwo', 'test', 'test two');
293        $rev2 = filemtime(wikiFN('pagetwo'));
294
295        $expected = [
296            [
297                'id' => 'pageone',
298                'revision' => $rev1,
299                'author' => 'testuser',
300                'sizechange' => 4,
301                'summary' => 'test one',
302                'type' => 'C',
303                'ip' => clientIP(),
304            ],
305            [
306                'id' => 'pagetwo',
307                'revision' => $rev2,
308                'author' => 'testuser',
309                'sizechange' => 4,
310                'summary' => 'test two',
311                'type' => 'C',
312                'ip' => clientIP(),
313            ]
314        ];
315
316        $this->assertEqualResult(
317            $expected,
318            $this->remote->call(
319                'core.getRecentPageChanges',
320                [
321                    'timestamp' => 0 // all recent changes
322                ]
323            )
324        );
325    }
326
327    // core.getPage
328    public function testGetPage()
329    {
330        $id = 'pageversion';
331        $file = wikiFN($id);
332
333        saveWikiText($id, 'first version', 'first');
334        $rev1 = filemtime($file);
335        clearstatcache(false, $file);
336        $this->waitForTick(true);
337        saveWikiText($id, 'second version', 'second');
338        $rev2 = filemtime($file);
339
340        $this->assertEqualResult(
341            'second version',
342            $this->remote->call('core.getPage', ['page' => $id, 'rev' => 0]),
343            'no revision given -> current'
344        );
345
346        $this->assertEqualResult(
347            'first version',
348            $this->remote->call('core.getPage', ['page' => $id, 'rev' => $rev1]),
349            '1st revision given'
350        );
351
352        $this->assertEqualResult(
353            'second version',
354            $this->remote->call('core.getPage', ['page' => $id, 'rev' => $rev2]),
355            '2nd revision given'
356        );
357
358        $this->assertEqualResult(
359            '',
360            $this->remote->call('core.getPage', ['page' => $id, 'rev' => 1234]),
361            'Non existing revision given'
362        );
363
364        $this->assertEqualResult(
365            '',
366            $this->remote->call('core.getPage', ['page' => 'foobar', 'rev' => 1234]),
367            'Non existing page given'
368        );
369    }
370
371    //core.getPageHTML
372    public function testGetPageHTMLVersion()
373    {
374        $id = 'htmltest';
375        $file = wikiFN($id);
376
377        $content1 = "====Title====\nText";
378        $html1 = "\n<h3 class=\"sectionedit1\" id=\"title\">Title</h3>\n<div class=\"level3\">\n\n<p>\nText\n</p>\n\n</div>\n";
379        $content2 = "====Foobar====\nText Bamm";
380        $html2 = "\n<h3 class=\"sectionedit1\" id=\"foobar\">Foobar</h3>\n<div class=\"level3\">\n\n<p>\nText Bamm\n</p>\n\n</div>\n";
381
382        saveWikiText($id, $content1, 'first');
383        $rev1 = filemtime($file);
384        clearstatcache(false, $file);
385        $this->waitForTick(true);
386        saveWikiText($id, $content2, 'second');
387        $rev2 = filemtime($file);
388
389        $this->assertEqualResult(
390            $html2,
391            $this->remote->call('core.getPageHTML', ['page' => $id, 'rev' => 0]),
392            'no revision given -> current'
393        );
394
395        $this->assertEqualResult(
396            $html1,
397            $this->remote->call('core.getPageHTML', ['page' => $id, 'rev' => $rev1]),
398            '1st revision given'
399        );
400
401        $this->assertEqualResult(
402            $html2,
403            $this->remote->call('core.getPageHTML', ['page' => $id, 'rev' => $rev2]),
404            '2nd revision given'
405        );
406
407        $e = null;
408        try {
409            $this->remote->call('core.getPageHTML', ['page' => $id, 'rev' => 1234]);
410        } catch (RemoteException $e) {
411        }
412        $this->assertInstanceOf(RemoteException::class, $e);
413        $this->assertEquals(121, $e->getCode(), 'Non existing revision given');
414
415        $e = null;
416        try {
417            $this->remote->call('core.getPageHTML', ['page' => 'foobar', 'rev' => 1234]);
418        } catch (RemoteException $e) {
419        }
420        $this->assertInstanceOf(RemoteException::class, $e);
421        $this->assertEquals(121, $e->getCode(), 'Non existing page given');
422    }
423
424    //core.getPageInfo
425    public function testGetPageInfo()
426    {
427        $id = 'pageinfo';
428        $file = wikiFN($id);
429
430        $_SERVER['REMOTE_USER'] = 'testuser';
431
432        saveWikiText($id, 'first version', 'first');
433        $rev1 = filemtime($file);
434        clearstatcache(false, $file);
435        $this->waitForTick(true);
436        saveWikiText($id, 'second version', 'second');
437        $rev2 = filemtime($file);
438
439        $expected = [
440            'id' => $id,
441            'revision' => $rev2,
442            'author' => 'testuser',
443            'hash' => md5(io_readFile($file)),
444            'title' => $id,
445            'size' => filesize($file),
446            'permission' => 8,
447        ];
448        $this->assertEqualResult(
449            $expected,
450            $this->remote->call('core.getPageInfo', ['page' => $id, 'rev' => 0, 'hash' => true, 'author' => true]),
451            'no revision given -> current'
452        );
453
454        $expected = [
455            'id' => $id,
456            'revision' => $rev1,
457            'author' => '',
458            'hash' => '',
459            'title' => $id,
460            'size' => filesize(wikiFN($id, $rev1)),
461            'permission' => 8,
462        ];
463        $this->assertEqualResult(
464            $expected,
465            $this->remote->call('core.getPageInfo', ['page' => $id, 'rev' => $rev1]),
466            '1st revision given'
467        );
468
469        $expected = [
470            'id' => $id,
471            'revision' => $rev2,
472            'author' => '',
473            'hash' => '',
474            'title' => $id,
475            'size' => filesize(wikiFN($id, $rev2)),
476            'permission' => 8,
477        ];
478        $this->assertEqualResult(
479            $expected,
480            $this->remote->call('core.getPageInfo', ['page' => $id, 'rev' => $rev2]),
481            '2nd revision given'
482        );
483
484        $e = null;
485        try {
486            $this->remote->call('core.getPageInfo', ['page' => $id, 'rev' => 1234]);
487        } catch (RemoteException $e) {
488        }
489        $this->assertInstanceOf(RemoteException::class, $e);
490        $this->assertEquals(121, $e->getCode(), 'Non existing revision given');
491
492        $e = null;
493        try {
494            $this->remote->call('core.getPageInfo', ['page' => 'foobar', 'rev' => 1234]);
495        } catch (RemoteException $e) {
496        }
497        $this->assertInstanceOf(RemoteException::class, $e);
498        $this->assertEquals(121, $e->getCode(), 'Non existing page given');
499    }
500
501    //core.getPageHistory
502    public function testGetPageHistory()
503    {
504        global $conf;
505
506        $id = 'revpage';
507        $file = wikiFN($id);
508
509        $rev = [];
510        for ($i = 0; $i < 6; $i++) {
511            $this->waitForTick();
512            saveWikiText($id, "rev$i", "rev$i");
513            clearstatcache(false, $file);
514            $rev[$i] = filemtime($file);
515        }
516
517        $params = ['page' => $id, 'first' => 0];
518        $versions = $this->remote->call('core.getPageHistory', $params);
519        $versions = json_decode(json_encode($versions), true);
520        $this->assertEquals(6, count($versions));
521        $this->assertEquals($rev[5], $versions[0]['revision']);
522        $this->assertEquals($rev[4], $versions[1]['revision']);
523        $this->assertEquals($rev[3], $versions[2]['revision']);
524        $this->assertEquals($rev[2], $versions[3]['revision']);
525        $this->assertEquals($rev[1], $versions[4]['revision']);
526        $this->assertEquals($rev[0], $versions[5]['revision']);
527
528        $params = ['page' => $id, 'first' => 1]; // offset 1
529        $versions = $this->remote->call('core.getPageHistory', $params);
530        $versions = json_decode(json_encode($versions), true);
531        $this->assertEquals(5, count($versions));
532        $this->assertEquals($rev[4], $versions[0]['revision']);
533        $this->assertEquals($rev[3], $versions[1]['revision']);
534        $this->assertEquals($rev[2], $versions[2]['revision']);
535        $this->assertEquals($rev[1], $versions[3]['revision']);
536        $this->assertEquals($rev[0], $versions[4]['revision']);
537
538        $conf['recent'] = 3; //set number of results per page
539
540        $params = ['page' => $id, 'first' => 0]; // first page
541        $versions = $this->remote->call('core.getPageHistory', $params);
542        $versions = json_decode(json_encode($versions), true);
543        $this->assertEquals(3, count($versions));
544        $this->assertEquals($rev[5], $versions[0]['revision']);
545        $this->assertEquals($rev[4], $versions[1]['revision']);
546        $this->assertEquals($rev[3], $versions[2]['revision']);
547
548        $params = ['page' => $id, 'first' => $conf['recent']]; // second page
549        $versions = $this->remote->call('core.getPageHistory', $params);
550        $versions = json_decode(json_encode($versions), true);
551        $this->assertEquals(3, count($versions));
552        $this->assertEquals($rev[2], $versions[0]['revision']);
553        $this->assertEquals($rev[1], $versions[1]['revision']);
554        $this->assertEquals($rev[0], $versions[2]['revision']);
555
556        $params = ['page' => $id, 'first' => $conf['recent'] * 2]; // third page
557        $versions = $this->remote->call('core.getPageHistory', $params);
558        $versions = json_decode(json_encode($versions), true);
559        $this->assertEquals(0, count($versions));
560    }
561
562    //core.getPageLinks
563    public function testGetPageLinks()
564    {
565        $localdoku = [
566            'type' => 'local',
567            'page' => 'DokuWiki',
568            'href' => DOKU_BASE . DOKU_SCRIPT . '?id=DokuWiki'
569        ];
570        $expected = [
571            $localdoku,
572            [
573                'type' => 'extern',
574                'page' => 'http://www.freelists.org',
575                'href' => 'http://www.freelists.org'
576            ],
577            [
578                'type' => 'interwiki',
579                'page' => 'rfc>1855',
580                'href' => 'https://tools.ietf.org/html/rfc1855'
581            ],
582            [
583                'type' => 'extern',
584                'page' => 'http://www.catb.org/~esr/faqs/smart-questions.html',
585                'href' => 'http://www.catb.org/~esr/faqs/smart-questions.html'
586            ],
587            $localdoku,
588            $localdoku
589        ];
590
591        $this->assertEqualResult(
592            $expected,
593            $this->remote->call('core.getPageLinks', ['page' => 'mailinglist'])
594        );
595
596        $this->expectExceptionCode(121);
597        $this->remote->call('core.getPageLinks', ['page' => 'foobar']);
598    }
599
600    //core.getPageBackLinks
601    public function testGetPageBackLinks()
602    {
603        saveWikiText('linky', '[[wiki:syntax]]', 'test');
604        // backlinks need index
605        idx_addPage('wiki:syntax');
606        idx_addPage('linky');
607
608        $result = $this->remote->call('core.getPageBackLinks', ['page' => 'wiki:syntax']);
609        $this->assertTrue(count($result) > 0);
610        $this->assertEqualResult(ft_backlinks('wiki:syntax'), $result);
611
612        $this->assertEquals([], $this->remote->call('core.getPageBackLinks', ['page' => 'foobar']));
613    }
614
615    //core.lockPages
616    public function testLockPages()
617    {
618        // lock a first set of pages
619        $_SERVER['REMOTE_USER'] = 'testuser1';
620        $tolock = ['wiki:dokuwiki', 'nonexisting'];
621        $this->assertEquals(
622            $tolock,
623            $this->remote->call('core.lockPages', ['pages' => $tolock]),
624            'all pages should lock'
625        );
626
627        // now we're someone else
628        $_SERVER['REMOTE_USER'] = 'testuser2';
629        $tolock = ['wiki:dokuwiki', 'nonexisting', 'wiki:syntax', 'another'];
630        $expected = ['wiki:syntax', 'another'];
631        $this->assertEquals(
632            $expected,
633            $this->remote->call('core.lockPages', ['pages' => $tolock]),
634            'only half the pages should lock'
635        );
636    }
637
638    // core.unlockPages
639    public function testUnlockPages()
640    {
641        $_SERVER['REMOTE_USER'] = 'testuser1';
642        lock('wiki:dokuwiki');
643        lock('nonexisting');
644
645        $_SERVER['REMOTE_USER'] = 'testuser2';
646        lock('wiki:syntax');
647        lock('another');
648
649        $tounlock = ['wiki:dokuwiki', 'nonexisting', 'wiki:syntax', 'another', 'notlocked'];
650        $expected = ['wiki:syntax', 'another'];
651
652        $this->assertEquals(
653            $expected,
654            $this->remote->call('core.unlockPages', ['pages' => $tounlock])
655        );
656    }
657
658    //core.savePage
659    public function testSavePage()
660    {
661        $id = 'putpage';
662
663        $content = "====Title====\nText";
664        $params = [
665            'page' => $id,
666            'text' => $content,
667            'isminor' => false,
668            'summary' => 'Summary of nice text'
669        ];
670        $this->assertTrue($this->remote->call('core.savePage', $params));
671        $this->assertEquals($content, rawWiki($id));
672
673        // remove page
674        $params = [
675            'page' => $id,
676            'text' => '',
677        ];
678        $this->assertTrue($this->remote->call('core.savePage', $params));
679        $this->assertFileNotExists(wikiFN($id));
680
681        // remove non existing page (reusing above params)
682        $e = null;
683        try {
684            $this->remote->call('core.savePage', $params);
685        } catch (RemoteException $e) {
686        }
687        $this->assertInstanceOf(RemoteException::class, $e);
688        $this->assertEquals(132, $e->getCode());
689    }
690
691    //core.appendPage
692    public function testAppendPage()
693    {
694        $id = 'appendpage';
695        $content = 'a test';
696        $morecontent = "\nOther text";
697        saveWikiText($id, $content, 'local');
698
699        $params = [
700            'page' => $id,
701            'text' => $morecontent,
702        ];
703        $this->assertEquals(true, $this->remote->call('core.appendPage', $params));
704        $this->assertEquals($content . $morecontent, rawWiki($id));
705    }
706
707    // endregion
708
709    // region media
710
711    // core.listMedia
712    public function testListMedia()
713    {
714        $id = 'wiki:dokuwiki-128.png';
715        $file = mediaFN($id);
716        $content = file_get_contents($file);
717
718        $expected = [
719            [
720                'id' => $id,
721                'size' => filesize($file),
722                'revision' => filemtime($file),
723                'isimage' => true,
724                'hash' => md5($content),
725                'permission' => 8,
726                'author' => '',
727            ]
728        ];
729        $this->assertEqualResult(
730            $expected,
731            $this->remote->call(
732                'core.listMedia',
733                [
734                    'namespace' => 'wiki',
735                    'pattern' => '/128/',
736                    'hash' => true,
737                ]
738            )
739        );
740    }
741
742    //core.getRecentMediaChanges
743    public function testGetRecentMediaChanges()
744    {
745        global $conf;
746
747        $_SERVER['REMOTE_USER'] = 'testuser';
748
749        $orig = mediaFN('wiki:dokuwiki-128.png');
750        $tmp = $conf['tmpdir'] . 'test.png';
751
752        $target1 = 'test:image1.png';
753        $file1 = mediaFN($target1);
754        copy($orig, $tmp);
755        media_save(['name' => $tmp], $target1, true, AUTH_UPLOAD, 'rename');
756
757        $target2 = 'test:image2.png';
758        $file2 = mediaFN($target2);
759        copy($orig, $tmp);
760        media_save(['name' => $tmp], $target2, true, AUTH_UPLOAD, 'rename');
761
762        $expected = [
763            [
764                'id' => $target1,
765                'revision' => filemtime($file1),
766                'author' => 'testuser',
767                'ip' => clientIP(),
768                'sizechange' => filesize($file1),
769                'summary' => 'created',
770                'type' => 'C',
771            ],
772            [
773                'id' => $target2,
774                'revision' => filemtime($file2),
775                'author' => 'testuser',
776                'ip' => clientIP(),
777                'sizechange' => filesize($file2),
778                'summary' => 'created',
779                'type' => 'C',
780            ]
781        ];
782
783        $this->assertEqualResult(
784            $expected,
785            $this->remote->call(
786                'core.getRecentMediaChanges',
787                [
788                    'timestamp' => 0 // all recent changes
789                ]
790            )
791        );
792    }
793
794    //core.getMedia
795    public function testGetMedia()
796    {
797        $id = 'wiki:dokuwiki-128.png';
798        $file = mediaFN($id);
799        $base64 = base64_encode(file_get_contents($file));
800
801        $this->assertEquals(
802            $base64,
803            $this->remote->call('core.getMedia', ['media' => $id])
804        );
805
806        $e = null;
807        try {
808            $this->remote->call('core.getMedia', ['media' => $id, 'rev' => 1234]);
809        } catch (RemoteException $e) {
810        }
811        $this->assertInstanceOf(RemoteException::class, $e);
812        $this->assertEquals(221, $e->getCode(), 'Non existing revision given');
813
814        $e = null;
815        try {
816            $this->remote->call('core.getMedia', ['media' => 'foobar.png']);
817        } catch (RemoteException $e) {
818        }
819        $this->assertInstanceOf(RemoteException::class, $e);
820        $this->assertEquals(221, $e->getCode(), 'Non existing media id given');
821    }
822
823
824    //core.getMediaInfo
825    public function testGetMediaInfo()
826    {
827        $id = 'wiki:dokuwiki-128.png';
828        $file = mediaFN($id);
829
830        $expected = [
831            'id' => $id,
832            'revision' => filemtime($file),
833            'author' => '',
834            'hash' => md5(file_get_contents($file)),
835            'size' => filesize($file),
836            'permission' => 8,
837            'isimage' => true,
838        ];
839        $this->assertEqualResult(
840            $expected,
841            $this->remote->call('core.getMediaInfo', ['media' => $id, 'hash' => true, 'author' => false])
842        );
843
844        $e = null;
845        try {
846            $this->remote->call('core.getMediaInfo', ['media' => $id, 'rev' => 1234]);
847        } catch (RemoteException $e) {
848        }
849        $this->assertInstanceOf(RemoteException::class, $e);
850        $this->assertEquals(221, $e->getCode(), 'Non existing revision given');
851
852        $e = null;
853        try {
854            $this->remote->call('core.getMediaInfo', ['media' => 'foobar.png']);
855        } catch (RemoteException $e) {
856        }
857        $this->assertInstanceOf(RemoteException::class, $e);
858        $this->assertEquals(221, $e->getCode(), 'Non existing media id given');
859    }
860
861    //core.saveMedia
862    public function testSaveMedia()
863    {
864        $orig = mediaFN('wiki:dokuwiki-128.png');
865        $base64 = base64_encode(file_get_contents($orig));
866
867        $target = 'test:putimage.png';
868        $targetfile = mediaFN($target);
869
870        $this->assertTrue($this->remote->call('core.saveMedia', ['media' => $target, 'base64' => $base64]));
871        $this->assertFileExists($targetfile);
872        $this->assertFileEquals($orig, $targetfile);
873    }
874
875    //core.deleteMedia
876    public function testDeleteMedia()
877    {
878        global $conf;
879        global $AUTH_ACL;
880        global $USERINFO;
881
882        $id = 'wiki:dokuwiki-128.png';
883        $file = mediaFN($id);
884
885        // deletion should fail, we only have AUTH_UPLOAD
886        $e = null;
887        try {
888            $this->remote->call('core.deleteMedia', ['media' => $id]);
889        } catch (AccessDeniedException $e) {
890        }
891        $this->assertInstanceOf(AccessDeniedException::class, $e);
892        $this->assertEquals(212, $e->getCode(), 'No permission to delete');
893        $this->assertFileExists($file);
894
895        // setup new ACLs
896        $conf['useacl'] = 1;
897        $_SERVER['REMOTE_USER'] = 'john';
898        $USERINFO['grps'] = array('user');
899        $AUTH_ACL = array(
900            '*                  @ALL           0',
901            '*                  @user          16',
902        );
903
904        // deletion should work now
905        $this->assertTrue($this->remote->call('core.deleteMedia', ['media' => $id]));
906        $this->assertFileNotExists($file);
907
908        clearstatcache(false, $file);
909
910        // deleting the file again should not work
911        $e = null;
912        try {
913            $this->remote->call('core.deleteMedia', ['media' => $id]);
914        } catch (RemoteException $e) {
915        }
916        $this->assertInstanceOf(RemoteException::class, $e);
917        $this->assertEquals(221, $e->getCode(), 'Non existing media id given');
918    }
919    // endregion
920}
921