Skip to content

Commit 3ab4aa6

Browse files
authored
Merge pull request dokuwiki#4420 from dokuwiki/api-mediahistory
Add core.getMediaHistory API endpoint
2 parents 337a0ff + a8f218d commit 3ab4aa6

File tree

2 files changed

+132
-3
lines changed

2 files changed

+132
-3
lines changed

_test/tests/Remote/ApiCoreTest.php

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -856,6 +856,53 @@ public function testGetMediaInfo()
856856
$this->assertEquals(221, $e->getCode(), 'Non existing media id given');
857857
}
858858

859+
//core.getMediaHistory
860+
public function testGetMediaHistory()
861+
{
862+
global $conf;
863+
864+
$_SERVER['REMOTE_USER'] = 'testuser';
865+
866+
//image to be uploaded
867+
$orig = mediaFN('wiki:dokuwiki-128.png');
868+
$tmp = $conf['tmpdir'] . 'test.png';
869+
870+
//create image to be revised
871+
$id = 'test:image3.png';
872+
$media = mediaFN($id);
873+
874+
$rev = [];
875+
for ($i = 0; $i < 2; $i++) {
876+
$this->waitForTick();
877+
copy($orig, $tmp);
878+
media_save(['name' => $tmp], $id, true, AUTH_UPLOAD, 'rename');
879+
$rev[$i] = filemtime($media);
880+
}
881+
882+
$params = ['media' => $id, 'first' => 0]; // offset 0
883+
$versions = $this->remote->call('core.getMediaHistory', $params);
884+
$versions = json_decode(json_encode($versions), true);
885+
$this->assertEquals(2, count($versions));
886+
$this->assertEquals($rev[1], $versions[0]['revision']);
887+
$this->assertEquals($rev[0], $versions[1]['revision']);
888+
889+
$params = ['media' => $id, 'first' => 1]; // offset 1
890+
$versions = $this->remote->call('core.getMediaHistory', $params);
891+
$versions = json_decode(json_encode($versions), true);
892+
$this->assertEquals(1, count($versions));
893+
$this->assertEquals($rev[0], $versions[0]['revision']);
894+
895+
$params = ['media' => $id, 'first' => 2]; // offset 2
896+
$versions = $this->remote->call('core.getMediaHistory', $params);
897+
$versions = json_decode(json_encode($versions), true);
898+
$this->assertEquals(0, count($versions));
899+
900+
$params = ['media' => $id, 'first' => 2]; // offset 3
901+
$versions = $this->remote->call('core.getMediaHistory', $params);
902+
$versions = json_decode(json_encode($versions), true);
903+
$this->assertEquals(0, count($versions));
904+
}
905+
859906
//core.saveMedia
860907
public function testSaveMedia()
861908
{

inc/Remote/ApiCore.php

Lines changed: 85 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
use Doku_Renderer_xhtml;
66
use dokuwiki\ChangeLog\PageChangeLog;
7+
use dokuwiki\ChangeLog\MediaChangeLog;
78
use dokuwiki\Extension\AuthPlugin;
89
use dokuwiki\Extension\Event;
910
use dokuwiki\Remote\Response\Link;
@@ -22,7 +23,7 @@
2223
class ApiCore
2324
{
2425
/** @var int Increased whenever the API is changed */
25-
public const API_VERSION = 13;
26+
public const API_VERSION = 14;
2627

2728
/**
2829
* Returns details about the core methods
@@ -65,7 +66,7 @@ public function getMethods()
6566
'core.getMedia' => new ApiCall([$this, 'getMedia'], 'media'),
6667
'core.getMediaInfo' => new ApiCall([$this, 'getMediaInfo'], 'media'),
6768
'core.getMediaUsage' => new ApiCall([$this, 'getMediaUsage'], 'media'),
68-
// todo: implement getMediaHistory
69+
'core.getMediaHistory' => new ApiCall([$this, 'getMediaHistory'], 'media'),
6970

7071
'core.saveMedia' => new ApiCall([$this, 'saveMedia'], 'media'),
7172
'core.deleteMedia' => new ApiCall([$this, 'deleteMedia'], 'media'),
@@ -463,7 +464,7 @@ public function getPageInfo($page, $rev = 0, $author = false, $hash = false)
463464
/**
464465
* Returns a list of available revisions of a given wiki page
465466
*
466-
* The number of returned pages is set by `$conf['recent']`, but non accessible revisions pages
467+
* The number of returned pages is set by `$conf['recent']`, but non accessible revisions
467468
* are skipped, so less than that may be returned.
468469
*
469470
* @link https://www.dokuwiki.org/config:recent
@@ -834,6 +835,11 @@ public function getMedia($media, $rev = 0)
834835
throw new AccessDeniedException('You are not allowed to read this media file', 211);
835836
}
836837

838+
// was the current revision requested?
839+
if ($this->isCurrentMediaRev($media, $rev)) {
840+
$rev = 0;
841+
}
842+
837843
$file = mediaFN($media, $rev);
838844
if (!@ file_exists($file)) {
839845
throw new RemoteException('The requested media file (revision) does not exist', 221);
@@ -865,6 +871,12 @@ public function getMediaInfo($media, $rev = 0, $author = false, $hash = false)
865871
if (auth_quickaclcheck($media) < AUTH_READ) {
866872
throw new AccessDeniedException('You are not allowed to read this media file', 211);
867873
}
874+
875+
// was the current revision requested?
876+
if ($this->isCurrentMediaRev($media, $rev)) {
877+
$rev = 0;
878+
}
879+
868880
if (!media_exists($media, $rev)) {
869881
throw new RemoteException('The requested media file does not exist', 221);
870882
}
@@ -903,6 +915,62 @@ public function getMediaUsage($media)
903915
return ft_mediause($media);
904916
}
905917

918+
/**
919+
* Returns a list of available revisions of a given media file
920+
*
921+
* The number of returned files is set by `$conf['recent']`, but non accessible revisions
922+
* are skipped, so less than that may be returned.
923+
*
924+
* Since API Version 14
925+
*
926+
* @link https://www.dokuwiki.org/config:recent
927+
* @param string $media file id
928+
* @param int $first skip the first n changelog lines, 0 starts at the current revision
929+
* @return MediaChange[]
930+
* @throws AccessDeniedException
931+
* @throws RemoteException
932+
* @author
933+
*/
934+
public function getMediaHistory($media, $first = 0)
935+
{
936+
global $conf;
937+
938+
$media = cleanID($media);
939+
// check that this media exists
940+
if (auth_quickaclcheck($media) < AUTH_READ) {
941+
throw new AccessDeniedException('You are not allowed to read this media file', 211);
942+
}
943+
if (!media_exists($media, 0)) {
944+
throw new RemoteException('The requested media file does not exist', 221);
945+
}
946+
947+
$medialog = new MediaChangeLog($media);
948+
$medialog->setChunkSize(1024);
949+
// old revisions are counted from 0, so we need to subtract 1 for the current one
950+
$revisions = $medialog->getRevisions($first - 1, $conf['recent']);
951+
952+
$result = [];
953+
foreach ($revisions as $rev) {
954+
// the current revision needs to be checked against the current file path
955+
$check = $this->isCurrentMediaRev($media, $rev) ? '' : $rev;
956+
if (!media_exists($media, $check)) continue; // skip non-existing revisions
957+
958+
$info = $medialog->getRevisionInfo($rev);
959+
960+
$result[] = new MediaChange(
961+
$media,
962+
$rev,
963+
$info['user'],
964+
$info['ip'],
965+
$info['sum'],
966+
$info['type'],
967+
$info['sizechange']
968+
);
969+
}
970+
971+
return $result;
972+
}
973+
906974
/**
907975
* Uploads a file to the wiki
908976
*
@@ -987,6 +1055,20 @@ public function deleteMedia($media)
9871055
}
9881056
}
9891057

1058+
/**
1059+
* Check if the given revision is the current revision of this file
1060+
*
1061+
* @param string $id
1062+
* @param int $rev
1063+
* @return bool
1064+
*/
1065+
protected function isCurrentMediaRev(string $id, int $rev)
1066+
{
1067+
$current = @filemtime(mediaFN($id));
1068+
if ($current === $rev) return true;
1069+
return false;
1070+
}
1071+
9901072
// endregion
9911073

9921074

0 commit comments

Comments
 (0)