summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--_test/tests/inc/changelog_getRevisionsAround.php183
-rw-r--r--_test/tests/inc/changelog_getrelativerevision.test.php418
-rw-r--r--_test/tests/inc/changelog_getrevisioninfo.test.php56
-rw-r--r--_test/tests/inc/changelog_getrevisions.test.php114
-rw-r--r--feed.php6
-rw-r--r--inc/RemoteAPICore.php11
-rw-r--r--inc/changelog.php819
-rw-r--r--inc/common.php8
-rw-r--r--inc/html.php105
-rw-r--r--inc/lang/en/lang.php4
-rw-r--r--inc/lang/nl/lang.php4
-rw-r--r--inc/media.php6
-rw-r--r--inc/subscription.php8
-rw-r--r--lib/plugins/revert/admin.php3
14 files changed, 1483 insertions, 262 deletions
diff --git a/_test/tests/inc/changelog_getRevisionsAround.php b/_test/tests/inc/changelog_getRevisionsAround.php
new file mode 100644
index 000000000..d4d6b8496
--- /dev/null
+++ b/_test/tests/inc/changelog_getRevisionsAround.php
@@ -0,0 +1,183 @@
+<?php
+/**
+ * Tests for requesting revisions of a page with getRevisions()
+ *
+ * This class uses the files:
+ * - data/pages/mailinglist.txt
+ * - data/meta/mailinglist.changes
+ */
+class changelog_getrevisionsaround_test extends DokuWikiTest {
+
+ /**
+ * list of revisions in mailinglist.changes
+ */
+ private $revsexpected = array(
+ 1360110636,
+ 1361901536, 1362524799,
+ 1362525145, 1362525359,
+ 1362525899, 1362525926,
+ 1362526039, 1362526119,
+ 1362526167, 1362526767,
+ 1362526861, 1362527046,
+ 1362527164, 1363436892,
+ 1368575634, 1368609772,
+ 1368612506, 1368612599,
+ 1368622152, 1368622195,
+ 1368622240, 1371579614,
+ 1374261194 //current page
+ );
+ private $pageid = 'mailinglist';
+
+ function setup() {
+ parent::setup();
+ global $cache_revinfo;
+ $cache =& $cache_revinfo;
+ if(isset($cache['nonexist'])) {
+ unset($cache['nonexist']);
+ }
+ if(isset($cache['mailinglist'])) {
+ unset($cache['mailinglist']);
+ }
+ }
+
+ /**
+ * no nonexist.changes meta file available
+ */
+ function test_changemetadatanotexists() {
+ $rev1 = 1362526767;
+ $rev2 = 1362527164;
+ $max = 50;
+ $id = 'nonexist';
+ $revsexpected = array(array(), array());
+
+ $pagelog = new PageChangeLog($id, $chunk_size = 8192);
+ $revs = $pagelog->getRevisionsAround($rev1, $rev2, $max);
+ $this->assertEquals($revsexpected, $revs);
+ }
+
+ /**
+ * Surrounding revisions of rev1 and rev2 overlaps
+ */
+ function test_request_overlapping() {
+ $rev1 = 1362526767;
+ $rev2 = 1362527164;
+ $max = 10;
+ $revsexpected = array(
+ array_slice($this->revsexpected, 5, 11),
+ array_slice($this->revsexpected, 8, 11)
+ );
+
+ $pagelog = new PageChangeLog($this->pageid, $chunk_size = 8192);
+ $revs = $pagelog->getRevisionsAround($rev1, $rev2, $max);
+ $this->assertEquals($revsexpected, $revs);
+
+ $pagelog = new PageChangeLog($this->pageid, $chunk_size = 512);
+ $revs = $pagelog->getRevisionsAround($rev1, $rev2, $max);
+ $this->assertEquals($revsexpected, $revs);
+
+ $pagelog = new PageChangeLog($this->pageid, $chunk_size = 20);
+ $revs = $pagelog->getRevisionsAround($rev1, $rev2, $max);
+ $this->assertEquals($revsexpected, $revs);
+ }
+
+ /**
+ * Surrounding revisions of rev1 and rev2 don't overlap.
+ */
+ function test_request_non_overlapping() {
+ $rev1 = 1362525899;
+ $rev2 = 1368612599;
+ $max = 10;
+ $revsexpected = array(
+ array_slice($this->revsexpected, 0, 11),
+ array_slice($this->revsexpected, 13, 11)
+ );
+
+ $pagelog = new PageChangeLog($this->pageid, $chunk_size = 8192);
+ $revs = $pagelog->getRevisionsAround($rev1, $rev2, $max);
+ $this->assertEquals($revsexpected, $revs);
+
+ $pagelog = new PageChangeLog($this->pageid, $chunk_size = 512);
+ $revs = $pagelog->getRevisionsAround($rev1, $rev2, $max);
+ $this->assertEquals($revsexpected, $revs);
+
+ $pagelog = new PageChangeLog($this->pageid, $chunk_size = 20);
+ $revs = $pagelog->getRevisionsAround($rev1, $rev2, $max);
+ $this->assertEquals($revsexpected, $revs);
+ }
+
+ /**
+ * rev1 and rev2 are at start and end of the changelog.
+ * Should return still a number of revisions equal to max
+ */
+ function test_request_first_last() {
+ $rev1 = 1360110636;
+ $rev2 = 1374261194;
+ $max = 10;
+ $revsexpected = array(
+ array_slice($this->revsexpected, 0, 11),
+ array_slice($this->revsexpected, 13, 11)
+ );
+
+ $pagelog = new PageChangeLog($this->pageid, $chunk_size = 8192);
+ $revs = $pagelog->getRevisionsAround($rev1, $rev2, $max);
+ $this->assertEquals($revsexpected, $revs);
+
+ $pagelog = new PageChangeLog($this->pageid, $chunk_size = 512);
+ $revs = $pagelog->getRevisionsAround($rev1, $rev2, $max);
+ $this->assertEquals($revsexpected, $revs);
+
+ $pagelog = new PageChangeLog($this->pageid, $chunk_size = 20);
+ $revs = $pagelog->getRevisionsAround($rev1, $rev2, $max);
+ $this->assertEquals($revsexpected, $revs);
+ }
+
+
+ /**
+ * Number of requested revisions is larger than available revisions,
+ * so returns whole log
+ */
+ function test_request_wholelog() {
+ $rev1 = 1362525899;
+ $rev2 = 1368612599;
+ $max = 50;
+ $revsexpected = array($this->revsexpected, $this->revsexpected);
+
+ $pagelog = new PageChangeLog($this->pageid, $chunk_size = 8192);
+ $revs = $pagelog->getRevisionsAround($rev1, $rev2, $max);
+ $this->assertEquals($revsexpected, $revs);
+
+ $pagelog = new PageChangeLog($this->pageid, $chunk_size = 512);
+ $revs = $pagelog->getRevisionsAround($rev1, $rev2, $max);
+ $this->assertEquals($revsexpected, $revs);
+
+ $pagelog = new PageChangeLog($this->pageid, $chunk_size = 20);
+ $revs = $pagelog->getRevisionsAround($rev1, $rev2, $max);
+ $this->assertEquals($revsexpected, $revs);
+ }
+
+ /**
+ * When rev1 > rev2, their order is changed
+ */
+ function test_request_wrong_order_revs() {
+ $rev1 = 1362527164;
+ $rev2 = 1362526767;
+ $max = 10;
+ $revsexpected = array(
+ array_slice($this->revsexpected, 5, 11),
+ array_slice($this->revsexpected, 8, 11)
+ );
+
+ $pagelog = new PageChangeLog($this->pageid, $chunk_size = 8192);
+ $revs = $pagelog->getRevisionsAround($rev1, $rev2, $max);
+ $this->assertEquals($revsexpected, $revs);
+
+ $pagelog = new PageChangeLog($this->pageid, $chunk_size = 512);
+ $revs = $pagelog->getRevisionsAround($rev1, $rev2, $max);
+ $this->assertEquals($revsexpected, $revs);
+
+ $pagelog = new PageChangeLog($this->pageid, $chunk_size = 20);
+ $revs = $pagelog->getRevisionsAround($rev1, $rev2, $max);
+ $this->assertEquals($revsexpected, $revs);
+ }
+
+} \ No newline at end of file
diff --git a/_test/tests/inc/changelog_getrelativerevision.test.php b/_test/tests/inc/changelog_getrelativerevision.test.php
new file mode 100644
index 000000000..f9962066a
--- /dev/null
+++ b/_test/tests/inc/changelog_getrelativerevision.test.php
@@ -0,0 +1,418 @@
+<?php
+
+/**
+ * Tests for requesting revisioninfo of a revision of a page with getRevisionInfo()
+ *
+ * This class uses the files:
+ * - data/pages/mailinglist.txt
+ * - data/meta/mailinglist.changes
+ */
+class changelog_getrelativerevision_test extends DokuWikiTest {
+
+ private $logline = "1362525899 127.0.0.1 E mailinglist pubcie [Data entry] \n";
+ private $pageid = 'mailinglist';
+
+ function setup() {
+ parent::setup();
+ global $cache_revinfo;
+ $cache =& $cache_revinfo;
+ if(isset($cache['nonexist'])) {
+ unset($cache['nonexist']);
+ }
+ if(isset($cache['mailinglist'])) {
+ unset($cache['mailinglist']);
+ }
+ }
+
+ /**
+ * no nonexist.changes meta file available
+ */
+ function test_changemetadatanotexists() {
+ $rev = 1362525899;
+ $dir = 1;
+ $id = 'nonexist';
+ $revsexpected = false;
+
+ $pagelog = new PageChangeLog($id, $chunk_size = 8192);
+ $revs = $pagelog->getRelativeRevision($rev, $dir);
+ $this->assertEquals($revsexpected, $revs);
+ }
+
+ /**
+ * no nonexist.changes meta file available
+ */
+ function test_nodirection() {
+ $rev = 1362525899;
+ $dir = 0;
+ $revsexpected = false;
+
+ $pagelog = new PageChangeLog($this->pageid, $chunk_size = 8192);
+ $revs = $pagelog->getRelativeRevision($rev, $dir);
+ $this->assertEquals($revsexpected, $revs);
+ }
+
+ /**
+ * start at exact current revision of mailinglist page
+ *
+ */
+ function test_startatexactcurrentrev() {
+ $rev = 1385051947;
+ $dir = 1;
+ $revsexpectedpos = false;
+ $revsexpectedneg = 1374261194;
+
+ //set a known timestamp
+ touch(wikiFN($this->pageid), $rev);
+
+ $pagelog = new PageChangeLog($this->pageid, $chunk_size = 8192);
+ $revs = $pagelog->getRelativeRevision($rev, $dir);
+ $this->assertEquals($revsexpectedpos, $revs);
+
+ $revs = $pagelog->getRelativeRevision($rev, -$dir);
+ $this->assertEquals($revsexpectedneg, $revs);
+ }
+
+ /**
+ * start at exact last revision of mailinglist page
+ *
+ */
+ function test_startatexactlastrev() {
+ $rev = 1360110636;
+ $dir = 1;
+ $revsexpectedpos = 1361901536;
+ $revsexpectedneg = false;
+
+ $pagelog = new PageChangeLog($this->pageid, $chunk_size = 8192);
+ $revs = $pagelog->getRelativeRevision($rev, $dir);
+ $this->assertEquals($revsexpectedpos, $revs);
+
+ $revs = $pagelog->getRelativeRevision($rev, -$dir);
+ $this->assertEquals($revsexpectedneg, $revs);
+ }
+
+ /**
+ * start at exact one before last revision of mailinglist page
+ *
+ */
+ function test_requestlastrevisions() {
+ $rev = 1361901536;
+ $dir = -1;
+ $revsexpectedlast = 1360110636;
+ $revsexpectedbeforelast = false;
+
+ $pagelog = new PageChangeLog($this->pageid, $chunk_size = 8192);
+ $revs = $pagelog->getRelativeRevision($rev, $dir);
+ $this->assertEquals($revsexpectedlast, $revs);
+
+ $revs = $pagelog->getRelativeRevision($rev, 2 * $dir);
+ $this->assertEquals($revsexpectedbeforelast, $revs);
+ }
+
+ /**
+ * request existing rev and check cache
+ */
+ function test_requestrev_checkcache() {
+ $rev = 1362525359;
+ $dir = 1;
+ $revexpected = 1362525899;
+ $infoexpected = parseChangelogLine($this->logline);
+
+ $pagelog = new PageChangeLog($this->pageid, $chunk_size = 8192);
+ $revfound = $pagelog->getRelativeRevision($rev, $dir);
+ $this->assertEquals($revexpected, $revfound);
+
+ //checked info returned from cache
+ $info = $pagelog->getRevisionInfo($revfound);
+ $this->assertEquals($infoexpected, $info);
+ }
+
+ /**
+ * request existing rev
+ */
+ function test_requestnextrev() {
+ $rev = 1362525899;
+
+ $pagelog = new PageChangeLog($this->pageid, $chunk_size = 8192);
+
+ $dir = 1;
+ $revexpected = 1362525926;
+ $revfound = $pagelog->getRelativeRevision($rev, $dir);
+ $this->assertEquals($revexpected, $revfound);
+
+ $dir = 2;
+ $revexpected = 1362526039;
+ $revfound = $pagelog->getRelativeRevision($rev, $dir);
+ $this->assertEquals($revexpected, $revfound);
+
+ $dir = -1;
+ $revexpected = 1362525359;
+ $revfound = $pagelog->getRelativeRevision($rev, $dir);
+ $this->assertEquals($revexpected, $revfound);
+
+ $dir = -2;
+ $revexpected = 1362525145;
+ $revfound = $pagelog->getRelativeRevision($rev, $dir);
+ $this->assertEquals($revexpected, $revfound);
+ }
+
+ /**
+ * request existing rev with chucked reading
+ */
+ function test_requestnextrev_chuncked() {
+ $rev = 1362525899;
+
+ $pagelog = new PageChangeLog($this->pageid, $chunk_size = 512);
+
+ $dir = 1;
+ $revexpected = 1362525926;
+ $revfound = $pagelog->getRelativeRevision($rev, $dir);
+ $this->assertEquals($revexpected, $revfound);
+
+ $dir = 2;
+ $revexpected = 1362526039;
+ $revfound = $pagelog->getRelativeRevision($rev, $dir);
+ $this->assertEquals($revexpected, $revfound);
+
+ $dir = -1;
+ $revexpected = 1362525359;
+ $revfound = $pagelog->getRelativeRevision($rev, $dir);
+ $this->assertEquals($revexpected, $revfound);
+
+ $dir = -2;
+ $revexpected = 1362525145;
+ $revfound = $pagelog->getRelativeRevision($rev, $dir);
+ $this->assertEquals($revexpected, $revfound);
+ }
+
+
+ /**
+ * request existing rev with chucked reading, chunk size smaller than line length
+ */
+ function test_requestnextrev_chunkshorterthanlines() {
+ $rev = 1362525899;
+
+ $pagelog = new PageChangeLog($this->pageid, $chunk_size = 20);
+
+ $dir = 1;
+ $revexpected = 1362525926;
+ $revfound = $pagelog->getRelativeRevision($rev, $dir);
+ $this->assertEquals($revexpected, $revfound);
+
+ $dir = 2;
+ $revexpected = 1362526039;
+ $revfound = $pagelog->getRelativeRevision($rev, $dir);
+ $this->assertEquals($revexpected, $revfound);
+
+ $dir = -1;
+ $revexpected = 1362525359;
+ $revfound = $pagelog->getRelativeRevision($rev, $dir);
+ $this->assertEquals($revexpected, $revfound);
+
+ $dir = -2;
+ $revexpected = 1362525145;
+ $revfound = $pagelog->getRelativeRevision($rev, $dir);
+ $this->assertEquals($revexpected, $revfound);
+ }
+
+ /**
+ * request existing rev
+ */
+ function test_requestnextfifthrev() {
+ $rev = 1362525899;
+ $dir = 5;
+ $revexpected = 1362526767;
+
+ $pagelog = new PageChangeLog($this->pageid, $chunk_size = 8192);
+ $revfound = $pagelog->getRelativeRevision($rev, $dir);
+ $this->assertEquals($revexpected, $revfound);
+ }
+
+ /**
+ * request existing rev with chucked reading
+ */
+ function test_requestnextfifthrev_chuncked() {
+ $rev = 1362525899;
+ $dir = 5;
+ $revexpected = 1362526767;
+
+ $pagelog = new PageChangeLog($this->pageid, $chunk_size = 512);
+ $revfound = $pagelog->getRelativeRevision($rev, $dir);
+ $this->assertEquals($revexpected, $revfound);
+ }
+
+ /**
+ * request existing rev
+ */
+ function test_requestprevrev() {
+ $rev = 1362525899;
+ $dir1 = -1;
+ $dir5 = -5;
+ $revexpected1 = 1362525359;
+ $revexpected5 = 1360110636;
+
+ $pagelog = new PageChangeLog($this->pageid, $chunk_size = 8192);
+ $revfound1 = $pagelog->getRelativeRevision($rev, $dir1);
+ $this->assertEquals($revexpected1, $revfound1);
+
+ $revfound5 = $pagelog->getRelativeRevision($rev, $dir5);
+ $this->assertEquals($revexpected5, $revfound5);
+ }
+
+ /**
+ * request existing rev with chucked reading
+ */
+ function test_requestprevrev_chuncked() {
+ $rev = 1362525899;
+ $dir1 = -1;
+ $dir5 = -5;
+ $revexpected1 = 1362525359;
+ $revexpected5 = 1360110636;
+
+ $pagelog = new PageChangeLog($this->pageid, $chunk_size = 512);
+ $revfound1 = $pagelog->getRelativeRevision($rev, $dir1);
+ $this->assertEquals($revexpected1, $revfound1);
+
+ $revfound5 = $pagelog->getRelativeRevision($rev, $dir5);
+ $this->assertEquals($revexpected5, $revfound5);
+ }
+
+ /**
+ * request after recentest version in changelog
+ */
+ function test_requestrecentestlogline_next() {
+ $rev = 1374261194;
+ $dir = 1;
+ $revexpected = false;
+
+ $pagelog = new PageChangeLog($this->pageid, $chunk_size = 8192);
+ $revfound = $pagelog->getRelativeRevision($rev, $dir);
+ $this->assertEquals($revexpected, $revfound);
+ }
+
+ /**
+ * request after recentest version in changelog, with chuncked reading
+ */
+ function test_requestrecentestlogline_next_chuncked() {
+ $rev = 1374261194;
+ $dir = 1;
+ $revexpected = false;
+
+ $pagelog = new PageChangeLog($this->pageid, $chunk_size = 512);
+ $revfound = $pagelog->getRelativeRevision($rev, $dir);
+ $this->assertEquals($revexpected, $revfound);
+ }
+
+ /**
+ * request before current version
+ */
+ function test_requestrecentestlogline_prev() {
+ $rev = 1374261194;
+ $dir = -1;
+ $revexpected = 1371579614;
+
+ $pagelog = new PageChangeLog($this->pageid, $chunk_size = 8192);
+ $revfound = $pagelog->getRelativeRevision($rev, $dir);
+ $this->assertEquals($revexpected, $revfound);
+ }
+
+ /**
+ * request before current version, with chuncked reading
+ */
+ function test_requestrecentestlogline_prev_chuncked() {
+ $rev = 1374261194;
+ $dir = -1;
+ $revexpected = 1371579614;
+
+ $pagelog = new PageChangeLog($this->pageid, $chunk_size = 512);
+ $revfound = $pagelog->getRelativeRevision($rev, $dir);
+ $this->assertEquals($revexpected, $revfound);
+ }
+
+ /**
+ * Request negative revision
+ * looks in positive direction, so it catches the oldest revision
+ */
+ function test_negativerev_posdir() {
+ $rev = -10;
+ $dir = 1;
+ $revexpected = 1360110636;
+
+ $pagelog = new PageChangeLog($this->pageid, $chunk_size = 8192);
+ $revfound = $pagelog->getRelativeRevision($rev, $dir);
+ $this->assertEquals($revexpected, $revfound);
+ }
+
+ /**
+ * Request negative revision
+ * looks in negative direction, but there is nothing
+ */
+ function test_negativerev_negdir() {
+ $rev = -10;
+ $dir = -1;
+ $revexpected = false;
+
+ $pagelog = new PageChangeLog($this->pageid, $chunk_size = 8192);
+ $revfound = $pagelog->getRelativeRevision($rev, $dir);
+ $this->assertEquals($revexpected, $revfound);
+ }
+
+ /**
+ * Start at non existing revision somewhere between existing revisions
+ */
+ function test_startatnotexistingrev_next() {
+ $rev = 1362525890;
+ $dir = 1;
+ $revexpected = 1362525899;
+
+ $pagelog = new PageChangeLog($this->pageid, $chunk_size = 8192);
+ $revfound = $pagelog->getRelativeRevision($rev, $dir);
+ $this->assertEquals($revexpected, $revfound);
+ }
+
+ /**
+ * Start at non existing revision somewhere between existing revisions
+ */
+ function test_startatnotexistingrev_prev() {
+ $rev = 1362525890;
+ $dir = -1;
+ $revexpected = 1362525359;
+
+ $pagelog = new PageChangeLog($this->pageid, $chunk_size = 8192);
+ $revfound = $pagelog->getRelativeRevision($rev, $dir);
+ $this->assertEquals($revexpected, $revfound);
+ }
+
+ function test_iscurrentpagerevision() {
+ $rev = 1385051947;
+ $currentexpected = true;
+
+ //set a known timestamp
+ touch(wikiFN($this->pageid), $rev);
+
+ $pagelog = new PageChangeLog($this->pageid, $chunk_size = 8192);
+ $current = $pagelog->isCurrentRevision($rev);
+ $this->assertEquals($currentexpected, $current);
+ }
+
+ function test_isnotcurrentpagerevision() {
+ $rev = 1385051947;
+ $not_current_rev = $rev - 1;
+ $currentexpected = false;
+
+ //set a known timestamp
+ touch(wikiFN($this->pageid), $rev);
+
+ $pagelog = new PageChangeLog($this->pageid, $chunk_size = 8192);
+ $current = $pagelog->isCurrentRevision($not_current_rev);
+ $this->assertEquals($currentexpected, $current);
+ }
+
+ function test_notexistingcurrentpage() {
+ $rev = 1385051947;
+ $currentexpected = false;
+
+ $pagelog = new PageChangeLog('nonexistingpage', $chunk_size = 8192);
+ $current = $pagelog->isCurrentRevision($rev);
+ $this->assertEquals($currentexpected, $current);
+ }
+} \ No newline at end of file
diff --git a/_test/tests/inc/changelog_getrevisioninfo.test.php b/_test/tests/inc/changelog_getrevisioninfo.test.php
index 9637d21c8..79b31d68e 100644
--- a/_test/tests/inc/changelog_getrevisioninfo.test.php
+++ b/_test/tests/inc/changelog_getrevisioninfo.test.php
@@ -21,7 +21,7 @@ class changelog_getrevisionsinfo_test extends DokuWikiTest {
unset($cache['nonexist']);
}
if(isset($cache['mailinglist'])) {
- unset($cache['nonexist']);
+ unset($cache['mailinglist']);
}
}
@@ -29,11 +29,12 @@ class changelog_getrevisionsinfo_test extends DokuWikiTest {
* no nonexist.changes meta file available
*/
function test_changemetadatanotexists() {
- $rev = 1362525899;
- $id = 'nonexist';
+ $rev = 1362525899;
+ $id = 'nonexist';
$revsexpected = false;
- $revs = getRevisionInfo($id, $rev, $chunk_size = 8192, $media = false);
+ $pagelog = new PageChangeLog($id, $chunk_size = 8192);
+ $revs = $pagelog->getRevisionInfo($rev);
$this->assertEquals($revsexpected, $revs);
}
@@ -41,13 +42,14 @@ class changelog_getrevisionsinfo_test extends DokuWikiTest {
* request existing rev
*/
function test_requestrev() {
- $rev = 1362525899;
+ $rev = 1362525899;
$infoexpected = parseChangelogLine($this->logline);
- $info = getRevisionInfo($this->pageid, $rev, $chunk_size = 8192, $media = false);
+ $pagelog = new PageChangeLog($this->pageid, $chunk_size = 8192);
+ $info = $pagelog->getRevisionInfo($rev);
$this->assertEquals($infoexpected, $info);
//returns cached value
- $info = getRevisionInfo($this->pageid, $rev, $chunk_size = 8192, $media = false);
+ $info = $pagelog->getRevisionInfo($rev);
$this->assertEquals($infoexpected, $info);
}
@@ -55,10 +57,23 @@ class changelog_getrevisionsinfo_test extends DokuWikiTest {
* request existing rev with chucked reading
*/
function test_requestrev_chuncked() {
- $rev = 1362525899;
+ $rev = 1362525899;
+ $infoexpected = parseChangelogLine($this->logline);
+
+ $pagelog = new PageChangeLog($this->pageid, $chunk_size = 512);
+ $info = $pagelog->getRevisionInfo($rev);
+ $this->assertEquals($infoexpected, $info);
+ }
+
+ /**
+ * request existing rev with chucked reading
+ */
+ function test_requestrev_chunckedsmallerthanlinelength() {
+ $rev = 1362525899;
$infoexpected = parseChangelogLine($this->logline);
- $info = getRevisionInfo($this->pageid, $rev, $chunk_size = 512, $media = false);
+ $pagelog = new PageChangeLog($this->pageid, $chunk_size = 20);
+ $info = $pagelog->getRevisionInfo($rev);
$this->assertEquals($infoexpected, $info);
}
@@ -66,13 +81,14 @@ class changelog_getrevisionsinfo_test extends DokuWikiTest {
* request current version
*/
function test_requestrecentestlogline() {
- $rev = 1374261194;
+ $rev = 1374261194;
$infoexpected = parseChangelogLine($this->firstlogline);
- $info = getRevisionInfo($this->pageid, $rev, $chunk_size = 8192, $media = false);
+ $pagelog = new PageChangeLog($this->pageid, $chunk_size = 8192);
+ $info = $pagelog->getRevisionInfo($rev);
$this->assertEquals($infoexpected, $info);
//returns cached value
- $info = getRevisionInfo($this->pageid, $rev, $chunk_size = 8192, $media = false);
+ $info = $pagelog->getRevisionInfo($rev);
$this->assertEquals($infoexpected, $info);
}
@@ -80,10 +96,11 @@ class changelog_getrevisionsinfo_test extends DokuWikiTest {
* request current version, with chuncked reading
*/
function test_requestrecentestlogline_chuncked() {
- $rev = 1374261194;
+ $rev = 1374261194;
$infoexpected = parseChangelogLine($this->firstlogline);
- $info = getRevisionInfo($this->pageid, $rev, $chunk_size = 512, $media = false);
+ $pagelog = new PageChangeLog($this->pageid, $chunk_size = 512);
+ $info = $pagelog->getRevisionInfo($rev);
$this->assertEquals($infoexpected, $info);
}
@@ -93,7 +110,8 @@ class changelog_getrevisionsinfo_test extends DokuWikiTest {
function test_negativerev() {
$rev = -10;
- $info = getRevisionInfo($this->pageid, $rev, $chunk_size = 8192, $media = false);
+ $pagelog = new PageChangeLog($this->pageid, $chunk_size = 8192);
+ $info = $pagelog->getRevisionInfo($rev);
$this->assertEquals(false, $info);
}
@@ -103,7 +121,8 @@ class changelog_getrevisionsinfo_test extends DokuWikiTest {
function test_notexistingrev() {
$rev = 1362525890;
- $info = getRevisionInfo($this->pageid, $rev, $chunk_size = 8192, $media = false);
+ $pagelog = new PageChangeLog($this->pageid, $chunk_size = 8192);
+ $info = $pagelog->getRevisionInfo($rev);
$this->assertEquals(false, $info);
}
@@ -111,10 +130,11 @@ class changelog_getrevisionsinfo_test extends DokuWikiTest {
* sometimes chuncksize is set to true
*/
function test_chuncksizetrue() {
- $rev = 1362525899;
+ $rev = 1362525899;
$infoexpected = parseChangelogLine($this->logline);
- $info = getRevisionInfo($this->pageid, $rev, true);
+ $pagelog = new PageChangeLog($this->pageid, true);
+ $info = $pagelog->getRevisionInfo($rev);
$this->assertEquals($infoexpected, $info);
}
} \ No newline at end of file
diff --git a/_test/tests/inc/changelog_getrevisions.test.php b/_test/tests/inc/changelog_getrevisions.test.php
index a9be26dae..b247ce3d6 100644
--- a/_test/tests/inc/changelog_getrevisions.test.php
+++ b/_test/tests/inc/changelog_getrevisions.test.php
@@ -36,7 +36,7 @@ class changelog_getrevisions_test extends DokuWikiTest {
unset($cache['nonexist']);
}
if(isset($cache['mailinglist'])) {
- unset($cache['nonexist']);
+ unset($cache['mailinglist']);
}
}
@@ -45,11 +45,12 @@ class changelog_getrevisions_test extends DokuWikiTest {
*/
function test_changemetadatanotexists() {
$first = 0;
- $num = 1;
- $id = 'nonexist';
-
- $revs = getRevisions($id, $first, $num, $chunk_size = 8192, $media = false);
+ $num = 1;
+ $id = 'nonexist';
$revsexpected = array();
+
+ $pagelog = new PageChangeLog($id, $chunk_size = 8192);
+ $revs = $pagelog->getRevisions($first, $num);
$this->assertEquals($revsexpected, $revs);
}
@@ -58,14 +59,20 @@ class changelog_getrevisions_test extends DokuWikiTest {
* (so skips first line which belongs to the current existing page)
*/
function test_requestlastrev() {
- $first = 0;
- $num = 1;
+ $first = 0;
+ $num = 1;
$revsexpected = array($this->revsexpected[1]);
- $revs = getRevisions($this->pageid, $first, $num, $chunk_size = 8192, $media = false);
+ $pagelog = new PageChangeLog($this->pageid, $chunk_size = 8192);
+ $revs = $pagelog->getRevisions($first, $num);
+ $this->assertEquals($revsexpected, $revs);
+
+ $pagelog = new PageChangeLog($this->pageid, $chunk_size = 512);
+ $revs = $pagelog->getRevisions($first, $num);
$this->assertEquals($revsexpected, $revs);
- $revs = getRevisions($this->pageid, $first, $num, $chunk_size = 512, $media = false);
+ $pagelog = new PageChangeLog($this->pageid, $chunk_size = 20);
+ $revs = $pagelog->getRevisions($first, $num);
$this->assertEquals($revsexpected, $revs);
}
@@ -74,14 +81,20 @@ class changelog_getrevisions_test extends DokuWikiTest {
* (so skips first line which belongs to the current existing page)
*/
function test_requestonebutlastrev() {
- $first = 1;
- $num = 1;
+ $first = 1;
+ $num = 1;
$revsexpected = array($this->revsexpected[2]);
- $revs = getRevisions($this->pageid, $first, $num, $chunk_size = 8192, $media = false);
+ $pagelog = new PageChangeLog($this->pageid, $chunk_size = 8192);
+ $revs = $pagelog->getRevisions($first, $num);
$this->assertEquals($revsexpected, $revs);
- $revs = getRevisions($this->pageid, $first, $num, $chunk_size = 512, $media = false);
+ $pagelog = new PageChangeLog($this->pageid, $chunk_size = 512);
+ $revs = $pagelog->getRevisions($first, $num);
+ $this->assertEquals($revsexpected, $revs);
+
+ $pagelog = new PageChangeLog($this->pageid, $chunk_size = 20);
+ $revs = $pagelog->getRevisions($first, $num);
$this->assertEquals($revsexpected, $revs);
}
@@ -90,14 +103,20 @@ class changelog_getrevisions_test extends DokuWikiTest {
* (so skips first line of current existing page)
*/
function test_requestrevswithoffset() {
- $first = 10;
- $num = 5;
+ $first = 10;
+ $num = 5;
$revsexpected = array_slice($this->revsexpected, $first + 1, $num);
- $revs = getRevisions($this->pageid, $first, $num, $chunk_size = 8192, $media = false);
+ $pagelog = new PageChangeLog($this->pageid, $chunk_size = 8192);
+ $revs = $pagelog->getRevisions($first, $num);
+ $this->assertEquals($revsexpected, $revs);
+
+ $pagelog = new PageChangeLog($this->pageid, $chunk_size = 512);
+ $revs = $pagelog->getRevisions($first, $num);
$this->assertEquals($revsexpected, $revs);
- $revs = getRevisions($this->pageid, $first, $num, $chunk_size = 512, $media = false);
+ $pagelog = new PageChangeLog($this->pageid, $chunk_size = 20);
+ $revs = $pagelog->getRevisions($first, $num);
$this->assertEquals($revsexpected, $revs);
}
@@ -105,14 +124,16 @@ class changelog_getrevisions_test extends DokuWikiTest {
* first = -1 requests recentest logline, without skipping
*/
function test_requestrecentestlogline() {
- $first = -1;
- $num = 1;
+ $first = -1;
+ $num = 1;
$revsexpected = array($this->revsexpected[0]);
- $revs = getRevisions($this->pageid, $first, $num, $chunk_size = 8192, $media = false);
+ $pagelog = new PageChangeLog($this->pageid, $chunk_size = 8192);
+ $revs = $pagelog->getRevisions($first, $num);
$this->assertEquals($revsexpected, $revs);
- $revs = getRevisions($this->pageid, $first, $num, $chunk_size = 512, $media = false);
+ $pagelog = new PageChangeLog($this->pageid, $chunk_size = 512);
+ $revs = $pagelog->getRevisions($first, $num);
$this->assertEquals($revsexpected, $revs);
}
@@ -120,11 +141,12 @@ class changelog_getrevisions_test extends DokuWikiTest {
* chunck size = 0 skips chuncked loading
*/
function test_wholefile() {
- $first = 0;
- $num = 1000;
+ $first = 0;
+ $num = 1000;
$revsexpected = array_slice($this->revsexpected, 1);
- $revs = getRevisions($this->pageid, $first, $num, $chunk_size = 0, $media = false);
+ $pagelog = new PageChangeLog($this->pageid, $chunk_size = 0);
+ $revs = $pagelog->getRevisions($first, $num);
$this->assertEquals($revsexpected, $revs);
}
@@ -132,14 +154,16 @@ class changelog_getrevisions_test extends DokuWikiTest {
* Negative range returns no result
*/
function test_negativenum() {
- $first = 0;
- $num = -10;
+ $first = 0;
+ $num = -10;
$revsexpected = array();
- $revs = getRevisions($this->pageid, $first, $num, $chunk_size = 8192, $media = false);
+ $pagelog = new PageChangeLog($this->pageid, $chunk_size = 8192);
+ $revs = $pagelog->getRevisions($first, $num);
$this->assertEquals($revsexpected, $revs);
- $revs = getRevisions($this->pageid, $first, $num, $chunk_size = 512, $media = false);
+ $pagelog = new PageChangeLog($this->pageid, $chunk_size = 512);
+ $revs = $pagelog->getRevisions($first, $num);
$this->assertEquals($revsexpected, $revs);
}
@@ -147,14 +171,16 @@ class changelog_getrevisions_test extends DokuWikiTest {
* Negative range returns no result
*/
function test_negativennumoffset() {
- $first = 2;
- $num = -10;
+ $first = 2;
+ $num = -10;
$revsexpected = array();
- $revs = getRevisions($this->pageid, $first, $num, $chunk_size = 8192, $media = false);
+ $pagelog = new PageChangeLog($this->pageid, $chunk_size = 8192);
+ $revs = $pagelog->getRevisions($first, $num);
$this->assertEquals($revsexpected, $revs);
- $revs = getRevisions($this->pageid, $first, $num, $chunk_size = 512, $media = false);
+ $pagelog = new PageChangeLog($this->pageid, $chunk_size = 512);
+ $revs = $pagelog->getRevisions($first, $num);
$this->assertEquals($revsexpected, $revs);
}
@@ -162,14 +188,16 @@ class changelog_getrevisions_test extends DokuWikiTest {
* zero range returns no result
*/
function test_zeronum() {
- $first = 5;
- $num = 0;
+ $first = 5;
+ $num = 0;
$revsexpected = array();
- $revs = getRevisions($this->pageid, $first, $num, $chunk_size = 8192, $media = false);
+ $pagelog = new PageChangeLog($this->pageid, $chunk_size = 8192);
+ $revs = $pagelog->getRevisions($first, $num);
$this->assertEquals($revsexpected, $revs);
- $revs = getRevisions($this->pageid, $first, $num, $chunk_size = 512, $media = false);
+ $pagelog = new PageChangeLog($this->pageid, $chunk_size = 512);
+ $revs = $pagelog->getRevisions($first, $num);
$this->assertEquals($revsexpected, $revs);
}
@@ -177,11 +205,12 @@ class changelog_getrevisions_test extends DokuWikiTest {
* get oldest revisions
*/
function test_requestlargeoffset() {
- $first = 22;
- $num = 50;
+ $first = 22;
+ $num = 50;
$revsexpected = array_slice($this->revsexpected, $first + 1);
- $revs = getRevisions($this->pageid, $first, $num, $chunk_size = 8192, $media = false);
+ $pagelog = new PageChangeLog($this->pageid, $chunk_size = 8192);
+ $revs = $pagelog->getRevisions($first, $num);
$this->assertEquals($revsexpected, $revs);
}
@@ -189,11 +218,12 @@ class changelog_getrevisions_test extends DokuWikiTest {
* request with too large offset and range
*/
function test_requesttoolargenumberrevs() {
- $first = 50;
- $num = 50;
+ $first = 50;
+ $num = 50;
$revsexpected = array();
- $revs = getRevisions($this->pageid, $first, $num, $chunk_size = 8192, $media = false);
+ $pagelog = new PageChangeLog($this->pageid, $chunk_size = 8192);
+ $revs = $pagelog->getRevisions($first, $num);
$this->assertEquals($revsexpected, $revs);
}
diff --git a/feed.php b/feed.php
index bdce666d2..7a6925d37 100644
--- a/feed.php
+++ b/feed.php
@@ -293,7 +293,8 @@ function rss_buildItems(&$rss, &$data, $opt) {
case 'diff':
case 'htmldiff':
if($ditem['media']) {
- $revs = getRevisions($id, 0, 1, 8192, true);
+ $medialog = new MediaChangeLog($id);
+ $revs = $medialog->getRevisions(0, 1);
$rev = $revs[0];
$src_r = '';
$src_l = '';
@@ -318,7 +319,8 @@ function rss_buildItems(&$rss, &$data, $opt) {
} else {
require_once(DOKU_INC.'inc/DifferenceEngine.php');
- $revs = getRevisions($id, 0, 1);
+ $pagelog = new PageChangeLog($id);
+ $revs = $pagelog->getRevisions(0, 1);
$rev = $revs[0];
if($rev) {
diff --git a/inc/RemoteAPICore.php b/inc/RemoteAPICore.php
index a26c2d0de..ffa03ee93 100644
--- a/inc/RemoteAPICore.php
+++ b/inc/RemoteAPICore.php
@@ -378,7 +378,8 @@ class RemoteAPICore {
throw new RemoteException('The requested page does not exist', 121);
}
- $info = getRevisionInfo($id, $time, 1024);
+ $pagelog = new PageChangeLog($id, 1024);
+ $info = $pagelog->getRevisionInfo($time);
$data = array(
'name' => $id,
@@ -650,11 +651,12 @@ class RemoteAPICore {
throw new RemoteException('Empty page ID', 131);
}
- $revisions = getRevisions($id, $first, $conf['recent']+1);
+ $pagelog = new PageChangeLog($id);
+ $revisions = $pagelog->getRevisions($first, $conf['recent']+1);
if(count($revisions)==0 && $first!=0) {
$first=0;
- $revisions = getRevisions($id, $first, $conf['recent']+1);
+ $revisions = $pagelog->getRevisions($first, $conf['recent']+1);
}
if(count($revisions)>0 && $first==0) {
@@ -676,7 +678,8 @@ class RemoteAPICore {
// case this can lead to less pages being returned than
// specified via $conf['recent']
if($time){
- $info = getRevisionInfo($id, $time, 1024);
+ $pagelog->setChunkSize(1024);
+ $info = $pagelog->getRevisionInfo($time);
if(!empty($info)) {
$data['user'] = $info['user'];
$data['ip'] = $info['ip'];
diff --git a/inc/changelog.php b/inc/changelog.php
index 6ff1e0eca..dfcd1f241 100644
--- a/inc/changelog.php
+++ b/inc/changelog.php
@@ -334,95 +334,678 @@ function _handleRecent($line,$ns,$flags,&$seen){
}
/**
- * Get the changelog information for a specific page id
- * and revision (timestamp). Adjacent changelog lines
- * are optimistically parsed and cached to speed up
- * consecutive calls to getRevisionInfo. For large
- * changelog files, only the chunk containing the
- * requested changelog line is read.
- *
- * @author Ben Coburn <btcoburn@silicodon.net>
- * @author Kate Arzamastseva <pshns@ukr.net>
+ * Class ChangeLog
+ * methods for handling of changelog of pages or media files
*/
-function getRevisionInfo($id, $rev, $chunk_size=8192, $media=false) {
- global $cache_revinfo;
- $cache =& $cache_revinfo;
- if (!isset($cache[$id])) { $cache[$id] = array(); }
- $rev = max($rev, 0);
-
- // check if it's already in the memory cache
- if (isset($cache[$id]) && isset($cache[$id][$rev])) {
- return $cache[$id][$rev];
+abstract class ChangeLog {
+
+ /** @var string */
+ protected $id;
+ /** @var int */
+ protected $chunk_size;
+ /** @var array */
+ protected $cache;
+
+ /**
+ * Constructor
+ *
+ * @param string $id page id
+ * @param int $chunk_size maximum block size read from file
+ */
+ public function __construct($id, $chunk_size = 8192) {
+ global $cache_revinfo;
+
+ $this->cache =& $cache_revinfo;
+ if(!isset($this->cache[$id])) {
+ $this->cache[$id] = array();
+ }
+
+ $this->id = $id;
+ $this->setChunkSize($chunk_size);
+
}
- if ($media) {
- $file = mediaMetaFN($id, '.changes');
- } else {
- $file = metaFN($id, '.changes');
+ /**
+ * Set chunk size for file reading
+ * Chunk size zero let read whole file at once
+ *
+ * @param int $chunk_size maximum block size read from file
+ */
+ public function setChunkSize($chunk_size) {
+ if(!is_numeric($chunk_size)) $chunk_size = 0;
+
+ $this->chunk_size = (int) max($chunk_size, 0);
}
- if (!@file_exists($file)) { return false; }
- if (filesize($file)<$chunk_size || $chunk_size==0) {
- // read whole file
- $lines = file($file);
- if ($lines===false) { return false; }
- } else {
- // read by chunk
- $fp = fopen($file, 'rb'); // "file pointer"
- if ($fp===false) { return false; }
- $head = 0;
- fseek($fp, 0, SEEK_END);
- $tail = ftell($fp);
- $finger = 0;
- $finger_rev = 0;
-
- // find chunk
- while ($tail-$head>$chunk_size) {
- $finger = $head+floor(($tail-$head)/2.0);
- fseek($fp, $finger);
- fgets($fp); // slip the finger forward to a new line
- $finger = ftell($fp);
- $tmp = fgets($fp); // then read at that location
- $tmp = parseChangelogLine($tmp);
- $finger_rev = $tmp['date'];
- if ($finger==$head || $finger==$tail) { break; }
- if ($finger_rev>$rev) {
- $tail = $finger;
- } else {
- $head = $finger;
+
+ /**
+ * Returns path to changelog
+ *
+ * @return string path to file
+ */
+ abstract protected function getChangelogFilename();
+
+ /**
+ * Returns path to current page/media
+ *
+ * @return string path to file
+ */
+ abstract protected function getFilename();
+
+ /**
+ * Get the changelog information for a specific page id and revision (timestamp)
+ *
+ * Adjacent changelog lines are optimistically parsed and cached to speed up
+ * consecutive calls to getRevisionInfo. For large changelog files, only the chunk
+ * containing the requested changelog line is read.
+ *
+ * @param int $rev revision timestamp
+ * @return bool|array false or array with entries:
+ * - date: unix timestamp
+ * - ip: IPv4 address (127.0.0.1)
+ * - type: log line type
+ * - id: page id
+ * - user: user name
+ * - sum: edit summary (or action reason)
+ * - extra: extra data (varies by line type)
+ *
+ * @author Ben Coburn <btcoburn@silicodon.net>
+ * @author Kate Arzamastseva <pshns@ukr.net>
+ */
+ public function getRevisionInfo($rev) {
+ $rev = max($rev, 0);
+
+ // check if it's already in the memory cache
+ if(isset($this->cache[$this->id]) && isset($this->cache[$this->id][$rev])) {
+ return $this->cache[$this->id][$rev];
+ }
+
+ //read lines from changelog
+ list($fp, $lines) = $this->readloglines($rev);
+ if($fp) {
+ fclose($fp);
+ }
+ if(empty($lines)) return false;
+
+ // parse and cache changelog lines
+ foreach($lines as $value) {
+ $tmp = parseChangelogLine($value);
+ if($tmp !== false) {
+ $this->cache[$this->id][$tmp['date']] = $tmp;
}
}
+ if(!isset($this->cache[$this->id][$rev])) {
+ return false;
+ }
+ return $this->cache[$this->id][$rev];
+ }
+
+ /**
+ * Return a list of page revisions numbers
+ *
+ * Does not guarantee that the revision exists in the attic,
+ * only that a line with the date exists in the changelog.
+ * By default the current revision is skipped.
+ *
+ * The current revision is automatically skipped when the page exists.
+ * See $INFO['meta']['last_change'] for the current revision.
+ * A negative $first let read the current revision too.
+ *
+ * For efficiency, the log lines are parsed and cached for later
+ * calls to getRevisionInfo. Large changelog files are read
+ * backwards in chunks until the requested number of changelog
+ * lines are recieved.
+ *
+ * @param int $first skip the first n changelog lines
+ * @param int $num number of revisions to return
+ * @return array with the revision timestamps
+ *
+ * @author Ben Coburn <btcoburn@silicodon.net>
+ * @author Kate Arzamastseva <pshns@ukr.net>
+ */
+ public function getRevisions($first, $num) {
+ $revs = array();
+ $lines = array();
+ $count = 0;
+
+ $num = max($num, 0);
+ if($num == 0) {
+ return $revs;
+ }
- if ($tail-$head<1) {
- // cound not find chunk, assume requested rev is missing
+ if($first < 0) {
+ $first = 0;
+ } else if(@file_exists($this->getFilename())) {
+ // skip current revision if the page exists
+ $first = max($first + 1, 0);
+ }
+
+ $file = $this->getChangelogFilename();
+
+ if(!@file_exists($file)) {
+ return $revs;
+ }
+ if(filesize($file) < $this->chunk_size || $this->chunk_size == 0) {
+ // read whole file
+ $lines = file($file);
+ if($lines === false) {
+ return $revs;
+ }
+ } else {
+ // read chunks backwards
+ $fp = fopen($file, 'rb'); // "file pointer"
+ if($fp === false) {
+ return $revs;
+ }
+ fseek($fp, 0, SEEK_END);
+ $tail = ftell($fp);
+
+ // chunk backwards
+ $finger = max($tail - $this->chunk_size, 0);
+ while($count < $num + $first) {
+ $nl = $this->getNewlinepointer($fp, $finger);
+
+ // was the chunk big enough? if not, take another bite
+ if($nl > 0 && $tail <= $nl) {
+ $finger = max($finger - $this->chunk_size, 0);
+ continue;
+ } else {
+ $finger = $nl;
+ }
+
+ // read chunk
+ $chunk = '';
+ $read_size = max($tail - $finger, 0); // found chunk size
+ $got = 0;
+ while($got < $read_size && !feof($fp)) {
+ $tmp = @fread($fp, max(min($this->chunk_size, $read_size - $got), 0));
+ if($tmp === false) {
+ break;
+ } //error state
+ $got += strlen($tmp);
+ $chunk .= $tmp;
+ }
+ $tmp = explode("\n", $chunk);
+ array_pop($tmp); // remove trailing newline
+
+ // combine with previous chunk
+ $count += count($tmp);
+ $lines = array_merge($tmp, $lines);
+
+ // next chunk
+ if($finger == 0) {
+ break;
+ } // already read all the lines
+ else {
+ $tail = $finger;
+ $finger = max($tail - $this->chunk_size, 0);
+ }
+ }
fclose($fp);
+ }
+
+ // skip parsing extra lines
+ $num = max(min(count($lines) - $first, $num), 0);
+ if ($first > 0 && $num > 0) { $lines = array_slice($lines, max(count($lines) - $first - $num, 0), $num); }
+ else if($first > 0 && $num == 0) { $lines = array_slice($lines, 0, max(count($lines) - $first, 0)); }
+ else if($first == 0 && $num > 0) { $lines = array_slice($lines, max(count($lines) - $num, 0)); }
+
+ // handle lines in reverse order
+ for($i = count($lines) - 1; $i >= 0; $i--) {
+ $tmp = parseChangelogLine($lines[$i]);
+ if($tmp !== false) {
+ $this->cache[$this->id][$tmp['date']] = $tmp;
+ $revs[] = $tmp['date'];
+ }
+ }
+
+ return $revs;
+ }
+
+ /**
+ * Get the nth revision left or right handside for a specific page id and revision (timestamp)
+ *
+ * For large changelog files, only the chunk containing the
+ * reference revision $rev is read and sometimes a next chunck.
+ *
+ * Adjacent changelog lines are optimistically parsed and cached to speed up
+ * consecutive calls to getRevisionInfo.
+ *
+ * @param int $rev revision timestamp used as startdate (doesn't need to be revisionnumber)
+ * @param int $direction give position of returned revision with respect to $rev; positive=next, negative=prev
+ * @return bool|int
+ * timestamp of the requested revision
+ * otherwise false
+ */
+ public function getRelativeRevision($rev, $direction) {
+ $rev = max($rev, 0);
+ $direction = (int) $direction;
+
+ //no direction given or last rev, so no follow-up
+ if(!$direction || ($direction > 0 && $this->isCurrentRevision($rev))) {
return false;
}
- // read chunk
+ //get lines from changelog
+ list($fp, $lines, $head, $tail, $eof) = $this->readloglines($rev);
+ if(empty($lines)) return false;
+
+ // look for revisions later/earlier then $rev, when founded count till the wanted revision is reached
+ // also parse and cache changelog lines for getRevisionInfo().
+ $revcounter = 0;
+ $relativerev = false;
+ $checkotherchunck = true; //always runs once
+ while(!$relativerev && $checkotherchunck) {
+ $tmp = array();
+ //parse in normal or reverse order
+ $count = count($lines);
+ if($direction > 0) {
+ $start = 0;
+ $step = 1;
+ } else {
+ $start = $count - 1;
+ $step = -1;
+ }
+ for($i = $start; $i >= 0 && $i < $count; $i = $i + $step) {
+ $tmp = parseChangelogLine($lines[$i]);
+ if($tmp !== false) {
+ $this->cache[$this->id][$tmp['date']] = $tmp;
+ //look for revs older/earlier then reference $rev and select $direction-th one
+ if(($direction > 0 && $tmp['date'] > $rev) || ($direction < 0 && $tmp['date'] < $rev)) {
+ $revcounter++;
+ if($revcounter == abs($direction)) {
+ $relativerev = $tmp['date'];
+ }
+ }
+ }
+ }
+
+ //true when $rev is found, but not the wanted follow-up.
+ $checkotherchunck = $fp
+ && ($tmp['date'] == $rev || ($revcounter > 0 && !$relativerev))
+ && !(($tail == $eof && $direction > 0) || ($head == 0 && $direction < 0));
+
+ if($checkotherchunck) {
+ list($lines, $head, $tail) = $this->readAdjacentChunk($fp, $head, $tail, $direction);
+
+ if(empty($lines)) break;
+ }
+ }
+ if($fp) {
+ fclose($fp);
+ }
+
+ return $relativerev;
+ }
+
+ /**
+ * Returns revisions around rev1 and rev2
+ * When available it returns $max entries for each revision
+ *
+ * @param int $rev1 oldest revision timestamp
+ * @param int $rev2 newest revision timestamp
+ * @param int $max maximum number of revisions returned
+ * @return array with two arrays with revisions surrounding rev1 respectively rev2
+ */
+ public function getRevisionsAround($rev1, $rev2, $max = 50) {
+ $max = floor(abs($max) / 2)*2 + 1;
+ $rev1 = max($rev1, 0);
+ $rev2 = max($rev2, 0);
+
+ if($rev2 < $rev1) {
+ $rev = $rev2;
+ $rev2 = $rev1;
+ $rev1 = $rev;
+ }
+ //collect revisions around rev2
+ list($revs2, $allrevs, $fp, $lines, $head, $tail) = $this->retrieveRevisionsAround($rev2, $max);
+
+ if(empty($revs2)) return array(array(), array());
+
+ //collect revisions around rev1
+ $index = array_search($rev1, $allrevs);
+ if($index === false) {
+ //no overlapping revisions
+ list($revs1,,,,,) = $this->retrieveRevisionsAround($rev1, $max);
+ if(empty($revs1)) $revs1 = array();
+ } else {
+ //revisions overlaps, reuse revisions around rev2
+ $revs1 = $allrevs;
+ while($head > 0) {
+ for($i = count($lines) - 1; $i >= 0; $i--) {
+ $tmp = parseChangelogLine($lines[$i]);
+ if($tmp !== false) {
+ $this->cache[$this->id][$tmp['date']] = $tmp;
+ $revs1[] = $tmp['date'];
+ $index++;
+
+ if($index > floor($max / 2)) break 2;
+ }
+ }
+
+ list($lines, $head, $tail) = $this->readAdjacentChunk($fp, $head, $tail, -1);
+ }
+ sort($revs1);
+ //return wanted selection
+ $revs1 = array_slice($revs1, max($index - floor($max/2), 0), $max);
+ }
+
+ return array($revs1, $revs2);
+ }
+
+ /**
+ * Returns lines from changelog.
+ * If file larger than $chuncksize, only chunck is read that could contain $rev.
+ *
+ * @param int $rev revision timestamp
+ * @return array(fp, array(changeloglines), $head, $tail, $eof)|bool
+ * returns false when not succeed. fp only defined for chuck reading, needs closing.
+ */
+ protected function readloglines($rev) {
+ $file = $this->getChangelogFilename();
+
+ if(!@file_exists($file)) {
+ return false;
+ }
+
+ $fp = null;
+ $head = 0;
+ $tail = 0;
+ $eof = 0;
+
+ if(filesize($file) < $this->chunk_size || $this->chunk_size == 0) {
+ // read whole file
+ $lines = file($file);
+ if($lines === false) {
+ return false;
+ }
+ } else {
+ // read by chunk
+ $fp = fopen($file, 'rb'); // "file pointer"
+ if($fp === false) {
+ return false;
+ }
+ $head = 0;
+ fseek($fp, 0, SEEK_END);
+ $eof = ftell($fp);
+ $tail = $eof;
+
+ // find chunk
+ while($tail - $head > $this->chunk_size) {
+ $finger = $head + floor(($tail - $head) / 2.0);
+ $finger = $this->getNewlinepointer($fp, $finger);
+ $tmp = fgets($fp);
+ if($finger == $head || $finger == $tail) {
+ break;
+ }
+ $tmp = parseChangelogLine($tmp);
+ $finger_rev = $tmp['date'];
+
+ if($finger_rev > $rev) {
+ $tail = $finger;
+ } else {
+ $head = $finger;
+ }
+ }
+
+ if($tail - $head < 1) {
+ // cound not find chunk, assume requested rev is missing
+ fclose($fp);
+ return false;
+ }
+
+ $lines = $this->readChunk($fp, $head, $tail);
+ }
+ return array(
+ $fp,
+ $lines,
+ $head,
+ $tail,
+ $eof
+ );
+ }
+
+ /**
+ * Read chunk and return array with lines of given chunck.
+ * Has no check if $head and $tail are really at a new line
+ *
+ * @param $fp resource filepointer
+ * @param $head int start point chunck
+ * @param $tail int end point chunck
+ * @return array lines read from chunck
+ */
+ protected function readChunk($fp, $head, $tail) {
$chunk = '';
- $chunk_size = max($tail-$head, 0); // found chunk size
+ $chunk_size = max($tail - $head, 0); // found chunk size
$got = 0;
fseek($fp, $head);
- while ($got<$chunk_size && !feof($fp)) {
- $tmp = @fread($fp, max($chunk_size-$got, 0));
- if ($tmp===false) { break; } //error state
+ while($got < $chunk_size && !feof($fp)) {
+ $tmp = @fread($fp, max(min($this->chunk_size, $chunk_size - $got), 0));
+ if($tmp === false) { //error state
+ break;
+ }
$got += strlen($tmp);
$chunk .= $tmp;
}
$lines = explode("\n", $chunk);
array_pop($lines); // remove trailing newline
- fclose($fp);
+ return $lines;
}
- // parse and cache changelog lines
- foreach ($lines as $value) {
- $tmp = parseChangelogLine($value);
- if ($tmp!==false) {
- $cache[$id][$tmp['date']] = $tmp;
+ /**
+ * Set pointer to first new line after $finger and return its position
+ *
+ * @param resource $fp filepointer
+ * @param $finger int a pointer
+ * @return int pointer
+ */
+ protected function getNewlinepointer($fp, $finger) {
+ fseek($fp, $finger);
+ $nl = $finger;
+ if($finger > 0) {
+ fgets($fp); // slip the finger forward to a new line
+ $nl = ftell($fp);
}
+ return $nl;
+ }
+
+ /**
+ * Check whether given revision is the current page
+ *
+ * @param int $rev timestamp of current page
+ * @return bool true if $rev is current revision, otherwise false
+ */
+ public function isCurrentRevision($rev) {
+ return $rev == @filemtime($this->getFilename());
+ }
+
+ /**
+ * Returns the next lines of the changelog of the chunck before head or after tail
+ *
+ * @param resource $fp filepointer
+ * @param int $head position head of last chunk
+ * @param int $tail position tail of last chunk
+ * @param int $direction positive forward, negative backward
+ * @return array with entries:
+ * - $lines: changelog lines of readed chunk
+ * - $head: head of chunk
+ * - $tail: tail of chunk
+ */
+ protected function readAdjacentChunk($fp, $head, $tail, $direction) {
+ if(!$fp) return array(array(), $head, $tail);
+
+ if($direction > 0) {
+ //read forward
+ $head = $tail;
+ $tail = $head + floor($this->chunk_size * (2 / 3));
+ $tail = $this->getNewlinepointer($fp, $tail);
+ } else {
+ //read backward
+ $tail = $head;
+ $head = max($tail - $this->chunk_size, 0);
+ while(true) {
+ $nl = $this->getNewlinepointer($fp, $head);
+ // was the chunk big enough? if not, take another bite
+ if($nl > 0 && $tail <= $nl) {
+ $head = max($head - $this->chunk_size, 0);
+ } else {
+ $head = $nl;
+ break;
+ }
+ }
+ }
+
+ //load next chunck
+ $lines = $this->readChunk($fp, $head, $tail);
+ return array($lines, $head, $tail);
+ }
+
+ /**
+ * Collect the $max revisions near to the timestamp $rev
+ *
+ * @param int $rev revision timestamp
+ * @param int $max maximum number of revisions to be returned
+ * @return bool|array
+ * return array with entries:
+ * - $requestedrevs: array of with $max revision timestamps
+ * - $revs: all parsed revision timestamps
+ * - $fp: filepointer only defined for chuck reading, needs closing.
+ * - $lines: non-parsed changelog lines before the parsed revisions
+ * - $head: position of first readed changelogline
+ * - $lasttail: position of end of last readed changelogline
+ * otherwise false
+ */
+ protected function retrieveRevisionsAround($rev, $max) {
+ //get lines from changelog
+ list($fp, $lines, $starthead, $starttail, $eof) = $this->readloglines($rev);
+ if(empty($lines)) return false;
+
+ //parse chunk containing $rev, and read forward more chunks until $max/2 is reached
+ $head = $starthead;
+ $tail = $starttail;
+ $revs = array();
+ $aftercount = $beforecount = 0;
+ while(count($lines) > 0) {
+ foreach($lines as $line) {
+ $tmp = parseChangelogLine($line);
+ if($tmp !== false) {
+ $this->cache[$this->id][$tmp['date']] = $tmp;
+ $revs[] = $tmp['date'];
+ if($tmp['date'] >= $rev) {
+ //count revs after reference $rev
+ $aftercount++;
+ if($aftercount == 1) $beforecount = count($revs);
+ }
+ //enough revs after reference $rev?
+ if($aftercount > floor($max / 2)) break 2;
+ }
+ }
+ //retrieve next chunk
+ list($lines, $head, $tail) = $this->readAdjacentChunk($fp, $head, $tail, 1);
+ }
+ if($aftercount == 0) return false;
+
+ $lasttail = $tail;
+
+ //read additional chuncks backward until $max/2 is reached and total number of revs is equal to $max
+ $lines = array();
+ $i = 0;
+ if($aftercount > 0) {
+ $head = $starthead;
+ $tail = $starttail;
+ while($head > 0) {
+ list($lines, $head, $tail) = $this->readAdjacentChunk($fp, $head, $tail, -1);
+
+ for($i = count($lines) - 1; $i >= 0; $i--) {
+ $tmp = parseChangelogLine($lines[$i]);
+ if($tmp !== false) {
+ $this->cache[$this->id][$tmp['date']] = $tmp;
+ $revs[] = $tmp['date'];
+ $beforecount++;
+ //enough revs before reference $rev?
+ if($beforecount > max(floor($max / 2), $max - $aftercount)) break 2;
+ }
+ }
+ }
+ }
+ sort($revs);
+
+ //keep only non-parsed lines
+ $lines = array_slice($lines, 0, $i);
+ //trunk desired selection
+ $requestedrevs = array_slice($revs, -$max, $max);
+
+ return array($requestedrevs, $revs, $fp, $lines, $head, $lasttail);
+ }
+}
+
+/**
+ * Class PageChangelog handles changelog of a wiki page
+ */
+class PageChangelog extends ChangeLog {
+
+ /**
+ * Returns path to changelog
+ *
+ * @return string path to file
+ */
+ protected function getChangelogFilename() {
+ return metaFN($this->id, '.changes');
+ }
+
+ /**
+ * Returns path to current page/media
+ *
+ * @return string path to file
+ */
+ protected function getFilename() {
+ return wikiFN($this->id);
+ }
+}
+
+/**
+ * Class MediaChangelog handles changelog of a media file
+ */
+class MediaChangelog extends ChangeLog {
+
+ /**
+ * Returns path to changelog
+ *
+ * @return string path to file
+ */
+ protected function getChangelogFilename() {
+ return mediaMetaFN($this->id, '.changes');
+ }
+
+ /**
+ * Returns path to current page/media
+ *
+ * @return string path to file
+ */
+ protected function getFilename() {
+ return mediaFN($this->id);
}
- if (!isset($cache[$id][$rev])) { return false; }
- return $cache[$id][$rev];
+}
+
+/**
+ * Get the changelog information for a specific page id
+ * and revision (timestamp). Adjacent changelog lines
+ * are optimistically parsed and cached to speed up
+ * consecutive calls to getRevisionInfo. For large
+ * changelog files, only the chunk containing the
+ * requested changelog line is read.
+ *
+ * @deprecated 20-11-2013
+ *
+ * @author Ben Coburn <btcoburn@silicodon.net>
+ * @author Kate Arzamastseva <pshns@ukr.net>
+ */
+function getRevisionInfo($id, $rev, $chunk_size = 8192, $media = false) {
+ if($media) {
+ $changelog = new MediaChangeLog($id, $chunk_size);
+ } else {
+ $changelog = new PageChangeLog($id, $chunk_size);
+ }
+ return $changelog->getRevisionInfo($rev);
}
/**
@@ -443,106 +1026,16 @@ function getRevisionInfo($id, $rev, $chunk_size=8192, $media=false) {
* backwards in chunks until the requested number of changelog
* lines are recieved.
*
+ * @deprecated 20-11-2013
+ *
* @author Ben Coburn <btcoburn@silicodon.net>
* @author Kate Arzamastseva <pshns@ukr.net>
*/
-function getRevisions($id, $first, $num, $chunk_size=8192, $media=false) {
- global $cache_revinfo;
- $cache =& $cache_revinfo;
- if (!isset($cache[$id])) { $cache[$id] = array(); }
-
- $revs = array();
- $lines = array();
- $count = 0;
- if ($media) {
- $file = mediaMetaFN($id, '.changes');
+function getRevisions($id, $first, $num, $chunk_size = 8192, $media = false) {
+ if($media) {
+ $changelog = new MediaChangeLog($id, $chunk_size);
} else {
- $file = metaFN($id, '.changes');
- }
- $num = max($num, 0);
- if ($num == 0) { return $revs; }
-
- $chunk_size = max($chunk_size, 0);
- if ($first<0) {
- $first = 0;
- } else if (!$media && @file_exists(wikiFN($id)) || $media && @file_exists(mediaFN($id))) {
- // skip current revision if the page exists
- $first = max($first+1, 0);
+ $changelog = new PageChangeLog($id, $chunk_size);
}
-
- if (!@file_exists($file)) { return $revs; }
- if (filesize($file)<$chunk_size || $chunk_size==0) {
- // read whole file
- $lines = file($file);
- if ($lines===false) { return $revs; }
- } else {
- // read chunks backwards
- $fp = fopen($file, 'rb'); // "file pointer"
- if ($fp===false) { return $revs; }
- fseek($fp, 0, SEEK_END);
- $tail = ftell($fp);
-
- // chunk backwards
- $finger = max($tail-$chunk_size, 0);
- while ($count<$num+$first) {
- fseek($fp, $finger);
- $nl = $finger;
- if ($finger>0) {
- fgets($fp); // slip the finger forward to a new line
- $nl = ftell($fp);
- }
-
- // was the chunk big enough? if not, take another bite
- if($nl > 0 && $tail <= $nl){
- $finger = max($finger-$chunk_size, 0);
- continue;
- }else{
- $finger = $nl;
- }
-
- // read chunk
- $chunk = '';
- $read_size = max($tail-$finger, 0); // found chunk size
- $got = 0;
- while ($got<$read_size && !feof($fp)) {
- $tmp = @fread($fp, max($read_size-$got, 0));
- if ($tmp===false) { break; } //error state
- $got += strlen($tmp);
- $chunk .= $tmp;
- }
- $tmp = explode("\n", $chunk);
- array_pop($tmp); // remove trailing newline
-
- // combine with previous chunk
- $count += count($tmp);
- $lines = array_merge($tmp, $lines);
-
- // next chunk
- if ($finger==0) { break; } // already read all the lines
- else {
- $tail = $finger;
- $finger = max($tail-$chunk_size, 0);
- }
- }
- fclose($fp);
- }
-
- // skip parsing extra lines
- $num = max(min(count($lines)-$first, $num), 0);
- if ($first>0 && $num>0) { $lines = array_slice($lines, max(count($lines)-$first-$num, 0), $num); }
- else if ($first>0 && $num==0) { $lines = array_slice($lines, 0, max(count($lines)-$first, 0)); }
- else if ($first==0 && $num>0) { $lines = array_slice($lines, max(count($lines)-$num, 0)); }
-
- // handle lines in reverse order
- for ($i = count($lines)-1; $i >= 0; $i--) {
- $tmp = parseChangelogLine($lines[$i]);
- if ($tmp!==false) {
- $cache[$id][$tmp['date']] = $tmp;
- $revs[] = $tmp['date'];
- }
- }
-
- return $revs;
+ return $changelog->getRevisions($first, $num);
}
-
-
diff --git a/inc/common.php b/inc/common.php
index 32771285b..7821cb3de 100644
--- a/inc/common.php
+++ b/inc/common.php
@@ -187,13 +187,14 @@ function pageinfo() {
$info['meta'] = p_get_metadata($ID);
//who's the editor
+ $pagelog = new PageChangeLog($ID, 1024);
if($REV) {
- $revinfo = getRevisionInfo($ID, $REV, 1024);
+ $revinfo = $pagelog->getRevisionInfo($REV);
} else {
if(is_array($info['meta']['last_change'])) {
$revinfo = $info['meta']['last_change'];
} else {
- $revinfo = getRevisionInfo($ID, $info['lastmod'], 1024);
+ $revinfo = $pagelog->getRevisionInfo($info['lastmod']);
// cache most recent changelog line in metadata if missing and still valid
if($revinfo !== false) {
$info['meta']['last_change'] = $revinfo;
@@ -1059,8 +1060,9 @@ function saveWikiText($id, $text, $summary, $minor = false) {
$wasRemoved = (trim($text) == ''); // check for empty or whitespace only
$wasCreated = !@file_exists($file);
$wasReverted = ($REV == true);
+ $pagelog = new PageChangeLog($id, 1024);
$newRev = false;
- $oldRev = getRevisions($id, -1, 1, 1024); // from changelog
+ $oldRev = $pagelog->getRevisions(-1, 1); // from changelog
$oldRev = (int) (empty($oldRev) ? 0 : $oldRev[0]);
if(!@file_exists(wikiFN($id, $old)) && @file_exists($file) && $old >= $oldRev) {
// add old revision to the attic if missing
diff --git a/inc/html.php b/inc/html.php
index 928991ae2..3e239cac3 100644
--- a/inc/html.php
+++ b/inc/html.php
@@ -414,20 +414,23 @@ function html_revisions($first=0, $media_id = false){
global $conf;
global $lang;
$id = $ID;
+ if ($media_id) {
+ $id = $media_id;
+ $changelog = new MediaChangeLog($id);
+ } else {
+ $changelog = new PageChangeLog($id);
+ }
+
/* we need to get one additional log entry to be able to
* decide if this is the last page or is there another one.
* see html_recent()
*/
- if (!$media_id) $revisions = getRevisions($ID, $first, $conf['recent']+1);
- else {
- $revisions = getRevisions($media_id, $first, $conf['recent']+1, 8192, true);
- $id = $media_id;
- }
+
+ $revisions = $changelog->getRevisions($first, $conf['recent']+1);
if(count($revisions)==0 && $first!=0){
$first=0;
- if (!$media_id) $revisions = getRevisions($ID, $first, $conf['recent']+1);
- else $revisions = getRevisions($media_id, $first, $conf['recent']+1, 8192, true);
+ $revisions = $changelog->getRevisions($first, $conf['recent']+1);
}
$hasNext = false;
if (count($revisions)>$conf['recent']) {
@@ -486,15 +489,18 @@ function html_revisions($first=0, $media_id = false){
$form->addElement(form_makeCloseTag('span'));
}
+ $changelog->setChunkSize(1024);
+
$form->addElement(form_makeOpenTag('span', array('class' => 'user')));
- if (!$media_id) $editor = $INFO['editor'];
- else {
- $revinfo = getRevisionInfo($id, @filemtime(fullpath(mediaFN($id))), 1024, true);
- if($revinfo['user']){
+ if($media_id) {
+ $revinfo = $changelog->getRevisionInfo(@filemtime(fullpath(mediaFN($id))));
+ if($revinfo['user']) {
$editor = $revinfo['user'];
- }else{
+ } else {
$editor = $revinfo['ip'];
}
+ } else {
+ $editor = $INFO['editor'];
}
$form->addElement((empty($editor))?('('.$lang['external_edit'].')'):editorinfo($editor));
$form->addElement(form_makeCloseTag('span'));
@@ -509,12 +515,11 @@ function html_revisions($first=0, $media_id = false){
foreach($revisions as $rev){
$date = dformat($rev);
- if (!$media_id) {
- $info = getRevisionInfo($id,$rev,true);
- $exists = page_exists($id,$rev);
- } else {
- $info = getRevisionInfo($id,$rev,true,true);
- $exists = @file_exists(mediaFN($id,$rev));
+ $info = $changelog->getRevisionInfo($rev);
+ if($media_id) {
+ $exists = @file_exists(mediaFN($id, $rev));
+ } else {
+ $exists = page_exists($id, $rev);
}
if ($info['type']===DOKU_CHANGE_TYPE_MINOR_EDIT)
@@ -706,7 +711,8 @@ function html_recent($first=0, $show_changes='both'){
$href = '';
if ($recent['media']) {
- $diff = (count(getRevisions($recent['id'], 0, 1, 8192, true)) && @file_exists(mediaFN($recent['id'])));
+ $medialog = new MediaChangeLog($recent['id']);
+ $diff = (count($medialog->getRevisions(0, 1)) && @file_exists(mediaFN($recent['id'])));
if ($diff) {
$href = media_managerURL(array('tab_details' => 'history',
'mediado' => 'diff', 'image' => $recent['id'], 'ns' => getNS($recent['id'])), '&');
@@ -1008,10 +1014,15 @@ function html_diff_head($l_rev, $r_rev, $id = null, $media = false, $inline = fa
$ml_or_wl = $media ? 'ml' : 'wl';
$l_minor = $r_minor = '';
+ if($media) {
+ $changelog = new MediaChangeLog($id);
+ } else {
+ $changelog = new PageChangeLog($id);
+ }
if(!$l_rev){
$l_head = '&mdash;';
}else{
- $l_info = getRevisionInfo($id,$l_rev,true, $media);
+ $l_info = $changelog->getRevisionInfo($l_rev);
if($l_info['user']){
$l_user = '<bdi>'.editorinfo($l_info['user']).'</bdi>';
if(auth_ismanager()) $l_user .= ' <bdo dir="ltr">('.$l_info['ip'].')</bdo>';
@@ -1029,7 +1040,7 @@ function html_diff_head($l_rev, $r_rev, $id = null, $media = false, $inline = fa
}
if($r_rev){
- $r_info = getRevisionInfo($id,$r_rev,true, $media);
+ $r_info = $changelog->getRevisionInfo($r_rev);
if($r_info['user']){
$r_user = '<bdi>'.editorinfo($r_info['user']).'</bdi>';
if(auth_ismanager()) $r_user .= ' <bdo dir="ltr">('.$r_info['ip'].')</bdo>';
@@ -1045,7 +1056,7 @@ function html_diff_head($l_rev, $r_rev, $id = null, $media = false, $inline = fa
$r_head_title.'</a></bdi>'.
$head_separator.$r_user.' '.$r_sum;
}elseif($_rev = @filemtime($media_or_wikiFN($id))){
- $_info = getRevisionInfo($id,$_rev,true, $media);
+ $_info = $changelog->getRevisionInfo($_rev);
if($_info['user']){
$_user = '<bdi>'.editorinfo($_info['user']).'</bdi>';
if(auth_ismanager()) $_user .= ' <bdo dir="ltr">('.$_info['ip'].')</bdo>';
@@ -1082,6 +1093,7 @@ function html_diff($text='',$intro=true,$type=null){
global $lang;
global $INPUT;
global $INFO;
+ $pagelog = new PageChangeLog($ID);
if(!$type) {
$type = $INPUT->str('difftype');
@@ -1140,7 +1152,7 @@ function html_diff($text='',$intro=true,$type=null){
$l_rev = $rev1;
}else{ // no revision was given, compare previous to current
$r_rev = '';
- $revs = getRevisions($ID, 0, 1);
+ $revs = $pagelog->getRevisions(0, 1);
$l_rev = $revs[0];
$REV = $l_rev; // store revision back in $REV
}
@@ -1153,6 +1165,18 @@ function html_diff($text='',$intro=true,$type=null){
}
$r_text = rawWiki($ID,$r_rev);
+ //look for previous/next revision
+ if($r_rev) {
+ $next_rev = $pagelog->getRelativeRevision($r_rev, 1);
+ } else {
+ $next_rev = false;
+ }
+ if($l_rev) {
+ $prev_rev = $pagelog->getRelativeRevision($l_rev, -1);
+ } else {
+ $prev_rev = false;
+ }
+
list($l_head, $r_head, $l_minor, $r_minor) = html_diff_head($l_rev, $r_rev, null, false, $type == 'inline');
}
@@ -1192,7 +1216,40 @@ function html_diff($text='',$intro=true,$type=null){
'rev2[1]' => $r_rev,
'difftype' => $type,
));
- ptln('<p><a class="wikilink1" href="'.$diffurl.'">'.$lang['difflink'].'</a></p>');
+ ptln('<p><a class="wikilink1" href="'.$diffurl.'">'.$lang['difflink'].'</a><br />');
+ if($prev_rev){
+ $diffurlprev = wl($ID, array(
+ 'do' => 'diff',
+ 'rev2[0]' => $prev_rev,
+ 'rev2[1]' => $l_rev,
+ 'difftype' => $type,
+ ));
+ ptln('<a class="wikilink1" href="'.$diffurlprev.'">← '.$lang['diffpreviousedit'].'</a> - ');
+ }
+ $recenturl = wl($ID, array(
+ 'do' => 'revisions'
+ ));
+ ptln('<a class="wikilink1" href="'.$recenturl.'">'.$lang['overviewrevs'].'</a>');
+ if($next_rev){
+ if($pagelog->isCurrentRevision($next_rev)) {
+ $diffurlnextparam = array(
+ 'do' => 'diff',
+ 'rev' => $r_rev,
+ 'difftype' => $type,
+ );
+ $navnexttitle = $lang['difflastedit'];
+ } else {
+ $diffurlnextparam = array(
+ 'do' => 'diff',
+ 'rev2[0]' => $r_rev,
+ 'rev2[1]' => $next_rev,
+ 'difftype' => $type,
+ );
+ $navnexttitle = $lang['diffnextedit'];
+ }
+ ptln(' - <a class="wikilink1" href="'.wl($ID, $diffurlnextparam).'">'.$navnexttitle.' →</a>');
+ }
+ ptln('</p>');
ptln('</div>');
}
?>
diff --git a/inc/lang/en/lang.php b/inc/lang/en/lang.php
index cbdef8661..6c531f425 100644
--- a/inc/lang/en/lang.php
+++ b/inc/lang/en/lang.php
@@ -191,6 +191,10 @@ $lang['difflink'] = 'Link to this comparison view';
$lang['diff_type'] = 'View differences:';
$lang['diff_inline'] = 'Inline';
$lang['diff_side'] = 'Side by Side';
+$lang['diffpreviousedit'] = 'Previous edit';
+$lang['diffnextedit'] = 'Next edit';
+$lang['difflastedit'] = 'Last edit';
+$lang['overviewrevs'] = 'Overview of revisions';
$lang['line'] = 'Line';
$lang['breadcrumb'] = 'Trace';
$lang['youarehere'] = 'You are here';
diff --git a/inc/lang/nl/lang.php b/inc/lang/nl/lang.php
index e5e3e3c76..4a0a49306 100644
--- a/inc/lang/nl/lang.php
+++ b/inc/lang/nl/lang.php
@@ -197,6 +197,10 @@ $lang['difflink'] = 'Link naar deze vergelijking';
$lang['diff_type'] = 'Bekijk verschillen:';
$lang['diff_inline'] = 'Inline';
$lang['diff_side'] = 'Zij aan zij';
+$lang['diffpreviousedit'] = 'Vorige bewerking';
+$lang['diffnextedit'] = 'Volgende bewerking';
+$lang['difflastedit'] = 'Laatste bewerking';
+$lang['overviewrevs'] = 'Overzicht van revisies';
$lang['line'] = 'Regel';
$lang['breadcrumb'] = 'Spoor';
$lang['youarehere'] = 'Je bent hier';
diff --git a/inc/media.php b/inc/media.php
index 93662ec17..8fb67c31d 100644
--- a/inc/media.php
+++ b/inc/media.php
@@ -501,7 +501,8 @@ function media_saveOldRevision($id){
$date = filemtime($oldf);
if (!$conf['mediarevisions']) return $date;
- if (!getRevisionInfo($id, $date, 8192, true)) {
+ $medialog = new MediaChangeLog($id);
+ if (!$medialog->getRevisionInfo($date)) {
// there was an external edit,
// there is no log entry for current version of file
if (!@file_exists(mediaMetaFN($id,'.changes'))) {
@@ -1077,7 +1078,8 @@ function media_diff($image, $ns, $auth, $fromajax = false) {
$l_rev = $rev1;
}else{ // no revision was given, compare previous to current
$r_rev = '';
- $revs = getRevisions($image, 0, 1, 8192, true);
+ $medialog = new MediaChangeLog($image);
+ $revs = $medialog->getRevisions(0, 1);
if (file_exists(mediaFN($image, $revs[0]))) {
$l_rev = $revs[0];
} else {
diff --git a/inc/subscription.php b/inc/subscription.php
index ddf2f39e6..e6fb23f63 100644
--- a/inc/subscription.php
+++ b/inc/subscription.php
@@ -288,7 +288,7 @@ class Subscription {
public function send_bulk($page) {
if(!$this->isenabled()) return 0;
- /** @var auth_basic $auth */
+ /** @var DokuWiki_Auth_Plugin $auth */
global $auth;
global $conf;
global $USERINFO;
@@ -336,7 +336,8 @@ class Subscription {
while(!is_null($rev) && $rev['date'] >= $lastupdate &&
($_SERVER['REMOTE_USER'] === $rev['user'] ||
$rev['type'] === DOKU_CHANGE_TYPE_MINOR_EDIT)) {
- $rev = getRevisions($rev['id'], $n++, 1);
+ $pagelog = new PageChangeLog($rev['id']);
+ $rev = $pagelog->getRevisions($n++, 1);
$rev = (count($rev) > 0) ? $rev[0] : null;
}
@@ -515,9 +516,10 @@ class Subscription {
* @return bool
*/
protected function send_digest($subscriber_mail, $id, $lastupdate) {
+ $pagelog = new PageChangeLog($id);
$n = 0;
do {
- $rev = getRevisions($id, $n++, 1);
+ $rev = $pagelog->getRevisions($n++, 1);
$rev = (count($rev) > 0) ? $rev[0] : null;
} while(!is_null($rev) && $rev > $lastupdate);
diff --git a/lib/plugins/revert/admin.php b/lib/plugins/revert/admin.php
index 423d67449..88d8cd93d 100644
--- a/lib/plugins/revert/admin.php
+++ b/lib/plugins/revert/admin.php
@@ -83,7 +83,8 @@ class admin_plugin_revert extends DokuWiki_Admin_Plugin {
// find the last non-spammy revision
$data = '';
- $old = getRevisions($id, 0, $this->max_revs);
+ $pagelog = new PageChangeLog($id);
+ $old = $pagelog->getRevisions(0, $this->max_revs);
if(count($old)){
foreach($old as $REV){
$data = rawWiki($id,$REV);