[ Index ]

PHP Cross Reference of DokuWiki

title

Body

[close]

/_test/tests/Remote/ -> ApiCoreTest.php (source)

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