1<?php 2 3namespace dokuwiki\test\Remote; 4 5use dokuwiki\Remote\AccessDeniedException; 6use dokuwiki\Remote\Api; 7use dokuwiki\Remote\ApiCore; 8use dokuwiki\Remote\RemoteException; 9use dokuwiki\Search\Indexer; 10use dokuwiki\Search\MetadataSearch; 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 $indexer = new Indexer(); 168 $indexer->addPage('wiki:syntax'); 169 $indexer->addPage('wiki:dokuwiki'); 170 171 $file1 = wikiFN('wiki:syntax'); 172 $file2 = wikiFN('wiki:dokuwiki'); 173 174 $expected = [ 175 [ 176 'id' => 'wiki:syntax', 177 'title' => 'wiki:syntax', 178 'permission' => 8, 179 'size' => filesize($file1), 180 'revision' => filemtime($file1), 181 'hash' => md5(trim(io_readFile($file1))), 182 'author' => '', 183 ], 184 [ 185 'id' => 'wiki:dokuwiki', 186 'title' => 'wiki:dokuwiki', 187 'permission' => 8, 188 'size' => filesize($file2), 189 'revision' => filemtime($file2), 190 'hash' => md5(trim(io_readFile($file2))), 191 'author' => '', 192 ] 193 ]; 194 $this->assertEqualResult( 195 $expected, 196 $this->remote->call( 197 'core.listPages', 198 [ 199 'namespace' => '', 200 'depth' => 0, // 0 for all 201 'hash' => true 202 ] 203 ) 204 ); 205 } 206 207 // core.listPages 208 public function testListPagesNamespace() 209 { 210 $file1 = wikiFN('wiki:syntax'); 211 $file2 = wikiFN('wiki:dokuwiki'); 212 // no indexing needed here 213 214 global $conf; 215 $conf['useheading'] = 1; 216 217 $expected = [ 218 [ 219 'id' => 'wiki:syntax', 220 'title' => 'Formatting Syntax', 221 'permission' => 8, 222 'size' => filesize($file1), 223 'revision' => filemtime($file1), 224 'hash' => '', 225 'author' => '', 226 ], 227 [ 228 'id' => 'wiki:dokuwiki', 229 'title' => 'DokuWiki', 230 'permission' => 8, 231 'size' => filesize($file2), 232 'revision' => filemtime($file2), 233 'hash' => '', 234 'author' => '', 235 ], 236 ]; 237 238 $this->assertEqualResult( 239 $expected, 240 $this->remote->call( 241 'core.listPages', 242 [ 243 'namespace' => 'wiki:', 244 'depth' => 1, 245 ] 246 ) 247 ); 248 } 249 250 // core.searchPages 251 public function testSearchPages() 252 { 253 $id = 'wiki:syntax'; 254 $file = wikiFN($id); 255 256 (new Indexer())->addPage($id); //full text search depends on index 257 $expected = [ 258 [ 259 'id' => $id, 260 'score' => 1, 261 'revision' => filemtime($file), 262 'permission' => 8, 263 'size' => filesize($file), 264 'snippet' => ' a footnote)) by using double parentheses. 265 266===== <strong class="search_hit">Sectioning</strong> ===== 267 268You can use up to five different levels of', 269 'title' => 'wiki:syntax', 270 'author' => '', 271 'hash' => '', 272 ] 273 ]; 274 275 $this->assertEqualResult( 276 $expected, 277 $this->remote->call( 278 'core.searchPages', 279 [ 280 'query' => 'Sectioning' 281 ] 282 ) 283 ); 284 } 285 286 //core.getRecentPageChanges 287 public function testGetRecentPageChanges() 288 { 289 $_SERVER['REMOTE_USER'] = 'testuser'; 290 291 saveWikiText('pageone', 'test', 'test one'); 292 $rev1 = filemtime(wikiFN('pageone')); 293 saveWikiText('pagetwo', 'test', 'test two'); 294 $rev2 = filemtime(wikiFN('pagetwo')); 295 296 $expected = [ 297 [ 298 'id' => 'pageone', 299 'revision' => $rev1, 300 'author' => 'testuser', 301 'sizechange' => 4, 302 'summary' => 'test one', 303 'type' => 'C', 304 'ip' => clientIP(), 305 ], 306 [ 307 'id' => 'pagetwo', 308 'revision' => $rev2, 309 'author' => 'testuser', 310 'sizechange' => 4, 311 'summary' => 'test two', 312 'type' => 'C', 313 'ip' => clientIP(), 314 ] 315 ]; 316 317 $this->assertEqualResult( 318 $expected, 319 $this->remote->call( 320 'core.getRecentPageChanges', 321 [ 322 'timestamp' => 0 // all recent changes 323 ] 324 ) 325 ); 326 } 327 328 // core.getPage 329 public function testGetPage() 330 { 331 $id = 'pageversion'; 332 $file = wikiFN($id); 333 334 saveWikiText($id, 'first version', 'first'); 335 $rev1 = filemtime($file); 336 clearstatcache(false, $file); 337 $this->waitForTick(true); 338 saveWikiText($id, 'second version', 'second'); 339 $rev2 = filemtime($file); 340 341 $this->assertEqualResult( 342 'second version', 343 $this->remote->call('core.getPage', ['page' => $id, 'rev' => 0]), 344 'no revision given -> current' 345 ); 346 347 $this->assertEqualResult( 348 'first version', 349 $this->remote->call('core.getPage', ['page' => $id, 'rev' => $rev1]), 350 '1st revision given' 351 ); 352 353 $this->assertEqualResult( 354 'second version', 355 $this->remote->call('core.getPage', ['page' => $id, 'rev' => $rev2]), 356 '2nd revision given' 357 ); 358 359 $this->assertEqualResult( 360 '', 361 $this->remote->call('core.getPage', ['page' => $id, 'rev' => 1234]), 362 'Non existing revision given' 363 ); 364 365 $this->assertEqualResult( 366 '', 367 $this->remote->call('core.getPage', ['page' => 'foobar', 'rev' => 1234]), 368 'Non existing page given' 369 ); 370 } 371 372 //core.getPageHTML 373 public function testGetPageHTMLVersion() 374 { 375 $id = 'htmltest'; 376 $file = wikiFN($id); 377 378 $content1 = "====Title====\nText"; 379 $html1 = "\n<h3 class=\"sectionedit1\" id=\"title\">Title</h3>\n<div class=\"level3\">\n\n<p>\nText\n</p>\n\n</div>\n"; 380 $content2 = "====Foobar====\nText Bamm"; 381 $html2 = "\n<h3 class=\"sectionedit1\" id=\"foobar\">Foobar</h3>\n<div class=\"level3\">\n\n<p>\nText Bamm\n</p>\n\n</div>\n"; 382 383 saveWikiText($id, $content1, 'first'); 384 $rev1 = filemtime($file); 385 clearstatcache(false, $file); 386 $this->waitForTick(true); 387 saveWikiText($id, $content2, 'second'); 388 $rev2 = filemtime($file); 389 390 $this->assertEqualResult( 391 $html2, 392 $this->remote->call('core.getPageHTML', ['page' => $id, 'rev' => 0]), 393 'no revision given -> current' 394 ); 395 396 $this->assertEqualResult( 397 $html1, 398 $this->remote->call('core.getPageHTML', ['page' => $id, 'rev' => $rev1]), 399 '1st revision given' 400 ); 401 402 $this->assertEqualResult( 403 $html2, 404 $this->remote->call('core.getPageHTML', ['page' => $id, 'rev' => $rev2]), 405 '2nd revision given' 406 ); 407 408 $e = null; 409 try { 410 $this->remote->call('core.getPageHTML', ['page' => $id, 'rev' => 1234]); 411 } catch (RemoteException $e) { 412 } 413 $this->assertInstanceOf(RemoteException::class, $e); 414 $this->assertEquals(121, $e->getCode(), 'Non existing revision given'); 415 416 $e = null; 417 try { 418 $this->remote->call('core.getPageHTML', ['page' => 'foobar', 'rev' => 1234]); 419 } catch (RemoteException $e) { 420 } 421 $this->assertInstanceOf(RemoteException::class, $e); 422 $this->assertEquals(121, $e->getCode(), 'Non existing page given'); 423 } 424 425 //core.getPageInfo 426 public function testGetPageInfo() 427 { 428 $id = 'pageinfo'; 429 $file = wikiFN($id); 430 431 $_SERVER['REMOTE_USER'] = 'testuser'; 432 433 saveWikiText($id, 'first version', 'first'); 434 $rev1 = filemtime($file); 435 clearstatcache(false, $file); 436 $this->waitForTick(true); 437 saveWikiText($id, 'second version', 'second'); 438 $rev2 = filemtime($file); 439 440 $expected = [ 441 'id' => $id, 442 'revision' => $rev2, 443 'author' => 'testuser', 444 'hash' => md5(trim(io_readFile($file))), 445 'title' => $id, 446 'size' => filesize($file), 447 'permission' => 8, 448 ]; 449 $this->assertEqualResult( 450 $expected, 451 $this->remote->call('core.getPageInfo', ['page' => $id, 'rev' => 0, 'hash' => true, 'author' => true]), 452 'no revision given -> current' 453 ); 454 455 $expected = [ 456 'id' => $id, 457 'revision' => $rev1, 458 'author' => '', 459 'hash' => '', 460 'title' => $id, 461 'size' => filesize(wikiFN($id, $rev1)), 462 'permission' => 8, 463 ]; 464 $this->assertEqualResult( 465 $expected, 466 $this->remote->call('core.getPageInfo', ['page' => $id, 'rev' => $rev1]), 467 '1st revision given' 468 ); 469 470 $expected = [ 471 'id' => $id, 472 'revision' => $rev2, 473 'author' => '', 474 'hash' => '', 475 'title' => $id, 476 'size' => filesize(wikiFN($id, $rev2)), 477 'permission' => 8, 478 ]; 479 $this->assertEqualResult( 480 $expected, 481 $this->remote->call('core.getPageInfo', ['page' => $id, 'rev' => $rev2]), 482 '2nd revision given' 483 ); 484 485 $e = null; 486 try { 487 $this->remote->call('core.getPageInfo', ['page' => $id, 'rev' => 1234]); 488 } catch (RemoteException $e) { 489 } 490 $this->assertInstanceOf(RemoteException::class, $e); 491 $this->assertEquals(121, $e->getCode(), 'Non existing revision given'); 492 493 $e = null; 494 try { 495 $this->remote->call('core.getPageInfo', ['page' => 'foobar', 'rev' => 1234]); 496 } catch (RemoteException $e) { 497 } 498 $this->assertInstanceOf(RemoteException::class, $e); 499 $this->assertEquals(121, $e->getCode(), 'Non existing page given'); 500 } 501 502 //core.getPageHistory 503 public function testGetPageHistory() 504 { 505 global $conf; 506 507 $id = 'revpage'; 508 $file = wikiFN($id); 509 510 $rev = []; 511 for ($i = 0; $i < 6; $i++) { 512 $this->waitForTick(); 513 saveWikiText($id, "rev$i", "rev$i"); 514 clearstatcache(false, $file); 515 $rev[$i] = filemtime($file); 516 } 517 518 $params = ['page' => $id, 'first' => 0]; 519 $versions = $this->remote->call('core.getPageHistory', $params); 520 $versions = json_decode(json_encode($versions), true); 521 $this->assertEquals(6, count($versions)); 522 $this->assertEquals($rev[5], $versions[0]['revision']); 523 $this->assertEquals($rev[4], $versions[1]['revision']); 524 $this->assertEquals($rev[3], $versions[2]['revision']); 525 $this->assertEquals($rev[2], $versions[3]['revision']); 526 $this->assertEquals($rev[1], $versions[4]['revision']); 527 $this->assertEquals($rev[0], $versions[5]['revision']); 528 529 $params = ['page' => $id, 'first' => 1]; // offset 1 530 $versions = $this->remote->call('core.getPageHistory', $params); 531 $versions = json_decode(json_encode($versions), true); 532 $this->assertEquals(5, count($versions)); 533 $this->assertEquals($rev[4], $versions[0]['revision']); 534 $this->assertEquals($rev[3], $versions[1]['revision']); 535 $this->assertEquals($rev[2], $versions[2]['revision']); 536 $this->assertEquals($rev[1], $versions[3]['revision']); 537 $this->assertEquals($rev[0], $versions[4]['revision']); 538 539 $conf['recent'] = 3; //set number of results per page 540 541 $params = ['page' => $id, 'first' => 0]; // first page 542 $versions = $this->remote->call('core.getPageHistory', $params); 543 $versions = json_decode(json_encode($versions), true); 544 $this->assertEquals(3, count($versions)); 545 $this->assertEquals($rev[5], $versions[0]['revision']); 546 $this->assertEquals($rev[4], $versions[1]['revision']); 547 $this->assertEquals($rev[3], $versions[2]['revision']); 548 549 $params = ['page' => $id, 'first' => $conf['recent']]; // second page 550 $versions = $this->remote->call('core.getPageHistory', $params); 551 $versions = json_decode(json_encode($versions), true); 552 $this->assertEquals(3, count($versions)); 553 $this->assertEquals($rev[2], $versions[0]['revision']); 554 $this->assertEquals($rev[1], $versions[1]['revision']); 555 $this->assertEquals($rev[0], $versions[2]['revision']); 556 557 $params = ['page' => $id, 'first' => $conf['recent'] * 2]; // third page 558 $versions = $this->remote->call('core.getPageHistory', $params); 559 $versions = json_decode(json_encode($versions), true); 560 $this->assertEquals(0, count($versions)); 561 } 562 563 //core.getPageLinks 564 public function testGetPageLinks() 565 { 566 $localdoku = [ 567 'type' => 'local', 568 'page' => 'DokuWiki', 569 'href' => DOKU_BASE . DOKU_SCRIPT . '?id=DokuWiki' 570 ]; 571 $expected = [ 572 $localdoku, 573 [ 574 'type' => 'extern', 575 'page' => 'http://www.freelists.org', 576 'href' => 'http://www.freelists.org' 577 ], 578 [ 579 'type' => 'interwiki', 580 'page' => 'rfc>1855', 581 'href' => 'https://tools.ietf.org/html/rfc1855' 582 ], 583 [ 584 'type' => 'extern', 585 'page' => 'http://www.catb.org/~esr/faqs/smart-questions.html', 586 'href' => 'http://www.catb.org/~esr/faqs/smart-questions.html' 587 ], 588 $localdoku, 589 $localdoku 590 ]; 591 592 $this->assertEqualResult( 593 $expected, 594 $this->remote->call('core.getPageLinks', ['page' => 'mailinglist']) 595 ); 596 597 $this->expectExceptionCode(121); 598 $this->remote->call('core.getPageLinks', ['page' => 'foobar']); 599 } 600 601 //core.getPageBackLinks 602 public function testGetPageBackLinks() 603 { 604 saveWikiText('linky', '[[wiki:syntax]]', 'test'); 605 // backlinks need index 606 $indexer = new Indexer(); 607 $indexer->addPage('wiki:syntax'); 608 $indexer->addPage('linky'); 609 610 $result = $this->remote->call('core.getPageBackLinks', ['page' => 'wiki:syntax']); 611 $this->assertTrue(count($result) > 0); 612 $this->assertEqualResult((new MetadataSearch())->backlinks('wiki:syntax'), $result); 613 614 $this->assertEquals([], $this->remote->call('core.getPageBackLinks', ['page' => 'foobar'])); 615 } 616 617 //core.lockPages 618 public function testLockPages() 619 { 620 // lock a first set of pages 621 $_SERVER['REMOTE_USER'] = 'testuser1'; 622 $tolock = ['wiki:dokuwiki', 'nonexisting']; 623 $this->assertEquals( 624 $tolock, 625 $this->remote->call('core.lockPages', ['pages' => $tolock]), 626 'all pages should lock' 627 ); 628 629 // now we're someone else 630 $_SERVER['REMOTE_USER'] = 'testuser2'; 631 $tolock = ['wiki:dokuwiki', 'nonexisting', 'wiki:syntax', 'another']; 632 $expected = ['wiki:syntax', 'another']; 633 $this->assertEquals( 634 $expected, 635 $this->remote->call('core.lockPages', ['pages' => $tolock]), 636 'only half the pages should lock' 637 ); 638 } 639 640 // core.unlockPages 641 public function testUnlockPages() 642 { 643 $_SERVER['REMOTE_USER'] = 'testuser1'; 644 lock('wiki:dokuwiki'); 645 lock('nonexisting'); 646 647 $_SERVER['REMOTE_USER'] = 'testuser2'; 648 lock('wiki:syntax'); 649 lock('another'); 650 651 $tounlock = ['wiki:dokuwiki', 'nonexisting', 'wiki:syntax', 'another', 'notlocked']; 652 $expected = ['wiki:syntax', 'another']; 653 654 $this->assertEquals( 655 $expected, 656 $this->remote->call('core.unlockPages', ['pages' => $tounlock]) 657 ); 658 } 659 660 //core.savePage 661 public function testSavePage() 662 { 663 $id = 'putpage'; 664 665 $content = "====Title====\nText"; 666 $params = [ 667 'page' => $id, 668 'text' => $content, 669 'isminor' => false, 670 'summary' => 'Summary of nice text' 671 ]; 672 $this->assertTrue($this->remote->call('core.savePage', $params)); 673 $this->assertEquals($content, rawWiki($id)); 674 675 // remove page 676 $params = [ 677 'page' => $id, 678 'text' => '', 679 ]; 680 $this->assertTrue($this->remote->call('core.savePage', $params)); 681 $this->assertFileDoesNotExist(wikiFN($id)); 682 683 // remove non existing page (reusing above params) 684 $e = null; 685 try { 686 $this->remote->call('core.savePage', $params); 687 } catch (RemoteException $e) { 688 } 689 $this->assertInstanceOf(RemoteException::class, $e); 690 $this->assertEquals(132, $e->getCode()); 691 } 692 693 //core.appendPage 694 public function testAppendPage() 695 { 696 $id = 'appendpage'; 697 $content = 'a test'; 698 $morecontent = "\nOther text"; 699 saveWikiText($id, $content, 'local'); 700 701 $params = [ 702 'page' => $id, 703 'text' => $morecontent, 704 ]; 705 $this->assertEquals(true, $this->remote->call('core.appendPage', $params)); 706 $this->assertEquals($content . $morecontent, rawWiki($id)); 707 } 708 709 // endregion 710 711 // region media 712 713 // core.listMedia 714 public function testListMedia() 715 { 716 $id = 'wiki:dokuwiki-128.png'; 717 $file = mediaFN($id); 718 $content = file_get_contents($file); 719 720 $expected = [ 721 [ 722 'id' => $id, 723 'size' => filesize($file), 724 'revision' => filemtime($file), 725 'isimage' => true, 726 'hash' => md5($content), 727 'permission' => 8, 728 'author' => '', 729 ] 730 ]; 731 $this->assertEqualResult( 732 $expected, 733 $this->remote->call( 734 'core.listMedia', 735 [ 736 'namespace' => 'wiki', 737 'pattern' => '/128/', 738 'hash' => true, 739 ] 740 ) 741 ); 742 } 743 744 //core.getRecentMediaChanges 745 public function testGetRecentMediaChanges() 746 { 747 global $conf; 748 749 $_SERVER['REMOTE_USER'] = 'testuser'; 750 751 $orig = mediaFN('wiki:dokuwiki-128.png'); 752 $tmp = $conf['tmpdir'] . 'test.png'; 753 754 $target1 = 'test:image1.png'; 755 $file1 = mediaFN($target1); 756 copy($orig, $tmp); 757 media_save(['name' => $tmp], $target1, true, AUTH_UPLOAD, 'rename'); 758 759 $target2 = 'test:image2.png'; 760 $file2 = mediaFN($target2); 761 copy($orig, $tmp); 762 media_save(['name' => $tmp], $target2, true, AUTH_UPLOAD, 'rename'); 763 764 $expected = [ 765 [ 766 'id' => $target1, 767 'revision' => filemtime($file1), 768 'author' => 'testuser', 769 'ip' => clientIP(), 770 'sizechange' => filesize($file1), 771 'summary' => 'created', 772 'type' => 'C', 773 ], 774 [ 775 'id' => $target2, 776 'revision' => filemtime($file2), 777 'author' => 'testuser', 778 'ip' => clientIP(), 779 'sizechange' => filesize($file2), 780 'summary' => 'created', 781 'type' => 'C', 782 ] 783 ]; 784 785 $this->assertEqualResult( 786 $expected, 787 $this->remote->call( 788 'core.getRecentMediaChanges', 789 [ 790 'timestamp' => 0 // all recent changes 791 ] 792 ) 793 ); 794 } 795 796 //core.getMedia 797 public function testGetMedia() 798 { 799 $id = 'wiki:dokuwiki-128.png'; 800 $file = mediaFN($id); 801 $base64 = base64_encode(file_get_contents($file)); 802 803 $this->assertEquals( 804 $base64, 805 $this->remote->call('core.getMedia', ['media' => $id]) 806 ); 807 808 $e = null; 809 try { 810 $this->remote->call('core.getMedia', ['media' => $id, 'rev' => 1234]); 811 } catch (RemoteException $e) { 812 } 813 $this->assertInstanceOf(RemoteException::class, $e); 814 $this->assertEquals(221, $e->getCode(), 'Non existing revision given'); 815 816 $e = null; 817 try { 818 $this->remote->call('core.getMedia', ['media' => 'foobar.png']); 819 } catch (RemoteException $e) { 820 } 821 $this->assertInstanceOf(RemoteException::class, $e); 822 $this->assertEquals(221, $e->getCode(), 'Non existing media id given'); 823 } 824 825 826 //core.getMediaInfo 827 public function testGetMediaInfo() 828 { 829 $id = 'wiki:dokuwiki-128.png'; 830 $file = mediaFN($id); 831 832 $expected = [ 833 'id' => $id, 834 'revision' => filemtime($file), 835 'author' => '', 836 'hash' => md5(file_get_contents($file)), 837 'size' => filesize($file), 838 'permission' => 8, 839 'isimage' => true, 840 ]; 841 $this->assertEqualResult( 842 $expected, 843 $this->remote->call('core.getMediaInfo', ['media' => $id, 'hash' => true, 'author' => false]) 844 ); 845 846 $e = null; 847 try { 848 $this->remote->call('core.getMediaInfo', ['media' => $id, 'rev' => 1234]); 849 } catch (RemoteException $e) { 850 } 851 $this->assertInstanceOf(RemoteException::class, $e); 852 $this->assertEquals(221, $e->getCode(), 'Non existing revision given'); 853 854 $e = null; 855 try { 856 $this->remote->call('core.getMediaInfo', ['media' => 'foobar.png']); 857 } catch (RemoteException $e) { 858 } 859 $this->assertInstanceOf(RemoteException::class, $e); 860 $this->assertEquals(221, $e->getCode(), 'Non existing media id given'); 861 } 862 863 //core.getMediaHistory 864 public function testGetMediaHistory() 865 { 866 global $conf; 867 868 $_SERVER['REMOTE_USER'] = 'testuser'; 869 870 //image to be uploaded 871 $orig = mediaFN('wiki:dokuwiki-128.png'); 872 $tmp = $conf['tmpdir'] . 'test.png'; 873 874 //create image to be revised 875 $id = 'test:image3.png'; 876 $media = mediaFN($id); 877 878 $rev = []; 879 for ($i = 0; $i < 2; $i++) { 880 $this->waitForTick(); 881 copy($orig, $tmp); 882 media_save(['name' => $tmp], $id, true, AUTH_UPLOAD, 'rename'); 883 $rev[$i] = filemtime($media); 884 } 885 886 $params = ['media' => $id, 'first' => 0]; // offset 0 887 $versions = $this->remote->call('core.getMediaHistory', $params); 888 $versions = json_decode(json_encode($versions), true); 889 $this->assertEquals(2, count($versions)); 890 $this->assertEquals($rev[1], $versions[0]['revision']); 891 $this->assertEquals($rev[0], $versions[1]['revision']); 892 893 $params = ['media' => $id, 'first' => 1]; // offset 1 894 $versions = $this->remote->call('core.getMediaHistory', $params); 895 $versions = json_decode(json_encode($versions), true); 896 $this->assertEquals(1, count($versions)); 897 $this->assertEquals($rev[0], $versions[0]['revision']); 898 899 $params = ['media' => $id, 'first' => 2]; // offset 2 900 $versions = $this->remote->call('core.getMediaHistory', $params); 901 $versions = json_decode(json_encode($versions), true); 902 $this->assertEquals(0, count($versions)); 903 904 $params = ['media' => $id, 'first' => 2]; // offset 3 905 $versions = $this->remote->call('core.getMediaHistory', $params); 906 $versions = json_decode(json_encode($versions), true); 907 $this->assertEquals(0, count($versions)); 908 } 909 910 //core.saveMedia 911 public function testSaveMedia() 912 { 913 $orig = mediaFN('wiki:dokuwiki-128.png'); 914 $base64 = base64_encode(file_get_contents($orig)); 915 916 $target = 'test:putimage.png'; 917 $targetfile = mediaFN($target); 918 919 $this->assertTrue($this->remote->call('core.saveMedia', ['media' => $target, 'base64' => $base64])); 920 $this->assertFileExists($targetfile); 921 $this->assertFileEquals($orig, $targetfile); 922 } 923 924 //core.deleteMedia 925 public function testDeleteMedia() 926 { 927 global $conf; 928 global $AUTH_ACL; 929 global $USERINFO; 930 931 $id = 'wiki:dokuwiki-128.png'; 932 $file = mediaFN($id); 933 934 // deletion should fail, we only have AUTH_UPLOAD 935 $e = null; 936 try { 937 $this->remote->call('core.deleteMedia', ['media' => $id]); 938 } catch (AccessDeniedException $e) { 939 } 940 $this->assertInstanceOf(AccessDeniedException::class, $e); 941 $this->assertEquals(212, $e->getCode(), 'No permission to delete'); 942 $this->assertFileExists($file); 943 944 // setup new ACLs 945 $conf['useacl'] = 1; 946 $_SERVER['REMOTE_USER'] = 'john'; 947 $USERINFO['grps'] = array('user'); 948 $AUTH_ACL = array( 949 '* @ALL 0', 950 '* @user 16', 951 ); 952 953 // deletion should work now 954 $this->assertTrue($this->remote->call('core.deleteMedia', ['media' => $id])); 955 $this->assertFileDoesNotExist($file); 956 957 clearstatcache(false, $file); 958 959 // deleting the file again should not work 960 $e = null; 961 try { 962 $this->remote->call('core.deleteMedia', ['media' => $id]); 963 } catch (RemoteException $e) { 964 } 965 $this->assertInstanceOf(RemoteException::class, $e); 966 $this->assertEquals(221, $e->getCode(), 'Non existing media id given'); 967 } 968 // endregion 969} 970